This source file includes following definitions.
- pcmk__node_available
- pcmk__copy_node_table
- pcmk__copy_node_list
- compare_nodes
- pcmk__sort_nodes
- pcmk__any_node_available
- pcmk__apply_node_health
- pcmk__top_allowed_node
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11 #include <crm/msg_xml.h>
12 #include <crm/lrmd.h>
13 #include <crm/common/xml_internal.h>
14 #include <pacemaker-internal.h>
15 #include <pacemaker.h>
16 #include "libpacemaker_private.h"
17
18
19
20
21
22
23
24
25
26
27
28
29
30 bool
31 pcmk__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
45 if (consider_guest && pe__is_guest_node(node)) {
46 pe_resource_t *guest = node->details->remote_rsc->container;
47
48 if (guest->fns->location(guest, NULL, FALSE) == NULL) {
49 return false;
50 }
51 }
52
53 return true;
54 }
55
56
57
58
59
60
61
62
63
64 GHashTable *
65 pcmk__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
85
86
87
88
89
90
91
92
93
94 GList *
95 pcmk__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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126 static gint
127 compare_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
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
169
170 if (pcmk__str_eq(node1->details->data_set->placement_strategy, "minimal",
171 pcmk__str_casei)) {
172 goto equal;
173 }
174
175 if (pcmk__str_eq(node1->details->data_set->placement_strategy, "balanced",
176 pcmk__str_casei)) {
177 result = pcmk__compare_node_capacities(node1, node2);
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
190
191 if (node1->details->num_resources < node2->details->num_resources) {
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
197 } else if (node1->details->num_resources > node2->details->num_resources) {
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
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
221 equal:
222 crm_trace("%s = %s", pe__node_name(node1), pe__node_name(node2));
223 return strcmp(node1->details->uname, node2->details->uname);
224 }
225
226
227
228
229
230
231
232
233
234
235 GList *
236 pcmk__sort_nodes(GList *nodes, pe_node_t *active_node)
237 {
238 return g_list_sort_with_data(nodes, compare_nodes, active_node);
239 }
240
241
242
243
244
245
246
247
248
249
250 bool
251 pcmk__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
268
269
270
271
272
273
274 void
275 pcmk__apply_node_health(pe_working_set_t *data_set)
276 {
277 int base_health = 0;
278 enum pcmk__health_strategy strategy;
279 const char *strategy_str = pe_pref(data_set->config_hash,
280 PCMK__OPT_NODE_HEALTH_STRATEGY);
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
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
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
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
312
313
314 constrain = !crm_is_true(g_hash_table_lookup(rsc->meta,
315 PCMK__META_ALLOW_UNHEALTHY_NODES));
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
328
329
330
331
332
333
334
335
336
337
338 pe_node_t *
339 pcmk__top_allowed_node(const pe_resource_t *rsc, const pe_node_t *node)
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 }