/src/pacemaker/lib/common/options.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright 2004-2025 the Pacemaker project contributors |
3 | | * |
4 | | * The version control history for this file may have further details. |
5 | | * |
6 | | * This source code is licensed under the GNU Lesser General Public License |
7 | | * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. |
8 | | */ |
9 | | |
10 | | #include <crm_internal.h> |
11 | | |
12 | | #include <stdbool.h> |
13 | | #include <stdio.h> |
14 | | #include <string.h> |
15 | | #include <stdlib.h> |
16 | | #include <sys/types.h> |
17 | | #include <sys/stat.h> |
18 | | |
19 | | #include <crm/crm.h> |
20 | | #include <crm/common/xml.h> |
21 | | |
22 | | |
23 | | /* |
24 | | * Option metadata |
25 | | */ |
26 | | |
27 | | static const pcmk__cluster_option_t cluster_options[] = { |
28 | | /* name, old name, type, allowed values, |
29 | | * default value, validator, |
30 | | * flags, |
31 | | * short description, |
32 | | * long description |
33 | | */ |
34 | | { |
35 | | PCMK_OPT_DC_VERSION, NULL, PCMK_VALUE_VERSION, NULL, |
36 | | NULL, NULL, |
37 | | pcmk__opt_controld|pcmk__opt_generated, |
38 | | N_("Pacemaker version on cluster node elected Designated Controller " |
39 | | "(DC)"), |
40 | | N_("Includes a hash which identifies the exact revision the code was " |
41 | | "built from. Used for diagnostic purposes."), |
42 | | }, |
43 | | { |
44 | | PCMK_OPT_CLUSTER_INFRASTRUCTURE, NULL, PCMK_VALUE_STRING, NULL, |
45 | | NULL, NULL, |
46 | | pcmk__opt_controld|pcmk__opt_generated, |
47 | | N_("The messaging layer on which Pacemaker is currently running"), |
48 | | N_("Used for informational and diagnostic purposes."), |
49 | | }, |
50 | | { |
51 | | PCMK_OPT_CLUSTER_NAME, NULL, PCMK_VALUE_STRING, NULL, |
52 | | NULL, NULL, |
53 | | pcmk__opt_controld, |
54 | | N_("An arbitrary name for the cluster"), |
55 | | N_("This optional value is mostly for users' convenience as desired " |
56 | | "in administration, but may also be used in Pacemaker " |
57 | | "configuration rules via the #cluster-name node attribute, and " |
58 | | "by higher-level tools and resource agents."), |
59 | | }, |
60 | | { |
61 | | PCMK_OPT_DC_DEADTIME, NULL, PCMK_VALUE_DURATION, NULL, |
62 | | "20s", pcmk__valid_interval_spec, |
63 | | pcmk__opt_controld, |
64 | | N_("How long to wait for a response from other nodes during start-up"), |
65 | | N_("The optimal value will depend on the speed and load of your " |
66 | | "network and the type of switches used."), |
67 | | }, |
68 | | { |
69 | | PCMK_OPT_CLUSTER_RECHECK_INTERVAL, NULL, PCMK_VALUE_DURATION, NULL, |
70 | | "15min", pcmk__valid_interval_spec, |
71 | | pcmk__opt_controld, |
72 | | N_("Polling interval to recheck cluster state and evaluate rules " |
73 | | "with date specifications"), |
74 | | N_("Pacemaker is primarily event-driven, and looks ahead to know when " |
75 | | "to recheck cluster state for failure-timeout settings and most " |
76 | | "time-based rules. However, it will also recheck the cluster after " |
77 | | "this amount of inactivity, to evaluate rules with date " |
78 | | "specifications and serve as a fail-safe for certain types of " |
79 | | "scheduler bugs. A value of 0 disables polling. A positive value " |
80 | | "sets an interval in seconds, unless other units are specified " |
81 | | "(for example, \"5min\")."), |
82 | | }, |
83 | | { |
84 | | PCMK_OPT_ELECTION_TIMEOUT, NULL, PCMK_VALUE_DURATION, NULL, |
85 | | "2min", pcmk__valid_interval_spec, |
86 | | pcmk__opt_controld|pcmk__opt_advanced, |
87 | | N_("Declare an election failed if it is not decided within this much " |
88 | | "time. If you need to adjust this value, it probably indicates " |
89 | | "the presence of a bug."), |
90 | | NULL, |
91 | | }, |
92 | | { |
93 | | PCMK_OPT_SHUTDOWN_ESCALATION, NULL, PCMK_VALUE_DURATION, NULL, |
94 | | "20min", pcmk__valid_interval_spec, |
95 | | pcmk__opt_controld|pcmk__opt_advanced, |
96 | | N_("Exit immediately if shutdown does not complete within this much " |
97 | | "time. If you need to adjust this value, it probably indicates " |
98 | | "the presence of a bug."), |
99 | | NULL, |
100 | | }, |
101 | | { |
102 | | PCMK_OPT_JOIN_INTEGRATION_TIMEOUT, NULL, PCMK_VALUE_DURATION, NULL, |
103 | | "3min", pcmk__valid_interval_spec, |
104 | | pcmk__opt_controld|pcmk__opt_advanced, |
105 | | N_("If you need to adjust this value, it probably indicates " |
106 | | "the presence of a bug."), |
107 | | NULL, |
108 | | }, |
109 | | { |
110 | | PCMK_OPT_JOIN_FINALIZATION_TIMEOUT, NULL, PCMK_VALUE_DURATION, NULL, |
111 | | "30min", pcmk__valid_interval_spec, |
112 | | pcmk__opt_controld|pcmk__opt_advanced, |
113 | | N_("If you need to adjust this value, it probably indicates " |
114 | | "the presence of a bug."), |
115 | | NULL, |
116 | | }, |
117 | | { |
118 | | PCMK_OPT_TRANSITION_DELAY, NULL, PCMK_VALUE_DURATION, NULL, |
119 | | "0s", pcmk__valid_interval_spec, |
120 | | pcmk__opt_controld|pcmk__opt_advanced, |
121 | | N_("Enabling this option will slow down cluster recovery under all " |
122 | | "conditions"), |
123 | | N_("Delay cluster recovery for this much time to allow for additional " |
124 | | "events to occur. Useful if your configuration is sensitive to " |
125 | | "the order in which ping updates arrive."), |
126 | | }, |
127 | | { |
128 | | PCMK_OPT_NO_QUORUM_POLICY, NULL, PCMK_VALUE_SELECT, |
129 | | PCMK_VALUE_STOP ", " PCMK_VALUE_FREEZE ", " PCMK_VALUE_IGNORE |
130 | | ", " PCMK_VALUE_DEMOTE ", " PCMK_VALUE_FENCE ", " |
131 | | PCMK_VALUE_FENCE_LEGACY, |
132 | | PCMK_VALUE_STOP, pcmk__valid_no_quorum_policy, |
133 | | pcmk__opt_schedulerd, |
134 | | N_("What to do when the cluster does not have quorum"), |
135 | | NULL, |
136 | | }, |
137 | | { |
138 | | PCMK_OPT_SHUTDOWN_LOCK, NULL, PCMK_VALUE_BOOLEAN, NULL, |
139 | | PCMK_VALUE_FALSE, pcmk__valid_boolean, |
140 | | pcmk__opt_schedulerd, |
141 | | N_("Whether to lock resources to a cleanly shut down node"), |
142 | | N_("When true, resources active on a node when it is cleanly shut down " |
143 | | "are kept \"locked\" to that node (not allowed to run elsewhere) " |
144 | | "until they start again on that node after it rejoins (or for at " |
145 | | "most shutdown-lock-limit, if set). Stonith resources and " |
146 | | "Pacemaker Remote connections are never locked. Clone and bundle " |
147 | | "instances and the promoted role of promotable clones are " |
148 | | "currently never locked, though support could be added in a future " |
149 | | "release."), |
150 | | }, |
151 | | { |
152 | | PCMK_OPT_SHUTDOWN_LOCK_LIMIT, NULL, PCMK_VALUE_DURATION, NULL, |
153 | | "0", pcmk__valid_interval_spec, |
154 | | pcmk__opt_schedulerd, |
155 | | N_("Do not lock resources to a cleanly shut down node longer than " |
156 | | "this"), |
157 | | N_("If shutdown-lock is true and this is set to a nonzero time " |
158 | | "duration, shutdown locks will expire after this much time has " |
159 | | "passed since the shutdown was initiated, even if the node has not " |
160 | | "rejoined."), |
161 | | }, |
162 | | { |
163 | | PCMK_OPT_ENABLE_ACL, NULL, PCMK_VALUE_BOOLEAN, NULL, |
164 | | PCMK_VALUE_FALSE, pcmk__valid_boolean, |
165 | | pcmk__opt_based, |
166 | | N_("Enable Access Control Lists (ACLs) for the CIB"), |
167 | | NULL, |
168 | | }, |
169 | | { |
170 | | PCMK_OPT_SYMMETRIC_CLUSTER, NULL, PCMK_VALUE_BOOLEAN, NULL, |
171 | | PCMK_VALUE_TRUE, pcmk__valid_boolean, |
172 | | pcmk__opt_schedulerd, |
173 | | N_("Whether resources can run on any node by default"), |
174 | | NULL, |
175 | | }, |
176 | | { |
177 | | PCMK_OPT_MAINTENANCE_MODE, NULL, PCMK_VALUE_BOOLEAN, NULL, |
178 | | PCMK_VALUE_FALSE, pcmk__valid_boolean, |
179 | | pcmk__opt_schedulerd, |
180 | | N_("Whether the cluster should refrain from monitoring, starting, and " |
181 | | "stopping resources"), |
182 | | NULL, |
183 | | }, |
184 | | { |
185 | | PCMK_OPT_START_FAILURE_IS_FATAL, NULL, PCMK_VALUE_BOOLEAN, NULL, |
186 | | PCMK_VALUE_TRUE, pcmk__valid_boolean, |
187 | | pcmk__opt_schedulerd, |
188 | | N_("Whether a start failure should prevent a resource from being " |
189 | | "recovered on the same node"), |
190 | | N_("When true, the cluster will immediately ban a resource from a node " |
191 | | "if it fails to start there. When false, the cluster will instead " |
192 | | "check the resource's fail count against its migration-threshold.") |
193 | | }, |
194 | | { |
195 | | PCMK__OPT_ENABLE_STARTUP_PROBES, NULL, PCMK_VALUE_BOOLEAN, NULL, |
196 | | PCMK_VALUE_TRUE, pcmk__valid_boolean, |
197 | | pcmk__opt_schedulerd|pcmk__opt_deprecated, |
198 | | N_("Whether the cluster should check for active resources during " |
199 | | "start-up"), |
200 | | NULL, |
201 | | }, |
202 | | |
203 | | // Fencing-related options |
204 | | { |
205 | | PCMK_OPT_FENCE_REMOTE_WITHOUT_QUORUM, NULL, PCMK_VALUE_BOOLEAN, NULL, |
206 | | PCMK_VALUE_FALSE, pcmk__valid_boolean, |
207 | | pcmk__opt_schedulerd|pcmk__opt_advanced, |
208 | | N_("Whether remote nodes can be fenced without quorum"), |
209 | | N_("By default, an inquorate node can not fence Pacemaker Remote nodes " |
210 | | "that are part of its partition as long as the cluster thinks they " |
211 | | "can be restarted. If true, inquorate nodes will be able to fence " |
212 | | "remote nodes regardless."), |
213 | | }, |
214 | | { |
215 | | PCMK_OPT_FENCING_ENABLED, "stonith-enabled", PCMK_VALUE_BOOLEAN, NULL, |
216 | | PCMK_VALUE_TRUE, pcmk__valid_boolean, |
217 | | pcmk__opt_schedulerd|pcmk__opt_advanced, |
218 | | N_("Whether nodes may be fenced as part of recovery"), |
219 | | N_("If false, unresponsive nodes are immediately assumed to be " |
220 | | "harmless, and resources that were active on them may be recovered " |
221 | | "elsewhere. This can result in a \"split-brain\" situation, " |
222 | | "potentially leading to data loss and/or service unavailability."), |
223 | | }, |
224 | | { |
225 | | PCMK_OPT_FENCING_ACTION, "stonith-action", PCMK_VALUE_SELECT, |
226 | | PCMK_ACTION_REBOOT ", " PCMK_ACTION_OFF, |
227 | | PCMK_ACTION_REBOOT, pcmk__is_fencing_action, |
228 | | pcmk__opt_schedulerd, |
229 | | N_("Action to send to fence device when a node needs to be fenced"), |
230 | | NULL, |
231 | | }, |
232 | | { |
233 | | PCMK_OPT_FENCING_REACTION, "fence-reaction", PCMK_VALUE_SELECT, |
234 | | PCMK_VALUE_STOP ", " PCMK_VALUE_PANIC, |
235 | | PCMK_VALUE_STOP, NULL, |
236 | | pcmk__opt_controld, |
237 | | N_("How a cluster node should react if notified of its own fencing"), |
238 | | N_("A cluster node may receive notification of a \"succeeded\" " |
239 | | "fencing that targeted it if fencing is misconfigured, or if " |
240 | | "fabric fencing is in use that doesn't cut cluster communication. " |
241 | | "Use \"stop\" to attempt to immediately stop Pacemaker and stay " |
242 | | "stopped, or \"panic\" to attempt to immediately reboot the local " |
243 | | "node, falling back to stop on failure."), |
244 | | }, |
245 | | { |
246 | | PCMK_OPT_FENCING_TIMEOUT, "stonith-timeout", PCMK_VALUE_DURATION, NULL, |
247 | | "60s", pcmk__valid_interval_spec, |
248 | | pcmk__opt_schedulerd, |
249 | | N_("How long to wait for on, off, and reboot fence actions to complete " |
250 | | "by default"), |
251 | | NULL, |
252 | | }, |
253 | | { |
254 | | PCMK_OPT_HAVE_WATCHDOG, NULL, PCMK_VALUE_BOOLEAN, NULL, |
255 | | PCMK_VALUE_FALSE, pcmk__valid_boolean, |
256 | | pcmk__opt_schedulerd|pcmk__opt_generated, |
257 | | N_("Whether watchdog integration is enabled"), |
258 | | N_("This is set automatically by the cluster according to whether SBD " |
259 | | "is detected to be in use. User-configured values are ignored. " |
260 | | "The value `true` is meaningful if diskless SBD is used and " |
261 | | "`fencing-watchdog-timeout` is nonzero. In that case, if fencing " |
262 | | "is required, watchdog-based self-fencing will be performed via " |
263 | | "SBD without requiring a fencing resource explicitly configured."), |
264 | | }, |
265 | | { |
266 | | /* @COMPAT Currently, unparsable values default to -1 (auto-calculate), |
267 | | * while missing values default to 0 (disable). All values are accepted |
268 | | * (unless the controller finds that the value conflicts with the |
269 | | * SBD_WATCHDOG_TIMEOUT). |
270 | | * |
271 | | * At a compatibility break: properly validate as a timeout, let |
272 | | * either negative values or a particular string like "auto" mean auto- |
273 | | * calculate, and use 0 as the single default for when the option either |
274 | | * is unset or fails to validate. |
275 | | */ |
276 | | PCMK_OPT_FENCING_WATCHDOG_TIMEOUT, "stonith-watchdog-timeout", |
277 | | PCMK_VALUE_TIMEOUT, NULL, |
278 | | "0", NULL, |
279 | | pcmk__opt_controld, |
280 | | N_("How long before nodes can be assumed to be safely down when " |
281 | | "watchdog-based self-fencing via SBD is in use"), |
282 | | N_("If this is set to a positive value, lost nodes are assumed to " |
283 | | "achieve self-fencing using watchdog-based SBD within this much " |
284 | | "time. This does not require a fencing resource to be explicitly " |
285 | | "configured, though a fence_watchdog resource can be configured, to " |
286 | | "limit use to specific nodes. If this is set to 0 (the default), " |
287 | | "the cluster will never assume watchdog-based self-fencing. If this " |
288 | | "is set to a negative value, the cluster will use twice the local " |
289 | | "value of the `SBD_WATCHDOG_TIMEOUT` environment variable if that " |
290 | | "is positive, or otherwise treat this as 0. WARNING: When used, " |
291 | | "this timeout must be larger than `SBD_WATCHDOG_TIMEOUT` on all " |
292 | | "nodes that use watchdog-based SBD, and Pacemaker will refuse to " |
293 | | "start on any of those nodes where this is not true for the local " |
294 | | "value or SBD is not active. When this is set to a negative value, " |
295 | | "`SBD_WATCHDOG_TIMEOUT` must be set to the same value on all nodes " |
296 | | "that use SBD, otherwise data corruption or loss could occur."), |
297 | | }, |
298 | | { |
299 | | PCMK_OPT_FENCING_MAX_ATTEMPTS, "stonith-max-attempts", PCMK_VALUE_SCORE, |
300 | | NULL, |
301 | | "10", pcmk__valid_positive_int, |
302 | | pcmk__opt_controld, |
303 | | N_("How many times fencing can fail before it will no longer be " |
304 | | "immediately re-attempted on a target"), |
305 | | NULL, |
306 | | }, |
307 | | { |
308 | | PCMK__OPT_CONCURRENT_FENCING, NULL, PCMK_VALUE_BOOLEAN, NULL, |
309 | | #if PCMK__CONCURRENT_FENCING_DEFAULT_TRUE |
310 | | PCMK_VALUE_TRUE, |
311 | | #else |
312 | | PCMK_VALUE_FALSE, |
313 | | #endif |
314 | | pcmk__valid_boolean, |
315 | | pcmk__opt_schedulerd|pcmk__opt_deprecated, |
316 | | N_("Allow performing fencing operations in parallel"), |
317 | | NULL, |
318 | | }, |
319 | | { |
320 | | PCMK_OPT_STARTUP_FENCING, NULL, PCMK_VALUE_BOOLEAN, NULL, |
321 | | PCMK_VALUE_TRUE, pcmk__valid_boolean, |
322 | | pcmk__opt_schedulerd|pcmk__opt_advanced, |
323 | | N_("Whether to fence unseen nodes at start-up"), |
324 | | N_("Setting this to false may lead to a \"split-brain\" situation, " |
325 | | "potentially leading to data loss and/or service unavailability."), |
326 | | }, |
327 | | { |
328 | | PCMK_OPT_PRIORITY_FENCING_DELAY, NULL, PCMK_VALUE_DURATION, NULL, |
329 | | "0", pcmk__valid_interval_spec, |
330 | | pcmk__opt_schedulerd, |
331 | | N_("Apply fencing delay targeting the lost nodes with the highest " |
332 | | "total resource priority"), |
333 | | N_("Apply specified delay for the fencings that are targeting the lost " |
334 | | "nodes with the highest total resource priority in case we don't " |
335 | | "have the majority of the nodes in our cluster partition, so that " |
336 | | "the more significant nodes potentially win any fencing match, " |
337 | | "which is especially meaningful under split-brain of 2-node " |
338 | | "cluster. A promoted resource instance takes the base priority + 1 " |
339 | | "on calculation if the base priority is not 0. Any static/random " |
340 | | "delays that are introduced by `pcmk_delay_base/max` configured " |
341 | | "for the corresponding fencing resources will be added to this " |
342 | | "delay. This delay should be significantly greater than, safely " |
343 | | "twice, the maximum `pcmk_delay_base/max`. By default, priority " |
344 | | "fencing delay is disabled."), |
345 | | }, |
346 | | { |
347 | | PCMK_OPT_NODE_PENDING_TIMEOUT, NULL, PCMK_VALUE_DURATION, NULL, |
348 | | "0", pcmk__valid_interval_spec, |
349 | | pcmk__opt_schedulerd, |
350 | | N_("How long to wait for a node that has joined the cluster to join " |
351 | | "the controller process group"), |
352 | | N_("Fence nodes that do not join the controller process group within " |
353 | | "this much time after joining the cluster, to allow the cluster " |
354 | | "to continue managing resources. A value of 0 means never fence " |
355 | | "pending nodes. Setting the value to 2h means fence nodes after " |
356 | | "2 hours."), |
357 | | }, |
358 | | { |
359 | | PCMK_OPT_CLUSTER_DELAY, NULL, PCMK_VALUE_DURATION, NULL, |
360 | | "60s", pcmk__valid_interval_spec, |
361 | | pcmk__opt_schedulerd, |
362 | | N_("Maximum time for node-to-node communication"), |
363 | | N_("The node elected Designated Controller (DC) will consider an action " |
364 | | "failed if it does not get a response from the node executing the " |
365 | | "action within this time (after considering the action's own " |
366 | | "timeout). The \"correct\" value will depend on the speed and " |
367 | | "load of your network and cluster nodes.") |
368 | | }, |
369 | | |
370 | | // Limits |
371 | | { |
372 | | PCMK_OPT_LOAD_THRESHOLD, NULL, PCMK_VALUE_PERCENTAGE, NULL, |
373 | | "80%", pcmk__valid_percentage, |
374 | | pcmk__opt_controld, |
375 | | N_("Maximum amount of system load that should be used by cluster " |
376 | | "nodes"), |
377 | | N_("The cluster will slow down its recovery process when the amount of " |
378 | | "system resources used (currently CPU) approaches this limit"), |
379 | | }, |
380 | | { |
381 | | PCMK_OPT_NODE_ACTION_LIMIT, NULL, PCMK_VALUE_INTEGER, NULL, |
382 | | "0", pcmk__valid_int, |
383 | | pcmk__opt_controld, |
384 | | N_("Maximum number of jobs that can be scheduled per node (defaults to " |
385 | | "2x cores)"), |
386 | | NULL, |
387 | | }, |
388 | | { |
389 | | PCMK_OPT_BATCH_LIMIT, NULL, PCMK_VALUE_INTEGER, NULL, |
390 | | "0", pcmk__valid_int, |
391 | | pcmk__opt_schedulerd, |
392 | | N_("Maximum number of jobs that the cluster may execute in parallel " |
393 | | "across all nodes"), |
394 | | N_("The \"correct\" value will depend on the speed and load of your " |
395 | | "network and cluster nodes. If set to 0, the cluster will " |
396 | | "impose a dynamically calculated limit when any node has a " |
397 | | "high load."), |
398 | | }, |
399 | | { |
400 | | PCMK_OPT_MIGRATION_LIMIT, NULL, PCMK_VALUE_INTEGER, NULL, |
401 | | "-1", pcmk__valid_int, |
402 | | pcmk__opt_schedulerd, |
403 | | N_("The number of live migration actions that the cluster is allowed " |
404 | | "to execute in parallel on a node (-1 means no limit)"), |
405 | | NULL, |
406 | | }, |
407 | | { |
408 | | "cluster-ipc-limit", NULL, PCMK_VALUE_NONNEGATIVE_INTEGER, NULL, |
409 | | NULL, NULL, |
410 | | pcmk__opt_based|pcmk__opt_deprecated, |
411 | | N_("Ignored"), |
412 | | NULL, |
413 | | }, |
414 | | |
415 | | // Stopping resources and removed resources |
416 | | { |
417 | | /* This option complicates display and precedence a bit. The same effect |
418 | | * can be achieved by placing all nodes in standby, or by creating a |
419 | | * constraint rule that sets all resources' target roles to stopped. |
420 | | * |
421 | | * We decided to keep it based on user feedback that it's useful in its |
422 | | * simplicity. Also, it is analogous to the situation with |
423 | | * PCMK_OPT_MAINTENANCE_MODE (cluster-level), |
424 | | * PCMK_NODE_ATTR_MAINTENANCE (node-level), and PCMK_META_MAINTENANCE |
425 | | * (resource-level). |
426 | | */ |
427 | | PCMK_OPT_STOP_ALL_RESOURCES, NULL, PCMK_VALUE_BOOLEAN, NULL, |
428 | | PCMK_VALUE_FALSE, pcmk__valid_boolean, |
429 | | pcmk__opt_schedulerd, |
430 | | N_("Whether the cluster should stop all active resources"), |
431 | | NULL, |
432 | | }, |
433 | | { |
434 | | PCMK__OPT_STOP_REMOVED_RESOURCES, "stop-orphan-resources", |
435 | | PCMK_VALUE_BOOLEAN, NULL, |
436 | | PCMK_VALUE_TRUE, pcmk__valid_boolean, |
437 | | pcmk__opt_schedulerd|pcmk__opt_deprecated, |
438 | | N_("Whether to stop resources that were removed from the " |
439 | | "configuration"), |
440 | | NULL, |
441 | | }, |
442 | | { |
443 | | PCMK__OPT_CANCEL_REMOVED_ACTIONS, "stop-orphan-actions", |
444 | | PCMK_VALUE_BOOLEAN, NULL, |
445 | | PCMK_VALUE_TRUE, pcmk__valid_boolean, |
446 | | pcmk__opt_schedulerd|pcmk__opt_deprecated, |
447 | | N_("Whether to cancel recurring actions removed from the " |
448 | | "configuration"), |
449 | | NULL, |
450 | | }, |
451 | | |
452 | | // Storing inputs |
453 | | { |
454 | | PCMK_OPT_PE_ERROR_SERIES_MAX, NULL, PCMK_VALUE_INTEGER, NULL, |
455 | | "-1", pcmk__valid_int, |
456 | | pcmk__opt_schedulerd, |
457 | | N_("The number of scheduler inputs resulting in errors to save"), |
458 | | N_("Zero to disable, -1 to store unlimited."), |
459 | | }, |
460 | | { |
461 | | PCMK_OPT_PE_WARN_SERIES_MAX, NULL, PCMK_VALUE_INTEGER, NULL, |
462 | | "5000", pcmk__valid_int, |
463 | | pcmk__opt_schedulerd, |
464 | | N_("The number of scheduler inputs resulting in warnings to save"), |
465 | | N_("Zero to disable, -1 to store unlimited."), |
466 | | }, |
467 | | { |
468 | | PCMK_OPT_PE_INPUT_SERIES_MAX, NULL, PCMK_VALUE_INTEGER, NULL, |
469 | | "4000", pcmk__valid_int, |
470 | | pcmk__opt_schedulerd, |
471 | | N_("The number of scheduler inputs without errors or warnings to save"), |
472 | | N_("Zero to disable, -1 to store unlimited."), |
473 | | }, |
474 | | |
475 | | // Node health |
476 | | { |
477 | | PCMK_OPT_NODE_HEALTH_STRATEGY, NULL, PCMK_VALUE_SELECT, |
478 | | PCMK_VALUE_NONE ", " PCMK_VALUE_MIGRATE_ON_RED ", " |
479 | | PCMK_VALUE_ONLY_GREEN ", " PCMK_VALUE_PROGRESSIVE ", " |
480 | | PCMK_VALUE_CUSTOM, |
481 | | PCMK_VALUE_NONE, pcmk__validate_health_strategy, |
482 | | pcmk__opt_schedulerd, |
483 | | N_("How cluster should react to node health attributes"), |
484 | | N_("Requires external entities to create node attributes (named with " |
485 | | "the prefix \"#health\") with values \"red\", \"yellow\", or " |
486 | | "\"green\".") |
487 | | }, |
488 | | { |
489 | | PCMK_OPT_NODE_HEALTH_BASE, NULL, PCMK_VALUE_SCORE, NULL, |
490 | | "0", pcmk__valid_int, |
491 | | pcmk__opt_schedulerd, |
492 | | N_("Base health score assigned to a node"), |
493 | | N_("Only used when \"node-health-strategy\" is set to " |
494 | | "\"progressive\"."), |
495 | | }, |
496 | | { |
497 | | PCMK_OPT_NODE_HEALTH_GREEN, NULL, PCMK_VALUE_SCORE, NULL, |
498 | | "0", pcmk__valid_int, |
499 | | pcmk__opt_schedulerd, |
500 | | N_("The score to use for a node health attribute whose value is " |
501 | | "\"green\""), |
502 | | N_("Only used when \"node-health-strategy\" is set to \"custom\" or " |
503 | | "\"progressive\"."), |
504 | | }, |
505 | | { |
506 | | PCMK_OPT_NODE_HEALTH_YELLOW, NULL, PCMK_VALUE_SCORE, NULL, |
507 | | "0", pcmk__valid_int, |
508 | | pcmk__opt_schedulerd, |
509 | | N_("The score to use for a node health attribute whose value is " |
510 | | "\"yellow\""), |
511 | | N_("Only used when \"node-health-strategy\" is set to \"custom\" or " |
512 | | "\"progressive\"."), |
513 | | }, |
514 | | { |
515 | | PCMK_OPT_NODE_HEALTH_RED, NULL, PCMK_VALUE_SCORE, NULL, |
516 | | "-INFINITY", pcmk__valid_int, |
517 | | pcmk__opt_schedulerd, |
518 | | N_("The score to use for a node health attribute whose value is " |
519 | | "\"red\""), |
520 | | N_("Only used when \"node-health-strategy\" is set to \"custom\" or " |
521 | | "\"progressive\".") |
522 | | }, |
523 | | |
524 | | // Placement strategy |
525 | | { |
526 | | PCMK_OPT_PLACEMENT_STRATEGY, NULL, PCMK_VALUE_SELECT, |
527 | | PCMK_VALUE_DEFAULT ", " PCMK_VALUE_UTILIZATION ", " |
528 | | PCMK_VALUE_MINIMAL ", " PCMK_VALUE_BALANCED, |
529 | | PCMK_VALUE_DEFAULT, pcmk__valid_placement_strategy, |
530 | | pcmk__opt_schedulerd, |
531 | | N_("How the cluster should allocate resources to nodes"), |
532 | | NULL, |
533 | | }, |
534 | | |
535 | | { NULL, }, |
536 | | }; |
537 | | |
538 | | static const pcmk__cluster_option_t fencing_params[] = { |
539 | | /* name, old name, type, allowed values, |
540 | | * default value, validator, |
541 | | * flags, |
542 | | * short description, |
543 | | * long description |
544 | | */ |
545 | | { |
546 | | PCMK_FENCING_HOST_ARGUMENT, NULL, PCMK_VALUE_STRING, NULL, |
547 | | NULL, NULL, |
548 | | pcmk__opt_advanced, |
549 | | N_("Name of agent parameter that should be set to the fencing target"), |
550 | | N_("If the fencing agent metadata advertises support for the \"port\" " |
551 | | "or \"plug\" parameter, that will be used as the default, " |
552 | | "otherwise \"none\" will be used, which tells the cluster not to " |
553 | | "supply any additional parameters."), |
554 | | }, |
555 | | { |
556 | | PCMK_FENCING_HOST_MAP, NULL, PCMK_VALUE_STRING, NULL, |
557 | | NULL, NULL, |
558 | | pcmk__opt_none, |
559 | | N_("A mapping of node names to port numbers for devices that do not " |
560 | | "support node names."), |
561 | | N_("For example, \"node1:1;node2:2,3\" would tell the cluster to use " |
562 | | "port 1 for node1 and ports 2 and 3 for node2."), |
563 | | }, |
564 | | { |
565 | | PCMK_FENCING_HOST_LIST, NULL, PCMK_VALUE_STRING, NULL, |
566 | | NULL, NULL, |
567 | | pcmk__opt_none, |
568 | | N_("Nodes targeted by this device"), |
569 | | N_("Comma-separated list of nodes that can be targeted by this device " |
570 | | "(for example, \"node1,node2,node3\"). If pcmk_host_check is " |
571 | | "\"static-list\", either this or pcmk_host_map must be set."), |
572 | | }, |
573 | | { |
574 | | PCMK_FENCING_HOST_CHECK, NULL, PCMK_VALUE_SELECT, |
575 | | PCMK_VALUE_DYNAMIC_LIST ", " PCMK_VALUE_STATIC_LIST ", " |
576 | | PCMK_VALUE_STATUS ", " PCMK_VALUE_NONE, |
577 | | NULL, NULL, |
578 | | pcmk__opt_none, |
579 | | N_("How to determine which nodes can be targeted by the device"), |
580 | | N_("Use \"dynamic-list\" to query the device via the 'list' command; " |
581 | | "\"static-list\" to check the pcmk_host_list attribute; " |
582 | | "\"status\" to query the device via the 'status' command; or " |
583 | | "\"none\" to assume every device can fence every node. " |
584 | | "The default value is \"static-list\" if pcmk_host_map or " |
585 | | "pcmk_host_list is set; otherwise \"dynamic-list\" if the device " |
586 | | "supports the list operation; otherwise \"status\" if the device " |
587 | | "supports the status operation; otherwise \"none\""), |
588 | | }, |
589 | | { |
590 | | PCMK_FENCING_DELAY_MAX, NULL, PCMK_VALUE_DURATION, NULL, |
591 | | "0s", NULL, |
592 | | pcmk__opt_none, |
593 | | N_("Enable a delay of no more than the time specified before executing " |
594 | | "fencing actions."), |
595 | | N_("Enable a delay of no more than the time specified before executing " |
596 | | "fencing actions. Pacemaker derives the overall delay by taking " |
597 | | "the value of pcmk_delay_base and adding a random delay value such " |
598 | | "that the sum is kept below this maximum."), |
599 | | }, |
600 | | { |
601 | | PCMK_FENCING_DELAY_BASE, NULL, PCMK_VALUE_STRING, NULL, |
602 | | "0s", NULL, |
603 | | pcmk__opt_none, |
604 | | N_("Enable a base delay for fencing actions and specify base delay " |
605 | | "value."), |
606 | | N_("This enables a static delay for fencing actions, which can help " |
607 | | "avoid \"death matches\" where two nodes try to fence each other " |
608 | | "at the same time. If pcmk_delay_max is also used, a random delay " |
609 | | "will be added such that the total delay is kept below that value. " |
610 | | "This can be set to a single time value to apply to any node " |
611 | | "targeted by this device (useful if a separate device is " |
612 | | "configured for each target), or to a node map (for example, " |
613 | | "\"node1:1s;node2:5\") to set a different value for each target."), |
614 | | }, |
615 | | { |
616 | | PCMK_FENCING_ACTION_LIMIT, NULL, PCMK_VALUE_INTEGER, NULL, |
617 | | "1", NULL, |
618 | | pcmk__opt_none, |
619 | | N_("The maximum number of actions can be performed in parallel on this " |
620 | | "device"), |
621 | | N_("If the concurrent-fencing cluster property is \"true\", this " |
622 | | "specifies the maximum number of actions that can be performed in " |
623 | | "parallel on this device. A value of -1 means unlimited."), |
624 | | }, |
625 | | { |
626 | | "pcmk_reboot_action", NULL, PCMK_VALUE_STRING, NULL, |
627 | | PCMK_ACTION_REBOOT, NULL, |
628 | | pcmk__opt_advanced, |
629 | | N_("An alternate command to run instead of 'reboot'"), |
630 | | N_("Some devices do not support the standard commands or may provide " |
631 | | "additional ones. Use this to specify an alternate, device-" |
632 | | "specific, command that implements the 'reboot' action."), |
633 | | }, |
634 | | { |
635 | | "pcmk_reboot_timeout", NULL, PCMK_VALUE_TIMEOUT, NULL, |
636 | | "60s", NULL, |
637 | | pcmk__opt_advanced, |
638 | | N_("Specify an alternate timeout to use for 'reboot' actions instead " |
639 | | "of fencing-timeout"), |
640 | | N_("Some devices need much more/less time to complete than normal. " |
641 | | "Use this to specify an alternate, device-specific, timeout for " |
642 | | "'reboot' actions."), |
643 | | }, |
644 | | { |
645 | | "pcmk_reboot_retries", NULL, PCMK_VALUE_INTEGER, NULL, |
646 | | "2", NULL, |
647 | | pcmk__opt_advanced, |
648 | | N_("The maximum number of times to try the 'reboot' command within the " |
649 | | "timeout period"), |
650 | | N_("Some devices do not support multiple connections. Operations may " |
651 | | "\"fail\" if the device is busy with another task. In that case, " |
652 | | "Pacemaker will automatically retry the operation if there is time " |
653 | | "remaining. Use this option to alter the number of times Pacemaker " |
654 | | "tries a 'reboot' action before giving up."), |
655 | | }, |
656 | | { |
657 | | "pcmk_off_action", NULL, PCMK_VALUE_STRING, NULL, |
658 | | PCMK_ACTION_OFF, NULL, |
659 | | pcmk__opt_advanced, |
660 | | N_("An alternate command to run instead of 'off'"), |
661 | | N_("Some devices do not support the standard commands or may provide " |
662 | | "additional ones. Use this to specify an alternate, device-" |
663 | | "specific, command that implements the 'off' action."), |
664 | | }, |
665 | | { |
666 | | "pcmk_off_timeout", NULL, PCMK_VALUE_TIMEOUT, NULL, |
667 | | "60s", NULL, |
668 | | pcmk__opt_advanced, |
669 | | N_("Specify an alternate timeout to use for 'off' actions instead of " |
670 | | "fencing-timeout"), |
671 | | N_("Some devices need much more/less time to complete than normal. " |
672 | | "Use this to specify an alternate, device-specific, timeout for " |
673 | | "'off' actions."), |
674 | | }, |
675 | | { |
676 | | "pcmk_off_retries", NULL, PCMK_VALUE_INTEGER, NULL, |
677 | | "2", NULL, |
678 | | pcmk__opt_advanced, |
679 | | N_("The maximum number of times to try the 'off' command within the " |
680 | | "timeout period"), |
681 | | N_("Some devices do not support multiple connections. Operations may " |
682 | | "\"fail\" if the device is busy with another task. In that case, " |
683 | | "Pacemaker will automatically retry the operation if there is time " |
684 | | "remaining. Use this option to alter the number of times Pacemaker " |
685 | | "tries a 'off' action before giving up."), |
686 | | }, |
687 | | { |
688 | | "pcmk_on_action", NULL, PCMK_VALUE_STRING, NULL, |
689 | | PCMK_ACTION_ON, NULL, |
690 | | pcmk__opt_advanced, |
691 | | N_("An alternate command to run instead of 'on'"), |
692 | | N_("Some devices do not support the standard commands or may provide " |
693 | | "additional ones. Use this to specify an alternate, device-" |
694 | | "specific, command that implements the 'on' action."), |
695 | | }, |
696 | | { |
697 | | "pcmk_on_timeout", NULL, PCMK_VALUE_TIMEOUT, NULL, |
698 | | "60s", NULL, |
699 | | pcmk__opt_advanced, |
700 | | N_("Specify an alternate timeout to use for 'on' actions instead of " |
701 | | "fencing-timeout"), |
702 | | N_("Some devices need much more/less time to complete than normal. " |
703 | | "Use this to specify an alternate, device-specific, timeout for " |
704 | | "'on' actions."), |
705 | | }, |
706 | | { |
707 | | "pcmk_on_retries", NULL, PCMK_VALUE_INTEGER, NULL, |
708 | | "2", NULL, |
709 | | pcmk__opt_advanced, |
710 | | N_("The maximum number of times to try the 'on' command within the " |
711 | | "timeout period"), |
712 | | N_("Some devices do not support multiple connections. Operations may " |
713 | | "\"fail\" if the device is busy with another task. In that case, " |
714 | | "Pacemaker will automatically retry the operation if there is time " |
715 | | "remaining. Use this option to alter the number of times Pacemaker " |
716 | | "tries a 'on' action before giving up."), |
717 | | }, |
718 | | { |
719 | | "pcmk_list_action", NULL, PCMK_VALUE_STRING, NULL, |
720 | | PCMK_ACTION_LIST, NULL, |
721 | | pcmk__opt_advanced, |
722 | | N_("An alternate command to run instead of 'list'"), |
723 | | N_("Some devices do not support the standard commands or may provide " |
724 | | "additional ones. Use this to specify an alternate, device-" |
725 | | "specific, command that implements the 'list' action."), |
726 | | }, |
727 | | { |
728 | | "pcmk_list_timeout", NULL, PCMK_VALUE_TIMEOUT, NULL, |
729 | | "60s", NULL, |
730 | | pcmk__opt_advanced, |
731 | | N_("Specify an alternate timeout to use for 'list' actions instead of " |
732 | | "fencing-timeout"), |
733 | | N_("Some devices need much more/less time to complete than normal. " |
734 | | "Use this to specify an alternate, device-specific, timeout for " |
735 | | "'list' actions."), |
736 | | }, |
737 | | { |
738 | | "pcmk_list_retries", NULL, PCMK_VALUE_INTEGER, NULL, |
739 | | "2", NULL, |
740 | | pcmk__opt_advanced, |
741 | | N_("The maximum number of times to try the 'list' command within the " |
742 | | "timeout period"), |
743 | | N_("Some devices do not support multiple connections. Operations may " |
744 | | "\"fail\" if the device is busy with another task. In that case, " |
745 | | "Pacemaker will automatically retry the operation if there is time " |
746 | | "remaining. Use this option to alter the number of times Pacemaker " |
747 | | "tries a 'list' action before giving up."), |
748 | | }, |
749 | | { |
750 | | "pcmk_monitor_action", NULL, PCMK_VALUE_STRING, NULL, |
751 | | PCMK_ACTION_MONITOR, NULL, |
752 | | pcmk__opt_advanced, |
753 | | N_("An alternate command to run instead of 'monitor'"), |
754 | | N_("Some devices do not support the standard commands or may provide " |
755 | | "additional ones. Use this to specify an alternate, device-" |
756 | | "specific, command that implements the 'monitor' action."), |
757 | | }, |
758 | | { |
759 | | "pcmk_monitor_timeout", NULL, PCMK_VALUE_TIMEOUT, NULL, |
760 | | "60s", NULL, |
761 | | pcmk__opt_advanced, |
762 | | N_("Specify an alternate timeout to use for 'monitor' actions instead " |
763 | | "of fencing-timeout"), |
764 | | N_("Some devices need much more/less time to complete than normal. " |
765 | | "Use this to specify an alternate, device-specific, timeout for " |
766 | | "'monitor' actions."), |
767 | | }, |
768 | | { |
769 | | "pcmk_monitor_retries", NULL, PCMK_VALUE_INTEGER, NULL, |
770 | | "2", NULL, |
771 | | pcmk__opt_advanced, |
772 | | N_("The maximum number of times to try the 'monitor' command within " |
773 | | "the timeout period"), |
774 | | N_("Some devices do not support multiple connections. Operations may " |
775 | | "\"fail\" if the device is busy with another task. In that case, " |
776 | | "Pacemaker will automatically retry the operation if there is time " |
777 | | "remaining. Use this option to alter the number of times Pacemaker " |
778 | | "tries a 'monitor' action before giving up."), |
779 | | }, |
780 | | { |
781 | | "pcmk_status_action", NULL, PCMK_VALUE_STRING, NULL, |
782 | | PCMK_ACTION_STATUS, NULL, |
783 | | pcmk__opt_advanced, |
784 | | N_("An alternate command to run instead of 'status'"), |
785 | | N_("Some devices do not support the standard commands or may provide " |
786 | | "additional ones. Use this to specify an alternate, device-" |
787 | | "specific, command that implements the 'status' action."), |
788 | | }, |
789 | | { |
790 | | "pcmk_status_timeout", NULL, PCMK_VALUE_TIMEOUT, NULL, |
791 | | "60s", NULL, |
792 | | pcmk__opt_advanced, |
793 | | N_("Specify an alternate timeout to use for 'status' actions instead " |
794 | | "of fencing-timeout"), |
795 | | N_("Some devices need much more/less time to complete than normal. " |
796 | | "Use this to specify an alternate, device-specific, timeout for " |
797 | | "'status' actions."), |
798 | | }, |
799 | | { |
800 | | "pcmk_status_retries", NULL, PCMK_VALUE_INTEGER, NULL, |
801 | | "2", NULL, |
802 | | pcmk__opt_advanced, |
803 | | N_("The maximum number of times to try the 'status' command within " |
804 | | "the timeout period"), |
805 | | N_("Some devices do not support multiple connections. Operations may " |
806 | | "\"fail\" if the device is busy with another task. In that case, " |
807 | | "Pacemaker will automatically retry the operation if there is time " |
808 | | "remaining. Use this option to alter the number of times Pacemaker " |
809 | | "tries a 'status' action before giving up."), |
810 | | }, |
811 | | |
812 | | { NULL, }, |
813 | | }; |
814 | | |
815 | | static const pcmk__cluster_option_t primitive_meta[] = { |
816 | | /* name, old name, type, allowed values, |
817 | | * default value, validator, |
818 | | * flags, |
819 | | * short description, |
820 | | * long description |
821 | | */ |
822 | | { |
823 | | PCMK_META_PRIORITY, NULL, PCMK_VALUE_SCORE, NULL, |
824 | | "0", NULL, |
825 | | pcmk__opt_none, |
826 | | N_("Resource assignment priority"), |
827 | | N_("If not all resources can be active, the cluster will stop " |
828 | | "lower-priority resources in order to keep higher-priority ones " |
829 | | "active."), |
830 | | }, |
831 | | { |
832 | | PCMK_META_CRITICAL, NULL, PCMK_VALUE_BOOLEAN, NULL, |
833 | | PCMK_VALUE_TRUE, NULL, |
834 | | pcmk__opt_none, |
835 | | N_("Default value for influence in colocation constraints"), |
836 | | N_("Use this value as the default for influence in all colocation " |
837 | | "constraints involving this resource, as well as in the implicit " |
838 | | "colocation constraints created if this resource is in a group."), |
839 | | }, |
840 | | { |
841 | | PCMK_META_TARGET_ROLE, NULL, PCMK_VALUE_SELECT, |
842 | | PCMK_ROLE_STOPPED ", " PCMK_ROLE_STARTED ", " |
843 | | PCMK_ROLE_UNPROMOTED ", " PCMK_ROLE_PROMOTED, |
844 | | PCMK_ROLE_STARTED, NULL, |
845 | | pcmk__opt_none, |
846 | | N_("State the cluster should attempt to keep this resource in"), |
847 | | N_("\"Stopped\" forces the resource to be stopped. " |
848 | | "\"Started\" allows the resource to be started (and in the case of " |
849 | | "promotable clone resources, promoted if appropriate). " |
850 | | "\"Unpromoted\" allows the resource to be started, but only in the " |
851 | | "unpromoted role if the resource is promotable. " |
852 | | "\"Promoted\" is equivalent to \"Started\"."), |
853 | | }, |
854 | | { |
855 | | PCMK_META_IS_MANAGED, NULL, PCMK_VALUE_BOOLEAN, NULL, |
856 | | PCMK_VALUE_TRUE, NULL, |
857 | | pcmk__opt_none, |
858 | | N_("Whether the cluster is allowed to actively change the resource's " |
859 | | "state"), |
860 | | N_("If false, the cluster will not start, stop, promote, or demote the " |
861 | | "resource on any node. Recurring actions for the resource are " |
862 | | "unaffected. If true, a true value for the maintenance-mode " |
863 | | "cluster option, the maintenance node attribute, or the " |
864 | | "maintenance resource meta-attribute overrides this."), |
865 | | }, |
866 | | { |
867 | | PCMK_META_MAINTENANCE, NULL, PCMK_VALUE_BOOLEAN, NULL, |
868 | | PCMK_VALUE_FALSE, NULL, |
869 | | pcmk__opt_none, |
870 | | N_("If true, the cluster will not schedule any actions involving the " |
871 | | "resource"), |
872 | | N_("If true, the cluster will not start, stop, promote, or demote the " |
873 | | "resource on any node, and will pause any recurring monitors " |
874 | | "(except those specifying role as \"Stopped\"). If false, a true " |
875 | | "value for the maintenance-mode cluster option or maintenance node " |
876 | | "attribute overrides this."), |
877 | | }, |
878 | | { |
879 | | PCMK_META_RESOURCE_STICKINESS, NULL, PCMK_VALUE_SCORE, NULL, |
880 | | NULL, NULL, |
881 | | pcmk__opt_none, |
882 | | N_("Score to add to the current node when a resource is already " |
883 | | "active"), |
884 | | N_("Score to add to the current node when a resource is already " |
885 | | "active. This allows running resources to stay where they are, " |
886 | | "even if they would be placed elsewhere if they were being started " |
887 | | "from a stopped state. " |
888 | | "The default is 1 for individual clone instances, and 0 for all " |
889 | | "other resources."), |
890 | | }, |
891 | | { |
892 | | PCMK_META_REQUIRES, NULL, PCMK_VALUE_SELECT, |
893 | | PCMK_VALUE_NOTHING ", " PCMK_VALUE_QUORUM ", " |
894 | | PCMK_VALUE_FENCING ", " PCMK_VALUE_UNFENCING, |
895 | | NULL, NULL, |
896 | | pcmk__opt_none, |
897 | | N_("Conditions under which the resource can be started"), |
898 | | N_("Conditions under which the resource can be started. " |
899 | | "\"nothing\" means the cluster can always start this resource. " |
900 | | "\"quorum\" means the cluster can start this resource only if a " |
901 | | "majority of the configured nodes are active. " |
902 | | "\"fencing\" means the cluster can start this resource only if a " |
903 | | "majority of the configured nodes are active and any failed or " |
904 | | "unknown nodes have been fenced. " |
905 | | "\"unfencing\" means the cluster can start this resource only if " |
906 | | "a majority of the configured nodes are active and any failed or " |
907 | | "unknown nodes have been fenced, and only on nodes that have been " |
908 | | "unfenced. " |
909 | | "The default is \"quorum\" for resources with a class of stonith; " |
910 | | "otherwise, \"unfencing\" if unfencing is active in the cluster; " |
911 | | "otherwise, \"fencing\" if the fencing-enabled cluster option is " |
912 | | "true; " |
913 | | "otherwise, \"quorum\"."), |
914 | | }, |
915 | | { |
916 | | PCMK_META_MIGRATION_THRESHOLD, NULL, PCMK_VALUE_SCORE, NULL, |
917 | | PCMK_VALUE_INFINITY, NULL, |
918 | | pcmk__opt_none, |
919 | | N_("Number of failures on a node before the resource becomes " |
920 | | "ineligible to run there."), |
921 | | N_("Number of failures that may occur for this resource on a node, " |
922 | | "before that node is marked ineligible to host this resource. A " |
923 | | "value of 0 indicates that this feature is disabled (the node will " |
924 | | "never be marked ineligible). By contrast, the cluster treats " |
925 | | "\"INFINITY\" (the default) as a very large but finite number. " |
926 | | "This option has an effect only if the failed operation specifies " |
927 | | "its on-fail attribute as \"restart\" (the default), and " |
928 | | "additionally for failed start operations, if the " |
929 | | "start-failure-is-fatal cluster property is set to false."), |
930 | | }, |
931 | | { |
932 | | PCMK_META_FAILURE_TIMEOUT, NULL, PCMK_VALUE_DURATION, NULL, |
933 | | "0", NULL, |
934 | | pcmk__opt_none, |
935 | | N_("Number of seconds before acting as if a failure had not occurred"), |
936 | | N_("Number of seconds after a failed action for this resource before " |
937 | | "acting as if the failure had not occurred, and potentially " |
938 | | "allowing the resource back to the node on which it failed. " |
939 | | "A value of 0 indicates that this feature is disabled."), |
940 | | }, |
941 | | { |
942 | | PCMK_META_MULTIPLE_ACTIVE, NULL, PCMK_VALUE_SELECT, |
943 | | PCMK_VALUE_BLOCK ", " PCMK_VALUE_STOP_ONLY ", " |
944 | | PCMK_VALUE_STOP_START ", " PCMK_VALUE_STOP_UNEXPECTED, |
945 | | PCMK_VALUE_STOP_START, NULL, |
946 | | pcmk__opt_none, |
947 | | N_("What to do if the cluster finds the resource active on more than " |
948 | | "one node"), |
949 | | N_("What to do if the cluster finds the resource active on more than " |
950 | | "one node. " |
951 | | "\"block\" means to mark the resource as unmanaged. " |
952 | | "\"stop_only\" means to stop all active instances of this resource " |
953 | | "and leave them stopped. " |
954 | | "\"stop_start\" means to stop all active instances of this " |
955 | | "resource and start the resource in one location only. " |
956 | | "\"stop_unexpected\" means to stop all active instances of this " |
957 | | "resource except where the resource should be active. (This should " |
958 | | "be used only when extra instances are not expected to disrupt " |
959 | | "existing instances, and the resource agent's monitor of an " |
960 | | "existing instance is capable of detecting any problems that could " |
961 | | "be caused. Note that any resources ordered after this one will " |
962 | | "still need to be restarted.)"), |
963 | | }, |
964 | | { |
965 | | PCMK_META_ALLOW_MIGRATE, NULL, PCMK_VALUE_BOOLEAN, NULL, |
966 | | NULL, NULL, |
967 | | pcmk__opt_none, |
968 | | N_("Whether the cluster should try to \"live migrate\" this resource " |
969 | | "when it needs to be moved"), |
970 | | N_("Whether the cluster should try to \"live migrate\" this resource " |
971 | | "when it needs to be moved. " |
972 | | "The default is true for ocf:pacemaker:remote resources, and false " |
973 | | "otherwise."), |
974 | | }, |
975 | | { |
976 | | PCMK_META_ALLOW_UNHEALTHY_NODES, NULL, PCMK_VALUE_BOOLEAN, NULL, |
977 | | PCMK_VALUE_FALSE, NULL, |
978 | | pcmk__opt_none, |
979 | | N_("Whether the resource should be allowed to run on a node even if " |
980 | | "the node's health score would otherwise prevent it"), |
981 | | NULL, |
982 | | }, |
983 | | { |
984 | | PCMK_META_CONTAINER_ATTRIBUTE_TARGET, NULL, PCMK_VALUE_STRING, NULL, |
985 | | NULL, NULL, |
986 | | pcmk__opt_none, |
987 | | N_("Where to check user-defined node attributes"), |
988 | | N_("Whether to check user-defined node attributes on the physical host " |
989 | | "where a container is running or on the local node. This is " |
990 | | "usually set for a bundle resource and inherited by the bundle's " |
991 | | "primitive resource. " |
992 | | "A value of \"host\" means to check user-defined node attributes " |
993 | | "on the underlying physical host. Any other value means to check " |
994 | | "user-defined node attributes on the local node (for a bundled " |
995 | | "primitive resource, this is the bundle node)."), |
996 | | }, |
997 | | { |
998 | | PCMK_META_REMOTE_NODE, NULL, PCMK_VALUE_STRING, NULL, |
999 | | NULL, NULL, |
1000 | | pcmk__opt_none, |
1001 | | N_("Name of the Pacemaker Remote guest node this resource is " |
1002 | | "associated with, if any"), |
1003 | | N_("Name of the Pacemaker Remote guest node this resource is " |
1004 | | "associated with, if any. If specified, this both enables the " |
1005 | | "resource as a guest node and defines the unique name used to " |
1006 | | "identify the guest node. The guest must be configured to run the " |
1007 | | "Pacemaker Remote daemon when it is started. " |
1008 | | "WARNING: This value cannot overlap with any resource or node " |
1009 | | "IDs."), |
1010 | | }, |
1011 | | { |
1012 | | PCMK_META_REMOTE_ADDR, NULL, PCMK_VALUE_STRING, NULL, |
1013 | | NULL, NULL, |
1014 | | pcmk__opt_none, |
1015 | | N_("If remote-node is specified, the IP address or hostname used to " |
1016 | | "connect to the guest via Pacemaker Remote"), |
1017 | | N_("If remote-node is specified, the IP address or hostname used to " |
1018 | | "connect to the guest via Pacemaker Remote. The Pacemaker Remote " |
1019 | | "daemon on the guest must be configured to accept connections on " |
1020 | | "this address. " |
1021 | | "The default is the value of the remote-node meta-attribute."), |
1022 | | }, |
1023 | | { |
1024 | | PCMK_META_REMOTE_PORT, NULL, PCMK_VALUE_PORT, NULL, |
1025 | | "3121", NULL, |
1026 | | pcmk__opt_none, |
1027 | | N_("If remote-node is specified, port on the guest used for its " |
1028 | | "Pacemaker Remote connection"), |
1029 | | N_("If remote-node is specified, the port on the guest used for its " |
1030 | | "Pacemaker Remote connection. The Pacemaker Remote daemon on the " |
1031 | | "guest must be configured to listen on this port."), |
1032 | | }, |
1033 | | { |
1034 | | PCMK_META_REMOTE_CONNECT_TIMEOUT, NULL, PCMK_VALUE_TIMEOUT, NULL, |
1035 | | "60s", NULL, |
1036 | | pcmk__opt_none, |
1037 | | N_("If remote-node is specified, how long before a pending Pacemaker " |
1038 | | "Remote guest connection times out."), |
1039 | | NULL, |
1040 | | }, |
1041 | | { |
1042 | | PCMK_META_REMOTE_ALLOW_MIGRATE, NULL, PCMK_VALUE_BOOLEAN, NULL, |
1043 | | PCMK_VALUE_TRUE, NULL, |
1044 | | pcmk__opt_none, |
1045 | | N_("If remote-node is specified, this acts as the allow-migrate " |
1046 | | "meta-attribute for the implicit remote connection resource " |
1047 | | "(ocf:pacemaker:remote)."), |
1048 | | NULL, |
1049 | | }, |
1050 | | |
1051 | | { NULL, }, |
1052 | | }; |
1053 | | |
1054 | | /* |
1055 | | * Environment variable option handling |
1056 | | */ |
1057 | | |
1058 | | /*! |
1059 | | * \internal |
1060 | | * \brief Get the value of a Pacemaker environment variable option |
1061 | | * |
1062 | | * If an environment variable option is set, with either a \c "PCMK_" or (for |
1063 | | * backward compatibility) \c "HA_" prefix, log and return the value. |
1064 | | * |
1065 | | * \param[in] option Environment variable name (without prefix) |
1066 | | * |
1067 | | * \return Value of environment variable, or \c NULL if not set |
1068 | | */ |
1069 | | const char * |
1070 | | pcmk__env_option(const char *option) |
1071 | 0 | { |
1072 | | // @COMPAT Drop support for "HA_" options eventually |
1073 | 0 | static const char *const prefixes[] = { "PCMK", "HA" }; |
1074 | |
|
1075 | 0 | CRM_CHECK(!pcmk__str_empty(option), return NULL); |
1076 | | |
1077 | 0 | for (int i = 0; i < PCMK__NELEM(prefixes); i++) { |
1078 | 0 | char *env_name = pcmk__assert_asprintf("%s_%s", prefixes[i], option); |
1079 | 0 | const char *value = getenv(env_name); |
1080 | |
|
1081 | 0 | if (value != NULL) { |
1082 | 0 | pcmk__trace("Found %s = %s", env_name, value); |
1083 | 0 | free(env_name); |
1084 | 0 | return value; |
1085 | 0 | } |
1086 | 0 | free(env_name); |
1087 | 0 | } |
1088 | | |
1089 | 0 | pcmk__trace("Nothing found for %s", option); |
1090 | 0 | return NULL; |
1091 | 0 | } |
1092 | | |
1093 | | /*! |
1094 | | * \internal |
1095 | | * \brief Set or unset a Pacemaker environment variable option |
1096 | | * |
1097 | | * Set an environment variable option with a \c "PCMK_" prefix and optionally |
1098 | | * an \c "HA_" prefix for backward compatibility. |
1099 | | * |
1100 | | * \param[in] option Environment variable name (without prefix) |
1101 | | * \param[in] value New value (or NULL to unset) |
1102 | | * \param[in] compat If false and \p value is not \c NULL, set only |
1103 | | * \c "PCMK_<option>"; otherwise, set (or unset) both |
1104 | | * \c "PCMK_<option>" and \c "HA_<option>" |
1105 | | * |
1106 | | * \note \p compat is ignored when \p value is \c NULL. A \c NULL \p value |
1107 | | * means we're unsetting \p option. \c pcmk__get_env_option() checks for |
1108 | | * both prefixes, so we want to clear them both. |
1109 | | */ |
1110 | | void |
1111 | | pcmk__set_env_option(const char *option, const char *value, bool compat) |
1112 | 0 | { |
1113 | | // @COMPAT Drop support for "HA_" options eventually |
1114 | 0 | static const char *const prefixes[] = { "PCMK", "HA" }; |
1115 | |
|
1116 | 0 | CRM_CHECK(!pcmk__str_empty(option), return); |
1117 | | |
1118 | 0 | for (int i = 0; i < PCMK__NELEM(prefixes); i++) { |
1119 | 0 | char *env_name = pcmk__assert_asprintf("%s_%s", prefixes[i], option); |
1120 | 0 | int rc = 0; |
1121 | |
|
1122 | 0 | if (value != NULL) { |
1123 | 0 | pcmk__trace("Setting %s to %s", env_name, value); |
1124 | 0 | rc = setenv(env_name, value, 1); |
1125 | 0 | } else { |
1126 | 0 | pcmk__trace("Unsetting %s", env_name); |
1127 | 0 | rc = unsetenv(env_name); |
1128 | 0 | } |
1129 | | |
1130 | 0 | if (rc < 0) { |
1131 | 0 | int err = errno; |
1132 | |
|
1133 | 0 | pcmk__err("Failed to %sset %s: %s", ((value != NULL)? "" : "un"), |
1134 | 0 | env_name, strerror(err)); |
1135 | 0 | } |
1136 | 0 | free(env_name); |
1137 | |
|
1138 | 0 | if (!compat && (value != NULL)) { |
1139 | | // For set, don't proceed to HA_<option> unless compat is enabled |
1140 | 0 | break; |
1141 | 0 | } |
1142 | 0 | } |
1143 | 0 | } |
1144 | | |
1145 | | /*! |
1146 | | * \internal |
1147 | | * \brief Check whether Pacemaker environment variable option is enabled |
1148 | | * |
1149 | | * Given a Pacemaker environment variable option that can either be boolean |
1150 | | * or a list of daemon names, return true if the option is enabled for a given |
1151 | | * daemon. |
1152 | | * |
1153 | | * \param[in] daemon Daemon name (can be NULL) |
1154 | | * \param[in] option Pacemaker environment variable name |
1155 | | * |
1156 | | * \return true if variable is enabled for daemon, otherwise false |
1157 | | */ |
1158 | | bool |
1159 | | pcmk__env_option_enabled(const char *daemon, const char *option) |
1160 | 0 | { |
1161 | 0 | const char *value = pcmk__env_option(option); |
1162 | 0 | gchar **subsystems = NULL; |
1163 | 0 | bool enabled = false; |
1164 | |
|
1165 | 0 | if (value == NULL) { |
1166 | 0 | return false; |
1167 | 0 | } |
1168 | | |
1169 | 0 | if (pcmk__parse_bool(value, &enabled) == pcmk_rc_ok) { |
1170 | 0 | return enabled; |
1171 | 0 | } |
1172 | | |
1173 | | /* Value did not parse to a boolean, so try to parse it as a daemon list if |
1174 | | * we have a daemon name to look for |
1175 | | */ |
1176 | | |
1177 | 0 | if (daemon == NULL) { |
1178 | 0 | return false; |
1179 | 0 | } |
1180 | | |
1181 | 0 | subsystems = g_strsplit(value, ",", 0); |
1182 | |
|
1183 | 0 | enabled = pcmk__g_strv_contains(subsystems, daemon); |
1184 | |
|
1185 | 0 | g_strfreev(subsystems); |
1186 | 0 | return enabled; |
1187 | 0 | } |
1188 | | |
1189 | | |
1190 | | /* |
1191 | | * Cluster option handling |
1192 | | */ |
1193 | | |
1194 | | /*! |
1195 | | * \internal |
1196 | | * \brief Check whether a string represents a valid interval specification |
1197 | | * |
1198 | | * \param[in] value String to validate |
1199 | | * |
1200 | | * \return \c true if \p value is a valid interval specification, or \c false |
1201 | | * otherwise |
1202 | | */ |
1203 | | bool |
1204 | | pcmk__valid_interval_spec(const char *value) |
1205 | 0 | { |
1206 | 0 | return pcmk_parse_interval_spec(value, NULL) == pcmk_rc_ok; |
1207 | 0 | } |
1208 | | |
1209 | | /*! |
1210 | | * \internal |
1211 | | * \brief Check whether a string represents a valid boolean value |
1212 | | * |
1213 | | * \param[in] value String to validate |
1214 | | * |
1215 | | * \return \c true if \p value is a valid boolean value, or \c false otherwise |
1216 | | */ |
1217 | | bool |
1218 | | pcmk__valid_boolean(const char *value) |
1219 | 0 | { |
1220 | 0 | return pcmk__parse_bool(value, NULL) == pcmk_rc_ok; |
1221 | 0 | } |
1222 | | |
1223 | | /*! |
1224 | | * \internal |
1225 | | * \brief Check whether a string represents a valid integer |
1226 | | * |
1227 | | * Valid values include \c INFINITY, \c -INFINITY, and all 64-bit integers. |
1228 | | * |
1229 | | * \param[in] value String to validate |
1230 | | * |
1231 | | * \return \c true if \p value is a valid integer, or \c false otherwise |
1232 | | */ |
1233 | | bool |
1234 | | pcmk__valid_int(const char *value) |
1235 | 0 | { |
1236 | 0 | return (value != NULL) |
1237 | 0 | && (pcmk_str_is_infinity(value) |
1238 | 0 | || pcmk_str_is_minus_infinity(value) |
1239 | 0 | || (pcmk__scan_ll(value, NULL, 0LL) == pcmk_rc_ok)); |
1240 | 0 | } |
1241 | | |
1242 | | /*! |
1243 | | * \internal |
1244 | | * \brief Check whether a string represents a valid positive integer |
1245 | | * |
1246 | | * Valid values include \c INFINITY and all 64-bit positive integers. |
1247 | | * |
1248 | | * \param[in] value String to validate |
1249 | | * |
1250 | | * \return \c true if \p value is a valid positive integer, or \c false |
1251 | | * otherwise |
1252 | | */ |
1253 | | bool |
1254 | | pcmk__valid_positive_int(const char *value) |
1255 | 0 | { |
1256 | 0 | long long num = 0LL; |
1257 | |
|
1258 | 0 | return pcmk_str_is_infinity(value) |
1259 | 0 | || ((pcmk__scan_ll(value, &num, 0LL) == pcmk_rc_ok) |
1260 | 0 | && (num > 0)); |
1261 | 0 | } |
1262 | | |
1263 | | /*! |
1264 | | * \internal |
1265 | | * \brief Check whether a string represents a valid |
1266 | | * \c PCMK__OPT_NO_QUORUM_POLICY value |
1267 | | * |
1268 | | * \param[in] value String to validate |
1269 | | * |
1270 | | * \return \c true if \p value is a valid \c PCMK__OPT_NO_QUORUM_POLICY value, |
1271 | | * or \c false otherwise |
1272 | | */ |
1273 | | bool |
1274 | | pcmk__valid_no_quorum_policy(const char *value) |
1275 | 0 | { |
1276 | 0 | return pcmk__strcase_any_of(value, |
1277 | 0 | PCMK_VALUE_STOP, PCMK_VALUE_FREEZE, |
1278 | 0 | PCMK_VALUE_IGNORE, PCMK_VALUE_DEMOTE, |
1279 | 0 | PCMK_VALUE_FENCE, PCMK_VALUE_FENCE_LEGACY, |
1280 | 0 | NULL); |
1281 | 0 | } |
1282 | | |
1283 | | /*! |
1284 | | * \internal |
1285 | | * \brief Check whether a string represents a valid percentage |
1286 | | * |
1287 | | * Valid values include long integers, with an optional trailing string |
1288 | | * beginning with '%'. |
1289 | | * |
1290 | | * \param[in] value String to validate |
1291 | | * |
1292 | | * \return \c true if \p value is a valid percentage value, or \c false |
1293 | | * otherwise |
1294 | | */ |
1295 | | bool |
1296 | | pcmk__valid_percentage(const char *value) |
1297 | 0 | { |
1298 | 0 | char *end = NULL; |
1299 | 0 | float number = strtof(value, &end); |
1300 | |
|
1301 | 0 | return ((end == NULL) || (end[0] == '%')) && (number >= 0); |
1302 | 0 | } |
1303 | | |
1304 | | /*! |
1305 | | * \internal |
1306 | | * \brief Check whether a string represents a valid placement strategy |
1307 | | * |
1308 | | * \param[in] value String to validate |
1309 | | * |
1310 | | * \return \c true if \p value is a valid placement strategy, or \c false |
1311 | | * otherwise |
1312 | | */ |
1313 | | bool |
1314 | | pcmk__valid_placement_strategy(const char *value) |
1315 | 0 | { |
1316 | 0 | return pcmk__strcase_any_of(value, |
1317 | 0 | PCMK_VALUE_DEFAULT, PCMK_VALUE_UTILIZATION, |
1318 | 0 | PCMK_VALUE_MINIMAL, PCMK_VALUE_BALANCED, NULL); |
1319 | 0 | } |
1320 | | |
1321 | | /*! |
1322 | | * \internal |
1323 | | * \brief Check a table of configured options for a particular option |
1324 | | * |
1325 | | * \param[in,out] table Name/value pairs for configured options |
1326 | | * \param[in] option Option to look up |
1327 | | * |
1328 | | * \return Option value (from supplied options table or default value) |
1329 | | */ |
1330 | | static const char * |
1331 | | cluster_option_value(GHashTable *table, const pcmk__cluster_option_t *option) |
1332 | 0 | { |
1333 | 0 | const char *value = NULL; |
1334 | |
|
1335 | 0 | pcmk__assert((option != NULL) && (option->name != NULL)); |
1336 | |
|
1337 | 0 | if (table != NULL) { |
1338 | 0 | value = g_hash_table_lookup(table, option->name); |
1339 | |
|
1340 | 0 | if ((value == NULL) && (option->alt_name != NULL)) { |
1341 | 0 | value = g_hash_table_lookup(table, option->alt_name); |
1342 | 0 | if (value != NULL) { |
1343 | 0 | pcmk__config_warn("Support for legacy name '%s' for cluster " |
1344 | 0 | "option '%s' is deprecated and will be " |
1345 | 0 | "removed in a future release", |
1346 | 0 | option->alt_name, option->name); |
1347 | | |
1348 | | // Inserting copy with current name ensures we only warn once |
1349 | 0 | pcmk__insert_dup(table, option->name, value); |
1350 | 0 | } |
1351 | 0 | } |
1352 | |
|
1353 | 0 | if ((value != NULL) && (option->is_valid != NULL) |
1354 | 0 | && !option->is_valid(value)) { |
1355 | |
|
1356 | 0 | pcmk__config_err("Using default value for cluster option '%s' " |
1357 | 0 | "because '%s' is invalid", option->name, value); |
1358 | 0 | value = NULL; |
1359 | 0 | } |
1360 | |
|
1361 | 0 | if (value != NULL) { |
1362 | 0 | return value; |
1363 | 0 | } |
1364 | 0 | } |
1365 | | |
1366 | | // No value found, use default |
1367 | 0 | value = option->default_value; |
1368 | |
|
1369 | 0 | if (value == NULL) { |
1370 | 0 | pcmk__trace("No value or default provided for cluster option '%s'", |
1371 | 0 | option->name); |
1372 | 0 | return NULL; |
1373 | 0 | } |
1374 | | |
1375 | 0 | CRM_CHECK((option->is_valid == NULL) || option->is_valid(value), |
1376 | 0 | pcmk__err("Bug: default value for cluster option '%s' is invalid", |
1377 | 0 | option->name); |
1378 | 0 | return NULL); |
1379 | | |
1380 | 0 | pcmk__trace("Using default value '%s' for cluster option '%s'", value, |
1381 | 0 | option->name); |
1382 | 0 | if (table != NULL) { |
1383 | 0 | pcmk__insert_dup(table, option->name, value); |
1384 | 0 | } |
1385 | 0 | return value; |
1386 | 0 | } |
1387 | | |
1388 | | /*! |
1389 | | * \internal |
1390 | | * \brief Get the value of a cluster option |
1391 | | * |
1392 | | * \param[in,out] options Name/value pairs for configured options |
1393 | | * \param[in] name (Primary) option name to look for |
1394 | | * |
1395 | | * \return Option value |
1396 | | */ |
1397 | | const char * |
1398 | | pcmk__cluster_option(GHashTable *options, const char *name) |
1399 | 0 | { |
1400 | 0 | for (const pcmk__cluster_option_t *option = cluster_options; |
1401 | 0 | option->name != NULL; option++) { |
1402 | |
|
1403 | 0 | if (pcmk__str_eq(name, option->name, pcmk__str_casei)) { |
1404 | 0 | return cluster_option_value(options, option); |
1405 | 0 | } |
1406 | 0 | } |
1407 | 0 | CRM_CHECK(FALSE, pcmk__err("Bug: looking for unknown option '%s'", name)); |
1408 | 0 | return NULL; |
1409 | 0 | } |
1410 | | |
1411 | | /*! |
1412 | | * \internal |
1413 | | * \brief Output cluster option metadata as OCF-like XML |
1414 | | * |
1415 | | * \param[in,out] out Output object |
1416 | | * \param[in] name Fake resource agent name for the option list |
1417 | | * \param[in] desc_short Short description of the option list |
1418 | | * \param[in] desc_long Long description of the option list |
1419 | | * \param[in] filter Group of <tt>enum pcmk__opt_flags</tt>; output an |
1420 | | * option only if its \c flags member has all these |
1421 | | * flags set |
1422 | | * \param[in] all If \c true, output all options; otherwise, exclude |
1423 | | * advanced and deprecated options unless |
1424 | | * \c pcmk__opt_advanced and \c pcmk__opt_deprecated |
1425 | | * flags (respectively) are set in \p filter. This is |
1426 | | * always treated as true for XML output objects. |
1427 | | * |
1428 | | * \return Standard Pacemaker return code |
1429 | | */ |
1430 | | int |
1431 | | pcmk__output_cluster_options(pcmk__output_t *out, const char *name, |
1432 | | const char *desc_short, const char *desc_long, |
1433 | | uint32_t filter, bool all) |
1434 | 0 | { |
1435 | 0 | return out->message(out, "option-list", name, desc_short, desc_long, filter, |
1436 | 0 | cluster_options, all); |
1437 | 0 | } |
1438 | | |
1439 | | /*! |
1440 | | * \internal |
1441 | | * \brief Output primitive resource meta-attributes as OCF-like XML |
1442 | | * |
1443 | | * \param[in,out] out Output object |
1444 | | * \param[in] name Fake resource agent name for the option list |
1445 | | * \param[in] desc_short Short description of the option list |
1446 | | * \param[in] desc_long Long description of the option list |
1447 | | * \param[in] all If \c true, output all options; otherwise, exclude |
1448 | | * advanced and deprecated options. This is always |
1449 | | * treated as true for XML output objects. |
1450 | | * |
1451 | | * \return Standard Pacemaker return code |
1452 | | */ |
1453 | | int |
1454 | | pcmk__output_primitive_meta(pcmk__output_t *out, const char *name, |
1455 | | const char *desc_short, const char *desc_long, |
1456 | | bool all) |
1457 | 0 | { |
1458 | 0 | return out->message(out, "option-list", name, desc_short, desc_long, |
1459 | 0 | pcmk__opt_none, primitive_meta, all); |
1460 | 0 | } |
1461 | | |
1462 | | /*! |
1463 | | * \internal |
1464 | | * \brief Output fence device common parameter metadata as OCF-like XML |
1465 | | * |
1466 | | * These are parameters that are available for all fencing resources, regardless |
1467 | | * of type. They are processed by Pacemaker, rather than by the fence agent or |
1468 | | * the fencing library. |
1469 | | * |
1470 | | * \param[in,out] out Output object |
1471 | | * \param[in] name Fake resource agent name for the option list |
1472 | | * \param[in] desc_short Short description of the option list |
1473 | | * \param[in] desc_long Long description of the option list |
1474 | | * \param[in] all If \c true, output all options; otherwise, exclude |
1475 | | * advanced and deprecated options. This is always |
1476 | | * treated as true for XML output objects. |
1477 | | * |
1478 | | * \return Standard Pacemaker return code |
1479 | | */ |
1480 | | int |
1481 | | pcmk__output_fencing_params(pcmk__output_t *out, const char *name, |
1482 | | const char *desc_short, const char *desc_long, |
1483 | | bool all) |
1484 | 0 | { |
1485 | 0 | return out->message(out, "option-list", name, desc_short, desc_long, |
1486 | 0 | pcmk__opt_none, fencing_params, all); |
1487 | 0 | } |
1488 | | |
1489 | | /*! |
1490 | | * \internal |
1491 | | * \brief Output a list of cluster options for a daemon |
1492 | | * |
1493 | | * \brief[in,out] out Output object |
1494 | | * \brief[in] name Daemon name |
1495 | | * \brief[in] desc_short Short description of the option list |
1496 | | * \brief[in] desc_long Long description of the option list |
1497 | | * \brief[in] filter <tt>enum pcmk__opt_flags</tt> flag corresponding |
1498 | | * to daemon |
1499 | | * |
1500 | | * \return Standard Pacemaker return code |
1501 | | */ |
1502 | | int |
1503 | | pcmk__daemon_metadata(pcmk__output_t *out, const char *name, |
1504 | | const char *desc_short, const char *desc_long, |
1505 | | enum pcmk__opt_flags filter) |
1506 | 0 | { |
1507 | | // @COMPAT Drop this function when we drop daemon metadata |
1508 | 0 | pcmk__output_t *tmp_out = NULL; |
1509 | 0 | xmlNode *top = NULL; |
1510 | 0 | const xmlNode *metadata = NULL; |
1511 | 0 | GString *metadata_s = NULL; |
1512 | |
|
1513 | 0 | int rc = pcmk__output_new(&tmp_out, "xml", "/dev/null", NULL); |
1514 | |
|
1515 | 0 | if (rc != pcmk_rc_ok) { |
1516 | 0 | return rc; |
1517 | 0 | } |
1518 | | |
1519 | 0 | pcmk__output_set_legacy_xml(tmp_out); |
1520 | |
|
1521 | 0 | if (filter == pcmk__opt_fencing) { |
1522 | 0 | pcmk__output_fencing_params(tmp_out, name, desc_short, desc_long, true); |
1523 | 0 | } else { |
1524 | 0 | pcmk__output_cluster_options(tmp_out, name, desc_short, desc_long, |
1525 | 0 | (uint32_t) filter, true); |
1526 | 0 | } |
1527 | |
|
1528 | 0 | tmp_out->finish(tmp_out, CRM_EX_OK, false, (void **) &top); |
1529 | 0 | metadata = pcmk__xe_first_child(top, PCMK_XE_RESOURCE_AGENT, NULL, NULL); |
1530 | |
|
1531 | 0 | metadata_s = g_string_sized_new(16384); |
1532 | 0 | pcmk__xml_string(metadata, pcmk__xml_fmt_pretty|pcmk__xml_fmt_text, |
1533 | 0 | metadata_s, 0); |
1534 | |
|
1535 | 0 | out->output_xml(out, PCMK_XE_METADATA, metadata_s->str); |
1536 | |
|
1537 | 0 | pcmk__output_free(tmp_out); |
1538 | 0 | pcmk__xml_free(top); |
1539 | 0 | g_string_free(metadata_s, TRUE); |
1540 | 0 | return pcmk_rc_ok; |
1541 | 0 | } |
1542 | | |
1543 | | void |
1544 | | pcmk__validate_cluster_options(GHashTable *options) |
1545 | 0 | { |
1546 | 0 | for (const pcmk__cluster_option_t *option = cluster_options; |
1547 | 0 | option->name != NULL; option++) { |
1548 | |
|
1549 | 0 | cluster_option_value(options, option); |
1550 | 0 | } |
1551 | 0 | } |