summaryrefslogtreecommitdiffstats
path: root/daemons/fenced/pacemaker-fenced.h
diff options
context:
space:
mode:
Diffstat (limited to 'daemons/fenced/pacemaker-fenced.h')
-rw-r--r--daemons/fenced/pacemaker-fenced.h315
1 files changed, 315 insertions, 0 deletions
diff --git a/daemons/fenced/pacemaker-fenced.h b/daemons/fenced/pacemaker-fenced.h
new file mode 100644
index 0000000..a3d2e17
--- /dev/null
+++ b/daemons/fenced/pacemaker-fenced.h
@@ -0,0 +1,315 @@
+/*
+ * Copyright 2009-2023 the Pacemaker project contributors
+ *
+ * This source code is licensed under the GNU General Public License version 2
+ * or later (GPLv2+) WITHOUT ANY WARRANTY.
+ */
+
+#include <stdint.h> // uint32_t, uint64_t
+#include <crm/common/mainloop.h>
+
+/*!
+ * \internal
+ * \brief Check whether target has already been fenced recently
+ *
+ * \param[in] tolerance Number of seconds to look back in time
+ * \param[in] target Name of node to search for
+ * \param[in] action Action we want to match
+ *
+ * \return TRUE if an equivalent fencing operation took place in the last
+ * \p tolerance seconds, FALSE otherwise
+ */
+gboolean stonith_check_fence_tolerance(int tolerance, const char *target, const char *action);
+
+typedef struct stonith_device_s {
+ char *id;
+ char *agent;
+ char *namespace;
+
+ /*! list of actions that must execute on the target node. Used for unfencing */
+ GString *on_target_actions;
+ GList *targets;
+ time_t targets_age;
+ gboolean has_attr_map;
+
+ // Whether target's nodeid should be passed as a parameter to the agent
+ gboolean include_nodeid;
+
+ /* whether the cluster should automatically unfence nodes with the device */
+ gboolean automatic_unfencing;
+ guint priority;
+
+ uint32_t flags; // Group of enum st_device_flags
+
+ GHashTable *params;
+ GHashTable *aliases;
+ GList *pending_ops;
+ mainloop_timer_t *timer;
+ crm_trigger_t *work;
+ xmlNode *agent_metadata;
+
+ /*! A verified device is one that has contacted the
+ * agent successfully to perform a monitor operation */
+ gboolean verified;
+
+ gboolean cib_registered;
+ gboolean api_registered;
+ gboolean dirty;
+} stonith_device_t;
+
+/* These values are used to index certain arrays by "phase". Usually an
+ * operation has only one "phase", so phase is always zero. However, some
+ * reboots are remapped to "off" then "on", in which case "reboot" will be
+ * phase 0, "off" will be phase 1 and "on" will be phase 2.
+ */
+enum st_remap_phase {
+ st_phase_requested = 0,
+ st_phase_off = 1,
+ st_phase_on = 2,
+ st_phase_max = 3
+};
+
+typedef struct remote_fencing_op_s {
+ /* The unique id associated with this operation */
+ char *id;
+ /*! The node this operation will fence */
+ char *target;
+ /*! The fencing action to perform on the target. (reboot, on, off) */
+ char *action;
+
+ /*! When was the fencing action recorded (seconds since epoch) */
+ time_t created;
+
+ /*! Marks if the final notifications have been sent to local stonith clients. */
+ gboolean notify_sent;
+ /*! The number of query replies received */
+ guint replies;
+ /*! The number of query replies expected */
+ guint replies_expected;
+ /*! Does this node own control of this operation */
+ gboolean owner;
+ /*! After query is complete, This the high level timer that expires the entire operation */
+ guint op_timer_total;
+ /*! This timer expires the current fencing request. Many fencing
+ * requests may exist in a single operation */
+ guint op_timer_one;
+ /*! This timer expires the query request sent out to determine
+ * what nodes are contain what devices, and who those devices can fence */
+ guint query_timer;
+ /*! This is the default timeout to use for each fencing device if no
+ * custom timeout is received in the query. */
+ gint base_timeout;
+ /*! This is the calculated total timeout an operation can take before
+ * expiring. This is calculated by adding together all the timeout
+ * values associated with the devices this fencing operation may call */
+ gint total_timeout;
+
+ /*! Requested fencing delay.
+ * Value -1 means disable any static/random fencing delays. */
+ int delay;
+
+ /*! Delegate is the node being asked to perform a fencing action
+ * on behalf of the node that owns the remote operation. Some operations
+ * will involve multiple delegates. This value represents the final delegate
+ * that is used. */
+ char *delegate;
+ /*! The point at which the remote operation completed */
+ time_t completed;
+ //! Group of enum stonith_call_options associated with this operation
+ uint32_t call_options;
+
+ /*! The current state of the remote operation. This indicates
+ * what stage the op is in, query, exec, done, duplicate, failed. */
+ enum op_state state;
+ /*! The node that owns the remote operation */
+ char *originator;
+ /*! The local client id that initiated the fencing request */
+ char *client_id;
+ /*! The client's call_id that initiated the fencing request */
+ int client_callid;
+ /*! The name of client that initiated the fencing request */
+ char *client_name;
+ /*! List of the received query results for all the nodes in the cpg group */
+ GList *query_results;
+ /*! The original request that initiated the remote stonith operation */
+ xmlNode *request;
+
+ /*! The current topology level being executed */
+ guint level;
+ /*! The current operation phase being executed */
+ enum st_remap_phase phase;
+
+ /*! Devices with automatic unfencing (always run if "on" requested, never if remapped) */
+ GList *automatic_list;
+ /*! List of all devices at the currently executing topology level */
+ GList *devices_list;
+ /*! Current entry in the topology device list */
+ GList *devices;
+
+ /*! List of duplicate operations attached to this operation. Once this operation
+ * completes, the duplicate operations will be closed out as well. */
+ GList *duplicates;
+
+ /*! The point at which the remote operation completed(nsec) */
+ long long completed_nsec;
+
+ /*! The (potentially intermediate) result of the operation */
+ pcmk__action_result_t result;
+} remote_fencing_op_t;
+
+void fenced_broadcast_op_result(const remote_fencing_op_t *op, bool op_merged);
+
+// Fencer-specific client flags
+enum st_client_flags {
+ st_callback_unknown = UINT64_C(0),
+ st_callback_notify_fence = (UINT64_C(1) << 0),
+ st_callback_device_add = (UINT64_C(1) << 2),
+ st_callback_device_del = (UINT64_C(1) << 4),
+ st_callback_notify_history = (UINT64_C(1) << 5),
+ st_callback_notify_history_synced = (UINT64_C(1) << 6)
+};
+
+// How the user specified the target of a topology level
+enum fenced_target_by {
+ fenced_target_by_unknown = -1, // Invalid or not yet parsed
+ fenced_target_by_name, // By target name
+ fenced_target_by_pattern, // By a pattern matching target names
+ fenced_target_by_attribute, // By a node attribute/value on target
+};
+
+/*
+ * Complex fencing requirements are specified via fencing topologies.
+ * A topology consists of levels; each level is a list of fencing devices.
+ * Topologies are stored in a hash table by node name. When a node needs to be
+ * fenced, if it has an entry in the topology table, the levels are tried
+ * sequentially, and the devices in each level are tried sequentially.
+ * Fencing is considered successful as soon as any level succeeds;
+ * a level is considered successful if all its devices succeed.
+ * Essentially, all devices at a given level are "and-ed" and the
+ * levels are "or-ed".
+ *
+ * This structure is used for the topology table entries.
+ * Topology levels start from 1, so levels[0] is unused and always NULL.
+ */
+typedef struct stonith_topology_s {
+ enum fenced_target_by kind; // How target was specified
+
+ /*! Node name regex or attribute name=value for which topology applies */
+ char *target;
+ char *target_value;
+ char *target_pattern;
+ char *target_attribute;
+
+ /*! Names of fencing devices at each topology level */
+ GList *levels[ST_LEVEL_MAX];
+
+} stonith_topology_t;
+
+void init_device_list(void);
+void free_device_list(void);
+void init_topology_list(void);
+void free_topology_list(void);
+void free_stonith_remote_op_list(void);
+void init_stonith_remote_op_hash_table(GHashTable **table);
+void free_metadata_cache(void);
+void fenced_unregister_handlers(void);
+
+uint64_t get_stonith_flag(const char *name);
+
+void stonith_command(pcmk__client_t *client, uint32_t id, uint32_t flags,
+ xmlNode *op_request, const char *remote_peer);
+
+int stonith_device_register(xmlNode *msg, gboolean from_cib);
+
+void stonith_device_remove(const char *id, bool from_cib);
+
+char *stonith_level_key(const xmlNode *msg, enum fenced_target_by);
+void fenced_register_level(xmlNode *msg, char **desc,
+ pcmk__action_result_t *result);
+void fenced_unregister_level(xmlNode *msg, char **desc,
+ pcmk__action_result_t *result);
+
+stonith_topology_t *find_topology_for_host(const char *host);
+
+void do_local_reply(xmlNode *notify_src, pcmk__client_t *client,
+ int call_options);
+
+xmlNode *fenced_construct_reply(const xmlNode *request, xmlNode *data,
+ const pcmk__action_result_t *result);
+
+void
+ do_stonith_async_timeout_update(const char *client, const char *call_id, int timeout);
+
+void fenced_send_notification(const char *type,
+ const pcmk__action_result_t *result,
+ xmlNode *data);
+void fenced_send_device_notification(const char *op,
+ const pcmk__action_result_t *result,
+ const char *desc);
+void fenced_send_level_notification(const char *op,
+ const pcmk__action_result_t *result,
+ const char *desc);
+
+remote_fencing_op_t *initiate_remote_stonith_op(const pcmk__client_t *client,
+ xmlNode *request,
+ gboolean manual_ack);
+
+void fenced_process_fencing_reply(xmlNode *msg);
+
+int process_remote_stonith_query(xmlNode * msg);
+
+void *create_remote_stonith_op(const char *client, xmlNode * request, gboolean peer);
+
+void stonith_fence_history(xmlNode *msg, xmlNode **output,
+ const char *remote_peer, int options);
+
+void stonith_fence_history_trim(void);
+
+bool fencing_peer_active(crm_node_t *peer);
+
+void set_fencing_completed(remote_fencing_op_t * op);
+
+int fenced_handle_manual_confirmation(const pcmk__client_t *client,
+ xmlNode *msg);
+void fencer_metadata(void);
+
+const char *fenced_device_reboot_action(const char *device_id);
+bool fenced_device_supports_on(const char *device_id);
+
+gboolean node_has_attr(const char *node, const char *name, const char *value);
+
+gboolean node_does_watchdog_fencing(const char *node);
+
+static inline void
+fenced_set_protocol_error(pcmk__action_result_t *result)
+{
+ pcmk__set_result(result, CRM_EX_PROTOCOL, PCMK_EXEC_INVALID,
+ "Fencer API request missing required information (bug?)");
+}
+
+/*!
+ * \internal
+ * \brief Get the device flag to use with a given action when searching devices
+ *
+ * \param[in] action Action to check
+ *
+ * \return st_device_supports_on if \p action is "on", otherwise
+ * st_device_supports_none
+ */
+static inline uint32_t
+fenced_support_flag(const char *action)
+{
+ if (pcmk__str_eq(action, "on", pcmk__str_none)) {
+ return st_device_supports_on;
+ }
+ return st_device_supports_none;
+}
+
+extern char *stonith_our_uname;
+extern gboolean stand_alone;
+extern GHashTable *device_list;
+extern GHashTable *topology;
+extern long stonith_watchdog_timeout_ms;
+extern GList *stonith_watchdog_targets;
+
+extern GHashTable *stonith_remote_op_list;