This source file includes following definitions.
- check_health
- check_stonith_action
- check_placement_strategy
- pe_metadata
- verify_pe_options
- pe_pref
- fail2text
- text2task
- task2text
- role2text
- text2role
- merge_weights
- add_hash_param
- pe_node_attribute_calculated
- pe_node_attribute_raw
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 #include <crm_internal.h>
19 #include <crm/crm.h>
20 #include <crm/msg_xml.h>
21 #include <crm/common/xml.h>
22 #include <crm/common/util.h>
23
24 #include <glib.h>
25
26 #include <crm/pengine/internal.h>
27
28 gboolean was_processing_error = FALSE;
29 gboolean was_processing_warning = FALSE;
30
31 static gboolean
32 check_health(const char *value)
33 {
34 if (safe_str_eq(value, "none")) {
35 return TRUE;
36
37 } else if (safe_str_eq(value, "custom")) {
38 return TRUE;
39
40 } else if (safe_str_eq(value, "only-green")) {
41 return TRUE;
42
43 } else if (safe_str_eq(value, "progressive")) {
44 return TRUE;
45
46 } else if (safe_str_eq(value, "migrate-on-red")) {
47 return TRUE;
48 }
49 return FALSE;
50 }
51
52 static gboolean
53 check_stonith_action(const char *value)
54 {
55 if (safe_str_eq(value, "reboot")) {
56 return TRUE;
57
58 } else if (safe_str_eq(value, "poweroff")) {
59 return TRUE;
60
61 } else if (safe_str_eq(value, "off")) {
62 return TRUE;
63 }
64 return FALSE;
65 }
66
67 static gboolean
68 check_placement_strategy(const char *value)
69 {
70 if (safe_str_eq(value, "default")) {
71 return TRUE;
72
73 } else if (safe_str_eq(value, "utilization")) {
74 return TRUE;
75
76 } else if (safe_str_eq(value, "minimal")) {
77 return TRUE;
78
79 } else if (safe_str_eq(value, "balanced")) {
80 return TRUE;
81 }
82 return FALSE;
83 }
84
85
86 pe_cluster_option pe_opts[] = {
87
88 { "no-quorum-policy", "no_quorum_policy", "enum", "stop, freeze, ignore, suicide", "stop", &check_quorum,
89 "What to do when the cluster does not have quorum", NULL },
90 { "symmetric-cluster", "symmetric_cluster", "boolean", NULL, "true", &check_boolean,
91 "All resources can run anywhere by default", NULL },
92 { "default-resource-stickiness", "default_resource_stickiness", "integer",
93 NULL, NULL, &check_number,
94 "Deprecated (use resource-stickiness in rsc_defaults instead)", NULL },
95 { "is-managed-default", "is_managed_default", "boolean", NULL, NULL,
96 &check_boolean, "Deprecated (use is-managed in rsc_defaults instead)",
97 NULL },
98 { "maintenance-mode", NULL, "boolean", NULL, "false", &check_boolean,
99 "Should the cluster monitor resources and start/stop them as required", NULL },
100 { "start-failure-is-fatal", NULL, "boolean", NULL, "true", &check_boolean, "Always treat start failures as fatal",
101 "When set to TRUE, the cluster will immediately ban a resource from a node if it fails to start there. When FALSE, the cluster will instead check the resource's fail count against its migration-threshold." },
102 { "enable-startup-probes", NULL, "boolean", NULL, "true", &check_boolean,
103 "Should the cluster check for active resources during startup", NULL },
104
105
106 { "stonith-enabled", "stonith_enabled", "boolean", NULL, "true", &check_boolean,
107 "Failed nodes are STONITH'd", NULL },
108 { "stonith-action", "stonith_action", "enum", "reboot, poweroff, off", "reboot", &check_stonith_action,
109 "Action to send to STONITH device", NULL },
110 { "stonith-timeout", NULL, "time", NULL, "60s", &check_timer,
111 "How long to wait for the STONITH action (reboot,on,off) to complete", NULL },
112 { XML_ATTR_HAVE_WATCHDOG, NULL, "boolean", NULL, "false", &check_boolean,
113 "Enable watchdog integration", "Set automatically by the cluster if SBD is detected. User configured values are ignored." },
114 { "concurrent-fencing", NULL, "boolean", NULL, "false", &check_boolean,
115 "Allow performing fencing operations in parallel", NULL },
116 { "startup-fencing", "startup_fencing", "boolean", NULL, "true", &check_boolean,
117 "STONITH unseen nodes", "Advanced Use Only! Not using the default is very unsafe!" },
118
119
120 { "cluster-delay", "transition_idle_timeout", "time", NULL, "60s", &check_time,
121 "Round trip delay over the network (excluding action execution)",
122 "The \"correct\" value will depend on the speed and load of your network and cluster nodes." },
123 { "batch-limit", NULL, "integer", NULL, "0", &check_number,
124 "The number of jobs that the TE is allowed to execute in parallel",
125 "The \"correct\" value will depend on the speed and load of your network and cluster nodes." },
126 { "migration-limit", NULL, "integer", NULL, "-1", &check_number,
127 "The number of migration jobs that the TE is allowed to execute in parallel on a node"},
128 { "default-action-timeout", "default_action_timeout", "time", NULL, NULL,
129 &check_time, "Deprecated (use 'timeout' in op_defaults instead)", NULL },
130
131
132 { "stop-all-resources", NULL, "boolean", NULL, "false", &check_boolean,
133 "Should the cluster stop all active resources (except those needed for fencing)", NULL },
134 { "stop-orphan-resources", "stop_orphan_resources", "boolean", NULL, "true", &check_boolean,
135 "Should deleted resources be stopped", NULL },
136 { "stop-orphan-actions", "stop_orphan_actions", "boolean", NULL, "true", &check_boolean,
137 "Should deleted actions be cancelled", NULL },
138 { "remove-after-stop", "remove_after_stop", "boolean", NULL, "false", &check_boolean,
139 "Remove resources from the LRM after they are stopped",
140 "Always set this to false. Other values are, at best, poorly tested and potentially dangerous." },
141
142
143
144 { "pe-error-series-max", NULL, "integer", NULL, "-1", &check_number,
145 "The number of PE inputs resulting in ERRORs to save", "Zero to disable, -1 to store unlimited." },
146 { "pe-warn-series-max", NULL, "integer", NULL, "5000", &check_number,
147 "The number of PE inputs resulting in WARNINGs to save", "Zero to disable, -1 to store unlimited." },
148 { "pe-input-series-max", NULL, "integer", NULL, "4000", &check_number,
149 "The number of other PE inputs to save", "Zero to disable, -1 to store unlimited." },
150
151
152 { "node-health-strategy", NULL, "enum", "none, migrate-on-red, only-green, progressive, custom", "none", &check_health,
153 "The strategy combining node attributes to determine overall node health.",
154 "Requires external entities to create node attributes (named with the prefix '#health') with values: 'red', 'yellow' or 'green'."},
155 { "node-health-base", NULL, "integer", NULL, "0", &check_number,
156 "The base score assigned to a node",
157 "Only used when node-health-strategy is set to progressive." },
158 { "node-health-green", NULL, "integer", NULL, "0", &check_number,
159 "The score 'green' translates to in rsc_location constraints",
160 "Only used when node-health-strategy is set to custom or progressive." },
161 { "node-health-yellow", NULL, "integer", NULL, "0", &check_number,
162 "The score 'yellow' translates to in rsc_location constraints",
163 "Only used when node-health-strategy is set to custom or progressive." },
164 { "node-health-red", NULL, "integer", NULL, "-INFINITY", &check_number,
165 "The score 'red' translates to in rsc_location constraints",
166 "Only used when node-health-strategy is set to custom or progressive." },
167
168
169 { "placement-strategy", NULL, "enum", "default, utilization, minimal, balanced", "default", &check_placement_strategy,
170 "The strategy to determine resource placement", NULL},
171 };
172
173
174 void
175 pe_metadata(void)
176 {
177 config_metadata("Policy Engine", "1.0",
178 "Policy Engine Options",
179 "This is a fake resource that details the options that can be configured for the Policy Engine.",
180 pe_opts, DIMOF(pe_opts));
181 }
182
183 void
184 verify_pe_options(GHashTable * options)
185 {
186 verify_all_options(options, pe_opts, DIMOF(pe_opts));
187 }
188
189 const char *
190 pe_pref(GHashTable * options, const char *name)
191 {
192 return get_cluster_pref(options, pe_opts, DIMOF(pe_opts), name);
193 }
194
195 const char *
196 fail2text(enum action_fail_response fail)
197 {
198 const char *result = "<unknown>";
199
200 switch (fail) {
201 case action_fail_ignore:
202 result = "ignore";
203 break;
204 case action_fail_block:
205 result = "block";
206 break;
207 case action_fail_recover:
208 result = "recover";
209 break;
210 case action_fail_migrate:
211 result = "migrate";
212 break;
213 case action_fail_stop:
214 result = "stop";
215 break;
216 case action_fail_fence:
217 result = "fence";
218 break;
219 case action_fail_standby:
220 result = "standby";
221 break;
222 case action_fail_restart_container:
223 result = "restart-container";
224 break;
225 case action_fail_reset_remote:
226 result = "reset-remote";
227 break;
228 }
229 return result;
230 }
231
232 enum action_tasks
233 text2task(const char *task)
234 {
235 if (safe_str_eq(task, CRMD_ACTION_STOP)) {
236 return stop_rsc;
237 } else if (safe_str_eq(task, CRMD_ACTION_STOPPED)) {
238 return stopped_rsc;
239 } else if (safe_str_eq(task, CRMD_ACTION_START)) {
240 return start_rsc;
241 } else if (safe_str_eq(task, CRMD_ACTION_STARTED)) {
242 return started_rsc;
243 } else if (safe_str_eq(task, CRM_OP_SHUTDOWN)) {
244 return shutdown_crm;
245 } else if (safe_str_eq(task, CRM_OP_FENCE)) {
246 return stonith_node;
247 } else if (safe_str_eq(task, CRMD_ACTION_STATUS)) {
248 return monitor_rsc;
249 } else if (safe_str_eq(task, CRMD_ACTION_NOTIFY)) {
250 return action_notify;
251 } else if (safe_str_eq(task, CRMD_ACTION_NOTIFIED)) {
252 return action_notified;
253 } else if (safe_str_eq(task, CRMD_ACTION_PROMOTE)) {
254 return action_promote;
255 } else if (safe_str_eq(task, CRMD_ACTION_DEMOTE)) {
256 return action_demote;
257 } else if (safe_str_eq(task, CRMD_ACTION_PROMOTED)) {
258 return action_promoted;
259 } else if (safe_str_eq(task, CRMD_ACTION_DEMOTED)) {
260 return action_demoted;
261 }
262 #if SUPPORT_TRACING
263 if (safe_str_eq(task, CRMD_ACTION_CANCEL)) {
264 return no_action;
265 } else if (safe_str_eq(task, CRMD_ACTION_DELETE)) {
266 return no_action;
267 } else if (safe_str_eq(task, CRMD_ACTION_STATUS)) {
268 return no_action;
269 } else if (safe_str_eq(task, CRM_OP_PROBED)) {
270 return no_action;
271 } else if (safe_str_eq(task, CRM_OP_LRM_REFRESH)) {
272 return no_action;
273 } else if (safe_str_eq(task, CRMD_ACTION_MIGRATE)) {
274 return no_action;
275 } else if (safe_str_eq(task, CRMD_ACTION_MIGRATED)) {
276 return no_action;
277 } else if (safe_str_eq(task, "fail")) {
278 return no_action;
279 } else if (safe_str_eq(task, "stonith_up")) {
280 return no_action;
281 } else if (safe_str_eq(task, "stonith_complete")) {
282 return no_action;
283 } else if (safe_str_eq(task, "all_stopped")) {
284 return no_action;
285 }
286 crm_trace("Unsupported action: %s", task);
287 #endif
288
289 return no_action;
290 }
291
292 const char *
293 task2text(enum action_tasks task)
294 {
295 const char *result = "<unknown>";
296
297 switch (task) {
298 case no_action:
299 result = "no_action";
300 break;
301 case stop_rsc:
302 result = CRMD_ACTION_STOP;
303 break;
304 case stopped_rsc:
305 result = CRMD_ACTION_STOPPED;
306 break;
307 case start_rsc:
308 result = CRMD_ACTION_START;
309 break;
310 case started_rsc:
311 result = CRMD_ACTION_STARTED;
312 break;
313 case shutdown_crm:
314 result = CRM_OP_SHUTDOWN;
315 break;
316 case stonith_node:
317 result = CRM_OP_FENCE;
318 break;
319 case monitor_rsc:
320 result = CRMD_ACTION_STATUS;
321 break;
322 case action_notify:
323 result = CRMD_ACTION_NOTIFY;
324 break;
325 case action_notified:
326 result = CRMD_ACTION_NOTIFIED;
327 break;
328 case action_promote:
329 result = CRMD_ACTION_PROMOTE;
330 break;
331 case action_promoted:
332 result = CRMD_ACTION_PROMOTED;
333 break;
334 case action_demote:
335 result = CRMD_ACTION_DEMOTE;
336 break;
337 case action_demoted:
338 result = CRMD_ACTION_DEMOTED;
339 break;
340 }
341
342 return result;
343 }
344
345 const char *
346 role2text(enum rsc_role_e role)
347 {
348 switch (role) {
349 case RSC_ROLE_UNKNOWN:
350 return RSC_ROLE_UNKNOWN_S;
351 case RSC_ROLE_STOPPED:
352 return RSC_ROLE_STOPPED_S;
353 case RSC_ROLE_STARTED:
354 return RSC_ROLE_STARTED_S;
355 case RSC_ROLE_SLAVE:
356 return RSC_ROLE_SLAVE_S;
357 case RSC_ROLE_MASTER:
358 return RSC_ROLE_MASTER_S;
359 }
360 CRM_CHECK(role >= RSC_ROLE_UNKNOWN, return RSC_ROLE_UNKNOWN_S);
361 CRM_CHECK(role < RSC_ROLE_MAX, return RSC_ROLE_UNKNOWN_S);
362
363 return RSC_ROLE_UNKNOWN_S;
364 }
365
366 enum rsc_role_e
367 text2role(const char *role)
368 {
369 CRM_ASSERT(role != NULL);
370 if (safe_str_eq(role, RSC_ROLE_STOPPED_S)) {
371 return RSC_ROLE_STOPPED;
372 } else if (safe_str_eq(role, RSC_ROLE_STARTED_S)) {
373 return RSC_ROLE_STARTED;
374 } else if (safe_str_eq(role, RSC_ROLE_SLAVE_S)) {
375 return RSC_ROLE_SLAVE;
376 } else if (safe_str_eq(role, RSC_ROLE_MASTER_S)) {
377 return RSC_ROLE_MASTER;
378 } else if (safe_str_eq(role, RSC_ROLE_UNKNOWN_S)) {
379 return RSC_ROLE_UNKNOWN;
380 }
381 crm_err("Unknown role: %s", role);
382 return RSC_ROLE_UNKNOWN;
383 }
384
385 int
386 merge_weights(int w1, int w2)
387 {
388 int result = w1 + w2;
389
390 if (w1 <= -INFINITY || w2 <= -INFINITY) {
391 if (w1 >= INFINITY || w2 >= INFINITY) {
392 crm_trace("-INFINITY + INFINITY == -INFINITY");
393 }
394 return -INFINITY;
395
396 } else if (w1 >= INFINITY || w2 >= INFINITY) {
397 return INFINITY;
398 }
399
400
401 if (result > 0) {
402 if (w1 <= 0 && w2 < 0) {
403 result = -INFINITY;
404 }
405
406 } else if (w1 > 0 && w2 > 0) {
407 result = INFINITY;
408 }
409
410
411 if (result >= INFINITY) {
412 result = INFINITY;
413
414 } else if (result <= -INFINITY) {
415 result = -INFINITY;
416 }
417
418 crm_trace("%d + %d = %d", w1, w2, result);
419 return result;
420 }
421
422 void
423 add_hash_param(GHashTable * hash, const char *name, const char *value)
424 {
425 CRM_CHECK(hash != NULL, return);
426
427 crm_trace("adding: name=%s value=%s", crm_str(name), crm_str(value));
428 if (name == NULL || value == NULL) {
429 return;
430
431 } else if (safe_str_eq(value, "#default")) {
432 return;
433
434 } else if (g_hash_table_lookup(hash, name) == NULL) {
435 g_hash_table_insert(hash, strdup(name), strdup(value));
436 }
437 }
438
439 const char *
440 pe_node_attribute_calculated(pe_node_t *node, const char *name, resource_t *rsc)
441 {
442 const char *source;
443
444 if(node == NULL) {
445 return NULL;
446
447 } else if(rsc == NULL) {
448 return g_hash_table_lookup(node->details->attrs, name);
449 }
450
451 source = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET);
452 if(source == NULL || safe_str_eq("host", source) == FALSE) {
453 return g_hash_table_lookup(node->details->attrs, name);
454 }
455
456
457
458
459
460
461
462
463 CRM_ASSERT(node->details->remote_rsc);
464 CRM_ASSERT(node->details->remote_rsc->container);
465
466 if(node->details->remote_rsc->container->running_on) {
467 pe_node_t *host = node->details->remote_rsc->container->running_on->data;
468 pe_rsc_trace(rsc, "%s: Looking for %s on the container host %s", rsc->id, name, host->details->uname);
469 return g_hash_table_lookup(host->details->attrs, name);
470 }
471
472 pe_rsc_trace(rsc, "%s: Not looking for %s on the container host: %s is inactive",
473 rsc->id, name, node->details->remote_rsc->container->id);
474 return NULL;
475 }
476
477 const char *
478 pe_node_attribute_raw(pe_node_t *node, const char *name)
479 {
480 if(node == NULL) {
481 return NULL;
482 }
483 return g_hash_table_lookup(node->details->attrs, name);
484 }