1 /*
2 * Copyright 2012-2024 the Pacemaker project contributors
3 *
4 * The version control history for this file may have further details.
5 *
6 * This source code is licensed under the GNU Lesser General Public License
7 * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
8 */
9
10 #ifndef PCMK__CRM_LRMD__H
11 # define PCMK__CRM_LRMD__H
12
13 #include <stdbool.h> // bool
14 #include <glib.h> // guint, GList
15 #include <crm_config.h>
16 #include <crm/lrmd_events.h>
17 #include <crm/services.h>
18
19 #ifdef __cplusplus
20 extern "C" {
21 #endif
22
23 /**
24 * \file
25 * \brief Resource agent executor
26 * \ingroup lrmd
27 */
28
29 typedef struct lrmd_s lrmd_t;
30 typedef struct lrmd_key_value_s {
31 char *key;
32 char *value;
33 struct lrmd_key_value_s *next;
34 } lrmd_key_value_t;
35
36 /* The major version should be bumped every time there is an incompatible
37 * change that prevents older clients from connecting to this version of
38 * the server. The minor version indicates feature support.
39 *
40 * Protocol Pacemaker Significant changes
41 * -------- --------- -------------------
42 * 1.2 2.1.8 PCMK__CIB_REQUEST_SCHEMAS
43 */
44 #define LRMD_PROTOCOL_VERSION "1.2"
45
46 #define LRMD_SUPPORTS_SCHEMA_XFER(x) (compare_version((x), "1.2") >= 0)
47
48 /* The major protocol version the client and server both need to support for
49 * the connection to be successful. This should only ever be the major
50 * version - not a complete version number.
51 */
52 #define LRMD_COMPATIBLE_PROTOCOL "1"
53
54 /* *INDENT-OFF* */
55 #define DEFAULT_REMOTE_KEY_LOCATION PACEMAKER_CONFIG_DIR "/authkey"
56 #define DEFAULT_REMOTE_PORT 3121
57 #define DEFAULT_REMOTE_USERNAME "lrmd"
58
59 #define LRMD_OP_RSC_REG "lrmd_rsc_register"
60 #define LRMD_OP_RSC_EXEC "lrmd_rsc_exec"
61 #define LRMD_OP_RSC_CANCEL "lrmd_rsc_cancel"
62 #define LRMD_OP_RSC_UNREG "lrmd_rsc_unregister"
63 #define LRMD_OP_RSC_INFO "lrmd_rsc_info"
64 #define LRMD_OP_RSC_METADATA "lrmd_rsc_metadata"
65 #define LRMD_OP_POKE "lrmd_rsc_poke"
66 #define LRMD_OP_NEW_CLIENT "lrmd_rsc_new_client"
67 #define LRMD_OP_CHECK "lrmd_check"
68 #define LRMD_OP_ALERT_EXEC "lrmd_alert_exec"
69 #define LRMD_OP_GET_RECURRING "lrmd_get_recurring"
70
71 #define LRMD_IPC_OP_NEW "new"
72 #define LRMD_IPC_OP_DESTROY "destroy"
73 #define LRMD_IPC_OP_EVENT "event"
74 #define LRMD_IPC_OP_REQUEST "request"
75 #define LRMD_IPC_OP_RESPONSE "response"
76 #define LRMD_IPC_OP_SHUTDOWN_REQ "shutdown_req"
77 #define LRMD_IPC_OP_SHUTDOWN_ACK "shutdown_ack"
78 #define LRMD_IPC_OP_SHUTDOWN_NACK "shutdown_nack"
79 /* *INDENT-ON* */
80
81 /*!
82 * \brief Create a new connection to the local executor
83 */
84 lrmd_t *lrmd_api_new(void);
85
86 /*!
87 * \brief Create a new TLS connection to a remote executor
88 *
89 * \param[in] nodename Name of remote node identified with this connection
90 * \param[in] server Hostname to connect to
91 * \param[in] port Port number to connect to (or 0 to use default)
92 *
93 * \return Newly created executor connection object
94 * \note If only one of \p nodename and \p server is non-NULL, it will be used
95 * for both purposes. If both are NULL, a local IPC connection will be
96 * created instead.
97 */
98 lrmd_t *lrmd_remote_api_new(const char *nodename, const char *server, int port);
99
100 /*!
101 * \brief Use after lrmd_poll returns 1 to read and dispatch a message
102 *
103 * \param[in,out] lrmd Executor connection object
104 *
105 * \return TRUE if connection is still up, FALSE if disconnected
106 */
107 bool lrmd_dispatch(lrmd_t *lrmd);
108
109 /*!
110 * \brief Check whether a message is available on an executor connection
111 *
112 * \param[in,out] lrmd Executor connection object to check
113 * \param[in] timeout Currently ignored
114 *
115 * \retval 1 Message is ready
116 * \retval 0 Timeout occurred
117 * \retval negative errno Error occurred
118 *
119 * \note This is intended for callers that do not use a main loop.
120 */
121 int lrmd_poll(lrmd_t *lrmd, int timeout);
122
123 /*!
124 * \brief Destroy executor connection object
125 *
126 * \param[in,out] lrmd Executor connection object to destroy
127 */
128 void lrmd_api_delete(lrmd_t *lrmd);
129
130 lrmd_key_value_t *lrmd_key_value_add(lrmd_key_value_t * kvp, const char *key, const char *value);
131
132 enum lrmd_call_options {
133 lrmd_opt_none = 0,
134
135 /*!
136 * Drop recurring operations initiated by a client when the client
137 * disconnects. This option is only valid when registering a resource. When
138 * used with a connection to a remote executor, recurring operations will be
139 * dropped once all remote connections disconnect.
140 */
141 lrmd_opt_drop_recurring = (1 << 0),
142
143 //! Notify only the client that made the request (rather than all clients)
144 lrmd_opt_notify_orig_only = (1 << 1),
145
146 //! Send notifications for recurring operations only when the result changes
147 lrmd_opt_notify_changes_only = (1 << 2),
148 };
149
150 typedef struct lrmd_rsc_info_s {
151 char *id;
152 char *type;
153 char *standard;
154 char *provider;
155 } lrmd_rsc_info_t;
156
157 typedef struct lrmd_op_info_s {
158 char *rsc_id;
159 char *action;
160 char *interval_ms_s;
161 char *timeout_ms_s;
162 } lrmd_op_info_t;
163
164 lrmd_rsc_info_t *lrmd_new_rsc_info(const char *rsc_id, const char *standard,
165 const char *provider, const char *type);
166 lrmd_rsc_info_t *lrmd_copy_rsc_info(lrmd_rsc_info_t * rsc_info);
167 void lrmd_free_rsc_info(lrmd_rsc_info_t * rsc_info);
168 void lrmd_free_op_info(lrmd_op_info_t *op_info);
169
170 typedef void (*lrmd_event_callback) (lrmd_event_data_t * event);
171
172 typedef struct lrmd_list_s {
173 const char *val;
174 struct lrmd_list_s *next;
175 } lrmd_list_t;
176
177 void lrmd_list_freeall(lrmd_list_t * head);
178 void lrmd_key_value_freeall(lrmd_key_value_t * head);
179
180 typedef struct lrmd_api_operations_s {
181 /*!
182 * \brief Connect to an executor
183 *
184 * \param[in,out] lrmd Executor connection object
185 * \param[in] client_name Arbitrary identifier to pass to server
186 * \param[out] fd If not NULL, where to store file descriptor
187 * for connection's socket
188 *
189 * \return Legacy Pacemaker return code
190 */
191 int (*connect) (lrmd_t *lrmd, const char *client_name, int *fd);
192
193 /*!
194 * \brief Initiate an executor connection without blocking
195 *
196 * \param[in,out] lrmd Executor connection object
197 * \param[in] client_name Arbitrary identifier to pass to server
198 * \param[in] timeout Error if not connected within this time
199 * (milliseconds)
200 *
201 * \return Legacy Pacemaker return code (if pcmk_ok, the event callback will
202 * be called later with the result)
203 * \note This function requires a mainloop.
204 */
205 int (*connect_async) (lrmd_t *lrmd, const char *client_name,
206 int timeout /*ms */ );
207
208 /*!
209 * \brief Check whether connection to executor daemon is (still) active
210 *
211 * \param[in,out] lrmd Executor connection object to check
212 *
213 * \return 1 if the executor connection is active, 0 otherwise
214 */
215 int (*is_connected) (lrmd_t *lrmd);
216
217 /*!
218 * \brief Poke executor connection to verify it is still active
219 *
220 * \param[in,out] lrmd Executor connection object to check
221 *
222 * \return Legacy Pacemaker return code (if pcmk_ok, the event callback will
223 * be called later with the result)
224 * \note The response comes in the form of a poke event to the callback.
225 *
226 */
227 int (*poke_connection) (lrmd_t *lrmd);
228
229 /*!
230 * \brief Disconnect from the executor.
231 *
232 * \param[in,out] lrmd Executor connection object to disconnect
233 *
234 * \return Legacy Pacemaker return code
235 */
236 int (*disconnect) (lrmd_t *lrmd);
237
238 /*!
239 * \brief Register a resource with the executor
240 *
241 * \param[in,out] lrmd Executor connection object
242 * \param[in] rsc_id ID of resource to register
243 * \param[in] standard Resource's resource agent standard
244 * \param[in] provider Resource's resource agent provider (or NULL)
245 * \param[in] agent Resource's resource agent name
246 * \param[in] options Group of enum lrmd_call_options flags
247 *
248 * \note Synchronous, guaranteed to occur in daemon before function returns.
249 *
250 * \return Legacy Pacemaker return code
251 */
252 int (*register_rsc) (lrmd_t *lrmd, const char *rsc_id, const char *standard,
253 const char *provider, const char *agent,
254 enum lrmd_call_options options);
255
256 /*!
257 * \brief Retrieve a resource's registration information
258 *
259 * \param[in,out] lrmd Executor connection object
260 * \param[in] rsc_id ID of resource to check
261 * \param[in] options Group of enum lrmd_call_options flags
262 *
263 * \return Resource information on success, otherwise NULL
264 */
265 lrmd_rsc_info_t *(*get_rsc_info) (lrmd_t *lrmd, const char *rsc_id,
266 enum lrmd_call_options options);
267
268 /*!
269 * \brief Retrieve recurring operations registered for a resource
270 *
271 * \param[in,out] lrmd Executor connection object
272 * \param[in] rsc_id ID of resource to check
273 * \param[in] timeout_ms Error if not completed within this time
274 * \param[in] options Group of enum lrmd_call_options flags
275 * \param[out] output Where to store list of lrmd_op_info_t
276 *
277 * \return Legacy Pacemaker return code
278 */
279 int (*get_recurring_ops) (lrmd_t *lrmd, const char *rsc_id, int timeout_ms,
280 enum lrmd_call_options options, GList **output);
281
282 /*!
283 * \brief Unregister a resource from the executor
284 *
285 * \param[in,out] lrmd Executor connection object
286 * \param[in] rsc_id ID of resource to unregister
287 * \param[in] options Group of enum lrmd_call_options flags
288 *
289 * \return Legacy Pacemaker return code (of particular interest, EINPROGRESS
290 * means that operations are in progress for the resource, and the
291 * unregistration will be done when they complete)
292 * \note Pending and recurring operations will be cancelled.
293 * \note Synchronous, guaranteed to occur in daemon before function returns.
294 *
295 */
296 int (*unregister_rsc) (lrmd_t *lrmd, const char *rsc_id,
297 enum lrmd_call_options options);
298
299 /*!
300 * \brief Set a callback for executor events
301 *
302 * \param[in,out] lrmd Executor connection object
303 * \param[in] callback Callback to set
304 */
305 void (*set_callback) (lrmd_t *lrmd, lrmd_event_callback callback);
306
307 /*!
308 * \brief Request execution of a resource action
309 *
310 * \param[in,out] lrmd Executor connection object
311 * \param[in] rsc_id ID of resource
312 * \param[in] action Name of resource action to execute
313 * \param[in] userdata Arbitrary string to pass to event callback
314 * \param[in] interval_ms If 0, execute action once, otherwise
315 * recurring at this interval (in milliseconds)
316 * \param[in] timeout Error if not complete within this time (in
317 * milliseconds)
318 * \param[in] start_delay Wait this long before execution (in
319 * milliseconds)
320 * \param[in] options Group of enum lrmd_call_options flags
321 * \param[in,out] params Parameters to pass to agent (will be freed)
322 *
323 * \return A call ID for the action on success (in which case the action is
324 * queued in the executor, and the event callback will be called
325 * later with the result), otherwise a negative legacy Pacemaker
326 * return code
327 * \note exec() and cancel() operations on an individual resource are
328 * guaranteed to occur in the order the client API is called. However,
329 * operations on different resources are not guaranteed to occur in
330 * any specific order.
331 */
332 int (*exec) (lrmd_t *lrmd, const char *rsc_id, const char *action,
333 const char *userdata, guint interval_ms, int timeout,
334 int start_delay, enum lrmd_call_options options,
335 lrmd_key_value_t *params);
336
337 /*!
338 * \brief Cancel a recurring resource action
339 *
340 * \param[in,out] lrmd Executor connection object
341 * \param[in] rsc_id ID of resource
342 * \param[in] action Name of resource action to cancel
343 * \param[in] interval_ms Action's interval (in milliseconds)
344 *
345 * \return Legacy Pacemaker return code (if pcmk_ok, cancellation is queued
346 * on function return, and the event callback will be called later
347 * with an exec_complete event with an lrmd_op_status signifying
348 * that the operation is cancelled)
349 *
350 * \note exec() and cancel() operations on an individual resource are
351 * guaranteed to occur in the order the client API is called. However,
352 * operations on different resources are not guaranteed to occur in
353 * any specific order.
354 */
355 int (*cancel) (lrmd_t *lrmd, const char *rsc_id, const char *action,
356 guint interval_ms);
357
358 /*!
359 * \brief Retrieve resource agent metadata synchronously
360 *
361 * \param[in] lrmd Executor connection (unused)
362 * \param[in] standard Resource agent class
363 * \param[in] provider Resource agent provider
364 * \param[in] agent Resource agent type
365 * \param[out] output Where to store metadata (must not be NULL)
366 * \param[in] options Group of enum lrmd_call_options flags (unused)
367 *
368 * \return Legacy Pacemaker return code
369 *
370 * \note Caller is responsible for freeing output. This call is always
371 * synchronous (blocking), and always done directly by the library
372 * (not via the executor connection). This means that it is based on
373 * the local host environment, even if the executor connection is to a
374 * remote node, so this may fail if the agent is not installed
375 * locally. This also means that, if an external agent must be
376 * executed, it will be executed by the caller's user, not the
377 * executor's.
378 */
379 int (*get_metadata) (lrmd_t *lrmd, const char *standard,
380 const char *provider, const char *agent,
381 char **output, enum lrmd_call_options options);
382
383 /*!
384 * \brief Retrieve a list of installed resource agents
385 *
386 * \param[in] lrmd Executor connection (unused)
387 * \param[out] agents Where to store agent list (must not be NULL)
388 * \param[in] standard Resource agent standard to list
389 * \param[in] provider Resource agent provider to list (or NULL)
390 *
391 * \return Number of items in list on success, negative legacy Pacemaker
392 * return code otherwise
393 *
394 * \note if standard is not provided, all known agents will be returned
395 * \note list must be freed using lrmd_list_freeall()
396 */
397 int (*list_agents) (lrmd_t *lrmd, lrmd_list_t **agents,
398 const char *standard, const char *provider);
399
400 /*!
401 * \brief Retrieve a list of resource agent providers
402 *
403 * \param[in] lrmd Executor connection (unused)
404 * \param[in] agent If not NULL, list providers for this agent only
405 * \param[out] providers Where to store provider list
406 *
407 * \return Number of items in list on success, negative legacy Pacemaker
408 * return code otherwise
409 * \note The caller is responsible for freeing *providers with
410 * lrmd_list_freeall().
411 */
412 int (*list_ocf_providers) (lrmd_t *lrmd, const char *agent,
413 lrmd_list_t **providers);
414
415 /*!
416 * \brief Retrieve a list of supported standards
417 *
418 * \param[in] lrmd Executor connection (unused)
419 * \param[out] standards Where to store standards list
420 *
421 * \return Number of items in list on success, negative legacy Pacemaker
422 * return code otherwise
423 * \note The caller is responsible for freeing *standards with
424 * lrmd_list_freeall().
425 */
426 int (*list_standards) (lrmd_t *lrmd, lrmd_list_t **standards);
427
428 /*!
429 * \brief Execute an alert agent
430 *
431 * \param[in,out] lrmd Executor connection
432 * \param[in] alert_id Name of alert to execute
433 * \param[in] alert_path Full path to alert executable
434 * \param[in] timeout Error if not complete within this many
435 * milliseconds
436 * \param[in,out] params Parameters to pass to agent (will be freed)
437 *
438 * \return Legacy Pacemaker return code (if pcmk_ok, the alert is queued in
439 * the executor, and the event callback will be called later with
440 * the result)
441 *
442 * \note Operations on individual alerts (by ID) are guaranteed to occur in
443 * the order the client API is called. Operations on different alerts
444 * are not guaranteed to occur in any specific order.
445 */
446 int (*exec_alert) (lrmd_t *lrmd, const char *alert_id,
447 const char *alert_path, int timeout,
448 lrmd_key_value_t *params);
449
450 /*!
451 * \brief Retrieve resource agent metadata synchronously with parameters
452 *
453 * \param[in] lrmd Executor connection (unused)
454 * \param[in] standard Resource agent class
455 * \param[in] provider Resource agent provider
456 * \param[in] agent Resource agent type
457 * \param[out] output Where to store metadata (must not be NULL)
458 * \param[in] options Group of enum lrmd_call_options flags (unused)
459 * \param[in,out] params Parameters to pass to agent (will be freed)
460 *
461 * \return Legacy Pacemaker return code
462 *
463 * \note This is identical to the get_metadata() API call, except parameters
464 * will be passed to the resource agent via environment variables.
465 */
466 int (*get_metadata_params) (lrmd_t *lrmd, const char *standard,
467 const char *provider, const char *agent,
468 char **output, enum lrmd_call_options options,
469 lrmd_key_value_t *params);
470
471 } lrmd_api_operations_t;
472
473 struct lrmd_s {
474 lrmd_api_operations_t *cmds;
475 void *lrmd_private;
476 };
477
478 static inline const char *
479 lrmd_event_type2str(enum lrmd_callback_event type)
/* ![[previous]](../icons/n_left.png)
![[next]](../icons/n_right.png)
![[first]](../icons/n_first.png)
![[last]](../icons/n_last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
480 {
481 switch (type) {
482 case lrmd_event_register:
483 return "register";
484 case lrmd_event_unregister:
485 return "unregister";
486 case lrmd_event_exec_complete:
487 return "exec_complete";
488 case lrmd_event_disconnect:
489 return "disconnect";
490 case lrmd_event_connect:
491 return "connect";
492 case lrmd_event_poke:
493 return "poke";
494 case lrmd_event_new_client:
495 return "new_client";
496 }
497 return "unknown";
498 }
499
500 #ifdef __cplusplus
501 }
502 #endif
503
504 #endif