1 /*
2 * Copyright (c) 2012 David Vossel <davidvossel@gmail.com>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 *
18 */
19
20 #ifndef LRMD__H
21 # define LRMD__H
22
23 /**
24 * \file
25 * \brief Local Resource Manager
26 * \ingroup lrmd
27 */
28 #include <stdbool.h>
29 #include <crm/services.h>
30
31 typedef struct lrmd_s lrmd_t;
32 typedef struct lrmd_key_value_s {
33 char *key;
34 char *value;
35 struct lrmd_key_value_s *next;
36 } lrmd_key_value_t;
37
38 /* This should be bumped every time there is an incompatible change that
39 * prevents older clients from connecting to this version of the server.
40 */
41 #define LRMD_PROTOCOL_VERSION "1.1"
42
43 /* This is the version that the client version will actually be compared
44 * against. This should be identical to LRMD_PROTOCOL_VERSION. However, we
45 * accidentally bumped LRMD_PROTOCOL_VERSION in 6424a647 (1.1.15) when we didn't
46 * need to, so for now it's different. If we ever have a truly incompatible
47 * bump, we can drop this and compare against LRMD_PROTOCOL_VERSION.
48 */
49 #define LRMD_MIN_PROTOCOL_VERSION "1.0"
50
51 /* *INDENT-OFF* */
52 #define DEFAULT_REMOTE_KEY_LOCATION "/etc/pacemaker/authkey"
53 #define ALT_REMOTE_KEY_LOCATION "/etc/corosync/authkey"
54 #define DEFAULT_REMOTE_PORT 3121
55 #define DEFAULT_REMOTE_USERNAME "lrmd"
56
57 #define F_LRMD_OPERATION "lrmd_op"
58 #define F_LRMD_CLIENTNAME "lrmd_clientname"
59 #define F_LRMD_IS_IPC_PROVIDER "lrmd_is_ipc_provider"
60 #define F_LRMD_CLIENTID "lrmd_clientid"
61 #define F_LRMD_PROTOCOL_VERSION "lrmd_protocol_version"
62 #define F_LRMD_REMOTE_MSG_TYPE "lrmd_remote_msg_type"
63 #define F_LRMD_REMOTE_MSG_ID "lrmd_remote_msg_id"
64 #define F_LRMD_CALLBACK_TOKEN "lrmd_async_id"
65 #define F_LRMD_CALLID "lrmd_callid"
66 #define F_LRMD_CANCEL_CALLID "lrmd_cancel_callid"
67 #define F_LRMD_CALLOPTS "lrmd_callopt"
68 #define F_LRMD_CALLDATA "lrmd_calldata"
69 #define F_LRMD_RC "lrmd_rc"
70 #define F_LRMD_EXEC_RC "lrmd_exec_rc"
71 #define F_LRMD_OP_STATUS "lrmd_exec_op_status"
72 #define F_LRMD_TIMEOUT "lrmd_timeout"
73 #define F_LRMD_WATCHDOG "lrmd_watchdog"
74 #define F_LRMD_CLASS "lrmd_class"
75 #define F_LRMD_PROVIDER "lrmd_provider"
76 #define F_LRMD_TYPE "lrmd_type"
77 #define F_LRMD_ORIGIN "lrmd_origin"
78
79 #define F_LRMD_RSC_RUN_TIME "lrmd_run_time"
80 #define F_LRMD_RSC_RCCHANGE_TIME "lrmd_rcchange_time"
81 #define F_LRMD_RSC_EXEC_TIME "lrmd_exec_time"
82 #define F_LRMD_RSC_QUEUE_TIME "lrmd_queue_time"
83
84 #define F_LRMD_RSC_ID "lrmd_rsc_id"
85 #define F_LRMD_RSC_ACTION "lrmd_rsc_action"
86 #define F_LRMD_RSC_USERDATA_STR "lrmd_rsc_userdata_str"
87 #define F_LRMD_RSC_OUTPUT "lrmd_rsc_output"
88 #define F_LRMD_RSC_EXIT_REASON "lrmd_rsc_exit_reason"
89 #define F_LRMD_RSC_START_DELAY "lrmd_rsc_start_delay"
90 #define F_LRMD_RSC_INTERVAL "lrmd_rsc_interval"
91 #define F_LRMD_RSC_METADATA "lrmd_rsc_metadata_res"
92 #define F_LRMD_RSC_DELETED "lrmd_rsc_deleted"
93 #define F_LRMD_RSC "lrmd_rsc"
94
95 #define F_LRMD_ALERT_ID "lrmd_alert_id"
96 #define F_LRMD_ALERT_PATH "lrmd_alert_path"
97 #define F_LRMD_ALERT "lrmd_alert"
98
99 #define LRMD_OP_RSC_CHK_REG "lrmd_rsc_check_register"
100 #define LRMD_OP_RSC_REG "lrmd_rsc_register"
101 #define LRMD_OP_RSC_EXEC "lrmd_rsc_exec"
102 #define LRMD_OP_RSC_CANCEL "lrmd_rsc_cancel"
103 #define LRMD_OP_RSC_UNREG "lrmd_rsc_unregister"
104 #define LRMD_OP_RSC_INFO "lrmd_rsc_info"
105 #define LRMD_OP_RSC_METADATA "lrmd_rsc_metadata"
106 #define LRMD_OP_POKE "lrmd_rsc_poke"
107 #define LRMD_OP_NEW_CLIENT "lrmd_rsc_new_client"
108 #define LRMD_OP_CHECK "lrmd_check"
109 #define LRMD_OP_ALERT_EXEC "lrmd_alert_exec"
110
111 #define LRMD_IPC_OP_NEW "new"
112 #define LRMD_IPC_OP_DESTROY "destroy"
113 #define LRMD_IPC_OP_EVENT "event"
114 #define LRMD_IPC_OP_REQUEST "request"
115 #define LRMD_IPC_OP_RESPONSE "response"
116 #define LRMD_IPC_OP_SHUTDOWN_REQ "shutdown_req"
117 #define LRMD_IPC_OP_SHUTDOWN_ACK "shutdown_ack"
118 #define LRMD_IPC_OP_SHUTDOWN_NACK "shutdown_nack"
119
120 #define F_LRMD_IPC_OP "lrmd_ipc_op"
121 #define F_LRMD_IPC_IPC_SERVER "lrmd_ipc_server"
122 #define F_LRMD_IPC_SESSION "lrmd_ipc_session"
123 #define F_LRMD_IPC_CLIENT "lrmd_ipc_client"
124 #define F_LRMD_IPC_PROXY_NODE "lrmd_ipc_proxy_node"
125 #define F_LRMD_IPC_USER "lrmd_ipc_user"
126 #define F_LRMD_IPC_MSG "lrmd_ipc_msg"
127 #define F_LRMD_IPC_MSG_ID "lrmd_ipc_msg_id"
128 #define F_LRMD_IPC_MSG_FLAGS "lrmd_ipc_msg_flags"
129
130 #define T_LRMD "lrmd"
131 #define T_LRMD_REPLY "lrmd_reply"
132 #define T_LRMD_NOTIFY "lrmd_notify"
133 #define T_LRMD_IPC_PROXY "lrmd_ipc_proxy"
134 /* *INDENT-ON* */
135
136 /*!
137 * \brief Create a new local lrmd connection
138 */
139 lrmd_t *lrmd_api_new(void);
140
141 /*!
142 * \brief Create a new remote lrmd connection using tls backend
143 *
144 * \param nodename name of remote node identified with this connection
145 * \param server name of server to connect to
146 * \param port port number to connect to
147 *
148 * \note nodename and server may be the same value.
149 */
150 lrmd_t *lrmd_remote_api_new(const char *nodename, const char *server, int port);
151
152 /*!
153 * \brief Use after lrmd_poll returns 1 to read and dispatch a message
154 *
155 * \param[in,out] lrmd lrmd connection object
156 *
157 * \return TRUE if connection is still up, FALSE if disconnected
158 */
159 bool lrmd_dispatch(lrmd_t * lrmd);
160
161 /*!
162 * \brief Poll for a specified timeout period to determine if a message
163 * is ready for dispatch.
164 * \retval 1 msg is ready
165 * \retval 0 timeout occurred
166 * \retval negative error code
167 */
168 int lrmd_poll(lrmd_t * lrmd, int timeout);
169
170 /*!
171 * \brief Destroy lrmd object
172 */
173 void lrmd_api_delete(lrmd_t * lrmd);
174 lrmd_key_value_t *lrmd_key_value_add(lrmd_key_value_t * kvp, const char *key, const char *value);
175
176 /* *INDENT-OFF* */
177 /* Reserved for future use */
178 enum lrmd_call_options {
179 lrmd_opt_none = 0x00000000,
180 /* lrmd_opt_sync_call = 0x00000001, //Not implemented, patches welcome. */
181 /*! Only notify the client originating a exec() the results */
182 lrmd_opt_notify_orig_only = 0x00000002,
183 /*! Drop recurring operations initiated by a client when client disconnects.
184 * This call_option is only valid when registering a resource. When used
185 * remotely with the pacemaker_remote daemon, this option means that recurring
186 * operations will be dropped once all the remote connections disconnect. */
187 lrmd_opt_drop_recurring = 0x00000003,
188 /*! Send notifications for recurring operations only when the result changes */
189 lrmd_opt_notify_changes_only = 0x00000004,
190 };
191
192 enum lrmd_callback_event {
193 lrmd_event_register,
194 lrmd_event_unregister,
195 lrmd_event_exec_complete,
196 lrmd_event_disconnect,
197 lrmd_event_connect,
198 lrmd_event_poke,
199 lrmd_event_new_client,
200 };
201
202 /* *INDENT-ON* */
203
204 typedef struct lrmd_event_data_s {
205 /*! Type of event, register, unregister, call_completed... */
206 enum lrmd_callback_event type;
207
208 /*! The resource this event occurred on. */
209 const char *rsc_id;
210 /*! The action performed, start, stop, monitor... */
211 const char *op_type;
212 /*! The userdata string given do exec() api function */
213 const char *user_data;
214
215 /*! The client api call id associated with this event */
216 int call_id;
217 /*! The operation's timeout period in ms. */
218 int timeout;
219 /*! The operation's recurring interval in ms. */
220 int interval;
221 /*! The operation's start delay value in ms. */
222 int start_delay;
223 /*! This operation that just completed is on a deleted rsc. */
224 int rsc_deleted;
225
226 /*! The executed ra return code mapped to OCF */
227 enum ocf_exitcode rc;
228 /*! The lrmd status returned for exec_complete events */
229 int op_status;
230 /*! stdout from resource agent operation */
231 const char *output;
232 /*! Timestamp of when op ran */
233 unsigned int t_run;
234 /*! Timestamp of last rc change */
235 unsigned int t_rcchange;
236 /*! Time in length op took to execute */
237 unsigned int exec_time;
238 /*! Time in length spent in queue */
239 unsigned int queue_time;
240
241 /*! int connection result. Used for connection and poke events */
242 int connection_rc;
243
244 /* This is a GHashTable containing the
245 * parameters given to the operation */
246 void *params;
247
248 /*! client node name associated with this connection
249 * (used to match actions to the proper client when there are multiple)
250 */
251 const char *remote_nodename;
252
253 /*! exit failure reason string from resource agent operation */
254 const char *exit_reason;
255 } lrmd_event_data_t;
256
257 lrmd_event_data_t *lrmd_copy_event(lrmd_event_data_t * event);
258 void lrmd_free_event(lrmd_event_data_t * event);
259
260 typedef struct lrmd_rsc_info_s {
261 char *id;
262 char *type;
263 char *class;
264 char *provider;
265 } lrmd_rsc_info_t;
266
267 lrmd_rsc_info_t *lrmd_copy_rsc_info(lrmd_rsc_info_t * rsc_info);
268 void lrmd_free_rsc_info(lrmd_rsc_info_t * rsc_info);
269
270 typedef void (*lrmd_event_callback) (lrmd_event_data_t * event);
271
272 typedef struct lrmd_list_s {
273 const char *val;
274 struct lrmd_list_s *next;
275 } lrmd_list_t;
276
277 void lrmd_list_freeall(lrmd_list_t * head);
278 void lrmd_key_value_freeall(lrmd_key_value_t * head);
279
280 typedef struct lrmd_api_operations_s {
281 /*!
282 * \brief Connect from the lrmd.
283 *
284 * \retval 0, success
285 * \retval negative error code on failure
286 */
287 int (*connect) (lrmd_t * lrmd, const char *client_name, int *fd);
288
289 /*!
290 * \brief Establish an connection to lrmd, don't block while connecting.
291 * \note this function requires the use of mainloop.
292 *
293 * \note The is returned using the event callback.
294 * \note When this function returns 0, the callback will be invoked
295 * to report the final result of the connect.
296 * \retval 0, connect in progress, wait for event callback
297 * \retval -1, failure.
298 */
299 int (*connect_async) (lrmd_t * lrmd, const char *client_name, int timeout /*ms */ );
300
301 /*!
302 * \brief Is connected to lrmd daemon?
303 *
304 * \retval 0, false
305 * \retval 1, true
306 */
307 int (*is_connected) (lrmd_t * lrmd);
308
309 /*!
310 * \brief Poke lrmd connection to verify it is still capable of serving requests
311 * \note The response comes in the form of a poke event to the callback.
312 *
313 * \retval 0, wait for response in callback
314 * \retval -1, connection failure, callback may not be invoked
315 */
316 int (*poke_connection) (lrmd_t * lrmd);
317
318 /*!
319 * \brief Disconnect from the lrmd.
320 *
321 * \retval 0, success
322 * \retval negative error code on failure
323 */
324 int (*disconnect) (lrmd_t * lrmd);
325
326 /*!
327 * \brief Register a resource with the lrmd.
328 *
329 * \note Synchronous, guaranteed to occur in daemon before function returns.
330 *
331 * \retval 0, success
332 * \retval negative error code on failure
333 */
334 int (*register_rsc) (lrmd_t * lrmd,
335 const char *rsc_id,
336 const char *class,
337 const char *provider, const char *agent, enum lrmd_call_options options);
338
339 /*!
340 * \brief Retrieve registration info for a rsc
341 *
342 * \retval info on success
343 * \retval NULL on failure
344 */
345 lrmd_rsc_info_t *(*get_rsc_info) (lrmd_t * lrmd,
346 const char *rsc_id, enum lrmd_call_options options);
347
348 /*!
349 * \brief Unregister a resource from the lrmd.
350 *
351 * \note All pending and recurring operations will be cancelled
352 * automatically.
353 *
354 * \note Synchronous, guaranteed to occur in daemon before function returns.
355 *
356 * \retval 0, success
357 * \retval -1, success, but operations are currently executing on the rsc which will
358 * return once they are completed.
359 * \retval negative error code on failure
360 *
361 */
362 int (*unregister_rsc) (lrmd_t * lrmd, const char *rsc_id, enum lrmd_call_options options);
363
364 /*!
365 * \brief Sets the callback to receive lrmd events on.
366 */
367 void (*set_callback) (lrmd_t * lrmd, lrmd_event_callback callback);
368
369 /*!
370 * \brief Issue a command on a resource
371 *
372 * \note Asynchronous, command is queued in daemon on function return, but
373 * execution of command is not synced.
374 *
375 * \note Operations on individual resources are guaranteed to occur
376 * in the order the client api calls them in.
377 *
378 * \note Operations between different resources are not guaranteed
379 * to occur in any specific order in relation to one another
380 * regardless of what order the client api is called in.
381 * \retval call_id to track async event result on success
382 * \retval negative error code on failure
383 */
384 int (*exec) (lrmd_t * lrmd, const char *rsc_id, const char *action, const char *userdata, /* userdata string given back in event notification */
385 int interval, /* ms */
386 int timeout, /* ms */
387 int start_delay, /* ms */
388 enum lrmd_call_options options, lrmd_key_value_t * params); /* ownership of params is given up to api here */
389
390 /*!
391 * \brief Cancel a recurring command.
392 *
393 * \note Synchronous, guaranteed to occur in daemon before function returns.
394 *
395 * \note The cancel is completed async from this call.
396 * We can be guaranteed the cancel has completed once
397 * the callback receives an exec_complete event with
398 * the lrmd_op_status signifying that the operation is
399 * cancelled.
400 * \note For each resource, cancel operations and exec operations
401 * are processed in the order they are received.
402 * It is safe to assume that for a single resource, a cancel
403 * will occur in the lrmd before an exec if the client's cancel
404 * api call occurs before the exec api call.
405 *
406 * It is not however safe to assume any operation on one resource will
407 * occur before an operation on another resource regardless of
408 * the order the client api is called in.
409 *
410 * \retval 0, cancel command sent.
411 * \retval negative error code on failure
412 */
413 int (*cancel) (lrmd_t * lrmd, const char *rsc_id, const char *action, int interval);
414
415 /*!
416 * \brief Get resource metadata for a specified resource agent
417 *
418 * \param[in] lrmd LRMD connection (unused)
419 * \param[in] class Resource agent class
420 * \param[in] provider Resource agent provider
421 * \param[in] agent Resource agent type
422 * \param[out] output Metadata will be stored here (must not be NULL)
423 * \param[in] options Options to use with any LRMD API calls (unused)
424 *
425 * \note Caller is responsible for freeing output. This call is currently
426 * always synchronous (blocking), and always done directly by the
427 * library (not via the LRMD connection). This means that it is based
428 * on the local host environment, even if the lrmd connection is to a
429 * remote node, so (for most resource agent classes) this will fail if
430 * the agent is not installed locally. This also means that, if an
431 * external agent must be executed, it will be executed by the
432 * caller's user, not the lrmd's.
433 * \todo Add a metadata call to the LRMD API and let the server handle this.
434 *
435 * \retval lrmd_ok success
436 * \retval negative error code on failure
437 */
438 int (*get_metadata) (lrmd_t * lrmd,
439 const char *class,
440 const char *provider,
441 const char *agent, char **output, enum lrmd_call_options options);
442
443 /*!
444 * \brief Retrieve a list of installed resource agents.
445 *
446 * \note if class is not provided, all known agents will be returned
447 * \note list must be freed using lrmd_list_freeall()
448 *
449 * \retval num items in list on success
450 * \retval negative error code on failure
451 */
452 int (*list_agents) (lrmd_t * lrmd, lrmd_list_t ** agents, const char *class,
453 const char *provider);
454
455 /*!
456 * \brief Retrieve a list of resource agent providers
457 *
458 * \note When the agent is provided, only the agent's provider will be returned
459 * \note When no agent is supplied, all providers will be returned.
460 * \note List must be freed using lrmd_list_freeall()
461 *
462 * \retval num items in list on success
463 * \retval negative error code on failure
464 */
465 int (*list_ocf_providers) (lrmd_t * lrmd, const char *agent, lrmd_list_t ** providers);
466
467 /*!
468 * \brief Retrieve a list of standards supported by this machine/installation
469 *
470 * \note List must be freed using lrmd_list_freeall()
471 *
472 * \retval num items in list on success
473 * \retval negative error code on failure
474 */
475 int (*list_standards) (lrmd_t * lrmd, lrmd_list_t ** standards);
476
477 /*!
478 * \brief Execute an alert agent
479 *
480 * \note Asynchronous, command is queued in daemon on function return, but
481 * execution of command is not synced.
482 *
483 * \note Operations on individual alerts are guaranteed to occur
484 * in the order the client api calls them in.
485 *
486 * \note Operations between different alerts are not guaranteed
487 * to occur in any specific order in relation to one another
488 * regardless of what order the client api is called in.
489 * \retval call_id to track async event result on success
490 * \retval negative error code on failure
491 */
492 int (*exec_alert) (lrmd_t *lrmd, const char *alert_id,
493 const char *alert_path, int timeout, /* ms */
494 lrmd_key_value_t *params); /* ownership of params is given up to api here */
495
496 } lrmd_api_operations_t;
497
498 struct lrmd_s {
499 lrmd_api_operations_t *cmds;
500 void *private;
501 };
502
503 static inline const char *
504 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)
*/
505 {
506 switch (type) {
507 case lrmd_event_register:
508 return "register";
509 case lrmd_event_unregister:
510 return "unregister";
511 case lrmd_event_exec_complete:
512 return "exec_complete";
513 case lrmd_event_disconnect:
514 return "disconnect";
515 case lrmd_event_connect:
516 return "connect";
517 case lrmd_event_poke:
518 return "poke";
519 case lrmd_event_new_client:
520 return "new_client";
521 }
522 return "unknown";
523 }
524
525 #endif