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