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
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 bool
28 pcmk__node_available(const pe_node_t *node)
29 {
30
31 return (node != NULL) && (node->details != NULL) && node->details->online
32 && !node->details->shutdown && !node->details->unclean
33 && !node->details->standby && !node->details->maintenance;
34 }
35
36
37
38
39
40
41
42
43
44 GHashTable *
45 pcmk__copy_node_table(GHashTable *nodes)
46 {
47 GHashTable *new_table = NULL;
48 GHashTableIter iter;
49 pe_node_t *node = NULL;
50
51 if (nodes == NULL) {
52 return NULL;
53 }
54 new_table = pcmk__strkey_table(NULL, free);
55 g_hash_table_iter_init(&iter, nodes);
56 while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &node)) {
57 pe_node_t *new_node = pe__copy_node(node);
58
59 g_hash_table_insert(new_table, (gpointer) new_node->details->id,
60 new_node);
61 }
62 return new_table;
63 }
64
65
66
67
68
69
70
71
72
73
74 GList *
75 pcmk__copy_node_list(const GList *list, bool reset)
76 {
77 GList *result = NULL;
78
79 for (const GList *gIter = list; gIter != NULL; gIter = gIter->next) {
80 pe_node_t *new_node = NULL;
81 pe_node_t *this_node = (pe_node_t *) gIter->data;
82
83 new_node = pe__copy_node(this_node);
84 if (reset) {
85 new_node->weight = 0;
86 }
87 result = g_list_prepend(result, new_node);
88 }
89 return result;
90 }
91
92 struct node_weight_s {
93 pe_node_t *active;
94 pe_working_set_t *data_set;
95 };
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111 static gint
112 compare_nodes(gconstpointer a, gconstpointer b, gpointer data)
113 {
114 const pe_node_t *node1 = (const pe_node_t *) a;
115 const pe_node_t *node2 = (const pe_node_t *) b;
116 struct node_weight_s *nw = data;
117
118 int node1_weight = 0;
119 int node2_weight = 0;
120
121 int result = 0;
122
123 if (a == NULL) {
124 return 1;
125 }
126 if (b == NULL) {
127 return -1;
128 }
129
130
131
132 node1_weight = pcmk__node_available(node1)? node1->weight : -INFINITY;
133 node2_weight = pcmk__node_available(node2)? node2->weight : -INFINITY;
134
135 if (node1_weight > node2_weight) {
136 crm_trace("%s (%d) > %s (%d) : weight",
137 node1->details->uname, node1_weight, node2->details->uname,
138 node2_weight);
139 return -1;
140 }
141
142 if (node1_weight < node2_weight) {
143 crm_trace("%s (%d) < %s (%d) : weight",
144 node1->details->uname, node1_weight, node2->details->uname,
145 node2_weight);
146 return 1;
147 }
148
149 crm_trace("%s (%d) == %s (%d) : weight",
150 node1->details->uname, node1_weight, node2->details->uname,
151 node2_weight);
152
153
154
155 if (pcmk__str_eq(nw->data_set->placement_strategy, "minimal",
156 pcmk__str_casei)) {
157 goto equal;
158 }
159
160 if (pcmk__str_eq(nw->data_set->placement_strategy, "balanced",
161 pcmk__str_casei)) {
162 result = pcmk__compare_node_capacities(node1, node2);
163 if (result < 0) {
164 crm_trace("%s > %s : capacity (%d)",
165 node1->details->uname, node2->details->uname, result);
166 return -1;
167 } else if (result > 0) {
168 crm_trace("%s < %s : capacity (%d)",
169 node1->details->uname, node2->details->uname, result);
170 return 1;
171 }
172 }
173
174
175
176 if (node1->details->num_resources < node2->details->num_resources) {
177 crm_trace("%s (%d) > %s (%d) : resources",
178 node1->details->uname, node1->details->num_resources,
179 node2->details->uname, node2->details->num_resources);
180 return -1;
181
182 } else if (node1->details->num_resources > node2->details->num_resources) {
183 crm_trace("%s (%d) < %s (%d) : resources",
184 node1->details->uname, node1->details->num_resources,
185 node2->details->uname, node2->details->num_resources);
186 return 1;
187 }
188
189
190
191 if (nw->active != NULL) {
192 if (nw->active->details == node1->details) {
193 crm_trace("%s (%d) > %s (%d) : active",
194 node1->details->uname, node1->details->num_resources,
195 node2->details->uname, node2->details->num_resources);
196 return -1;
197 } else if (nw->active->details == node2->details) {
198 crm_trace("%s (%d) < %s (%d) : active",
199 node1->details->uname, node1->details->num_resources,
200 node2->details->uname, node2->details->num_resources);
201 return 1;
202 }
203 }
204
205
206 equal:
207 crm_trace("%s = %s", node1->details->uname, node2->details->uname);
208 return strcmp(node1->details->uname, node2->details->uname);
209 }
210
211
212
213
214
215
216
217
218
219
220
221 GList *
222 pcmk__sort_nodes(GList *nodes, pe_node_t *active_node,
223 pe_working_set_t *data_set)
224 {
225 struct node_weight_s nw = { active_node, data_set };
226
227 return g_list_sort_with_data(nodes, compare_nodes, &nw);
228 }
229
230
231
232
233
234
235
236
237
238
239 bool
240 pcmk__any_node_available(GHashTable *nodes)
241 {
242 GHashTableIter iter;
243 pe_node_t *node = NULL;
244
245 if (nodes == NULL) {
246 return false;
247 }
248 g_hash_table_iter_init(&iter, nodes);
249 while (g_hash_table_iter_next(&iter, NULL, (void **) &node)) {
250 if ((node->weight >= 0) && pcmk__node_available(node)) {
251 return true;
252 }
253 }
254 return false;
255 }
256
257
258
259
260
261
262
263 void
264 pcmk__apply_node_health(pe_working_set_t *data_set)
265 {
266 int base_health = 0;
267 enum pcmk__health_strategy strategy;
268 const char *strategy_str = pe_pref(data_set->config_hash,
269 PCMK__OPT_NODE_HEALTH_STRATEGY);
270
271 strategy = pcmk__parse_health_strategy(strategy_str);
272 if (strategy == pcmk__health_strategy_none) {
273 return;
274 }
275 crm_info("Applying node health strategy '%s'", strategy_str);
276
277
278 if (strategy == pcmk__health_strategy_progressive) {
279 base_health = pe__health_score(PCMK__OPT_NODE_HEALTH_BASE, data_set);
280 }
281
282 for (GList *iter = data_set->nodes; iter != NULL; iter = iter->next) {
283 pe_node_t *node = (pe_node_t *) iter->data;
284 int health = pe__sum_node_health_scores(node, base_health);
285
286
287 if (health == 0) {
288 continue;
289 }
290 crm_info("Node %s overall system health is %d",
291 node->details->uname, health);
292
293
294 for (GList *r = data_set->resources; r != NULL; r = r->next) {
295 pe_resource_t *rsc = (pe_resource_t *) r->data;
296
297 bool constrain = true;
298
299 if (health < 0) {
300
301
302
303 constrain = !crm_is_true(g_hash_table_lookup(rsc->meta,
304 PCMK__META_ALLOW_UNHEALTHY_NODES));
305 }
306 if (constrain) {
307 pcmk__new_location(strategy_str, rsc, health, NULL, node,
308 data_set);
309 } else {
310 pe_rsc_trace(rsc, "%s is immune from health ban on %s",
311 rsc->id, node->details->uname);
312 }
313 }
314 }
315 }