This source file includes following definitions.
- pe_new_working_set
- pe_free_working_set
- check_for_deprecated_rules
- cluster_status
- pe_free_resources
- pe_free_actions
- pe_free_nodes
- pe__free_ordering
- pe__free_location
- cleanup_calculations
- pe_reset_working_set
- set_working_set_defaults
- pe_find_resource
- pe_find_resource_with_flags
- pe_find_node_any
- pe_find_node_id
- pe_find_node
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <sys/param.h>
13
14 #include <crm/crm.h>
15 #include <crm/common/xml.h>
16 #include <crm/common/cib_internal.h>
17
18 #include <glib.h>
19
20 #include <crm/pengine/internal.h>
21 #include <pe_status_private.h>
22
23
24
25
26
27
28
29
30
31
32
33 pcmk_scheduler_t *
34 pe_new_working_set(void)
35 {
36 pcmk_scheduler_t *scheduler = calloc(1, sizeof(pcmk_scheduler_t));
37
38 if (scheduler == NULL) {
39 return NULL;
40 }
41 scheduler->priv = calloc(1, sizeof(pcmk__scheduler_private_t));
42 if (scheduler->priv == NULL) {
43 free(scheduler);
44 return NULL;
45 }
46 set_working_set_defaults(scheduler);
47 return scheduler;
48 }
49
50
51
52
53
54
55 void
56 pe_free_working_set(pcmk_scheduler_t *scheduler)
57 {
58 if (scheduler != NULL) {
59 pe_reset_working_set(scheduler);
60 free(scheduler->priv->local_node_name);
61 free(scheduler->priv);
62 free(scheduler);
63 }
64 }
65
66 #define XPATH_DEPRECATED_RULES \
67 "//" PCMK_XE_OP_DEFAULTS "//" PCMK_XE_EXPRESSION \
68 "|//" PCMK_XE_OP "//" PCMK_XE_EXPRESSION
69
70
71
72
73
74
75
76 static void
77 check_for_deprecated_rules(pcmk_scheduler_t *scheduler)
78 {
79
80 xmlNode *deprecated = get_xpath_object(XPATH_DEPRECATED_RULES,
81 scheduler->input, LOG_NEVER);
82
83 if (deprecated != NULL) {
84 pcmk__warn_once(pcmk__wo_op_attr_expr,
85 "Support for rules with node attribute expressions in "
86 PCMK_XE_OP " or " PCMK_XE_OP_DEFAULTS " is deprecated "
87 "and will be dropped in a future release");
88 }
89 }
90
91
92
93
94
95
96
97
98
99
100
101
102 gboolean
103 cluster_status(pcmk_scheduler_t * scheduler)
104 {
105 const char *new_version = NULL;
106 xmlNode *section = NULL;
107
108 if ((scheduler == NULL) || (scheduler->input == NULL)) {
109 return FALSE;
110 }
111
112 new_version = crm_element_value(scheduler->input, PCMK_XA_CRM_FEATURE_SET);
113
114 if (pcmk__check_feature_set(new_version) != pcmk_rc_ok) {
115 pcmk__config_err("Can't process CIB with feature set '%s' greater than our own '%s'",
116 new_version, CRM_FEATURE_SET);
117 return FALSE;
118 }
119
120 crm_trace("Beginning unpack");
121
122 if (scheduler->priv->failed != NULL) {
123 pcmk__xml_free(scheduler->priv->failed);
124 }
125 scheduler->priv->failed = pcmk__xe_create(NULL, "failed-ops");
126
127 if (scheduler->priv->now == NULL) {
128 scheduler->priv->now = crm_time_new(NULL);
129 }
130
131 if (pcmk__xe_attr_is_true(scheduler->input, PCMK_XA_HAVE_QUORUM)) {
132 pcmk__set_scheduler_flags(scheduler, pcmk__sched_quorate);
133 } else {
134 pcmk__clear_scheduler_flags(scheduler, pcmk__sched_quorate);
135 }
136
137 scheduler->priv->op_defaults = get_xpath_object("//" PCMK_XE_OP_DEFAULTS,
138 scheduler->input,
139 LOG_NEVER);
140 check_for_deprecated_rules(scheduler);
141
142 scheduler->priv->rsc_defaults = get_xpath_object("//" PCMK_XE_RSC_DEFAULTS,
143 scheduler->input,
144 LOG_NEVER);
145
146 section = get_xpath_object("//" PCMK_XE_CRM_CONFIG, scheduler->input,
147 LOG_TRACE);
148 unpack_config(section, scheduler);
149
150 if (!pcmk_any_flags_set(scheduler->flags,
151 pcmk__sched_location_only|pcmk__sched_quorate)
152 && (scheduler->no_quorum_policy != pcmk_no_quorum_ignore)) {
153 pcmk__sched_warn(scheduler,
154 "Fencing and resource management disabled "
155 "due to lack of quorum");
156 }
157
158 section = get_xpath_object("//" PCMK_XE_NODES, scheduler->input, LOG_TRACE);
159 unpack_nodes(section, scheduler);
160
161 section = get_xpath_object("//" PCMK_XE_RESOURCES, scheduler->input,
162 LOG_TRACE);
163 if (!pcmk_is_set(scheduler->flags, pcmk__sched_location_only)) {
164 unpack_remote_nodes(section, scheduler);
165 }
166 unpack_resources(section, scheduler);
167
168 section = get_xpath_object("//" PCMK_XE_FENCING_TOPOLOGY, scheduler->input,
169 LOG_TRACE);
170 pcmk__validate_fencing_topology(section);
171
172 section = get_xpath_object("//" PCMK_XE_TAGS, scheduler->input, LOG_NEVER);
173 unpack_tags(section, scheduler);
174
175 if (!pcmk_is_set(scheduler->flags, pcmk__sched_location_only)) {
176 section = get_xpath_object("//" PCMK_XE_STATUS, scheduler->input,
177 LOG_TRACE);
178 unpack_status(section, scheduler);
179 }
180
181 if (!pcmk_is_set(scheduler->flags, pcmk__sched_no_counts)) {
182 for (GList *item = scheduler->priv->resources;
183 item != NULL; item = item->next) {
184
185 pcmk_resource_t *rsc = item->data;
186
187 rsc->priv->fns->count(item->data);
188 }
189 crm_trace("Cluster resource count: %d (%d disabled, %d blocked)",
190 scheduler->priv->ninstances,
191 scheduler->priv->disabled_resources,
192 scheduler->priv->blocked_resources);
193 }
194
195 if ((scheduler->priv->local_node_name != NULL)
196 && (pcmk_find_node(scheduler,
197 scheduler->priv->local_node_name) == NULL)) {
198 crm_info("Creating a fake local node for %s",
199 scheduler->priv->local_node_name);
200 pe_create_node(scheduler->priv->local_node_name,
201 scheduler->priv->local_node_name, NULL, 0, scheduler);
202 }
203
204 pcmk__set_scheduler_flags(scheduler, pcmk__sched_have_status);
205 return TRUE;
206 }
207
208
209
210
211
212
213
214
215
216
217
218
219 static void
220 pe_free_resources(GList *resources)
221 {
222 pcmk_resource_t *rsc = NULL;
223 GList *iterator = resources;
224
225 while (iterator != NULL) {
226 rsc = (pcmk_resource_t *) iterator->data;
227 iterator = iterator->next;
228 rsc->priv->fns->free(rsc);
229 }
230 if (resources != NULL) {
231 g_list_free(resources);
232 }
233 }
234
235 static void
236 pe_free_actions(GList *actions)
237 {
238 GList *iterator = actions;
239
240 while (iterator != NULL) {
241 pe_free_action(iterator->data);
242 iterator = iterator->next;
243 }
244 if (actions != NULL) {
245 g_list_free(actions);
246 }
247 }
248
249 static void
250 pe_free_nodes(GList *nodes)
251 {
252 for (GList *iterator = nodes; iterator != NULL; iterator = iterator->next) {
253 pcmk_node_t *node = (pcmk_node_t *) iterator->data;
254
255
256 if (node == NULL) {
257 continue;
258 }
259 if (node->details == NULL) {
260 free(node);
261 continue;
262 }
263
264
265
266
267 crm_trace("Freeing node %s", (pcmk__is_pacemaker_remote_node(node)?
268 "(guest or remote)" : pcmk__node_name(node)));
269
270 if (node->priv->attrs != NULL) {
271 g_hash_table_destroy(node->priv->attrs);
272 }
273 if (node->priv->utilization != NULL) {
274 g_hash_table_destroy(node->priv->utilization);
275 }
276 if (node->priv->digest_cache != NULL) {
277 g_hash_table_destroy(node->priv->digest_cache);
278 }
279 g_list_free(node->details->running_rsc);
280 g_list_free(node->priv->assigned_resources);
281 free(node->priv);
282 free(node->details);
283 free(node->assign);
284 free(node);
285 }
286 if (nodes != NULL) {
287 g_list_free(nodes);
288 }
289 }
290
291 static void
292 pe__free_ordering(GList *constraints)
293 {
294 GList *iterator = constraints;
295
296 while (iterator != NULL) {
297 pcmk__action_relation_t *order = iterator->data;
298
299 iterator = iterator->next;
300
301 free(order->task1);
302 free(order->task2);
303 free(order);
304 }
305 if (constraints != NULL) {
306 g_list_free(constraints);
307 }
308 }
309
310 static void
311 pe__free_location(GList *constraints)
312 {
313 GList *iterator = constraints;
314
315 while (iterator != NULL) {
316 pcmk__location_t *cons = iterator->data;
317
318 iterator = iterator->next;
319
320 g_list_free_full(cons->nodes, pcmk__free_node_copy);
321 free(cons->id);
322 free(cons);
323 }
324 if (constraints != NULL) {
325 g_list_free(constraints);
326 }
327 }
328
329
330
331
332
333
334
335
336
337 void
338 cleanup_calculations(pcmk_scheduler_t *scheduler)
339 {
340 if (scheduler == NULL) {
341 return;
342 }
343
344 pcmk__clear_scheduler_flags(scheduler, pcmk__sched_have_status);
345 if (scheduler->priv->options != NULL) {
346 g_hash_table_destroy(scheduler->priv->options);
347 }
348
349 if (scheduler->priv->singletons != NULL) {
350 g_hash_table_destroy(scheduler->priv->singletons);
351 }
352
353 if (scheduler->priv->ticket_constraints != NULL) {
354 g_hash_table_destroy(scheduler->priv->ticket_constraints);
355 }
356
357 if (scheduler->priv->templates != NULL) {
358 g_hash_table_destroy(scheduler->priv->templates);
359 }
360
361 if (scheduler->priv->tags != NULL) {
362 g_hash_table_destroy(scheduler->priv->tags);
363 }
364
365 crm_trace("deleting resources");
366 pe_free_resources(scheduler->priv->resources);
367
368 crm_trace("deleting actions");
369 pe_free_actions(scheduler->priv->actions);
370
371 crm_trace("deleting nodes");
372 pe_free_nodes(scheduler->nodes);
373
374 pe__free_param_checks(scheduler);
375 g_list_free(scheduler->priv->stop_needed);
376 crm_time_free(scheduler->priv->now);
377 pcmk__xml_free(scheduler->input);
378 pcmk__xml_free(scheduler->priv->failed);
379 pcmk__xml_free(scheduler->priv->graph);
380
381 set_working_set_defaults(scheduler);
382
383 CRM_LOG_ASSERT((scheduler->priv->location_constraints == NULL)
384 && (scheduler->priv->ordering_constraints == NULL));
385 }
386
387
388
389
390
391
392 void
393 pe_reset_working_set(pcmk_scheduler_t *scheduler)
394 {
395 if (scheduler == NULL) {
396 return;
397 }
398
399 crm_trace("Deleting %d ordering constraints",
400 g_list_length(scheduler->priv->ordering_constraints));
401 pe__free_ordering(scheduler->priv->ordering_constraints);
402 scheduler->priv->ordering_constraints = NULL;
403
404 crm_trace("Deleting %d location constraints",
405 g_list_length(scheduler->priv->location_constraints));
406 pe__free_location(scheduler->priv->location_constraints);
407 scheduler->priv->location_constraints = NULL;
408
409 crm_trace("Deleting %d colocation constraints",
410 g_list_length(scheduler->priv->colocation_constraints));
411 g_list_free_full(scheduler->priv->colocation_constraints, free);
412 scheduler->priv->colocation_constraints = NULL;
413
414 cleanup_calculations(scheduler);
415 }
416
417 void
418 set_working_set_defaults(pcmk_scheduler_t *scheduler)
419 {
420
421 pcmk__scheduler_private_t *priv = scheduler->priv;
422 pcmk__output_t *out = priv->out;
423 char *local_node_name = scheduler->priv->local_node_name;
424
425
426 memset(scheduler, 0, sizeof(pcmk_scheduler_t));
427 memset(priv, 0, sizeof(pcmk__scheduler_private_t));
428
429
430 scheduler->priv = priv;
431 scheduler->priv->out = out;
432 scheduler->priv->local_node_name = local_node_name;
433
434
435 scheduler->priv->next_ordering_id = 1;
436 scheduler->priv->next_action_id = 1;
437 scheduler->no_quorum_policy = pcmk_no_quorum_stop;
438 #if PCMK__CONCURRENT_FENCING_DEFAULT_TRUE
439 pcmk__set_scheduler_flags(scheduler,
440 pcmk__sched_symmetric_cluster
441 |pcmk__sched_concurrent_fencing
442 |pcmk__sched_stop_removed_resources
443 |pcmk__sched_cancel_removed_actions);
444 #else
445 pcmk__set_scheduler_flags(scheduler,
446 pcmk__sched_symmetric_cluster
447 |pcmk__sched_stop_removed_resources
448 |pcmk__sched_cancel_removed_actions);
449 #endif
450 }
451
452 pcmk_resource_t *
453 pe_find_resource(GList *rsc_list, const char *id)
454 {
455 return pe_find_resource_with_flags(rsc_list, id, pcmk_rsc_match_history);
456 }
457
458 pcmk_resource_t *
459 pe_find_resource_with_flags(GList *rsc_list, const char *id, enum pe_find flags)
460 {
461 GList *rIter = NULL;
462
463 for (rIter = rsc_list; id && rIter; rIter = rIter->next) {
464 pcmk_resource_t *parent = rIter->data;
465 pcmk_resource_t *match = parent->priv->fns->find_rsc(parent, id, NULL,
466 flags);
467
468 if (match != NULL) {
469 return match;
470 }
471 }
472 crm_trace("No match for %s", id);
473 return NULL;
474 }
475
476
477
478
479
480
481
482
483
484
485
486
487 pcmk_node_t *
488 pe_find_node_any(const GList *nodes, const char *id, const char *uname)
489 {
490 pcmk_node_t *match = NULL;
491
492 if (id != NULL) {
493 match = pe_find_node_id(nodes, id);
494 }
495 if ((match == NULL) && (uname != NULL)) {
496 match = pcmk__find_node_in_list(nodes, uname);
497 }
498 return match;
499 }
500
501
502
503
504
505
506
507
508
509 pcmk_node_t *
510 pe_find_node_id(const GList *nodes, const char *id)
511 {
512 for (const GList *iter = nodes; iter != NULL; iter = iter->next) {
513 pcmk_node_t *node = (pcmk_node_t *) iter->data;
514
515
516
517
518
519 if (pcmk__str_eq(node->priv->id, id, pcmk__str_casei)) {
520 return node;
521 }
522 }
523 return NULL;
524 }
525
526
527
528
529 #include <crm/pengine/status_compat.h>
530
531
532
533
534
535
536
537
538
539 pcmk_node_t *
540 pe_find_node(const GList *nodes, const char *node_name)
541 {
542 return pcmk__find_node_in_list(nodes, node_name);
543 }
544
545
546