This source file includes following definitions.
- pe_free_ordering
- pe_free_rsc_to_node
- rsc2node_new
- can_run_resources
- sort_node_weight
- native_deallocate
- native_assign_node
- log_action
- can_run_any
- create_pseudo_resource_op
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #include <crm_internal.h>
20 #include <crm/msg_xml.h>
21 #include <allocate.h>
22 #include <utils.h>
23
24 void
25 pe_free_ordering(GListPtr constraints)
26 {
27 GListPtr iterator = constraints;
28
29 while (iterator != NULL) {
30 order_constraint_t *order = iterator->data;
31
32 iterator = iterator->next;
33
34 free(order->lh_action_task);
35 free(order->rh_action_task);
36 free(order);
37 }
38 if (constraints != NULL) {
39 g_list_free(constraints);
40 }
41 }
42
43 void
44 pe_free_rsc_to_node(GListPtr constraints)
45 {
46 GListPtr iterator = constraints;
47
48 while (iterator != NULL) {
49 rsc_to_node_t *cons = iterator->data;
50
51 iterator = iterator->next;
52
53 g_list_free_full(cons->node_list_rh, free);
54 free(cons->id);
55 free(cons);
56 }
57 if (constraints != NULL) {
58 g_list_free(constraints);
59 }
60 }
61
62 rsc_to_node_t *
63 rsc2node_new(const char *id, resource_t * rsc,
64 int node_weight, const char *discover_mode,
65 node_t * foo_node, pe_working_set_t * data_set)
66 {
67 rsc_to_node_t *new_con = NULL;
68
69 if (rsc == NULL || id == NULL) {
70 pe_err("Invalid constraint %s for rsc=%p", crm_str(id), rsc);
71 return NULL;
72
73 } else if (foo_node == NULL) {
74 CRM_CHECK(node_weight == 0, return NULL);
75 }
76
77 new_con = calloc(1, sizeof(rsc_to_node_t));
78 if (new_con != NULL) {
79 new_con->id = strdup(id);
80 new_con->rsc_lh = rsc;
81 new_con->node_list_rh = NULL;
82 new_con->role_filter = RSC_ROLE_UNKNOWN;
83
84
85 if (discover_mode == NULL || safe_str_eq(discover_mode, "always")) {
86 new_con->discover_mode = pe_discover_always;
87 } else if (safe_str_eq(discover_mode, "never")) {
88 new_con->discover_mode = pe_discover_never;
89 } else if (safe_str_eq(discover_mode, "exclusive")) {
90 new_con->discover_mode = pe_discover_exclusive;
91 rsc->exclusive_discover = TRUE;
92 } else {
93 pe_err("Invalid %s value %s in location constraint", XML_LOCATION_ATTR_DISCOVERY, discover_mode);
94 }
95
96 if (foo_node != NULL) {
97 node_t *copy = node_copy(foo_node);
98
99 copy->weight = node_weight;
100 new_con->node_list_rh = g_list_prepend(NULL, copy);
101 }
102
103 data_set->placement_constraints = g_list_prepend(data_set->placement_constraints, new_con);
104 rsc->rsc_location = g_list_prepend(rsc->rsc_location, new_con);
105 }
106
107 return new_con;
108 }
109
110 gboolean
111 can_run_resources(const node_t * node)
112 {
113 if (node == NULL) {
114 return FALSE;
115 }
116 #if 0
117 if (node->weight < 0) {
118 return FALSE;
119 }
120 #endif
121
122 if (node->details->online == FALSE
123 || node->details->shutdown || node->details->unclean
124 || node->details->standby || node->details->maintenance) {
125 crm_trace("%s: online=%d, unclean=%d, standby=%d, maintenance=%d",
126 node->details->uname, node->details->online,
127 node->details->unclean, node->details->standby, node->details->maintenance);
128 return FALSE;
129 }
130 return TRUE;
131 }
132
133
134
135
136
137 gint
138 sort_node_weight(gconstpointer a, gconstpointer b, gpointer data)
139 {
140 const node_t *node1 = (const node_t *)a;
141 const node_t *node2 = (const node_t *)b;
142 const node_t *active = (node_t *) data;
143
144 int node1_weight = 0;
145 int node2_weight = 0;
146
147 int result = 0;
148
149 if (a == NULL) {
150 return 1;
151 }
152 if (b == NULL) {
153 return -1;
154 }
155
156 node1_weight = node1->weight;
157 node2_weight = node2->weight;
158
159 if (can_run_resources(node1) == FALSE) {
160 node1_weight = -INFINITY;
161 }
162 if (can_run_resources(node2) == FALSE) {
163 node2_weight = -INFINITY;
164 }
165
166 if (node1_weight > node2_weight) {
167 crm_trace("%s (%d) > %s (%d) : weight",
168 node1->details->uname, node1_weight, node2->details->uname, node2_weight);
169 return -1;
170 }
171
172 if (node1_weight < node2_weight) {
173 crm_trace("%s (%d) < %s (%d) : weight",
174 node1->details->uname, node1_weight, node2->details->uname, node2_weight);
175 return 1;
176 }
177
178 crm_trace("%s (%d) == %s (%d) : weight",
179 node1->details->uname, node1_weight, node2->details->uname, node2_weight);
180
181 if (safe_str_eq(pe_dataset->placement_strategy, "minimal")) {
182 goto equal;
183 }
184
185 if (safe_str_eq(pe_dataset->placement_strategy, "balanced")) {
186 result = compare_capacity(node1, node2);
187 if (result < 0) {
188 crm_trace("%s > %s : capacity (%d)",
189 node1->details->uname, node2->details->uname, result);
190 return -1;
191 } else if (result > 0) {
192 crm_trace("%s < %s : capacity (%d)",
193 node1->details->uname, node2->details->uname, result);
194 return 1;
195 }
196 }
197
198
199 if (node1->details->num_resources < node2->details->num_resources) {
200 crm_trace("%s (%d) > %s (%d) : resources",
201 node1->details->uname, node1->details->num_resources,
202 node2->details->uname, node2->details->num_resources);
203 return -1;
204
205 } else if (node1->details->num_resources > node2->details->num_resources) {
206 crm_trace("%s (%d) < %s (%d) : resources",
207 node1->details->uname, node1->details->num_resources,
208 node2->details->uname, node2->details->num_resources);
209 return 1;
210 }
211
212 if (active && active->details == node1->details) {
213 crm_trace("%s (%d) > %s (%d) : active",
214 node1->details->uname, node1->details->num_resources,
215 node2->details->uname, node2->details->num_resources);
216 return -1;
217 } else if (active && active->details == node2->details) {
218 crm_trace("%s (%d) < %s (%d) : active",
219 node1->details->uname, node1->details->num_resources,
220 node2->details->uname, node2->details->num_resources);
221 return 1;
222 }
223 equal:
224 crm_trace("%s = %s", node1->details->uname, node2->details->uname);
225 return strcmp(node1->details->uname, node2->details->uname);
226 }
227
228 void
229 native_deallocate(resource_t * rsc)
230 {
231 if (rsc->allocated_to) {
232 node_t *old = rsc->allocated_to;
233
234 crm_info("Deallocating %s from %s", rsc->id, old->details->uname);
235 set_bit(rsc->flags, pe_rsc_provisional);
236 rsc->allocated_to = NULL;
237
238 old->details->allocated_rsc = g_list_remove(old->details->allocated_rsc, rsc);
239 old->details->num_resources--;
240
241 calculate_utilization(old->details->utilization, rsc->utilization, TRUE);
242 free(old);
243 }
244 }
245
246 gboolean
247 native_assign_node(resource_t * rsc, GListPtr nodes, node_t * chosen, gboolean force)
248 {
249 CRM_ASSERT(rsc->variant == pe_native);
250
251 if (force == FALSE && chosen != NULL) {
252 bool unset = FALSE;
253
254 if(chosen->weight < 0) {
255 unset = TRUE;
256
257
258 } else if(can_run_resources(chosen) == FALSE && !is_container_remote_node(chosen)) {
259 unset = TRUE;
260 }
261
262 if(unset) {
263 crm_debug("All nodes for resource %s are unavailable"
264 ", unclean or shutting down (%s: %d, %d)",
265 rsc->id, chosen->details->uname, can_run_resources(chosen), chosen->weight);
266 rsc->next_role = RSC_ROLE_STOPPED;
267 chosen = NULL;
268 }
269 }
270
271
272
273
274
275 native_deallocate(rsc);
276 clear_bit(rsc->flags, pe_rsc_provisional);
277
278 if (chosen == NULL) {
279 GListPtr gIter = NULL;
280 char *rc_inactive = crm_itoa(PCMK_OCF_NOT_RUNNING);
281
282 crm_debug("Could not allocate a node for %s", rsc->id);
283 rsc->next_role = RSC_ROLE_STOPPED;
284
285 for (gIter = rsc->actions; gIter != NULL; gIter = gIter->next) {
286 action_t *op = (action_t *) gIter->data;
287 const char *interval = g_hash_table_lookup(op->meta, XML_LRM_ATTR_INTERVAL);
288
289 crm_debug("Processing %s", op->uuid);
290 if(safe_str_eq(RSC_STOP, op->task)) {
291 update_action_flags(op, pe_action_optional | pe_action_clear, __FUNCTION__, __LINE__);
292
293 } else if(safe_str_eq(RSC_START, op->task)) {
294 update_action_flags(op, pe_action_runnable | pe_action_clear, __FUNCTION__, __LINE__);
295
296
297 } else if(interval && safe_str_neq(interval, "0")) {
298 if(safe_str_eq(rc_inactive, g_hash_table_lookup(op->meta, XML_ATTR_TE_TARGET_RC))) {
299
300
301 } else {
302
303 update_action_flags(op, pe_action_runnable | pe_action_clear, __FUNCTION__, __LINE__);
304 }
305 }
306 }
307
308 free(rc_inactive);
309 return FALSE;
310 }
311
312 crm_debug("Assigning %s to %s", chosen->details->uname, rsc->id);
313 rsc->allocated_to = node_copy(chosen);
314
315 chosen->details->allocated_rsc = g_list_prepend(chosen->details->allocated_rsc, rsc);
316 chosen->details->num_resources++;
317 chosen->count++;
318 calculate_utilization(chosen->details->utilization, rsc->utilization, FALSE);
319 dump_rsc_utilization(show_utilization ? 0 : utilization_log_level, __FUNCTION__, rsc, chosen);
320
321 return TRUE;
322 }
323
324 void
325 log_action(unsigned int log_level, const char *pre_text, action_t * action, gboolean details)
326 {
327 const char *node_uname = NULL;
328 const char *node_uuid = NULL;
329
330 if (action == NULL) {
331 crm_trace("%s%s: <NULL>", pre_text == NULL ? "" : pre_text, pre_text == NULL ? "" : ": ");
332 return;
333 }
334
335 if (is_set(action->flags, pe_action_pseudo)) {
336 node_uname = NULL;
337 node_uuid = NULL;
338
339 } else if (action->node != NULL) {
340 node_uname = action->node->details->uname;
341 node_uuid = action->node->details->id;
342 } else {
343 node_uname = "<none>";
344 node_uuid = NULL;
345 }
346
347 switch (text2task(action->task)) {
348 case stonith_node:
349 case shutdown_crm:
350 crm_trace("%s%s%sAction %d: %s%s%s%s%s%s",
351 pre_text == NULL ? "" : pre_text,
352 pre_text == NULL ? "" : ": ",
353 is_set(action->flags,
354 pe_action_pseudo) ? "Pseudo " : is_set(action->flags,
355 pe_action_optional) ?
356 "Optional " : is_set(action->flags,
357 pe_action_runnable) ? is_set(action->flags,
358 pe_action_processed)
359 ? "" : "(Provisional) " : "!!Non-Startable!! ", action->id,
360 action->uuid, node_uname ? "\ton " : "",
361 node_uname ? node_uname : "", node_uuid ? "\t\t(" : "",
362 node_uuid ? node_uuid : "", node_uuid ? ")" : "");
363 break;
364 default:
365 crm_trace("%s%s%sAction %d: %s %s%s%s%s%s%s",
366 pre_text == NULL ? "" : pre_text,
367 pre_text == NULL ? "" : ": ",
368 is_set(action->flags,
369 pe_action_optional) ? "Optional " : is_set(action->flags,
370 pe_action_pseudo)
371 ? "Pseudo " : is_set(action->flags,
372 pe_action_runnable) ? is_set(action->flags,
373 pe_action_processed)
374 ? "" : "(Provisional) " : "!!Non-Startable!! ", action->id,
375 action->uuid, action->rsc ? action->rsc->id : "<none>",
376 node_uname ? "\ton " : "", node_uname ? node_uname : "",
377 node_uuid ? "\t\t(" : "", node_uuid ? node_uuid : "", node_uuid ? ")" : "");
378
379 break;
380 }
381
382 if (details) {
383 GListPtr gIter = NULL;
384
385 crm_trace("\t\t====== Preceding Actions");
386
387 gIter = action->actions_before;
388 for (; gIter != NULL; gIter = gIter->next) {
389 action_wrapper_t *other = (action_wrapper_t *) gIter->data;
390
391 log_action(log_level + 1, "\t\t", other->action, FALSE);
392 }
393
394 crm_trace("\t\t====== Subsequent Actions");
395
396 gIter = action->actions_after;
397 for (; gIter != NULL; gIter = gIter->next) {
398 action_wrapper_t *other = (action_wrapper_t *) gIter->data;
399
400 log_action(log_level + 1, "\t\t", other->action, FALSE);
401 }
402
403 crm_trace("\t\t====== End");
404
405 } else {
406 crm_trace("\t\t(seen=%d, before=%d, after=%d)",
407 action->seen_count,
408 g_list_length(action->actions_before), g_list_length(action->actions_after));
409 }
410 }
411
412 gboolean
413 can_run_any(GHashTable * nodes)
414 {
415 GHashTableIter iter;
416 node_t *node = NULL;
417
418 if (nodes == NULL) {
419 return FALSE;
420 }
421
422 g_hash_table_iter_init(&iter, nodes);
423 while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
424 if (can_run_resources(node) && node->weight >= 0) {
425 return TRUE;
426 }
427 }
428
429 return FALSE;
430 }
431
432 pe_action_t *
433 create_pseudo_resource_op(resource_t * rsc, const char *task, bool optional, bool runnable, pe_working_set_t *data_set)
434 {
435 pe_action_t *action = custom_action(rsc, generate_op_key(rsc->id, task, 0), task, NULL, optional, TRUE, data_set);
436 update_action_flags(action, pe_action_pseudo, __FUNCTION__, __LINE__);
437 update_action_flags(action, pe_action_runnable, __FUNCTION__, __LINE__);
438 if(runnable) {
439 update_action_flags(action, pe_action_runnable, __FUNCTION__, __LINE__);
440 }
441 return action;
442 }