LCOV - code coverage report
Current view: top level - common - options.c (source / functions) Hit Total Coverage
Test: Pacemaker code coverage Lines: 37 134 27.6 %
Date: 2024-05-07 11:09:47 Functions: 3 18 16.7 %

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

Generated by: LCOV version 1.14