pacemaker 2.1.6-6fdc9deea29
Scalable High-Availability cluster resource manager
Loading...
Searching...
No Matches
pcmk_sched_nodes.c
Go to the documentation of this file.
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#include <crm/msg_xml.h>
12#include <crm/lrmd.h> // lrmd_event_data_t
14#include <pacemaker-internal.h>
15#include <pacemaker.h>
17
30bool
31pcmk__node_available(const pe_node_t *node, bool consider_score,
32 bool consider_guest)
33{
34 if ((node == NULL) || (node->details == NULL) || !node->details->online
35 || node->details->shutdown || node->details->unclean
36 || node->details->standby || node->details->maintenance) {
37 return false;
38 }
39
40 if (consider_score && (node->weight < 0)) {
41 return false;
42 }
43
44 // @TODO Go through all callers to see which should set consider_guest
45 if (consider_guest && pe__is_guest_node(node)) {
47
48 if (guest->fns->location(guest, NULL, FALSE) == NULL) {
49 return false;
50 }
51 }
52
53 return true;
54}
55
64GHashTable *
65pcmk__copy_node_table(GHashTable *nodes)
66{
67 GHashTable *new_table = NULL;
68 GHashTableIter iter;
69 pe_node_t *node = NULL;
70
71 if (nodes == NULL) {
72 return NULL;
73 }
74 new_table = pcmk__strkey_table(NULL, free);
75 g_hash_table_iter_init(&iter, nodes);
76 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
77 pe_node_t *new_node = pe__copy_node(node);
78
79 g_hash_table_insert(new_table, (gpointer) new_node->details->id,
80 new_node);
81 }
82 return new_table;
83}
84
94GList *
95pcmk__copy_node_list(const GList *list, bool reset)
96{
97 GList *result = NULL;
98
99 for (const GList *gIter = list; gIter != NULL; gIter = gIter->next) {
100 pe_node_t *new_node = NULL;
101 pe_node_t *this_node = (pe_node_t *) gIter->data;
102
103 new_node = pe__copy_node(this_node);
104 if (reset) {
105 new_node->weight = 0;
106 }
107 result = g_list_prepend(result, new_node);
108 }
109 return result;
110}
111
126static gint
127compare_nodes(gconstpointer a, gconstpointer b, gpointer data)
128{
129 const pe_node_t *node1 = (const pe_node_t *) a;
130 const pe_node_t *node2 = (const pe_node_t *) b;
131 const pe_node_t *active = (const pe_node_t *) data;
132
133 int node1_weight = 0;
134 int node2_weight = 0;
135
136 int result = 0;
137
138 if (a == NULL) {
139 return 1;
140 }
141 if (b == NULL) {
142 return -1;
143 }
144
145 // Compare node weights
146
147 node1_weight = pcmk__node_available(node1, false, false)? node1->weight : -INFINITY;
148 node2_weight = pcmk__node_available(node2, false, false)? node2->weight : -INFINITY;
149
150 if (node1_weight > node2_weight) {
151 crm_trace("%s (%d) > %s (%d) : weight",
152 pe__node_name(node1), node1_weight, pe__node_name(node2),
153 node2_weight);
154 return -1;
155 }
156
157 if (node1_weight < node2_weight) {
158 crm_trace("%s (%d) < %s (%d) : weight",
159 pe__node_name(node1), node1_weight, pe__node_name(node2),
160 node2_weight);
161 return 1;
162 }
163
164 crm_trace("%s (%d) == %s (%d) : weight",
165 pe__node_name(node1), node1_weight, pe__node_name(node2),
166 node2_weight);
167
168 // If appropriate, compare node utilization
169
170 if (pcmk__str_eq(node1->details->data_set->placement_strategy, "minimal",
172 goto equal;
173 }
174
175 if (pcmk__str_eq(node1->details->data_set->placement_strategy, "balanced",
178 if (result < 0) {
179 crm_trace("%s > %s : capacity (%d)",
180 pe__node_name(node1), pe__node_name(node2), result);
181 return -1;
182 } else if (result > 0) {
183 crm_trace("%s < %s : capacity (%d)",
184 pe__node_name(node1), pe__node_name(node2), result);
185 return 1;
186 }
187 }
188
189 // Compare number of allocated resources
190
192 crm_trace("%s (%d) > %s (%d) : resources",
193 pe__node_name(node1), node1->details->num_resources,
194 pe__node_name(node2), node2->details->num_resources);
195 return -1;
196
198 crm_trace("%s (%d) < %s (%d) : resources",
199 pe__node_name(node1), node1->details->num_resources,
200 pe__node_name(node2), node2->details->num_resources);
201 return 1;
202 }
203
204 // Check whether one node is already running desired resource
205
206 if (active != NULL) {
207 if (active->details == node1->details) {
208 crm_trace("%s (%d) > %s (%d) : active",
209 pe__node_name(node1), node1->details->num_resources,
210 pe__node_name(node2), node2->details->num_resources);
211 return -1;
212 } else if (active->details == node2->details) {
213 crm_trace("%s (%d) < %s (%d) : active",
214 pe__node_name(node1), node1->details->num_resources,
215 pe__node_name(node2), node2->details->num_resources);
216 return 1;
217 }
218 }
219
220 // If all else is equal, prefer node with lowest-sorting name
221equal:
222 crm_trace("%s = %s", pe__node_name(node1), pe__node_name(node2));
223 return strcmp(node1->details->uname, node2->details->uname);
224}
225
235GList *
236pcmk__sort_nodes(GList *nodes, pe_node_t *active_node)
237{
238 return g_list_sort_with_data(nodes, compare_nodes, active_node);
239}
240
250bool
251pcmk__any_node_available(GHashTable *nodes)
252{
253 GHashTableIter iter;
254 const pe_node_t *node = NULL;
255
256 if (nodes == NULL) {
257 return false;
258 }
259 g_hash_table_iter_init(&iter, nodes);
260 while (g_hash_table_iter_next(&iter, NULL, (void **) &node)) {
261 if (pcmk__node_available(node, true, false)) {
262 return true;
263 }
264 }
265 return false;
266}
267
274void
276{
277 int base_health = 0;
278 enum pcmk__health_strategy strategy;
279 const char *strategy_str = pe_pref(data_set->config_hash,
281
282 strategy = pcmk__parse_health_strategy(strategy_str);
283 if (strategy == pcmk__health_strategy_none) {
284 return;
285 }
286 crm_info("Applying node health strategy '%s'", strategy_str);
287
288 // The progressive strategy can use a base health score
289 if (strategy == pcmk__health_strategy_progressive) {
290 base_health = pe__health_score(PCMK__OPT_NODE_HEALTH_BASE, data_set);
291 }
292
293 for (GList *iter = data_set->nodes; iter != NULL; iter = iter->next) {
294 pe_node_t *node = (pe_node_t *) iter->data;
295 int health = pe__sum_node_health_scores(node, base_health);
296
297 // An overall health score of 0 has no effect
298 if (health == 0) {
299 continue;
300 }
301 crm_info("Overall system health of %s is %d",
302 pe__node_name(node), health);
303
304 // Use node health as a location score for each resource on the node
305 for (GList *r = data_set->resources; r != NULL; r = r->next) {
306 pe_resource_t *rsc = (pe_resource_t *) r->data;
307
308 bool constrain = true;
309
310 if (health < 0) {
311 /* Negative health scores do not apply to resources with
312 * allow-unhealthy-nodes=true.
313 */
314 constrain = !crm_is_true(g_hash_table_lookup(rsc->meta,
316 }
317 if (constrain) {
318 pcmk__new_location(strategy_str, rsc, health, NULL, node,
319 data_set);
320 } else {
321 pe_rsc_trace(rsc, "%s is immune from health ban on %s",
322 rsc->id, pe__node_name(node));
323 }
324 }
325 }
326}
327
338pe_node_t *
340{
341 GHashTable *allowed_nodes = NULL;
342
343 if ((rsc == NULL) || (node == NULL)) {
344 return NULL;
345 } else if (rsc->parent == NULL) {
346 allowed_nodes = rsc->allowed_nodes;
347 } else {
348 allowed_nodes = rsc->parent->allowed_nodes;
349 }
350 return pe_hash_table_lookup(allowed_nodes, node->details->id);
351}
gboolean crm_is_true(const char *s)
Definition strings.c:416
const char * pe_pref(GHashTable *options, const char *name)
Definition common.c:303
char data[0]
Definition cpg.c:10
#define INFINITY
Definition crm.h:99
pcmk__health_strategy
@ pcmk__health_strategy_progressive
@ pcmk__health_strategy_none
enum pcmk__health_strategy pcmk__parse_health_strategy(const char *value)
Definition health.c:41
G_GNUC_INTERNAL pe__location_t * pcmk__new_location(const char *id, pe_resource_t *rsc, int node_weight, const char *discover_mode, pe_node_t *foo_node, pe_working_set_t *data_set)
G_GNUC_INTERNAL int pcmk__compare_node_capacities(const pe_node_t *node1, const pe_node_t *node2)
#define crm_info(fmt, args...)
Definition logging.h:378
#define crm_trace(fmt, args...)
Definition logging.h:381
Resource agent executor.
pe_working_set_t * data_set
#define PCMK__OPT_NODE_HEALTH_STRATEGY
#define PCMK__META_ALLOW_UNHEALTHY_NODES
#define PCMK__OPT_NODE_HEALTH_BASE
High Level API.
pcmk__action_result_t result
Definition pcmk_fence.c:35
GHashTable * pcmk__copy_node_table(GHashTable *nodes)
bool pcmk__any_node_available(GHashTable *nodes)
void pcmk__apply_node_health(pe_working_set_t *data_set)
GList * pcmk__copy_node_list(const GList *list, bool reset)
bool pcmk__node_available(const pe_node_t *node, bool consider_score, bool consider_guest)
GList * pcmk__sort_nodes(GList *nodes, pe_node_t *active_node)
pe_node_t * pcmk__top_allowed_node(const pe_resource_t *rsc, const pe_node_t *node)
pe_node_t node1
pe_node_t node2
int pe__sum_node_health_scores(const pe_node_t *node, int base_health)
Definition pe_health.c:96
#define pe_rsc_trace(rsc, fmt, args...)
Definition internal.h:50
pe_node_t * pe__copy_node(const pe_node_t *this_node)
Definition utils.c:89
bool pe__is_guest_node(const pe_node_t *node)
Definition remote.c:33
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
Definition strings.c:611
@ pcmk__str_casei
int weight
Definition pe_types.h:265
struct pe_node_shared_s * details
Definition pe_types.h:268
gboolean shutdown
Definition pe_types.h:242
const char * id
Definition pe_types.h:231
gboolean online
Definition pe_types.h:236
const char * uname
Definition pe_types.h:232
pe_working_set_t * data_set
Cluster that this node is part of.
Definition pe_types.h:261
gboolean standby
Definition pe_types.h:237
pe_resource_t * remote_rsc
Definition pe_types.h:253
gboolean unclean
Definition pe_types.h:240
gboolean maintenance
Definition pe_types.h:245
GHashTable * meta
Definition pe_types.h:405
pe_resource_t * container
Definition pe_types.h:412
GHashTable * allowed_nodes
Definition pe_types.h:400
pe_resource_t * parent
Definition pe_types.h:354
resource_object_functions_t * fns
Definition pe_types.h:358
const char * placement_strategy
Definition pe_types.h:167
GHashTable * config_hash
Definition pe_types.h:174
GList * resources
Definition pe_types.h:181
pe_node_t *(* location)(const pe_resource_t *, GList **, int)
Definition pe_types.h:55