Page MenuHomeClusterLabs Projects

No OneTemporary

diff --git a/include/crm/Makefile.am b/include/crm/Makefile.am
index ec2752f433..47fd80966a 100644
--- a/include/crm/Makefile.am
+++ b/include/crm/Makefile.am
@@ -1,34 +1,32 @@
#
# Copyright 2004-2024 the Pacemaker project contributors
#
# The version control history for this file may have further details.
#
# This source code is licensed under the GNU General Public License version 2
# or later (GPLv2+) WITHOUT ANY WARRANTY.
#
MAINTAINERCLEANFILES = Makefile.in
headerdir=$(pkgincludedir)/crm
header_HEADERS = cib.h \
cib_compat.h \
cluster.h \
crm.h \
crm_compat.h \
lrmd.h \
- lrmd_compat.h \
lrmd_events.h \
msg_xml.h \
msg_xml_compat.h \
services.h \
- services_compat.h \
stonith-ng.h
noinst_HEADERS = $(wildcard *_internal.h)
SUBDIRS = common \
pengine \
cib \
fencing \
cluster
diff --git a/include/crm/lrmd.h b/include/crm/lrmd.h
index 9b3f698635..3d9b9c052a 100644
--- a/include/crm/lrmd.h
+++ b/include/crm/lrmd.h
@@ -1,525 +1,521 @@
/*
* Copyright 2012-2024 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_LRMD__H
# define PCMK__CRM_LRMD__H
#include <stdbool.h> // bool
#include <glib.h> // guint, GList
#include <crm_config.h>
#include <crm/lrmd_events.h>
#include <crm/services.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* \file
* \brief Resource agent executor
* \ingroup lrmd
*/
typedef struct lrmd_s lrmd_t;
typedef struct lrmd_key_value_s {
char *key;
char *value;
struct lrmd_key_value_s *next;
} lrmd_key_value_t;
/* The major version should be bumped every time there is an incompatible
* change that prevents older clients from connecting to this version of
* the server. The minor version indicates feature support.
*
* Protocol Pacemaker Significant changes
* -------- --------- -------------------
* 1.2 2.1.8 PCMK__CIB_REQUEST_SCHEMAS
*/
#define LRMD_PROTOCOL_VERSION "1.2"
#define LRMD_SUPPORTS_SCHEMA_XFER(x) (compare_version((x), "1.2") >= 0)
/* The major protocol version the client and server both need to support for
* the connection to be successful. This should only ever be the major
* version - not a complete version number.
*/
#define LRMD_COMPATIBLE_PROTOCOL "1"
/* \deprecated Do not use (will be removed in a future release)
*
* This is the version that the client version will actually be compared
* against. This should be identical to LRMD_PROTOCOL_VERSION. However, we
* accidentally bumped LRMD_PROTOCOL_VERSION in 6424a647 (1.1.15) when we didn't
* need to, so for now it's different. If we ever have a truly incompatible
* bump, we can drop this and compare against LRMD_PROTOCOL_VERSION.
*/
#define LRMD_MIN_PROTOCOL_VERSION "1.0"
/* *INDENT-OFF* */
#define DEFAULT_REMOTE_KEY_LOCATION PACEMAKER_CONFIG_DIR "/authkey"
#define ALT_REMOTE_KEY_LOCATION "/etc/corosync/authkey"
#define DEFAULT_REMOTE_PORT 3121
#define DEFAULT_REMOTE_USERNAME "lrmd"
#define LRMD_OP_RSC_REG "lrmd_rsc_register"
#define LRMD_OP_RSC_EXEC "lrmd_rsc_exec"
#define LRMD_OP_RSC_CANCEL "lrmd_rsc_cancel"
#define LRMD_OP_RSC_UNREG "lrmd_rsc_unregister"
#define LRMD_OP_RSC_INFO "lrmd_rsc_info"
#define LRMD_OP_RSC_METADATA "lrmd_rsc_metadata"
#define LRMD_OP_POKE "lrmd_rsc_poke"
#define LRMD_OP_NEW_CLIENT "lrmd_rsc_new_client"
#define LRMD_OP_CHECK "lrmd_check"
#define LRMD_OP_ALERT_EXEC "lrmd_alert_exec"
#define LRMD_OP_GET_RECURRING "lrmd_get_recurring"
#define LRMD_IPC_OP_NEW "new"
#define LRMD_IPC_OP_DESTROY "destroy"
#define LRMD_IPC_OP_EVENT "event"
#define LRMD_IPC_OP_REQUEST "request"
#define LRMD_IPC_OP_RESPONSE "response"
#define LRMD_IPC_OP_SHUTDOWN_REQ "shutdown_req"
#define LRMD_IPC_OP_SHUTDOWN_ACK "shutdown_ack"
#define LRMD_IPC_OP_SHUTDOWN_NACK "shutdown_nack"
/* *INDENT-ON* */
/*!
* \brief Create a new connection to the local executor
*/
lrmd_t *lrmd_api_new(void);
/*!
* \brief Create a new TLS connection to a remote executor
*
* \param[in] nodename Name of remote node identified with this connection
* \param[in] server Hostname to connect to
* \param[in] port Port number to connect to (or 0 to use default)
*
* \return Newly created executor connection object
* \note If only one of \p nodename and \p server is non-NULL, it will be used
* for both purposes. If both are NULL, a local IPC connection will be
* created instead.
*/
lrmd_t *lrmd_remote_api_new(const char *nodename, const char *server, int port);
/*!
* \brief Use after lrmd_poll returns 1 to read and dispatch a message
*
* \param[in,out] lrmd Executor connection object
*
* \return TRUE if connection is still up, FALSE if disconnected
*/
bool lrmd_dispatch(lrmd_t *lrmd);
/*!
* \brief Check whether a message is available on an executor connection
*
* \param[in,out] lrmd Executor connection object to check
* \param[in] timeout Currently ignored
*
* \retval 1 Message is ready
* \retval 0 Timeout occurred
* \retval negative errno Error occurred
*
* \note This is intended for callers that do not use a main loop.
*/
int lrmd_poll(lrmd_t *lrmd, int timeout);
/*!
* \brief Destroy executor connection object
*
* \param[in,out] lrmd Executor connection object to destroy
*/
void lrmd_api_delete(lrmd_t *lrmd);
lrmd_key_value_t *lrmd_key_value_add(lrmd_key_value_t * kvp, const char *key, const char *value);
enum lrmd_call_options {
lrmd_opt_none = 0,
//! Notify only the client that made the request (rather than all clients)
lrmd_opt_notify_orig_only = (1 << 1),
/*!
* Drop recurring operations initiated by a client when the client
* disconnects. This option is only valid when registering a resource. When
* used with a connection to a remote executor, recurring operations will be
* dropped once all remote connections disconnect.
*
* @COMPAT This is broken, because these values should be unique bits, and
* this value overlaps lrmd_opt_notify_orig_only (0x02). The impact is low
* since this value is used only with registration requests and the other
* one is used only with execution requests. Regardless, when we can break
* API compatibility, this should be changed to (1 << 0) or (1 << 3).
*/
lrmd_opt_drop_recurring = 0x00000003,
//! Send notifications for recurring operations only when the result changes
lrmd_opt_notify_changes_only = (1 << 2),
};
typedef struct lrmd_rsc_info_s {
char *id;
char *type;
char *standard;
char *provider;
} lrmd_rsc_info_t;
typedef struct lrmd_op_info_s {
char *rsc_id;
char *action;
char *interval_ms_s;
char *timeout_ms_s;
} lrmd_op_info_t;
lrmd_rsc_info_t *lrmd_new_rsc_info(const char *rsc_id, const char *standard,
const char *provider, const char *type);
lrmd_rsc_info_t *lrmd_copy_rsc_info(lrmd_rsc_info_t * rsc_info);
void lrmd_free_rsc_info(lrmd_rsc_info_t * rsc_info);
void lrmd_free_op_info(lrmd_op_info_t *op_info);
typedef void (*lrmd_event_callback) (lrmd_event_data_t * event);
typedef struct lrmd_list_s {
const char *val;
struct lrmd_list_s *next;
} lrmd_list_t;
void lrmd_list_freeall(lrmd_list_t * head);
void lrmd_key_value_freeall(lrmd_key_value_t * head);
typedef struct lrmd_api_operations_s {
/*!
* \brief Connect to an executor
*
* \param[in,out] lrmd Executor connection object
* \param[in] client_name Arbitrary identifier to pass to server
* \param[out] fd If not NULL, where to store file descriptor
* for connection's socket
*
* \return Legacy Pacemaker return code
*/
int (*connect) (lrmd_t *lrmd, const char *client_name, int *fd);
/*!
* \brief Initiate an executor connection without blocking
*
* \param[in,out] lrmd Executor connection object
* \param[in] client_name Arbitrary identifier to pass to server
* \param[in] timeout Error if not connected within this time
* (milliseconds)
*
* \return Legacy Pacemaker return code (if pcmk_ok, the event callback will
* be called later with the result)
* \note This function requires a mainloop.
*/
int (*connect_async) (lrmd_t *lrmd, const char *client_name,
int timeout /*ms */ );
/*!
* \brief Check whether connection to executor daemon is (still) active
*
* \param[in,out] lrmd Executor connection object to check
*
* \return 1 if the executor connection is active, 0 otherwise
*/
int (*is_connected) (lrmd_t *lrmd);
/*!
* \brief Poke executor connection to verify it is still active
*
* \param[in,out] lrmd Executor connection object to check
*
* \return Legacy Pacemaker return code (if pcmk_ok, the event callback will
* be called later with the result)
* \note The response comes in the form of a poke event to the callback.
*
*/
int (*poke_connection) (lrmd_t *lrmd);
/*!
* \brief Disconnect from the executor.
*
* \param[in,out] lrmd Executor connection object to disconnect
*
* \return Legacy Pacemaker return code
*/
int (*disconnect) (lrmd_t *lrmd);
/*!
* \brief Register a resource with the executor
*
* \param[in,out] lrmd Executor connection object
* \param[in] rsc_id ID of resource to register
* \param[in] standard Resource's resource agent standard
* \param[in] provider Resource's resource agent provider (or NULL)
* \param[in] agent Resource's resource agent name
* \param[in] options Group of enum lrmd_call_options flags
*
* \note Synchronous, guaranteed to occur in daemon before function returns.
*
* \return Legacy Pacemaker return code
*/
int (*register_rsc) (lrmd_t *lrmd, const char *rsc_id, const char *standard,
const char *provider, const char *agent,
enum lrmd_call_options options);
/*!
* \brief Retrieve a resource's registration information
*
* \param[in,out] lrmd Executor connection object
* \param[in] rsc_id ID of resource to check
* \param[in] options Group of enum lrmd_call_options flags
*
* \return Resource information on success, otherwise NULL
*/
lrmd_rsc_info_t *(*get_rsc_info) (lrmd_t *lrmd, const char *rsc_id,
enum lrmd_call_options options);
/*!
* \brief Retrieve recurring operations registered for a resource
*
* \param[in,out] lrmd Executor connection object
* \param[in] rsc_id ID of resource to check
* \param[in] timeout_ms Error if not completed within this time
* \param[in] options Group of enum lrmd_call_options flags
* \param[out] output Where to store list of lrmd_op_info_t
*
* \return Legacy Pacemaker return code
*/
int (*get_recurring_ops) (lrmd_t *lrmd, const char *rsc_id, int timeout_ms,
enum lrmd_call_options options, GList **output);
/*!
* \brief Unregister a resource from the executor
*
* \param[in,out] lrmd Executor connection object
* \param[in] rsc_id ID of resource to unregister
* \param[in] options Group of enum lrmd_call_options flags
*
* \return Legacy Pacemaker return code (of particular interest, EINPROGRESS
* means that operations are in progress for the resource, and the
* unregistration will be done when they complete)
* \note Pending and recurring operations will be cancelled.
* \note Synchronous, guaranteed to occur in daemon before function returns.
*
*/
int (*unregister_rsc) (lrmd_t *lrmd, const char *rsc_id,
enum lrmd_call_options options);
/*!
* \brief Set a callback for executor events
*
* \param[in,out] lrmd Executor connection object
* \param[in] callback Callback to set
*/
void (*set_callback) (lrmd_t *lrmd, lrmd_event_callback callback);
/*!
* \brief Request execution of a resource action
*
* \param[in,out] lrmd Executor connection object
* \param[in] rsc_id ID of resource
* \param[in] action Name of resource action to execute
* \param[in] userdata Arbitrary string to pass to event callback
* \param[in] interval_ms If 0, execute action once, otherwise
* recurring at this interval (in milliseconds)
* \param[in] timeout Error if not complete within this time (in
* milliseconds)
* \param[in] start_delay Wait this long before execution (in
* milliseconds)
* \param[in] options Group of enum lrmd_call_options flags
* \param[in,out] params Parameters to pass to agent (will be freed)
*
* \return A call ID for the action on success (in which case the action is
* queued in the executor, and the event callback will be called
* later with the result), otherwise a negative legacy Pacemaker
* return code
* \note exec() and cancel() operations on an individual resource are
* guaranteed to occur in the order the client API is called. However,
* operations on different resources are not guaranteed to occur in
* any specific order.
*/
int (*exec) (lrmd_t *lrmd, const char *rsc_id, const char *action,
const char *userdata, guint interval_ms, int timeout,
int start_delay, enum lrmd_call_options options,
lrmd_key_value_t *params);
/*!
* \brief Cancel a recurring resource action
*
* \param[in,out] lrmd Executor connection object
* \param[in] rsc_id ID of resource
* \param[in] action Name of resource action to cancel
* \param[in] interval_ms Action's interval (in milliseconds)
*
* \return Legacy Pacemaker return code (if pcmk_ok, cancellation is queued
* on function return, and the event callback will be called later
* with an exec_complete event with an lrmd_op_status signifying
* that the operation is cancelled)
*
* \note exec() and cancel() operations on an individual resource are
* guaranteed to occur in the order the client API is called. However,
* operations on different resources are not guaranteed to occur in
* any specific order.
*/
int (*cancel) (lrmd_t *lrmd, const char *rsc_id, const char *action,
guint interval_ms);
/*!
* \brief Retrieve resource agent metadata synchronously
*
* \param[in] lrmd Executor connection (unused)
* \param[in] standard Resource agent class
* \param[in] provider Resource agent provider
* \param[in] agent Resource agent type
* \param[out] output Where to store metadata (must not be NULL)
* \param[in] options Group of enum lrmd_call_options flags (unused)
*
* \return Legacy Pacemaker return code
*
* \note Caller is responsible for freeing output. This call is always
* synchronous (blocking), and always done directly by the library
* (not via the executor connection). This means that it is based on
* the local host environment, even if the executor connection is to a
* remote node, so this may fail if the agent is not installed
* locally. This also means that, if an external agent must be
* executed, it will be executed by the caller's user, not the
* executor's.
*/
int (*get_metadata) (lrmd_t *lrmd, const char *standard,
const char *provider, const char *agent,
char **output, enum lrmd_call_options options);
/*!
* \brief Retrieve a list of installed resource agents
*
* \param[in] lrmd Executor connection (unused)
* \param[out] agents Where to store agent list (must not be NULL)
* \param[in] standard Resource agent standard to list
* \param[in] provider Resource agent provider to list (or NULL)
*
* \return Number of items in list on success, negative legacy Pacemaker
* return code otherwise
*
* \note if standard is not provided, all known agents will be returned
* \note list must be freed using lrmd_list_freeall()
*/
int (*list_agents) (lrmd_t *lrmd, lrmd_list_t **agents,
const char *standard, const char *provider);
/*!
* \brief Retrieve a list of resource agent providers
*
* \param[in] lrmd Executor connection (unused)
* \param[in] agent If not NULL, list providers for this agent only
* \param[out] providers Where to store provider list
*
* \return Number of items in list on success, negative legacy Pacemaker
* return code otherwise
* \note The caller is responsible for freeing *providers with
* lrmd_list_freeall().
*/
int (*list_ocf_providers) (lrmd_t *lrmd, const char *agent,
lrmd_list_t **providers);
/*!
* \brief Retrieve a list of supported standards
*
* \param[in] lrmd Executor connection (unused)
* \param[out] standards Where to store standards list
*
* \return Number of items in list on success, negative legacy Pacemaker
* return code otherwise
* \note The caller is responsible for freeing *standards with
* lrmd_list_freeall().
*/
int (*list_standards) (lrmd_t *lrmd, lrmd_list_t **standards);
/*!
* \brief Execute an alert agent
*
* \param[in,out] lrmd Executor connection
* \param[in] alert_id Name of alert to execute
* \param[in] alert_path Full path to alert executable
* \param[in] timeout Error if not complete within this many
* milliseconds
* \param[in,out] params Parameters to pass to agent (will be freed)
*
* \return Legacy Pacemaker return code (if pcmk_ok, the alert is queued in
* the executor, and the event callback will be called later with
* the result)
*
* \note Operations on individual alerts (by ID) are guaranteed to occur in
* the order the client API is called. Operations on different alerts
* are not guaranteed to occur in any specific order.
*/
int (*exec_alert) (lrmd_t *lrmd, const char *alert_id,
const char *alert_path, int timeout,
lrmd_key_value_t *params);
/*!
* \brief Retrieve resource agent metadata synchronously with parameters
*
* \param[in] lrmd Executor connection (unused)
* \param[in] standard Resource agent class
* \param[in] provider Resource agent provider
* \param[in] agent Resource agent type
* \param[out] output Where to store metadata (must not be NULL)
* \param[in] options Group of enum lrmd_call_options flags (unused)
* \param[in,out] params Parameters to pass to agent (will be freed)
*
* \return Legacy Pacemaker return code
*
* \note This is identical to the get_metadata() API call, except parameters
* will be passed to the resource agent via environment variables.
*/
int (*get_metadata_params) (lrmd_t *lrmd, const char *standard,
const char *provider, const char *agent,
char **output, enum lrmd_call_options options,
lrmd_key_value_t *params);
} lrmd_api_operations_t;
struct lrmd_s {
lrmd_api_operations_t *cmds;
void *lrmd_private;
};
static inline const char *
lrmd_event_type2str(enum lrmd_callback_event type)
{
switch (type) {
case lrmd_event_register:
return "register";
case lrmd_event_unregister:
return "unregister";
case lrmd_event_exec_complete:
return "exec_complete";
case lrmd_event_disconnect:
return "disconnect";
case lrmd_event_connect:
return "connect";
case lrmd_event_poke:
return "poke";
case lrmd_event_new_client:
return "new_client";
}
return "unknown";
}
-#if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1)
-#include <crm/lrmd_compat.h>
-#endif
-
#ifdef __cplusplus
}
#endif
#endif
diff --git a/include/crm/lrmd_compat.h b/include/crm/lrmd_compat.h
deleted file mode 100644
index 98461e0968..0000000000
--- a/include/crm/lrmd_compat.h
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright 2012-2024 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_LRMD_COMPAT__H
-# define PCMK__CRM_LRMD_COMPAT__H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * \file
- * \brief Deprecated executor utilities
- * \ingroup core
- * \deprecated Do not include this header directly. The utilities in this
- * header, and the header itself, will be removed in a future
- * release.
- */
-
-//! \deprecated Do not use
-#define F_LRMD_OPERATION "lrmd_op"
-
-//! \deprecated Do not use
-#define F_LRMD_CLIENTNAME "lrmd_clientname"
-
-//! \deprecated Do not use
-#define F_LRMD_CALLBACK_TOKEN "lrmd_async_id"
-
-//! \deprecated Do not use
-#define F_LRMD_IS_IPC_PROVIDER "lrmd_is_ipc_provider"
-
-//! \deprecated Do not use
-#define F_LRMD_CLIENTID "lrmd_clientid"
-
-//! \deprecated Do not use
-#define F_LRMD_PROTOCOL_VERSION "lrmd_protocol_version"
-
-//! \deprecated Do not use
-#define F_LRMD_REMOTE_MSG_TYPE "lrmd_remote_msg_type"
-
-//! \deprecated Do not use
-#define F_LRMD_REMOTE_MSG_ID "lrmd_remote_msg_id"
-
-//! \deprecated Do not use
-#define F_LRMD_CALLID "lrmd_callid"
-
-//! \deprecated Do not use
-#define F_LRMD_CALLOPTS "lrmd_callopt"
-
-//! \deprecated Do not use
-#define F_LRMD_CALLDATA "lrmd_calldata"
-
-//! \deprecated Do not use
-#define F_LRMD_RC "lrmd_rc"
-
-//! \deprecated Do not use
-#define F_LRMD_EXEC_RC "lrmd_exec_rc"
-
-//! \deprecated Do not use
-#define F_LRMD_OP_STATUS "lrmd_exec_op_status"
-
-//! \deprecated Do not use
-#define F_LRMD_TIMEOUT "lrmd_timeout"
-
-//! \deprecated Do not use
-#define F_LRMD_WATCHDOG "lrmd_watchdog"
-
-//! \deprecated Do not use
-#define F_LRMD_CLASS "lrmd_class"
-
-//! \deprecated Do not use
-#define F_LRMD_PROVIDER "lrmd_provider"
-
-//! \deprecated Do not use
-#define F_LRMD_TYPE "lrmd_type"
-
-//! \deprecated Do not use
-#define F_LRMD_ORIGIN "lrmd_origin"
-
-//! \deprecated Do not use
-#define F_LRMD_RSC_RUN_TIME "lrmd_run_time"
-
-//! \deprecated Do not use
-#define F_LRMD_RSC_RCCHANGE_TIME "lrmd_rcchange_time"
-
-//! \deprecated Do not use
-#define F_LRMD_RSC_EXEC_TIME "lrmd_exec_time"
-
-//! \deprecated Do not use
-#define F_LRMD_RSC_QUEUE_TIME "lrmd_queue_time"
-
-//! \deprecated Do not use
-#define F_LRMD_RSC_ID "lrmd_rsc_id"
-
-//! \deprecated Do not use
-#define F_LRMD_RSC_ACTION "lrmd_rsc_action"
-
-//! \deprecated Do not use
-#define F_LRMD_RSC_USERDATA_STR "lrmd_rsc_userdata_str"
-
-//! \deprecated Do not use
-#define F_LRMD_RSC_OUTPUT "lrmd_rsc_output"
-
-//! \deprecated Do not use
-#define F_LRMD_RSC_EXIT_REASON "lrmd_rsc_exit_reason"
-
-//! \deprecated Do not use
-#define F_LRMD_RSC_START_DELAY "lrmd_rsc_start_delay"
-
-//! \deprecated Do not use
-#define F_LRMD_RSC_INTERVAL "lrmd_rsc_interval"
-
-//! \deprecated Do not use
-#define F_LRMD_RSC_DELETED "lrmd_rsc_deleted"
-
-//! \deprecated Do not use
-#define F_LRMD_RSC "lrmd_rsc"
-
-//! \deprecated Do not use
-#define F_LRMD_ALERT_ID "lrmd_alert_id"
-
-//! \deprecated Do not use
-#define F_LRMD_ALERT_PATH "lrmd_alert_path"
-
-//! \deprecated Do not use
-#define F_LRMD_ALERT "lrmd_alert"
-
-//! \deprecated Do not use
-#define F_LRMD_IPC_OP "lrmd_ipc_op"
-
-//! \deprecated Do not use
-#define F_LRMD_IPC_IPC_SERVER "lrmd_ipc_server"
-
-//! \deprecated Do not use
-#define F_LRMD_IPC_SESSION "lrmd_ipc_session"
-
-//! \deprecated Do not use
-#define F_LRMD_IPC_CLIENT "lrmd_ipc_client"
-
-//! \deprecated Do not use
-#define F_LRMD_IPC_USER "lrmd_ipc_user"
-
-//! \deprecated Do not use
-#define F_LRMD_IPC_MSG "lrmd_ipc_msg"
-
-//! \deprecated Do not use
-#define F_LRMD_IPC_MSG_ID "lrmd_ipc_msg_id"
-
-//! \deprecated Do not use
-#define F_LRMD_IPC_MSG_FLAGS "lrmd_ipc_msg_flags"
-
-//! \deprecated Do not use
-#define T_LRMD "lrmd"
-
-//! \deprecated Do not use
-#define T_LRMD_REPLY "lrmd_reply"
-
-//! \deprecated Do not use
-#define T_LRMD_NOTIFY "lrmd_notify"
-
-//! \deprecated Do not use
-#define T_LRMD_IPC_PROXY "lrmd_ipc_proxy"
-
-//! \deprecated Do not use
-#define T_LRMD_RSC_OP "lrmd_rsc_op"
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // PCMK__CRM_LRMD_COMPAT__H
diff --git a/include/crm/services.h b/include/crm/services.h
index 3e66eb07dd..c14a0c176c 100644
--- a/include/crm/services.h
+++ b/include/crm/services.h
@@ -1,437 +1,433 @@
/*
* Copyright 2010-2024 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
// NOTE: booth (as of at least 1.1) checks for the existence of this header
/*!
* \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,
// NOTE: booth (as of at least 1.1) uses this value
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__ */
diff --git a/include/crm/services_compat.h b/include/crm/services_compat.h
deleted file mode 100644
index 456d35195b..0000000000
--- a/include/crm/services_compat.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * 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_COMPAT__H
-# define PCMK__CRM_SERVICES_COMPAT__H
-
-#include <crm/common/actions.h>
-#include <crm/common/results.h>
-#include <crm/services.h>
-#include <glib.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*!
- * \file
- * \brief Deprecated services API
- * \ingroup core
- * \deprecated Do not include this header directly. The service APIs in this
- * header, and the header itself, will be removed in a future
- * release.
- */
-
-# ifndef LSB_ROOT_DIR
- //! \deprecated Do not use
-# define LSB_ROOT_DIR "/etc/init.d"
-# endif
-
-//! \deprecated Use enum pcmk_exec_status instead
-enum op_status {
- PCMK_LRM_OP_UNKNOWN = PCMK_EXEC_UNKNOWN,
- PCMK_LRM_OP_PENDING = PCMK_EXEC_PENDING,
- PCMK_LRM_OP_DONE = PCMK_EXEC_DONE,
- PCMK_LRM_OP_CANCELLED = PCMK_EXEC_CANCELLED,
- PCMK_LRM_OP_TIMEOUT = PCMK_EXEC_TIMEOUT,
- PCMK_LRM_OP_NOTSUPPORTED = PCMK_EXEC_NOT_SUPPORTED,
- PCMK_LRM_OP_ERROR = PCMK_EXEC_ERROR,
- PCMK_LRM_OP_ERROR_HARD = PCMK_EXEC_ERROR_HARD,
- PCMK_LRM_OP_ERROR_FATAL = PCMK_EXEC_ERROR_FATAL,
- PCMK_LRM_OP_NOT_INSTALLED = PCMK_EXEC_NOT_INSTALLED,
- PCMK_LRM_OP_NOT_CONNECTED = PCMK_EXEC_NOT_CONNECTED,
- PCMK_LRM_OP_INVALID = PCMK_EXEC_INVALID,
-};
-
-//! \deprecated Use resources_action_create() instead
-svc_action_t *services_action_create(const char *name, const char *action,
- guint interval_ms, int timeout);
-
-//! \deprecated Use resources_list_agents() instead
-GList *services_list(void);
-
-//! \deprecated Use pcmk_exec_status_str() instead
-static inline const char *
-services_lrm_status_str(enum op_status status)
-{
- return pcmk_exec_status_str((enum pcmk_exec_status) status);
-}
-
-//! \deprecated Use services_result2ocf() instead
-static inline enum ocf_exitcode
-services_get_ocf_exitcode(const char *action, int lsb_exitcode)
-{
- /* For non-status actions, LSB and OCF share error code meaning <= 7 */
- if ((action != NULL) && (strcmp(action, PCMK_ACTION_STATUS) != 0)
- && (strcmp(action, PCMK_ACTION_MONITOR) != 0)) {
- if ((lsb_exitcode < 0) || (lsb_exitcode > PCMK_LSB_NOT_RUNNING)) {
- return PCMK_OCF_UNKNOWN_ERROR;
- }
- return (enum ocf_exitcode)lsb_exitcode;
- }
-
- /* status has different return codes */
- switch (lsb_exitcode) {
- case PCMK_LSB_STATUS_OK:
- return PCMK_OCF_OK;
- case PCMK_LSB_STATUS_NOT_INSTALLED:
- return PCMK_OCF_NOT_INSTALLED;
- case PCMK_LSB_STATUS_INSUFFICIENT_PRIV:
- return PCMK_OCF_INSUFFICIENT_PRIV;
- case PCMK_LSB_STATUS_VAR_PID:
- case PCMK_LSB_STATUS_VAR_LOCK:
- case PCMK_LSB_STATUS_NOT_RUNNING:
- return PCMK_OCF_NOT_RUNNING;
- }
- return PCMK_OCF_UNKNOWN_ERROR;
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/lib/services/services_lsb.c b/lib/services/services_lsb.c
index 83587f2f7b..a9a2832514 100644
--- a/lib/services/services_lsb.c
+++ b/lib/services/services_lsb.c
@@ -1,345 +1,323 @@
/*
* Copyright 2010-2024 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.
*/
#include <crm_internal.h>
#ifndef _GNU_SOURCE
# define _GNU_SOURCE
#endif
#include <stdio.h>
#include <errno.h>
#include <sys/stat.h>
#include <crm/crm.h>
#include <crm/common/xml.h>
#include <crm/services.h>
#include "services_private.h"
#include "services_lsb.h"
// @TODO Use XML string constants and maybe a real XML object
#define lsb_metadata_template \
"<?xml " PCMK_XA_VERSION "='1.0'?>\n" \
"<" PCMK_XE_RESOURCE_AGENT " " \
PCMK_XA_NAME "='%s' " \
PCMK_XA_VERSION "='" PCMK_DEFAULT_AGENT_VERSION "'>\n" \
" <" PCMK_XE_VERSION ">1.1</" PCMK_XE_VERSION ">\n" \
" <" PCMK_XE_LONGDESC " " PCMK_XA_LANG "='" PCMK__VALUE_EN "'>\n" \
"%s" \
" </" PCMK_XE_LONGDESC ">\n" \
" <" PCMK_XE_SHORTDESC " " PCMK_XA_LANG "='" PCMK__VALUE_EN "'>" \
"%s" \
"</" PCMK_XE_SHORTDESC ">\n" \
" <" PCMK_XE_PARAMETERS "/>\n" \
" <" PCMK_XE_ACTIONS ">\n" \
" <" PCMK_XE_ACTION " " PCMK_XA_NAME "='" PCMK_ACTION_META_DATA "'" \
" " PCMK_META_TIMEOUT "='5s' />\n" \
" <" PCMK_XE_ACTION " " PCMK_XA_NAME "='" PCMK_ACTION_START "'" \
" " PCMK_META_TIMEOUT "='15s' />\n" \
" <" PCMK_XE_ACTION " " PCMK_XA_NAME "='" PCMK_ACTION_STOP "'" \
" " PCMK_META_TIMEOUT "='15s' />\n" \
" <" PCMK_XE_ACTION " " PCMK_XA_NAME "='" PCMK_ACTION_STATUS "'" \
" " PCMK_META_TIMEOUT "='15s' />\n" \
" <" PCMK_XE_ACTION " " PCMK_XA_NAME "='restart'" \
" " PCMK_META_TIMEOUT "='15s' />\n" \
" <" PCMK_XE_ACTION " " PCMK_XA_NAME "='force-reload'" \
" " PCMK_META_TIMEOUT "='15s' />\n" \
" <" PCMK_XE_ACTION " " PCMK_XA_NAME "='" PCMK_ACTION_MONITOR "'" \
" " PCMK_META_TIMEOUT "='15s'" \
" " PCMK_META_INTERVAL "='15s' />\n" \
" </" PCMK_XE_ACTIONS ">\n" \
" <" PCMK_XE_SPECIAL " " PCMK_XA_TAG "='LSB'>\n" \
" <Provides>%s</Provides>\n" \
" <Required-Start>%s</Required-Start>\n" \
" <Required-Stop>%s</Required-Stop>\n" \
" <Should-Start>%s</Should-Start>\n" \
" <Should-Stop>%s</Should-Stop>\n" \
" <Default-Start>%s</Default-Start>\n" \
" <Default-Stop>%s</Default-Stop>\n" \
" </" PCMK_XE_SPECIAL ">\n" \
"</" PCMK_XE_RESOURCE_AGENT ">\n"
/* See "Comment Conventions for Init Scripts" in the LSB core specification at:
* http://refspecs.linuxfoundation.org/lsb.shtml
*/
#define LSB_INITSCRIPT_INFOBEGIN_TAG "### BEGIN INIT INFO"
#define LSB_INITSCRIPT_INFOEND_TAG "### END INIT INFO"
#define PROVIDES "# Provides:"
#define REQUIRED_START "# Required-Start:"
#define REQUIRED_STOP "# Required-Stop:"
#define SHOULD_START "# Should-Start:"
#define SHOULD_STOP "# Should-Stop:"
#define DEFAULT_START "# Default-Start:"
#define DEFAULT_STOP "# Default-Stop:"
#define SHORT_DESC "# Short-Description:"
#define DESCRIPTION "# Description:"
/*!
* \internal
* \brief Grab an LSB header value
*
* \param[in] line Line read from LSB init script
* \param[in,out] value If not set, will be set to XML-safe copy of value
* \param[in] prefix Set value if line starts with this pattern
*
* \return TRUE if value was set, FALSE otherwise
*/
static inline gboolean
lsb_meta_helper_get_value(const char *line, gchar **value, const char *prefix)
{
/* @TODO Perhaps update later to use pcmk__xml_needs_escape(). Involves many
* extra variables in the caller.
*/
if ((*value == NULL) && pcmk__starts_with(line, prefix)) {
*value = pcmk__xml_escape(line + strlen(prefix), pcmk__xml_escape_text);
return TRUE;
}
return FALSE;
}
int
services__get_lsb_metadata(const char *type, char **output)
{
char ra_pathname[PATH_MAX] = { 0, };
FILE *fp = NULL;
char buffer[1024] = { 0, };
gchar *provides = NULL;
gchar *required_start = NULL;
gchar *required_stop = NULL;
gchar *should_start = NULL;
gchar *should_stop = NULL;
gchar *default_start = NULL;
gchar *default_stop = NULL;
gchar *short_desc = NULL;
gchar *long_desc = NULL;
bool in_header = FALSE;
if (type[0] == '/') {
snprintf(ra_pathname, sizeof(ra_pathname), "%s", type);
} else {
snprintf(ra_pathname, sizeof(ra_pathname), "%s/%s",
PCMK__LSB_INIT_DIR, type);
}
crm_trace("Looking into %s", ra_pathname);
fp = fopen(ra_pathname, "r");
if (fp == NULL) {
return -errno;
}
/* Enter into the LSB-compliant comment block */
while (fgets(buffer, sizeof(buffer), fp)) {
// Ignore lines up to and including the block delimiter
if (pcmk__starts_with(buffer, LSB_INITSCRIPT_INFOBEGIN_TAG)) {
in_header = TRUE;
continue;
}
if (!in_header) {
continue;
}
/* Assume each of the following eight arguments contain one line */
if (lsb_meta_helper_get_value(buffer, &provides, PROVIDES)) {
continue;
}
if (lsb_meta_helper_get_value(buffer, &required_start,
REQUIRED_START)) {
continue;
}
if (lsb_meta_helper_get_value(buffer, &required_stop, REQUIRED_STOP)) {
continue;
}
if (lsb_meta_helper_get_value(buffer, &should_start, SHOULD_START)) {
continue;
}
if (lsb_meta_helper_get_value(buffer, &should_stop, SHOULD_STOP)) {
continue;
}
if (lsb_meta_helper_get_value(buffer, &default_start, DEFAULT_START)) {
continue;
}
if (lsb_meta_helper_get_value(buffer, &default_stop, DEFAULT_STOP)) {
continue;
}
if (lsb_meta_helper_get_value(buffer, &short_desc, SHORT_DESC)) {
continue;
}
/* Long description may cross multiple lines */
if ((long_desc == NULL) // Haven't already found long description
&& pcmk__starts_with(buffer, DESCRIPTION)) {
bool processed_line = TRUE;
GString *desc = g_string_sized_new(2048);
// Get remainder of description line itself
g_string_append(desc, buffer + sizeof(DESCRIPTION) - 1);
// Read any continuation lines of the description
buffer[0] = '\0';
while (fgets(buffer, sizeof(buffer), fp)) {
if (pcmk__starts_with(buffer, "# ")
|| pcmk__starts_with(buffer, "#\t")) {
/* '#' followed by a tab or more than one space indicates a
* continuation of the long description.
*/
g_string_append(desc, buffer + 1);
} else {
/* This line is not part of the long description,
* so continue with normal processing.
*/
processed_line = FALSE;
break;
}
}
// Make long description safe to use in XML
long_desc = pcmk__xml_escape(desc->str, pcmk__xml_escape_text);
g_string_free(desc, TRUE);
if (processed_line) {
// We grabbed the line into the long description
continue;
}
}
// Stop if we leave the header block
if (pcmk__starts_with(buffer, LSB_INITSCRIPT_INFOEND_TAG)) {
break;
}
if (buffer[0] != '#') {
break;
}
}
fclose(fp);
*output = crm_strdup_printf(lsb_metadata_template, type,
pcmk__s(long_desc, type),
pcmk__s(short_desc, type),
pcmk__s(provides, ""),
pcmk__s(required_start, ""),
pcmk__s(required_stop, ""),
pcmk__s(should_start, ""),
pcmk__s(should_stop, ""),
pcmk__s(default_start, ""),
pcmk__s(default_stop, ""));
g_free(long_desc);
g_free(short_desc);
g_free(provides);
g_free(required_start);
g_free(required_stop);
g_free(should_start);
g_free(should_stop);
g_free(default_start);
g_free(default_stop);
return pcmk_ok;
}
GList *
services__list_lsb_agents(void)
{
return services_os_get_directory_list(PCMK__LSB_INIT_DIR, TRUE, TRUE);
}
bool
services__lsb_agent_exists(const char *agent)
{
bool rc = FALSE;
struct stat st;
char *path = pcmk__full_path(agent, PCMK__LSB_INIT_DIR);
rc = (stat(path, &st) == 0);
free(path);
return rc;
}
/*!
* \internal
* \brief Prepare an LSB action
*
* \param[in,out] op Action to prepare
*
* \return Standard Pacemaker return code
*/
int
services__lsb_prepare(svc_action_t *op)
{
op->opaque->exec = pcmk__full_path(op->agent, PCMK__LSB_INIT_DIR);
op->opaque->args[0] = strdup(op->opaque->exec);
op->opaque->args[1] = strdup(op->action);
if ((op->opaque->args[0] == NULL) || (op->opaque->args[1] == NULL)) {
return ENOMEM;
}
return pcmk_rc_ok;
}
/*!
* \internal
* \brief Map an LSB result to a standard OCF result
*
* \param[in] action Action that result is for
* \param[in] exit_status LSB agent exit status
*
* \return Standard OCF result
*/
enum ocf_exitcode
services__lsb2ocf(const char *action, int exit_status)
{
// For non-status actions, LSB and OCF share error codes <= 7
if (!pcmk__str_any_of(action, PCMK_ACTION_STATUS, PCMK_ACTION_MONITOR,
NULL)) {
if ((exit_status < 0) || (exit_status > PCMK_LSB_NOT_RUNNING)) {
return PCMK_OCF_UNKNOWN_ERROR;
}
return (enum ocf_exitcode) exit_status;
}
// LSB status actions have their own codes
switch (exit_status) {
case PCMK_LSB_STATUS_OK:
return PCMK_OCF_OK;
case PCMK_LSB_STATUS_NOT_INSTALLED:
return PCMK_OCF_NOT_INSTALLED;
case PCMK_LSB_STATUS_INSUFFICIENT_PRIV:
return PCMK_OCF_INSUFFICIENT_PRIV;
case PCMK_LSB_STATUS_VAR_PID:
case PCMK_LSB_STATUS_VAR_LOCK:
case PCMK_LSB_STATUS_NOT_RUNNING:
return PCMK_OCF_NOT_RUNNING;
default:
return PCMK_OCF_UNKNOWN_ERROR;
}
}
-
-// Deprecated functions kept only for backward API compatibility
-// LCOV_EXCL_START
-
-#include <crm/services_compat.h>
-
-svc_action_t *
-services_action_create(const char *name, const char *action,
- guint interval_ms, int timeout)
-{
- return resources_action_create(name, PCMK_RESOURCE_CLASS_LSB, NULL, name,
- action, interval_ms, timeout, NULL, 0);
-}
-
-GList *
-services_list(void)
-{
- return resources_list_agents(PCMK_RESOURCE_CLASS_LSB, NULL);
-}
-
-// LCOV_EXCL_STOP
-// End deprecated API

File Metadata

Mime Type
text/x-diff
Expires
Tue, Jul 8, 6:11 PM (21 h, 12 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2002517
Default Alt Text
(58 KB)

Event Timeline