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