Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F4624284
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
58 KB
Referenced Files
None
Subscribers
None
View Options
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
Details
Attached
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)
Attached To
Mode
rP Pacemaker
Attached
Detach File
Event Timeline
Log In to Comment