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