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) /**/ 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