diff options
Diffstat (limited to 'include/crm/services.h')
-rw-r--r-- | include/crm/services.h | 432 |
1 files changed, 432 insertions, 0 deletions
diff --git a/include/crm/services.h b/include/crm/services.h new file mode 100644 index 0000000..4f0a5f0 --- /dev/null +++ b/include/crm/services.h @@ -0,0 +1,432 @@ +/* + * Copyright 2010-2023 the Pacemaker project contributors + * + * The version control history for this file may have further details. + * + * This source code is licensed under the GNU Lesser General Public License + * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. + */ + +#ifndef PCMK__CRM_SERVICES__H +# define PCMK__CRM_SERVICES__H + + +# include <glib.h> +# include <stdio.h> +# include <stdint.h> +# include <string.h> +# include <stdbool.h> +# include <sys/types.h> + +# include <crm_config.h> // OCF_ROOT_DIR +# include <crm/common/agents.h> +# include <crm/common/results.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * \file + * \brief Services API + * \ingroup core + */ + +/* TODO: Autodetect these two ?*/ +# ifndef SYSTEMCTL +# define SYSTEMCTL "/bin/systemctl" +# endif + +/* This is the string passed in the OCF_EXIT_REASON_PREFIX environment variable. + * The stderr output that occurs after this prefix is encountered is considered + * the exit reason for a completed operation. + */ +#define PCMK_OCF_REASON_PREFIX "ocf-exit-reason:" + +// Agent version to use if agent doesn't specify one +#define PCMK_DEFAULT_AGENT_VERSION "0.1" + +enum lsb_exitcode { + PCMK_LSB_OK = 0, + PCMK_LSB_UNKNOWN_ERROR = 1, + PCMK_LSB_INVALID_PARAM = 2, + PCMK_LSB_UNIMPLEMENT_FEATURE = 3, + PCMK_LSB_INSUFFICIENT_PRIV = 4, + PCMK_LSB_NOT_INSTALLED = 5, + PCMK_LSB_NOT_CONFIGURED = 6, + PCMK_LSB_NOT_RUNNING = 7, +}; + +// LSB uses different return codes for status actions +enum lsb_status_exitcode { + PCMK_LSB_STATUS_OK = 0, + PCMK_LSB_STATUS_VAR_PID = 1, + PCMK_LSB_STATUS_VAR_LOCK = 2, + PCMK_LSB_STATUS_NOT_RUNNING = 3, + PCMK_LSB_STATUS_UNKNOWN = 4, + + /* custom codes should be in the 150-199 range reserved for application use */ + PCMK_LSB_STATUS_NOT_INSTALLED = 150, + PCMK_LSB_STATUS_INSUFFICIENT_PRIV = 151, +}; + +//!@{ +//! \deprecated Do not use + +enum nagios_exitcode { + NAGIOS_STATE_OK = 0, + NAGIOS_STATE_WARNING = 1, + NAGIOS_STATE_CRITICAL = 2, + NAGIOS_STATE_UNKNOWN = 3, + + /* This is a custom Pacemaker value (not a nagios convention), used as an + * intermediate value between the services library and the executor, so the + * executor can map it to the corresponding OCF code. + */ + NAGIOS_INSUFFICIENT_PRIV = 100, + +#if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) + NAGIOS_STATE_DEPENDENT = 4, + NAGIOS_NOT_INSTALLED = 101, +#endif +}; + +//!@} + +enum svc_action_flags { + /* On timeout, only kill pid, do not kill entire pid group */ + SVC_ACTION_LEAVE_GROUP = 0x01, + SVC_ACTION_NON_BLOCKED = 0x02, +}; + +typedef struct svc_action_private_s svc_action_private_t; + +/*! + * \brief Object for executing external actions + * + * \note This object should never be instantiated directly, but instead created + * using one of the constructor functions (resources_action_create() for + * resource agents, services_alert_create() for alert agents, or + * services_action_create_generic() for generic executables). Similarly, + * do not use sizeof() on this struct. + */ +/* + * NOTE: Internally, services__create_resource_action() is preferable to + * resources_action_create(). + */ +typedef struct svc_action_s { + /*! Operation key (<resource>_<action>_<interval>) for resource actions, + * XML ID for alert actions, or NULL for generic actions + */ + char *id; + + //! XML ID of resource being executed for resource actions, otherwise NULL + char *rsc; + + //! Name of action being executed for resource actions, otherwise NULL + char *action; + + //! Action interval for recurring resource actions, otherwise 0 + guint interval_ms; + + //! Resource standard for resource actions, otherwise NULL + char *standard; + + //! Resource provider for resource actions that require it, otherwise NULL + char *provider; + + //! Resource agent name for resource actions, otherwise NULL + char *agent; + + int timeout; //!< Action timeout (in milliseconds) + + /*! A hash table of name/value pairs to use as parameters for resource and + * alert actions, otherwise NULL. These will be used to set environment + * variables for non-fencing resource agents and alert agents, and to send + * stdin to fence agents. + */ + GHashTable *params; + + int rc; //!< Exit status of action (set by library upon completion) + + //!@{ + //! This field should be treated as internal to Pacemaker + int pid; // Process ID of child + int cancel; // Whether this is a cancellation of a recurring action + //!@} + + int status; //!< Execution status (enum pcmk_exec_status set by library) + + /*! Action counter (set by library for resource actions, or by caller + * otherwise) + */ + int sequence; + + //!@{ + //! This field should be treated as internal to Pacemaker + int expected_rc; // Unused + int synchronous; // Whether execution should be synchronous (blocking) + //!@} + + enum svc_action_flags flags; //!< Flag group of enum svc_action_flags + char *stderr_data; //!< Action stderr (set by library) + char *stdout_data; //!< Action stdout (set by library) + void *cb_data; //!< For caller's use (not used by library) + + //! This field should be treated as internal to Pacemaker + svc_action_private_t *opaque; +} svc_action_t; + +/*! + * \brief Get a list of files or directories in a given path + * + * \param[in] root Full path to a directory to read + * \param[in] files Return list of files if TRUE or directories if FALSE + * \param[in] executable If TRUE and files is TRUE, only return executable files + * + * \return List of what was found as char * items. + * \note The caller is responsibile for freeing the result with + * g_list_free_full(list, free). + */ +GList *get_directory_list(const char *root, gboolean files, + gboolean executable); + +/*! + * \brief Get a list of providers + * + * \param[in] standard List providers of this resource agent standard + * + * \return List of providers as char * list items (or NULL if standard does not + * support providers) + * \note The caller is responsible for freeing the result using + * g_list_free_full(list, free). + */ +GList *resources_list_providers(const char *standard); + +/*! + * \brief Get a list of resource agents + * + * \param[in] standard List agents of this standard (or NULL for all) + * \param[in] provider List agents of this provider (or NULL for all) + * + * \return List of resource agents as char * items. + * \note The caller is responsible for freeing the result using + * g_list_free_full(list, free). + */ +GList *resources_list_agents(const char *standard, const char *provider); + +/*! + * Get list of available standards + * + * \return List of resource standards as char * items. + * \note The caller is responsible for freeing the result using + * g_list_free_full(list, free). + */ +GList *resources_list_standards(void); + +/*! + * \brief Check whether a resource agent exists on the local host + * + * \param[in] standard Resource agent standard of agent to check + * \param[in] provider Provider of agent to check (or NULL) + * \param[in] agent Name of agent to check + * + * \return TRUE if agent exists locally, otherwise FALSE + */ +gboolean resources_agent_exists(const char *standard, const char *provider, + const char *agent); + +/*! + * \brief Create a new resource action + * + * \param[in] name Name of resource that action is for + * \param[in] standard Resource agent standard + * \param[in] provider Resource agent provider + * \param[in] agent Resource agent name + * \param[in] action Name of action to create + * \param[in] interval_ms How often to repeat action (if 0, execute once) + * \param[in] timeout Error if not complete within this time (ms) + * \param[in,out] params Action parameters + * \param[in] flags Group of enum svc_action_flags + * + * \return Newly allocated action + * \note This function assumes ownership of (and may free) \p params. + * \note The caller is responsible for freeing the return value using + * services_action_free(). + */ +svc_action_t *resources_action_create(const char *name, const char *standard, + const char *provider, const char *agent, + const char *action, guint interval_ms, + int timeout, GHashTable *params, + enum svc_action_flags flags); + +/*! + * \brief Reschedule a recurring action for immediate execution + * + * \param[in] name Name of resource that action is for + * \param[in] action Action's name + * \param[in] interval_ms Action's interval (in milliseconds) + * + * \return TRUE on success, otherwise FALSE + */ +gboolean services_action_kick(const char *name, const char *action, + guint interval_ms); + +const char *resources_find_service_class(const char *agent); + +/*! + * \brief Request execution of an arbitrary command + * + * This API has useful infrastructure in place to be able to run a command + * in the background and get notified via a callback when the command finishes. + * + * \param[in] exec Full path to command executable + * \param[in] args NULL-terminated list of arguments to pass to command + * + * \return Newly allocated action object + */ +svc_action_t *services_action_create_generic(const char *exec, + const char *args[]); + +void services_action_cleanup(svc_action_t *op); +void services_action_free(svc_action_t *op); +int services_action_user(svc_action_t *op, const char *user); +gboolean services_action_sync(svc_action_t *op); + +/*! + * \brief Run an action asynchronously, with callback after process is forked + * + * \param[in,out] op Action to run + * \param[in] action_callback Function to call when action completes + * (if NULL, any previously set callback will + * continue to be used) + * \param[in] action_fork_callback Function to call after child process is + * forked for action (if NULL, any + * previously set callback will continue to + * be used) + * + * \retval TRUE if the caller should not free or otherwise use \p op again, + * because one of these conditions is true: + * + * * \p op is NULL. + * * The action was successfully initiated, in which case + * \p action_fork_callback has been called, but \p action_callback has + * not (it will be called when the action completes). + * * The action's ID matched an existing recurring action. The existing + * action has taken over the callback and callback data from \p op + * and has been re-initiated asynchronously, and \p op has been freed. + * * Another action for the same resource is in flight, and \p op will + * be blocked until it completes. + * * The action could not be initiated, and is either non-recurring or + * being cancelled. \p action_fork_callback has not been called, but + * \p action_callback has, and \p op has been freed. + * + * \retval FALSE if \op is still valid, because the action cannot be initiated, + * and is a recurring action that is not being cancelled. + * \p action_fork_callback has not been called, but \p action_callback + * has, and a timer has been set for the next invocation of \p op. + */ +gboolean services_action_async_fork_notify(svc_action_t *op, + void (*action_callback) (svc_action_t *), + void (*action_fork_callback) (svc_action_t *)); + +/*! + * \brief Request asynchronous execution of an action + * + * \param[in,out] op Action to execute + * \param[in] action_callback Function to call when the action completes + * (if NULL, any previously set callback will + * continue to be used) + * + * \retval TRUE if the caller should not free or otherwise use \p op again, + * because one of these conditions is true: + * + * * \p op is NULL. + * * The action was successfully initiated, in which case + * \p action_callback has not been called (it will be called when the + * action completes). + * * The action's ID matched an existing recurring action. The existing + * action has taken over the callback and callback data from \p op + * and has been re-initiated asynchronously, and \p op has been freed. + * * Another action for the same resource is in flight, and \p op will + * be blocked until it completes. + * * The action could not be initiated, and is either non-recurring or + * being cancelled. \p action_callback has been called, and \p op has + * been freed. + * + * \retval FALSE if \op is still valid, because the action cannot be initiated, + * and is a recurring action that is not being cancelled. + * \p action_callback has been called, and a timer has been set for the + * next invocation of \p op. + */ +gboolean services_action_async(svc_action_t *op, + void (*action_callback) (svc_action_t *)); + +gboolean services_action_cancel(const char *name, const char *action, + guint interval_ms); + +/* functions for alert agents */ +svc_action_t *services_alert_create(const char *id, const char *exec, + int timeout, GHashTable *params, + int sequence, void *cb_data); +gboolean services_alert_async(svc_action_t *action, + void (*cb)(svc_action_t *op)); + +enum ocf_exitcode services_result2ocf(const char *standard, const char *action, + int exit_status); + + static inline const char *services_ocf_exitcode_str(enum ocf_exitcode code) { + switch (code) { + case PCMK_OCF_OK: + return "ok"; + case PCMK_OCF_UNKNOWN_ERROR: + return "error"; + case PCMK_OCF_INVALID_PARAM: + return "invalid parameter"; + case PCMK_OCF_UNIMPLEMENT_FEATURE: + return "unimplemented feature"; + case PCMK_OCF_INSUFFICIENT_PRIV: + return "insufficient privileges"; + case PCMK_OCF_NOT_INSTALLED: + return "not installed"; + case PCMK_OCF_NOT_CONFIGURED: + return "not configured"; + case PCMK_OCF_NOT_RUNNING: + return "not running"; + case PCMK_OCF_RUNNING_PROMOTED: + return "promoted"; + case PCMK_OCF_FAILED_PROMOTED: + return "promoted (failed)"; + case PCMK_OCF_DEGRADED: + return "OCF_DEGRADED"; + case PCMK_OCF_DEGRADED_PROMOTED: + return "promoted (degraded)"; + +#if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) + case PCMK_OCF_NOT_SUPPORTED: + return "not supported (DEPRECATED STATUS)"; + case PCMK_OCF_CANCELLED: + return "cancelled (DEPRECATED STATUS)"; + case PCMK_OCF_OTHER_ERROR: + return "other error (DEPRECATED STATUS)"; + case PCMK_OCF_SIGNAL: + return "interrupted by signal (DEPRECATED STATUS)"; + case PCMK_OCF_PENDING: + return "pending (DEPRECATED STATUS)"; + case PCMK_OCF_TIMEOUT: + return "timeout (DEPRECATED STATUS)"; +#endif + default: + return "unknown"; + } + } + +#if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) +#include <crm/services_compat.h> +#endif + +# ifdef __cplusplus +} +# endif + +#endif /* __PCMK_SERVICES__ */ |