diff --git a/include/crm/lrmd.h b/include/crm/lrmd.h index c42da62224..55dcdd998b 100644 --- a/include/crm/lrmd.h +++ b/include/crm/lrmd.h @@ -1,415 +1,415 @@ /* * Copyright (c) 2012 David Vossel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifndef LRMD__H #define LRMD__H typedef struct lrmd_s lrmd_t; typedef struct lrmd_key_value_s lrmd_key_value_t; struct lrmd_key_value_t; /* *INDENT-OFF* */ #define F_LRMD_OPERATION "lrmd_op" #define F_LRMD_CLIENTNAME "lrmd_clientname" #define F_LRMD_CLIENTID "lrmd_clientid" #define F_LRMD_CALLBACK_TOKEN "lrmd_async_id" #define F_LRMD_CALLID "lrmd_callid" #define F_LRMD_CANCEL_CALLID "lrmd_cancel_callid" #define F_LRMD_CALLOPTS "lrmd_callopt" #define F_LRMD_CALLDATA "lrmd_calldata" #define F_LRMD_RC "lrmd_rc" #define F_LRMD_EXEC_RC "lrmd_exec_rc" #define F_LRMD_OP_STATUS "lrmd_exec_op_status" #define F_LRMD_TIMEOUT "lrmd_timeout" #define F_LRMD_CLASS "lrmd_class" #define F_LRMD_PROVIDER "lrmd_provider" #define F_LRMD_TYPE "lrmd_type" #define F_LRMD_ORIGIN "lrmd_origin" #define F_LRMD_RSC_RUN_TIME "lrmd_run_time" #define F_LRMD_RSC_RCCHANGE_TIME "lrmd_rcchange_time" #define F_LRMD_RSC_EXEC_TIME "lrmd_exec_time" #define F_LRMD_RSC_QUEUE_TIME "lrmd_queue_time" #define F_LRMD_RSC_ID "lrmd_rsc_id" #define F_LRMD_RSC_ACTION "lrmd_rsc_action" #define F_LRMD_RSC_USERDATA_STR "lrmd_rsc_userdata_str" #define F_LRMD_RSC_OUTPUT "lrmd_rsc_output" #define F_LRMD_RSC_START_DELAY "lrmd_rsc_start_delay" #define F_LRMD_RSC_INTERVAL "lrmd_rsc_interval" #define F_LRMD_RSC_METADATA "lrmd_rsc_metadata_res" #define F_LRMD_RSC_DELETED "lrmd_rsc_deleted" #define F_LRMD_RSC "lrmd_rsc" #define LRMD_OP_RSC_CHK_REG "lrmd_rsc_check_register" #define LRMD_OP_RSC_REG "lrmd_rsc_register" #define LRMD_OP_RSC_EXEC "lrmd_rsc_exec" #define LRMD_OP_RSC_CANCEL "lrmd_rsc_cancel" #define LRMD_OP_RSC_UNREG "lrmd_rsc_unregister" #define LRMD_OP_RSC_INFO "lrmd_rsc_info" #define LRMD_OP_RSC_METADATA "lrmd_rsc_metadata" #define T_LRMD "lrmd" #define T_LRMD_REPLY "lrmd_reply" #define T_LRMD_NOTIFY "lrmd_notify" /* *INDENT-ON* */ lrmd_t *lrmd_api_new(void); bool lrmd_dispatch(lrmd_t *lrmd); void lrmd_api_delete(lrmd_t * lrmd); lrmd_key_value_t *lrmd_key_value_add(lrmd_key_value_t *kvp, - const char *key, - const char *value); + const char *key, + const char *value); /* *INDENT-OFF* */ /* Reserved for future use */ enum lrmd_call_options { - lrmd_opt_none = 0x00000000, - /* lrmd_opt_sync_call = 0x00000001, //Not implemented, patches welcome. */ - /*! Only notify the client originating a exec() the results */ - lrmd_opt_notify_orig_only = 0x00000002, + lrmd_opt_none = 0x00000000, + /* lrmd_opt_sync_call = 0x00000001, //Not implemented, patches welcome. */ + /*! Only notify the client originating a exec() the results */ + lrmd_opt_notify_orig_only = 0x00000002, }; enum lrmd_errors { - lrmd_ok = 0, - lrmd_pending = -1, - lrmd_err_generic = -2, - lrmd_err_internal = -3, - lrmd_err_not_supported = -4, - lrmd_err_connection = -5, - lrmd_err_missing = -6, - lrmd_err_exists = -7, - lrmd_err_timeout = -8, - lrmd_err_ipc = -9, - lrmd_err_peer = -10, - lrmd_err_unknown_operation = -11, - lrmd_err_unknown_rsc = -12, - lrmd_err_none_available = -13, - lrmd_err_authentication = -14, - lrmd_err_signal = -15, - lrmd_err_exec_failed = -16, - lrmd_err_no_metadata = -17, - lrmd_err_stonith_connection = -18, - lrmd_err_provider_required = -19, + lrmd_ok = 0, + lrmd_pending = -1, + lrmd_err_generic = -2, + lrmd_err_internal = -3, + lrmd_err_not_supported = -4, + lrmd_err_connection = -5, + lrmd_err_missing = -6, + lrmd_err_exists = -7, + lrmd_err_timeout = -8, + lrmd_err_ipc = -9, + lrmd_err_peer = -10, + lrmd_err_unknown_operation = -11, + lrmd_err_unknown_rsc = -12, + lrmd_err_none_available = -13, + lrmd_err_authentication = -14, + lrmd_err_signal = -15, + lrmd_err_exec_failed = -16, + lrmd_err_no_metadata = -17, + lrmd_err_stonith_connection = -18, + lrmd_err_provider_required = -19, }; enum lrmd_callback_event { - lrmd_event_register, - lrmd_event_unregister, - lrmd_event_exec_complete, - lrmd_event_disconnect, + lrmd_event_register, + lrmd_event_unregister, + lrmd_event_exec_complete, + lrmd_event_disconnect, }; enum lrmd_exec_rc { - PCMK_EXECRA_OK = 0, - PCMK_EXECRA_UNKNOWN_ERROR = 1, - PCMK_EXECRA_INVALID_PARAM = 2, - PCMK_EXECRA_UNIMPLEMENT_FEATURE = 3, - PCMK_EXECRA_INSUFFICIENT_PRIV = 4, - PCMK_EXECRA_NOT_INSTALLED = 5, - PCMK_EXECRA_NOT_CONFIGURED = 6, - PCMK_EXECRA_NOT_RUNNING = 7, - PCMK_EXECRA_RUNNING_MASTER = 8, - PCMK_EXECRA_FAILED_MASTER = 9, - - /* For status command only */ - PCMK_EXECRA_STATUS_UNKNOWN = 14, + PCMK_EXECRA_OK = 0, + PCMK_EXECRA_UNKNOWN_ERROR = 1, + PCMK_EXECRA_INVALID_PARAM = 2, + PCMK_EXECRA_UNIMPLEMENT_FEATURE = 3, + PCMK_EXECRA_INSUFFICIENT_PRIV = 4, + PCMK_EXECRA_NOT_INSTALLED = 5, + PCMK_EXECRA_NOT_CONFIGURED = 6, + PCMK_EXECRA_NOT_RUNNING = 7, + PCMK_EXECRA_RUNNING_MASTER = 8, + PCMK_EXECRA_FAILED_MASTER = 9, + + /* For status command only */ + PCMK_EXECRA_STATUS_UNKNOWN = 14, }; /* *INDENT-ON* */ typedef struct lrmd_event_data_s { - /*! Type of event, register, unregister, call_completed... */ - enum lrmd_callback_event type; - - /*! The resource this event occurred on. */ - const char *rsc_id; - /*! The action performed, start, stop, monitor... */ - const char *op_type; - /*! The userdata string given do exec() api function */ - const char *user_data; - - /*! The client api call id associated with this event */ - int call_id; - /*! The operation's timeout period in ms. */ - int timeout; - /*! The operation's recurring interval in ms. */ - int interval; - /*! The operation's start delay value in ms. */ - int start_delay; - /*! This operation that just completed is on a deleted rsc. */ - int rsc_deleted; - - /*! The executed ra return code */ - enum lrmd_exec_rc rc; - /*! The lrmd status returned for exec_complete events */ - int op_status; - /*! stdout from resource agent operation */ - const char *output; - /*! Timestamp of when op ran */ - unsigned int t_run; - /*! Timestamp of last rc change */ - unsigned int t_rcchange; - /*! Time in length op took to execute */ - unsigned int exec_time; - /*! Time in length spent in queue */ - unsigned int queue_time; - - /* This is a GHashTable containing the - * parameters given to the operation */ - void *params; + /*! Type of event, register, unregister, call_completed... */ + enum lrmd_callback_event type; + + /*! The resource this event occurred on. */ + const char *rsc_id; + /*! The action performed, start, stop, monitor... */ + const char *op_type; + /*! The userdata string given do exec() api function */ + const char *user_data; + + /*! The client api call id associated with this event */ + int call_id; + /*! The operation's timeout period in ms. */ + int timeout; + /*! The operation's recurring interval in ms. */ + int interval; + /*! The operation's start delay value in ms. */ + int start_delay; + /*! This operation that just completed is on a deleted rsc. */ + int rsc_deleted; + + /*! The executed ra return code */ + enum lrmd_exec_rc rc; + /*! The lrmd status returned for exec_complete events */ + int op_status; + /*! stdout from resource agent operation */ + const char *output; + /*! Timestamp of when op ran */ + unsigned int t_run; + /*! Timestamp of last rc change */ + unsigned int t_rcchange; + /*! Time in length op took to execute */ + unsigned int exec_time; + /*! Time in length spent in queue */ + unsigned int queue_time; + + /* This is a GHashTable containing the + * parameters given to the operation */ + void *params; } lrmd_event_data_t; lrmd_event_data_t *lrmd_copy_event(lrmd_event_data_t *event); void lrmd_free_event(lrmd_event_data_t *event); typedef struct lrmd_rsc_info_s { char *id; char *type; char *class; char *provider; } lrmd_rsc_info_t; lrmd_rsc_info_t *lrmd_copy_rsc_info(lrmd_rsc_info_t *rsc_info); void lrmd_free_rsc_info(lrmd_rsc_info_t *rsc_info); typedef void (*lrmd_event_callback)(lrmd_event_data_t *event); typedef struct lrmd_list_s { - const char *val; - struct lrmd_list_s *next; + const char *val; + struct lrmd_list_s *next; } lrmd_list_t; void lrmd_list_freeall(lrmd_list_t *head); typedef struct lrmd_api_operations_s { - /*! - * \brief Connect from the lrmd. - * - * \retval 0, success - * \retval negative error code on failure - */ - int (*connect) (lrmd_t *lrmd, const char *client_name, int *fd); - - /*! - * \brief Disconnect from the lrmd. - * - * \retval 0, success - * \retval negative error code on failure - */ - int (*disconnect)(lrmd_t *lrmd); - - /*! - * \brief Register a resource with the lrmd. - * - * \note Synchronous, guaranteed to occur in daemon before function returns. - * - * \retval 0, success - * \retval negative error code on failure - */ - int (*register_rsc) (lrmd_t *lrmd, - const char *rsc_id, - const char *class, - const char *provider, - const char *agent, - enum lrmd_call_options options); - - /*! - * \brief Retrieve registration info for a rsc - * - * \retval info on success - * \retval NULL on failure - */ - lrmd_rsc_info_t *(*get_rsc_info) (lrmd_t *lrmd, - const char *rsc_id, - enum lrmd_call_options options); - - /*! - * \brief Unregister a resource from the lrmd. - * - * \note All pending and recurring operations will be cancelled - * automatically. - * - * \note Synchronous, guaranteed to occur in daemon before function returns. - * - * \retval 0, success - * \retval -1, success, but operations are currently executing on the rsc which will - * return once they are completed. - * \retval negative error code on failure - * - */ - int (*unregister_rsc) (lrmd_t *lrmd, - const char *rsc_id, - enum lrmd_call_options options); - - /*! - * \brief Sets the callback to receive lrmd events on. - */ - void (*set_callback) (lrmd_t *lrmd, - lrmd_event_callback callback); - - /*! - * \brief Issue a command on a resource - * - * \note Asynchronous, command is queued in daemon on function return, but - * execution of command is not synced. - * - * \note Operations on individual resources are guaranteed to occur - * in the order the client api calls them in. - * - * \note Operations between different resources are not guaranteed - * to occur in any specific order in relation to one another - * regardless of what order the client api is called in. - * \retval call_id to track async event result on success - * \retval negative error code on failure - */ - int (*exec)(lrmd_t *lrmd, - const char *rsc_id, - const char *action, - const char *userdata, /* userdata string given back in event notification */ - int interval, /* ms */ - int timeout, /* ms */ - int start_delay, /* ms */ - enum lrmd_call_options options, - lrmd_key_value_t *params); /* ownership of params is given up to api here */ - - /*! - * \brief Cancel a recurring command. - * - * \note Synchronous, guaranteed to occur in daemon before function returns. - * - * \note The cancel is completed async from this call. - * We can be guaranteed the cancel has completed once - * the callback receives an exec_complete event with - * the lrmd_op_status signifying that the operation is - * cancelled. - * \note For each resource, cancel operations and exec operations - * are processed in the order they are received. - * It is safe to assume that for a single resource, a cancel - * will occur in the lrmd before an exec if the client's cancel - * api call occurs before the exec api call. - * - * It is not however safe to assume any operation on one resource will - * occur before an operation on another resource regardless of - * the order the client api is called in. - * - * \retval 0, cancel command sent. - * \retval negative error code on failure - */ - int (*cancel)(lrmd_t *lrmd, - const char *rsc_id, - const char *action, - int interval); - - /*! - * \brief Get the metadata documentation for a resource. - * - * \note Value is returned in output. Output must be freed when set - * - * \retval lrmd_ok success - * \retval negative error code on failure - */ - int (*get_metadata) (lrmd_t *lrmd, - const char *class, - const char *provider, - const char *agent, - char **output, - enum lrmd_call_options options); - - /*! - * \brief Retrieve a list of installed resource agents. - * - * \note if class is not provided, all known agents will be returned - * \note list must be freed using lrmd_list_freeall() - * - * \retval num items in list on success - * \retval negative error code on failure - */ - int (*list_agents)(lrmd_t *lrmd, lrmd_list_t **agents, const char *class, const char *provider); - - /*! - * \brief Retrieve a list of resource agent providers - * - * \note When the agent is provided, only the agent's provider will be returned - * \note When no agent is supplied, all providers will be returned. - * \note List must be freed using lrmd_list_freeall() - * - * \retval num items in list on success - * \retval negative error code on failure - */ - int (*list_ocf_providers)(lrmd_t *lrmd, - const char *agent, - lrmd_list_t **providers); + /*! + * \brief Connect from the lrmd. + * + * \retval 0, success + * \retval negative error code on failure + */ + int (*connect) (lrmd_t *lrmd, const char *client_name, int *fd); + + /*! + * \brief Disconnect from the lrmd. + * + * \retval 0, success + * \retval negative error code on failure + */ + int (*disconnect)(lrmd_t *lrmd); + + /*! + * \brief Register a resource with the lrmd. + * + * \note Synchronous, guaranteed to occur in daemon before function returns. + * + * \retval 0, success + * \retval negative error code on failure + */ + int (*register_rsc) (lrmd_t *lrmd, + const char *rsc_id, + const char *class, + const char *provider, + const char *agent, + enum lrmd_call_options options); + + /*! + * \brief Retrieve registration info for a rsc + * + * \retval info on success + * \retval NULL on failure + */ + lrmd_rsc_info_t *(*get_rsc_info) (lrmd_t *lrmd, + const char *rsc_id, + enum lrmd_call_options options); + + /*! + * \brief Unregister a resource from the lrmd. + * + * \note All pending and recurring operations will be cancelled + * automatically. + * + * \note Synchronous, guaranteed to occur in daemon before function returns. + * + * \retval 0, success + * \retval -1, success, but operations are currently executing on the rsc which will + * return once they are completed. + * \retval negative error code on failure + * + */ + int (*unregister_rsc) (lrmd_t *lrmd, + const char *rsc_id, + enum lrmd_call_options options); + + /*! + * \brief Sets the callback to receive lrmd events on. + */ + void (*set_callback) (lrmd_t *lrmd, + lrmd_event_callback callback); + + /*! + * \brief Issue a command on a resource + * + * \note Asynchronous, command is queued in daemon on function return, but + * execution of command is not synced. + * + * \note Operations on individual resources are guaranteed to occur + * in the order the client api calls them in. + * + * \note Operations between different resources are not guaranteed + * to occur in any specific order in relation to one another + * regardless of what order the client api is called in. + * \retval call_id to track async event result on success + * \retval negative error code on failure + */ + int (*exec)(lrmd_t *lrmd, + const char *rsc_id, + const char *action, + const char *userdata, /* userdata string given back in event notification */ + int interval, /* ms */ + int timeout, /* ms */ + int start_delay, /* ms */ + enum lrmd_call_options options, + lrmd_key_value_t *params); /* ownership of params is given up to api here */ + + /*! + * \brief Cancel a recurring command. + * + * \note Synchronous, guaranteed to occur in daemon before function returns. + * + * \note The cancel is completed async from this call. + * We can be guaranteed the cancel has completed once + * the callback receives an exec_complete event with + * the lrmd_op_status signifying that the operation is + * cancelled. + * \note For each resource, cancel operations and exec operations + * are processed in the order they are received. + * It is safe to assume that for a single resource, a cancel + * will occur in the lrmd before an exec if the client's cancel + * api call occurs before the exec api call. + * + * It is not however safe to assume any operation on one resource will + * occur before an operation on another resource regardless of + * the order the client api is called in. + * + * \retval 0, cancel command sent. + * \retval negative error code on failure + */ + int (*cancel)(lrmd_t *lrmd, + const char *rsc_id, + const char *action, + int interval); + + /*! + * \brief Get the metadata documentation for a resource. + * + * \note Value is returned in output. Output must be freed when set + * + * \retval lrmd_ok success + * \retval negative error code on failure + */ + int (*get_metadata) (lrmd_t *lrmd, + const char *class, + const char *provider, + const char *agent, + char **output, + enum lrmd_call_options options); + + /*! + * \brief Retrieve a list of installed resource agents. + * + * \note if class is not provided, all known agents will be returned + * \note list must be freed using lrmd_list_freeall() + * + * \retval num items in list on success + * \retval negative error code on failure + */ + int (*list_agents)(lrmd_t *lrmd, lrmd_list_t **agents, const char *class, const char *provider); + + /*! + * \brief Retrieve a list of resource agent providers + * + * \note When the agent is provided, only the agent's provider will be returned + * \note When no agent is supplied, all providers will be returned. + * \note List must be freed using lrmd_list_freeall() + * + * \retval num items in list on success + * \retval negative error code on failure + */ + int (*list_ocf_providers)(lrmd_t *lrmd, + const char *agent, + lrmd_list_t **providers); } lrmd_api_operations_t; struct lrmd_s { - lrmd_api_operations_t *cmds; - void *private; + lrmd_api_operations_t *cmds; + void *private; }; static inline const char * lrmd_event_rc2str(enum lrmd_exec_rc rc) { - switch(rc) { - case PCMK_EXECRA_OK: - return "ok"; - case PCMK_EXECRA_UNKNOWN_ERROR: - return "unknown error"; - case PCMK_EXECRA_INVALID_PARAM: - return "invalid parameter"; - case PCMK_EXECRA_UNIMPLEMENT_FEATURE: - return "unimplemented feature"; - case PCMK_EXECRA_INSUFFICIENT_PRIV: - return "insufficient privileges"; - case PCMK_EXECRA_NOT_INSTALLED: - return "not installed"; - case PCMK_EXECRA_NOT_CONFIGURED: - return "not configured"; - case PCMK_EXECRA_NOT_RUNNING: - return "not running"; - case PCMK_EXECRA_RUNNING_MASTER: - return "master"; - case PCMK_EXECRA_FAILED_MASTER: - return "master (failed)"; - case PCMK_EXECRA_STATUS_UNKNOWN: - return "status: unknown"; - default: - break; - } - return ""; + switch(rc) { + case PCMK_EXECRA_OK: + return "ok"; + case PCMK_EXECRA_UNKNOWN_ERROR: + return "unknown error"; + case PCMK_EXECRA_INVALID_PARAM: + return "invalid parameter"; + case PCMK_EXECRA_UNIMPLEMENT_FEATURE: + return "unimplemented feature"; + case PCMK_EXECRA_INSUFFICIENT_PRIV: + return "insufficient privileges"; + case PCMK_EXECRA_NOT_INSTALLED: + return "not installed"; + case PCMK_EXECRA_NOT_CONFIGURED: + return "not configured"; + case PCMK_EXECRA_NOT_RUNNING: + return "not running"; + case PCMK_EXECRA_RUNNING_MASTER: + return "master"; + case PCMK_EXECRA_FAILED_MASTER: + return "master (failed)"; + case PCMK_EXECRA_STATUS_UNKNOWN: + return "status: unknown"; + default: + break; + } + return ""; } static inline const char * lrmd_event_type2str(enum lrmd_callback_event type) { - switch (type) { - case lrmd_event_register: - return "register"; - case lrmd_event_unregister: - return "unregister"; - case lrmd_event_exec_complete: - return "exec_complete"; - case lrmd_event_disconnect: - return "disconnect"; - } - return "unknown"; + switch (type) { + case lrmd_event_register: + return "register"; + case lrmd_event_unregister: + return "unregister"; + case lrmd_event_exec_complete: + return "exec_complete"; + case lrmd_event_disconnect: + return "disconnect"; + } + return "unknown"; } #endif diff --git a/lib/lrmd/lrmd_client.c b/lib/lrmd/lrmd_client.c index 3da4c10e00..5e34106970 100644 --- a/lib/lrmd/lrmd_client.c +++ b/lib/lrmd/lrmd_client.c @@ -1,1087 +1,1066 @@ /* * Copyright (c) 2012 David Vossel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include CRM_TRACE_INIT_DATA(lrmd); static stonith_t *stonith_api = NULL; typedef struct lrmd_key_value_s { - char *key; - char *value; - struct lrmd_key_value_s *next; + char *key; + char *value; + struct lrmd_key_value_s *next; } lrmd_key_value_t; typedef struct lrmd_private_s { - int call_id; + int call_id; - char *token; - crm_ipc_t *ipc; - mainloop_io_t *source; + char *token; + crm_ipc_t *ipc; + mainloop_io_t *source; - lrmd_event_callback callback; + lrmd_event_callback callback; } lrmd_private_t; static lrmd_list_t * -lrmd_list_add(lrmd_list_t *head, const char *value) +lrmd_list_add(lrmd_list_t * head, const char *value) { - lrmd_list_t *p, *end; + lrmd_list_t *p, *end; - p = calloc(1, sizeof(lrmd_list_t)); - p->val = crm_strdup(value); + p = calloc(1, sizeof(lrmd_list_t)); + p->val = crm_strdup(value); - end = head; - while (end && end->next) { - end = end->next; - } + end = head; + while (end && end->next) { + end = end->next; + } - if (end) { - end->next = p; - } else { - head = p; - } + if (end) { + end->next = p; + } else { + head = p; + } - return head; + return head; } void -lrmd_list_freeall(lrmd_list_t *head) +lrmd_list_freeall(lrmd_list_t * head) { - lrmd_list_t *p; - while (head) { - char *val = (char *) head->val; - p = head->next; - free(val); - free(head); - head = p; - } + lrmd_list_t *p; + + while (head) { + char *val = (char *)head->val; + + p = head->next; + free(val); + free(head); + head = p; + } } lrmd_key_value_t * -lrmd_key_value_add(lrmd_key_value_t *head, const char *key, const char *value) +lrmd_key_value_add(lrmd_key_value_t * head, const char *key, const char *value) { - lrmd_key_value_t *p, *end; + lrmd_key_value_t *p, *end; - p = calloc(1, sizeof(lrmd_key_value_t)); - p->key = crm_strdup(key); - p->value = crm_strdup(value); + p = calloc(1, sizeof(lrmd_key_value_t)); + p->key = crm_strdup(key); + p->value = crm_strdup(value); - end = head; - while (end && end->next) { - end = end->next; - } + end = head; + while (end && end->next) { + end = end->next; + } - if (end) { - end->next = p; - } else { - head = p; - } + if (end) { + end->next = p; + } else { + head = p; + } - return head; + return head; } static void lrmd_key_value_freeall(lrmd_key_value_t * head) { - lrmd_key_value_t *p; - while (head) { - p = head->next; - free(head->key); - free(head->value); - free(head); - head = p; - } + lrmd_key_value_t *p; + + while (head) { + p = head->next; + free(head->key); + free(head->value); + free(head); + head = p; + } } static void dup_attr(gpointer key, gpointer value, gpointer user_data) { - g_hash_table_replace(user_data, crm_strdup(key), crm_strdup(value)); + g_hash_table_replace(user_data, crm_strdup(key), crm_strdup(value)); } -lrmd_event_data_t *lrmd_copy_event(lrmd_event_data_t *event) +lrmd_event_data_t * +lrmd_copy_event(lrmd_event_data_t * event) { - lrmd_event_data_t *copy = NULL; + lrmd_event_data_t *copy = NULL; - copy = calloc(1, sizeof(lrmd_event_data_t)); + copy = calloc(1, sizeof(lrmd_event_data_t)); - /* This will get all the int values. - * we just have to be careful not to leave any - * dangling pointers to strings. */ - memcpy(copy, event, sizeof(lrmd_event_data_t)); + /* This will get all the int values. + * we just have to be careful not to leave any + * dangling pointers to strings. */ + memcpy(copy, event, sizeof(lrmd_event_data_t)); - copy->rsc_id = event->rsc_id ? crm_strdup(event->rsc_id) : NULL; - copy->op_type = event->op_type ? crm_strdup(event->op_type) : NULL; - copy->user_data = event->user_data ? crm_strdup(event->user_data) : NULL; - copy->output = event->output ? crm_strdup(event->output) : NULL; + copy->rsc_id = event->rsc_id ? crm_strdup(event->rsc_id) : NULL; + copy->op_type = event->op_type ? crm_strdup(event->op_type) : NULL; + copy->user_data = event->user_data ? crm_strdup(event->user_data) : NULL; + copy->output = event->output ? crm_strdup(event->output) : NULL; - if (event->params) { - copy->params = g_hash_table_new_full(crm_str_hash, - g_str_equal, - g_hash_destroy_str, - g_hash_destroy_str); + if (event->params) { + copy->params = g_hash_table_new_full(crm_str_hash, + g_str_equal, g_hash_destroy_str, g_hash_destroy_str); - if (copy->params != NULL) { - g_hash_table_foreach(event->params, dup_attr, copy->params); - } - } + if (copy->params != NULL) { + g_hash_table_foreach(event->params, dup_attr, copy->params); + } + } - return copy; + return copy; } -void lrmd_free_event(lrmd_event_data_t *event) +void +lrmd_free_event(lrmd_event_data_t * event) { - if (!event) { - return; - } - - /* free gives me grief if i try to cast */ - free((char *) event->rsc_id); - free((char *) event->op_type); - free((char *) event->user_data); - free((char *) event->output); - if (event->params) { - g_hash_table_destroy(event->params); - } - free(event); + if (!event) { + return; + } + + /* free gives me grief if i try to cast */ + free((char *)event->rsc_id); + free((char *)event->op_type); + free((char *)event->user_data); + free((char *)event->output); + if (event->params) { + g_hash_table_destroy(event->params); + } + free(event); } static int lrmd_dispatch_internal(const char *buffer, ssize_t length, gpointer userdata) { - const char *type; - lrmd_t *lrmd = userdata; - lrmd_private_t *native = lrmd->private; - lrmd_event_data_t event = { 0, }; - xmlNode *msg; - - if (!native->callback) { - /* no callback set */ - return 1; - } - - msg = string2xml(buffer); - type = crm_element_value(msg, F_LRMD_OPERATION); - crm_element_value_int(msg, F_LRMD_CALLID, &event.call_id); - event.rsc_id = crm_element_value(msg, F_LRMD_RSC_ID); - - if (crm_str_eq(type, LRMD_OP_RSC_REG, TRUE)) { - event.type = lrmd_event_register; - } else if (crm_str_eq(type, LRMD_OP_RSC_UNREG, TRUE)) { - event.type = lrmd_event_unregister; - } else if (crm_str_eq(type, LRMD_OP_RSC_EXEC, TRUE)) { - crm_element_value_int(msg, F_LRMD_TIMEOUT, &event.timeout); - crm_element_value_int(msg, F_LRMD_RSC_INTERVAL, &event.interval); - crm_element_value_int(msg, F_LRMD_RSC_START_DELAY, &event.start_delay); - crm_element_value_int(msg, F_LRMD_EXEC_RC, (int *) &event.rc); - crm_element_value_int(msg, F_LRMD_OP_STATUS, &event.op_status); - crm_element_value_int(msg, F_LRMD_RSC_DELETED, &event.rsc_deleted); - - crm_element_value_int(msg, F_LRMD_RSC_RUN_TIME, (int *) &event.t_run); - crm_element_value_int(msg, F_LRMD_RSC_RCCHANGE_TIME, (int *) &event.t_rcchange); - crm_element_value_int(msg, F_LRMD_RSC_EXEC_TIME, (int *) &event.exec_time); - crm_element_value_int(msg, F_LRMD_RSC_QUEUE_TIME, (int *) &event.queue_time); - - event.op_type = crm_element_value(msg, F_LRMD_RSC_ACTION); - event.user_data = crm_element_value(msg, F_LRMD_RSC_USERDATA_STR); - event.output = crm_element_value(msg, F_LRMD_RSC_OUTPUT); - event.type = lrmd_event_exec_complete; - - event.params = xml2list(msg); - } - - native->callback(&event); - - if (event.params) { - g_hash_table_destroy(event.params); - } - free_xml(msg); - return 1; + const char *type; + lrmd_t *lrmd = userdata; + lrmd_private_t *native = lrmd->private; + lrmd_event_data_t event = { 0, }; + xmlNode *msg; + + if (!native->callback) { + /* no callback set */ + return 1; + } + + msg = string2xml(buffer); + type = crm_element_value(msg, F_LRMD_OPERATION); + crm_element_value_int(msg, F_LRMD_CALLID, &event.call_id); + event.rsc_id = crm_element_value(msg, F_LRMD_RSC_ID); + + if (crm_str_eq(type, LRMD_OP_RSC_REG, TRUE)) { + event.type = lrmd_event_register; + } else if (crm_str_eq(type, LRMD_OP_RSC_UNREG, TRUE)) { + event.type = lrmd_event_unregister; + } else if (crm_str_eq(type, LRMD_OP_RSC_EXEC, TRUE)) { + crm_element_value_int(msg, F_LRMD_TIMEOUT, &event.timeout); + crm_element_value_int(msg, F_LRMD_RSC_INTERVAL, &event.interval); + crm_element_value_int(msg, F_LRMD_RSC_START_DELAY, &event.start_delay); + crm_element_value_int(msg, F_LRMD_EXEC_RC, (int *)&event.rc); + crm_element_value_int(msg, F_LRMD_OP_STATUS, &event.op_status); + crm_element_value_int(msg, F_LRMD_RSC_DELETED, &event.rsc_deleted); + + crm_element_value_int(msg, F_LRMD_RSC_RUN_TIME, (int *)&event.t_run); + crm_element_value_int(msg, F_LRMD_RSC_RCCHANGE_TIME, (int *)&event.t_rcchange); + crm_element_value_int(msg, F_LRMD_RSC_EXEC_TIME, (int *)&event.exec_time); + crm_element_value_int(msg, F_LRMD_RSC_QUEUE_TIME, (int *)&event.queue_time); + + event.op_type = crm_element_value(msg, F_LRMD_RSC_ACTION); + event.user_data = crm_element_value(msg, F_LRMD_RSC_USERDATA_STR); + event.output = crm_element_value(msg, F_LRMD_RSC_OUTPUT); + event.type = lrmd_event_exec_complete; + + event.params = xml2list(msg); + } + + native->callback(&event); + + if (event.params) { + g_hash_table_destroy(event.params); + } + free_xml(msg); + return 1; } /* Not used with mainloop */ bool -lrmd_dispatch(lrmd_t *lrmd) +lrmd_dispatch(lrmd_t * lrmd) { - gboolean stay_connected = TRUE; - lrmd_private_t *private = NULL; - - CRM_ASSERT(lrmd != NULL); - private = lrmd->private; - - while(crm_ipc_ready(private->ipc)) { - if (crm_ipc_read(private->ipc) > 0) { - const char *msg = crm_ipc_buffer(private->ipc); - lrmd_dispatch_internal(msg, strlen(msg), lrmd); - } - if (crm_ipc_connected(private->ipc) == FALSE) { - crm_err("Connection closed"); - stay_connected = FALSE; - } - } + gboolean stay_connected = TRUE; + lrmd_private_t *private = NULL; + + CRM_ASSERT(lrmd != NULL); + private = lrmd->private; + + while (crm_ipc_ready(private->ipc)) { + if (crm_ipc_read(private->ipc) > 0) { + const char *msg = crm_ipc_buffer(private->ipc); - return stay_connected; + lrmd_dispatch_internal(msg, strlen(msg), lrmd); + } + if (crm_ipc_connected(private->ipc) == FALSE) { + crm_err("Connection closed"); + stay_connected = FALSE; + } + } + + return stay_connected; } static xmlNode * lrmd_create_op(int call_id, - const char *token, - const char *op, xmlNode *data, - enum lrmd_call_options options) + const char *token, const char *op, xmlNode * data, enum lrmd_call_options options) { - xmlNode *op_msg = create_xml_node(NULL, "lrmd_command"); + xmlNode *op_msg = create_xml_node(NULL, "lrmd_command"); - CRM_CHECK(op_msg != NULL, return NULL); - CRM_CHECK(token != NULL, return NULL); + CRM_CHECK(op_msg != NULL, return NULL); + CRM_CHECK(token != NULL, return NULL); - crm_xml_add(op_msg, F_XML_TAGNAME, "lrmd_command"); + crm_xml_add(op_msg, F_XML_TAGNAME, "lrmd_command"); - crm_xml_add(op_msg, F_TYPE, T_LRMD); - crm_xml_add(op_msg, F_LRMD_CALLBACK_TOKEN, token); - crm_xml_add(op_msg, F_LRMD_OPERATION, op); - crm_xml_add_int(op_msg, F_LRMD_CALLID, call_id); - crm_trace("Sending call options: %.8lx, %d", (long)options, options); - crm_xml_add_int(op_msg, F_LRMD_CALLOPTS, options); + crm_xml_add(op_msg, F_TYPE, T_LRMD); + crm_xml_add(op_msg, F_LRMD_CALLBACK_TOKEN, token); + crm_xml_add(op_msg, F_LRMD_OPERATION, op); + crm_xml_add_int(op_msg, F_LRMD_CALLID, call_id); + crm_trace("Sending call options: %.8lx, %d", (long)options, options); + crm_xml_add_int(op_msg, F_LRMD_CALLOPTS, options); - if (data != NULL) { - add_message_xml(op_msg, F_LRMD_CALLDATA, data); - } + if (data != NULL) { + add_message_xml(op_msg, F_LRMD_CALLDATA, data); + } - return op_msg; + return op_msg; } static void lrmd_connection_destroy(gpointer userdata) { - lrmd_t *lrmd = userdata; - lrmd_private_t *native = lrmd->private; - crm_info("connection destroyed"); - if (native->callback) { - lrmd_event_data_t event = { 0, }; - event.type = lrmd_event_disconnect; - native->callback(&event); - } + lrmd_t *lrmd = userdata; + lrmd_private_t *native = lrmd->private; + + crm_info("connection destroyed"); + if (native->callback) { + lrmd_event_data_t event = { 0, }; + event.type = lrmd_event_disconnect; + native->callback(&event); + } } static int -lrmd_send_command(lrmd_t * lrmd, - const char *op, - xmlNode *data, - xmlNode **output_data, - int timeout, /* ms. defaults to 1000 if set to 0 */ - enum lrmd_call_options options) +lrmd_send_command(lrmd_t * lrmd, const char *op, xmlNode * data, xmlNode ** output_data, int timeout, /* ms. defaults to 1000 if set to 0 */ + enum lrmd_call_options options) { - int rc = lrmd_ok; - int reply_id = -1; - lrmd_private_t *native = lrmd->private; - xmlNode *op_msg = NULL; - xmlNode *op_reply = NULL; - - if (!native->ipc) { - return lrmd_err_connection; - } - - if (op == NULL) { - crm_err("No operation specified"); - return lrmd_err_missing; - } - - native->call_id++; - if (native->call_id < 1) { - native->call_id = 1; - } - - CRM_CHECK(native->token != NULL,;); - - op_msg = lrmd_create_op(native->call_id, - native->token, - op, - data, - options); - - if (op_msg == NULL) { - return lrmd_err_missing; - } - - crm_xml_add_int(op_msg, F_LRMD_TIMEOUT, timeout); - - rc = crm_ipc_send(native->ipc, op_msg, &op_reply, timeout); - free_xml(op_msg); - - if (rc < 0) { - crm_perror(LOG_ERR, "Couldn't perform %s operation (timeout=%d): %d", op, timeout, rc); - rc = lrmd_err_ipc; - goto done; - } - - rc = lrmd_ok; - crm_element_value_int(op_reply, F_LRMD_CALLID, &reply_id); - if (reply_id == native->call_id) { - crm_trace("reply received"); - if (crm_element_value_int(op_reply, F_LRMD_RC, &rc) != 0) { - rc = lrmd_err_peer; - goto done; - } - - if (output_data) { - *output_data = op_reply; - op_reply = NULL; /* Prevent subsequent free */ - } - - } else if (reply_id <= 0) { - crm_err("Recieved bad reply: No id set"); - crm_log_xml_err(op_reply, "Bad reply"); - rc = lrmd_err_peer; - } else { - crm_err("Recieved bad reply: %d (wanted %d)", reply_id, native->call_id); - crm_log_xml_err(op_reply, "Old reply"); - rc = lrmd_err_peer; - } - - crm_log_xml_trace(op_reply, "Reply"); - -done: - if (crm_ipc_connected(native->ipc) == FALSE) { - crm_err("LRMD disconnected"); - } - - free_xml(op_reply); - return rc; + int rc = lrmd_ok; + int reply_id = -1; + lrmd_private_t *native = lrmd->private; + xmlNode *op_msg = NULL; + xmlNode *op_reply = NULL; + + if (!native->ipc) { + return lrmd_err_connection; + } + + if (op == NULL) { + crm_err("No operation specified"); + return lrmd_err_missing; + } + + native->call_id++; + if (native->call_id < 1) { + native->call_id = 1; + } + + CRM_CHECK(native->token != NULL,;); + + op_msg = lrmd_create_op(native->call_id, native->token, op, data, options); + + if (op_msg == NULL) { + return lrmd_err_missing; + } + + crm_xml_add_int(op_msg, F_LRMD_TIMEOUT, timeout); + + rc = crm_ipc_send(native->ipc, op_msg, &op_reply, timeout); + free_xml(op_msg); + + if (rc < 0) { + crm_perror(LOG_ERR, "Couldn't perform %s operation (timeout=%d): %d", op, timeout, rc); + rc = lrmd_err_ipc; + goto done; + } + + rc = lrmd_ok; + crm_element_value_int(op_reply, F_LRMD_CALLID, &reply_id); + if (reply_id == native->call_id) { + crm_trace("reply received"); + if (crm_element_value_int(op_reply, F_LRMD_RC, &rc) != 0) { + rc = lrmd_err_peer; + goto done; + } + + if (output_data) { + *output_data = op_reply; + op_reply = NULL; /* Prevent subsequent free */ + } + + } else if (reply_id <= 0) { + crm_err("Recieved bad reply: No id set"); + crm_log_xml_err(op_reply, "Bad reply"); + rc = lrmd_err_peer; + } else { + crm_err("Recieved bad reply: %d (wanted %d)", reply_id, native->call_id); + crm_log_xml_err(op_reply, "Old reply"); + rc = lrmd_err_peer; + } + + crm_log_xml_trace(op_reply, "Reply"); + + done: + if (crm_ipc_connected(native->ipc) == FALSE) { + crm_err("LRMD disconnected"); + } + + free_xml(op_reply); + return rc; } static int lrmd_api_connect(lrmd_t * lrmd, const char *name, int *fd) { - int rc = lrmd_ok; - lrmd_private_t *native = lrmd->private; - static struct ipc_client_callbacks lrmd_callbacks = { - .dispatch = lrmd_dispatch_internal, - .destroy = lrmd_connection_destroy - }; - - crm_info("Connecting to lrmd"); - - if (fd) { - /* No mainloop */ - native->ipc = crm_ipc_new("lrmd", 0); - if (native->ipc && crm_ipc_connect(native->ipc)) { - *fd = crm_ipc_get_fd(native->ipc); - } else if (native->ipc) { - rc = lrmd_err_connection; - } - } else { - native->source = mainloop_add_ipc_client("lrmd", 0, lrmd, &lrmd_callbacks); - native->ipc = mainloop_get_ipc_client(native->source); - } - - if (native->ipc == NULL) { - crm_debug("Could not connect to the LRMD API"); - rc = lrmd_err_connection; - } - - if (!rc) { - xmlNode *reply = NULL; - xmlNode *hello = create_xml_node(NULL, "lrmd_command"); - - crm_xml_add(hello, F_TYPE, T_LRMD); - crm_xml_add(hello, F_LRMD_OPERATION, CRM_OP_REGISTER); - crm_xml_add(hello, F_LRMD_CLIENTNAME, name); - - rc = crm_ipc_send(native->ipc, hello, &reply, -1); - - if (rc < 0) { - crm_perror(LOG_DEBUG, "Couldn't complete registration with the lrmd API: %d", rc); - rc = lrmd_err_ipc; - } else if(reply == NULL) { - crm_err("Did not receive registration reply"); - rc = lrmd_err_internal; - } else { - const char *msg_type = crm_element_value(reply, F_LRMD_OPERATION); - const char *tmp_ticket = crm_element_value(reply, F_LRMD_CLIENTID); - - if (safe_str_neq(msg_type, CRM_OP_REGISTER)) { - crm_err("Invalid registration message: %s", msg_type); - crm_log_xml_err(reply, "Bad reply"); - rc = lrmd_err_internal; - } else if (tmp_ticket == NULL) { - crm_err("No registration token provided"); - crm_log_xml_err(reply, "Bad reply"); - rc = lrmd_err_internal; - } else { - crm_trace("Obtained registration token: %s", tmp_ticket); - native->token = crm_strdup(tmp_ticket); - rc = lrmd_ok; - } - } - - free_xml(reply); - free_xml(hello); - } - - return rc; + int rc = lrmd_ok; + lrmd_private_t *native = lrmd->private; + + static struct ipc_client_callbacks lrmd_callbacks = { + .dispatch = lrmd_dispatch_internal, + .destroy = lrmd_connection_destroy + }; + + crm_info("Connecting to lrmd"); + + if (fd) { + /* No mainloop */ + native->ipc = crm_ipc_new("lrmd", 0); + if (native->ipc && crm_ipc_connect(native->ipc)) { + *fd = crm_ipc_get_fd(native->ipc); + } else if (native->ipc) { + rc = lrmd_err_connection; + } + } else { + native->source = mainloop_add_ipc_client("lrmd", 0, lrmd, &lrmd_callbacks); + native->ipc = mainloop_get_ipc_client(native->source); + } + + if (native->ipc == NULL) { + crm_debug("Could not connect to the LRMD API"); + rc = lrmd_err_connection; + } + + if (!rc) { + xmlNode *reply = NULL; + xmlNode *hello = create_xml_node(NULL, "lrmd_command"); + + crm_xml_add(hello, F_TYPE, T_LRMD); + crm_xml_add(hello, F_LRMD_OPERATION, CRM_OP_REGISTER); + crm_xml_add(hello, F_LRMD_CLIENTNAME, name); + + rc = crm_ipc_send(native->ipc, hello, &reply, -1); + + if (rc < 0) { + crm_perror(LOG_DEBUG, "Couldn't complete registration with the lrmd API: %d", rc); + rc = lrmd_err_ipc; + } else if (reply == NULL) { + crm_err("Did not receive registration reply"); + rc = lrmd_err_internal; + } else { + const char *msg_type = crm_element_value(reply, F_LRMD_OPERATION); + const char *tmp_ticket = crm_element_value(reply, F_LRMD_CLIENTID); + + if (safe_str_neq(msg_type, CRM_OP_REGISTER)) { + crm_err("Invalid registration message: %s", msg_type); + crm_log_xml_err(reply, "Bad reply"); + rc = lrmd_err_internal; + } else if (tmp_ticket == NULL) { + crm_err("No registration token provided"); + crm_log_xml_err(reply, "Bad reply"); + rc = lrmd_err_internal; + } else { + crm_trace("Obtained registration token: %s", tmp_ticket); + native->token = crm_strdup(tmp_ticket); + rc = lrmd_ok; + } + } + + free_xml(reply); + free_xml(hello); + } + + return rc; } static int lrmd_api_disconnect(lrmd_t * lrmd) { - lrmd_private_t *native = lrmd->private; - - crm_info("Disconnecting from lrmd service"); - - if (native->source) { - mainloop_del_ipc_client(native->source); - native->source = NULL; - native->ipc = NULL; - } else if (native->ipc) { - crm_ipc_close(native->ipc); - crm_ipc_destroy(native->ipc); - native->source = NULL; - native->ipc = NULL; - } - - free(native->token); - native->token = NULL; - return 0; + lrmd_private_t *native = lrmd->private; + + crm_info("Disconnecting from lrmd service"); + + if (native->source) { + mainloop_del_ipc_client(native->source); + native->source = NULL; + native->ipc = NULL; + } else if (native->ipc) { + crm_ipc_close(native->ipc); + crm_ipc_destroy(native->ipc); + native->source = NULL; + native->ipc = NULL; + } + + free(native->token); + native->token = NULL; + return 0; } static int -lrmd_api_register_rsc(lrmd_t *lrmd, - const char *rsc_id, - const char *class, - const char *provider, - const char *type, - enum lrmd_call_options options) +lrmd_api_register_rsc(lrmd_t * lrmd, + const char *rsc_id, + const char *class, + const char *provider, const char *type, enum lrmd_call_options options) { - int rc = lrmd_ok; - xmlNode *data = NULL; - - if (!class || !type || !rsc_id) { - return lrmd_err_missing; - } - if (safe_str_eq(class, "ocf") && !provider) { - return lrmd_err_provider_required; - } - - data = create_xml_node(NULL, F_LRMD_RSC); - - crm_xml_add(data, F_LRMD_ORIGIN, __FUNCTION__); - crm_xml_add(data, F_LRMD_RSC_ID, rsc_id); - crm_xml_add(data, F_LRMD_CLASS, class); - crm_xml_add(data, F_LRMD_PROVIDER, provider); - crm_xml_add(data, F_LRMD_TYPE, type); - rc = lrmd_send_command(lrmd, LRMD_OP_RSC_REG, data, NULL, 0, options); - free_xml(data); - - return rc; + int rc = lrmd_ok; + xmlNode *data = NULL; + + if (!class || !type || !rsc_id) { + return lrmd_err_missing; + } + if (safe_str_eq(class, "ocf") && !provider) { + return lrmd_err_provider_required; + } + + data = create_xml_node(NULL, F_LRMD_RSC); + + crm_xml_add(data, F_LRMD_ORIGIN, __FUNCTION__); + crm_xml_add(data, F_LRMD_RSC_ID, rsc_id); + crm_xml_add(data, F_LRMD_CLASS, class); + crm_xml_add(data, F_LRMD_PROVIDER, provider); + crm_xml_add(data, F_LRMD_TYPE, type); + rc = lrmd_send_command(lrmd, LRMD_OP_RSC_REG, data, NULL, 0, options); + free_xml(data); + + return rc; } static int -lrmd_api_unregister_rsc(lrmd_t *lrmd, - const char *rsc_id, - enum lrmd_call_options options) +lrmd_api_unregister_rsc(lrmd_t * lrmd, const char *rsc_id, enum lrmd_call_options options) { - int rc = lrmd_ok; - xmlNode *data = create_xml_node(NULL, F_LRMD_RSC); + int rc = lrmd_ok; + xmlNode *data = create_xml_node(NULL, F_LRMD_RSC); - crm_xml_add(data, F_LRMD_ORIGIN, __FUNCTION__); - crm_xml_add(data, F_LRMD_RSC_ID, rsc_id); - rc = lrmd_send_command(lrmd, LRMD_OP_RSC_UNREG, data, NULL, 0, options); - free_xml(data); + crm_xml_add(data, F_LRMD_ORIGIN, __FUNCTION__); + crm_xml_add(data, F_LRMD_RSC_ID, rsc_id); + rc = lrmd_send_command(lrmd, LRMD_OP_RSC_UNREG, data, NULL, 0, options); + free_xml(data); - return rc; + return rc; } -lrmd_rsc_info_t *lrmd_copy_rsc_info(lrmd_rsc_info_t *rsc_info) +lrmd_rsc_info_t * +lrmd_copy_rsc_info(lrmd_rsc_info_t * rsc_info) { - lrmd_rsc_info_t *copy = NULL; + lrmd_rsc_info_t *copy = NULL; - copy = calloc(1, sizeof(lrmd_rsc_info_t)); + copy = calloc(1, sizeof(lrmd_rsc_info_t)); - copy->id = crm_strdup(rsc_info->id); - copy->type = crm_strdup(rsc_info->type); - copy->class = crm_strdup(rsc_info->class); - if (rsc_info->provider) { - copy->provider = crm_strdup(rsc_info->provider); - } + copy->id = crm_strdup(rsc_info->id); + copy->type = crm_strdup(rsc_info->type); + copy->class = crm_strdup(rsc_info->class); + if (rsc_info->provider) { + copy->provider = crm_strdup(rsc_info->provider); + } - return copy; + return copy; } -void lrmd_free_rsc_info(lrmd_rsc_info_t *rsc_info) +void +lrmd_free_rsc_info(lrmd_rsc_info_t * rsc_info) { - if (!rsc_info) { - return; - } - free(rsc_info->id); - free(rsc_info->type); - free(rsc_info->class); - free(rsc_info->provider); - free(rsc_info); + if (!rsc_info) { + return; + } + free(rsc_info->id); + free(rsc_info->type); + free(rsc_info->class); + free(rsc_info->provider); + free(rsc_info); } static lrmd_rsc_info_t * -lrmd_api_get_rsc_info(lrmd_t *lrmd, - const char *rsc_id, - enum lrmd_call_options options) +lrmd_api_get_rsc_info(lrmd_t * lrmd, const char *rsc_id, enum lrmd_call_options options) { - int rc = lrmd_ok; - lrmd_rsc_info_t *rsc_info = NULL; - xmlNode *data = create_xml_node(NULL, F_LRMD_RSC); - xmlNode *output = NULL; - const char *class = NULL; - const char *provider = NULL; - const char *type = NULL; - - crm_xml_add(data, F_LRMD_ORIGIN, __FUNCTION__); - crm_xml_add(data, F_LRMD_RSC_ID, rsc_id); - rc = lrmd_send_command(lrmd, LRMD_OP_RSC_INFO, data, &output, 0, options); - free_xml(data); - - class = crm_element_value(output, F_LRMD_CLASS); - provider = crm_element_value(output, F_LRMD_PROVIDER); - type = crm_element_value(output, F_LRMD_TYPE); - - if (!output) { - return NULL; - } else if (!class || !type) { - free_xml(output); - return NULL; - } else if (safe_str_eq(class, "ocf") && !provider) { - free_xml(output); - return NULL; - } - - rsc_info = calloc(1, sizeof(lrmd_rsc_info_t)); - rsc_info->id = crm_strdup(rsc_id); - rsc_info->class = crm_strdup(class); - if (provider) { - rsc_info->provider = crm_strdup(provider); - } - rsc_info->type = crm_strdup(type); - - free_xml(output); - return rsc_info; + int rc = lrmd_ok; + lrmd_rsc_info_t *rsc_info = NULL; + xmlNode *data = create_xml_node(NULL, F_LRMD_RSC); + xmlNode *output = NULL; + const char *class = NULL; + const char *provider = NULL; + const char *type = NULL; + + crm_xml_add(data, F_LRMD_ORIGIN, __FUNCTION__); + crm_xml_add(data, F_LRMD_RSC_ID, rsc_id); + rc = lrmd_send_command(lrmd, LRMD_OP_RSC_INFO, data, &output, 0, options); + free_xml(data); + + class = crm_element_value(output, F_LRMD_CLASS); + provider = crm_element_value(output, F_LRMD_PROVIDER); + type = crm_element_value(output, F_LRMD_TYPE); + + if (!output) { + return NULL; + } else if (!class || !type) { + free_xml(output); + return NULL; + } else if (safe_str_eq(class, "ocf") && !provider) { + free_xml(output); + return NULL; + } + + rsc_info = calloc(1, sizeof(lrmd_rsc_info_t)); + rsc_info->id = crm_strdup(rsc_id); + rsc_info->class = crm_strdup(class); + if (provider) { + rsc_info->provider = crm_strdup(provider); + } + rsc_info->type = crm_strdup(type); + + free_xml(output); + return rsc_info; } static void -lrmd_api_set_callback(lrmd_t *lrmd, lrmd_event_callback callback) +lrmd_api_set_callback(lrmd_t * lrmd, lrmd_event_callback callback) { - lrmd_private_t *native = lrmd->private; + lrmd_private_t *native = lrmd->private; - native->callback = callback; + native->callback = callback; } static int stonith_get_metadata(const char *provider, const char *type, char **output) { - int rc = lrmd_ok; - stonith_api->cmds->metadata(stonith_api, st_opt_sync_call, type, provider, output, 0); - if (*output == NULL) { - rc = lrmd_err_no_metadata; - } - return rc; + int rc = lrmd_ok; + + stonith_api->cmds->metadata(stonith_api, st_opt_sync_call, type, provider, output, 0); + if (*output == NULL) { + rc = lrmd_err_no_metadata; + } + return rc; } static int lsb_get_metadata(const char *type, char **output) { #define lsb_metadata_template \ "\n"\ "\n"\ "\n"\ " 1.0\n"\ " \n"\ " %s"\ " \n"\ " %s\n"\ " \n"\ " \n"\ " \n"\ " \n"\ " \n"\ " \n"\ " \n"\ " \n"\ " \n"\ " \n"\ " \n"\ " \n"\ " %s\n"\ " %s\n"\ " %s\n"\ " %s\n"\ " %s\n"\ " %s\n"\ " %s\n"\ " \n"\ "\n" #define LSB_INITSCRIPT_INFOBEGIN_TAG "### BEGIN INIT INFO" #define LSB_INITSCRIPT_INFOEND_TAG "### END INIT INFO" #define PROVIDES "# Provides:" #define REQ_START "# Required-Start:" #define REQ_STOP "# Required-Stop:" #define SHLD_START "# Should-Start:" #define SHLD_STOP "# Should-Stop:" #define DFLT_START "# Default-Start:" #define DFLT_STOP "# Default-Stop:" #define SHORT_DSCR "# Short-Description:" #define DESCRIPTION "# Description:" #define lsb_meta_helper_free_value(m) \ if ((m) != NULL) { \ xmlFree(m); \ (m) = NULL; \ } #define lsb_meta_helper_get_value(buffer, ptr, keyword) \ if (!ptr && !strncasecmp(buffer, keyword, strlen(keyword))) { \ (ptr) = (char *)xmlEncodeEntitiesReentrant(NULL, BAD_CAST buffer+strlen(keyword)); \ continue; \ } - char ra_pathname[PATH_MAX] = { 0, }; - FILE *fp; - GString *meta_data = NULL; - char buffer[1024]; - char *provides = NULL; - char *req_start = NULL; - char *req_stop = NULL; - char *shld_start = NULL; - char *shld_stop = NULL; - char *dflt_start = NULL; - char *dflt_stop = NULL; - char *s_dscrpt = NULL; - char *xml_l_dscrpt = NULL; - GString *l_dscrpt = NULL; - - snprintf(ra_pathname, sizeof(ra_pathname), "%s%s%s", - type[0] == '/' ? "" : LSB_ROOT_DIR, - type[0] == '/' ? "" : "/", - type); - - if (!(fp = fopen(ra_pathname, "r"))) { - return lrmd_err_no_metadata; - } - - /* Enter into the lsb-compliant comment block */ - while (fgets(buffer, sizeof(buffer), fp)) { - /* Now suppose each of the following eight arguments contain only one line */ - lsb_meta_helper_get_value(buffer, provides, PROVIDES) - lsb_meta_helper_get_value(buffer, req_start, REQ_START) - lsb_meta_helper_get_value(buffer, req_stop, REQ_STOP) - lsb_meta_helper_get_value(buffer, shld_start, SHLD_START) - lsb_meta_helper_get_value(buffer, shld_stop, SHLD_STOP) - lsb_meta_helper_get_value(buffer, dflt_start, DFLT_START) - lsb_meta_helper_get_value(buffer, dflt_stop, DFLT_STOP) - lsb_meta_helper_get_value(buffer, s_dscrpt, SHORT_DSCR) - - /* Long description may cross multiple lines */ - if ((l_dscrpt == NULL) && (0 == strncasecmp(buffer, DESCRIPTION, strlen(DESCRIPTION))) ) { - l_dscrpt = g_string_new(buffer+strlen(DESCRIPTION)); - /* Between # and keyword, more than one space, or a tab character, - * indicates the continuation line. Extracted from LSB init script standard */ - while (fgets(buffer, sizeof(buffer), fp)) { - if (!strncmp(buffer, "# ", 3) || !strncmp(buffer, "#\t", 2)) { - buffer[0] = ' '; - l_dscrpt = g_string_append(l_dscrpt, buffer); - } else { - fputs(buffer, fp); - break; /* Long description ends */ - } - } - continue; - } - if (l_dscrpt) { - xml_l_dscrpt = (char *)xmlEncodeEntitiesReentrant(NULL, BAD_CAST (l_dscrpt->str)); - } - if (!strncasecmp(buffer, LSB_INITSCRIPT_INFOEND_TAG, strlen(LSB_INITSCRIPT_INFOEND_TAG))) { - /* Get to the out border of LSB comment block */ - break; - } - if (buffer[0] != '#') { - break; /* Out of comment block in the beginning */ - } - } - fclose(fp); - - meta_data = g_string_new(""); - g_string_sprintf(meta_data, lsb_metadata_template, type - , (xml_l_dscrpt == NULL)? type : xml_l_dscrpt - , (s_dscrpt == NULL)? type : s_dscrpt - , (provides == NULL)? "" : provides - , (req_start == NULL)? "" : req_start - , (req_stop == NULL)? "" : req_stop - , (shld_start == NULL)? "" : shld_start - , (shld_stop == NULL)? "" : shld_stop - , (dflt_start == NULL)? "" : dflt_start - , (dflt_stop == NULL)? "" : dflt_stop); - - lsb_meta_helper_free_value(xml_l_dscrpt); - lsb_meta_helper_free_value(s_dscrpt); - lsb_meta_helper_free_value(provides); - lsb_meta_helper_free_value(req_start); - lsb_meta_helper_free_value(req_stop); - lsb_meta_helper_free_value(shld_start); - lsb_meta_helper_free_value(shld_stop); - lsb_meta_helper_free_value(dflt_start); - lsb_meta_helper_free_value(dflt_stop); - - if (l_dscrpt) { - g_string_free(l_dscrpt, TRUE); - } - - *output = crm_strdup(meta_data->str); - g_string_free(meta_data, TRUE); - - return lrmd_ok; + char ra_pathname[PATH_MAX] = { 0, }; + FILE *fp; + GString *meta_data = NULL; + char buffer[1024]; + char *provides = NULL; + char *req_start = NULL; + char *req_stop = NULL; + char *shld_start = NULL; + char *shld_stop = NULL; + char *dflt_start = NULL; + char *dflt_stop = NULL; + char *s_dscrpt = NULL; + char *xml_l_dscrpt = NULL; + GString *l_dscrpt = NULL; + + snprintf(ra_pathname, sizeof(ra_pathname), "%s%s%s", + type[0] == '/' ? "" : LSB_ROOT_DIR, type[0] == '/' ? "" : "/", type); + + if (!(fp = fopen(ra_pathname, "r"))) { + return lrmd_err_no_metadata; + } + + /* Enter into the lsb-compliant comment block */ + while (fgets(buffer, sizeof(buffer), fp)) { + /* Now suppose each of the following eight arguments contain only one line */ + lsb_meta_helper_get_value(buffer, provides, PROVIDES) + lsb_meta_helper_get_value(buffer, req_start, REQ_START) + lsb_meta_helper_get_value(buffer, req_stop, REQ_STOP) + lsb_meta_helper_get_value(buffer, shld_start, SHLD_START) + lsb_meta_helper_get_value(buffer, shld_stop, SHLD_STOP) + lsb_meta_helper_get_value(buffer, dflt_start, DFLT_START) + lsb_meta_helper_get_value(buffer, dflt_stop, DFLT_STOP) + lsb_meta_helper_get_value(buffer, s_dscrpt, SHORT_DSCR) + + /* Long description may cross multiple lines */ + if ((l_dscrpt == NULL) && (0 == strncasecmp(buffer, DESCRIPTION, strlen(DESCRIPTION)))) { + l_dscrpt = g_string_new(buffer + strlen(DESCRIPTION)); + /* Between # and keyword, more than one space, or a tab character, + * indicates the continuation line. Extracted from LSB init script standard */ + while (fgets(buffer, sizeof(buffer), fp)) { + if (!strncmp(buffer, "# ", 3) || !strncmp(buffer, "#\t", 2)) { + buffer[0] = ' '; + l_dscrpt = g_string_append(l_dscrpt, buffer); + } else { + fputs(buffer, fp); + break; /* Long description ends */ + } + } + continue; + } + if (l_dscrpt) { + xml_l_dscrpt = (char *)xmlEncodeEntitiesReentrant(NULL, BAD_CAST(l_dscrpt->str)); + } + if (!strncasecmp(buffer, LSB_INITSCRIPT_INFOEND_TAG, strlen(LSB_INITSCRIPT_INFOEND_TAG))) { + /* Get to the out border of LSB comment block */ + break; + } + if (buffer[0] != '#') { + break; /* Out of comment block in the beginning */ + } + } + fclose(fp); + + meta_data = g_string_new(""); + g_string_sprintf(meta_data, lsb_metadata_template, type, + (xml_l_dscrpt == NULL) ? type : xml_l_dscrpt, + (s_dscrpt == NULL) ? type : s_dscrpt, (provides == NULL) ? "" : provides, + (req_start == NULL) ? "" : req_start, (req_stop == NULL) ? "" : req_stop, + (shld_start == NULL) ? "" : shld_start, (shld_stop == NULL) ? "" : shld_stop, + (dflt_start == NULL) ? "" : dflt_start, (dflt_stop == NULL) ? "" : dflt_stop); + + lsb_meta_helper_free_value(xml_l_dscrpt); + lsb_meta_helper_free_value(s_dscrpt); + lsb_meta_helper_free_value(provides); + lsb_meta_helper_free_value(req_start); + lsb_meta_helper_free_value(req_stop); + lsb_meta_helper_free_value(shld_start); + lsb_meta_helper_free_value(shld_stop); + lsb_meta_helper_free_value(dflt_start); + lsb_meta_helper_free_value(dflt_stop); + + if (l_dscrpt) { + g_string_free(l_dscrpt, TRUE); + } + + *output = crm_strdup(meta_data->str); + g_string_free(meta_data, TRUE); + + return lrmd_ok; } static int ocf_get_metadata(const char *provider, const char *type, char **output) { - svc_action_t *action = resources_action_create("get_meta", - "ocf", - provider, - type, - "meta-data", - 0, - 5000, - NULL); - - if (!(services_action_sync(action))) { - crm_err("Failed to retrieve meta-data for ocf:%s:%s", provider, type); - services_action_free(action); - return lrmd_err_no_metadata; - } - - if (!action->stdout_data) { - crm_err("Failed to retrieve meta-data for ocf:%s:%s", provider, type); - services_action_free(action); - return lrmd_err_no_metadata; - } - - *output = crm_strdup(action->stdout_data); - services_action_free(action); - - return lrmd_ok; + svc_action_t *action = resources_action_create("get_meta", + "ocf", + provider, + type, + "meta-data", + 0, + 5000, + NULL); + + if (!(services_action_sync(action))) { + crm_err("Failed to retrieve meta-data for ocf:%s:%s", provider, type); + services_action_free(action); + return lrmd_err_no_metadata; + } + + if (!action->stdout_data) { + crm_err("Failed to retrieve meta-data for ocf:%s:%s", provider, type); + services_action_free(action); + return lrmd_err_no_metadata; + } + + *output = crm_strdup(action->stdout_data); + services_action_free(action); + + return lrmd_ok; } static int -lrmd_api_get_metadata(lrmd_t *lrmd, - const char *class, - const char *provider, - const char *type, - char **output, - enum lrmd_call_options options) +lrmd_api_get_metadata(lrmd_t * lrmd, + const char *class, + const char *provider, + const char *type, char **output, enum lrmd_call_options options) { - if (!class || !type) { - return lrmd_err_missing; - } + if (!class || !type) { + return lrmd_err_missing; + } - if (safe_str_eq(class, "stonith")) { - return stonith_get_metadata(provider, type, output); - } else if (safe_str_eq(class, "ocf")) { - return ocf_get_metadata(provider, type, output); - } else if (safe_str_eq(class, "lsb")) { - return lsb_get_metadata(type, output); - } + if (safe_str_eq(class, "stonith")) { + return stonith_get_metadata(provider, type, output); + } else if (safe_str_eq(class, "ocf")) { + return ocf_get_metadata(provider, type, output); + } else if (safe_str_eq(class, "lsb")) { + return lsb_get_metadata(type, output); + } - return lrmd_err_no_metadata; + return lrmd_err_no_metadata; } static int -lrmd_api_exec(lrmd_t *lrmd, - const char *rsc_id, - const char *action, - const char *userdata, - int interval, /* ms */ - int timeout, /* ms */ - int start_delay, /* ms */ - enum lrmd_call_options options, - lrmd_key_value_t *params) +lrmd_api_exec(lrmd_t * lrmd, const char *rsc_id, const char *action, const char *userdata, int interval, /* ms */ + int timeout, /* ms */ + int start_delay, /* ms */ + enum lrmd_call_options options, lrmd_key_value_t * params) { - int rc = lrmd_ok; - xmlNode *data = create_xml_node(NULL, F_LRMD_RSC); - xmlNode *args = create_xml_node(data, XML_TAG_ATTRS); - - crm_xml_add(data, F_LRMD_ORIGIN, __FUNCTION__); - crm_xml_add(data, F_LRMD_RSC_ID, rsc_id); - crm_xml_add(data, F_LRMD_RSC_ACTION, action); - crm_xml_add(data, F_LRMD_RSC_USERDATA_STR, userdata); - crm_xml_add_int(data, F_LRMD_RSC_INTERVAL, interval); - crm_xml_add_int(data, F_LRMD_TIMEOUT, timeout); - crm_xml_add_int(data, F_LRMD_RSC_START_DELAY, start_delay); - - for (; params; params = params->next) { - hash2field((gpointer) params->key, (gpointer) params->value, args); - } - - rc = lrmd_send_command(lrmd, LRMD_OP_RSC_EXEC, data, NULL, timeout, options); - free_xml(data); - - lrmd_key_value_freeall(params); - return rc; + int rc = lrmd_ok; + xmlNode *data = create_xml_node(NULL, F_LRMD_RSC); + xmlNode *args = create_xml_node(data, XML_TAG_ATTRS); + + crm_xml_add(data, F_LRMD_ORIGIN, __FUNCTION__); + crm_xml_add(data, F_LRMD_RSC_ID, rsc_id); + crm_xml_add(data, F_LRMD_RSC_ACTION, action); + crm_xml_add(data, F_LRMD_RSC_USERDATA_STR, userdata); + crm_xml_add_int(data, F_LRMD_RSC_INTERVAL, interval); + crm_xml_add_int(data, F_LRMD_TIMEOUT, timeout); + crm_xml_add_int(data, F_LRMD_RSC_START_DELAY, start_delay); + + for (; params; params = params->next) { + hash2field((gpointer) params->key, (gpointer) params->value, args); + } + + rc = lrmd_send_command(lrmd, LRMD_OP_RSC_EXEC, data, NULL, timeout, options); + free_xml(data); + + lrmd_key_value_freeall(params); + return rc; } static int -lrmd_api_cancel(lrmd_t *lrmd, - const char *rsc_id, - const char *action, - int interval) +lrmd_api_cancel(lrmd_t * lrmd, const char *rsc_id, const char *action, int interval) { - int rc = lrmd_ok; - xmlNode *data = create_xml_node(NULL, F_LRMD_RSC); - - crm_xml_add(data, F_LRMD_ORIGIN, __FUNCTION__); - crm_xml_add(data, F_LRMD_RSC_ACTION, action); - crm_xml_add(data, F_LRMD_RSC_ID, rsc_id); - crm_xml_add_int(data, F_LRMD_RSC_INTERVAL, interval); - rc = lrmd_send_command(lrmd, LRMD_OP_RSC_CANCEL, data, NULL, 0, 0); - free_xml(data); - return rc; + int rc = lrmd_ok; + xmlNode *data = create_xml_node(NULL, F_LRMD_RSC); + + crm_xml_add(data, F_LRMD_ORIGIN, __FUNCTION__); + crm_xml_add(data, F_LRMD_RSC_ACTION, action); + crm_xml_add(data, F_LRMD_RSC_ID, rsc_id); + crm_xml_add_int(data, F_LRMD_RSC_INTERVAL, interval); + rc = lrmd_send_command(lrmd, LRMD_OP_RSC_CANCEL, data, NULL, 0, 0); + free_xml(data); + return rc; } static int -list_stonith_agents(lrmd_list_t **resources) +list_stonith_agents(lrmd_list_t ** resources) { - int rc = 0; - stonith_key_value_t *stonith_resources = NULL; - stonith_key_value_t *dIter = NULL; + int rc = 0; + stonith_key_value_t *stonith_resources = NULL; + stonith_key_value_t *dIter = NULL; - stonith_api->cmds->list(stonith_api, st_opt_sync_call, NULL, &stonith_resources, 0); + stonith_api->cmds->list(stonith_api, st_opt_sync_call, NULL, &stonith_resources, 0); - for (dIter = stonith_resources; dIter; dIter = dIter->next) { - rc++; - *resources = lrmd_list_add(*resources, dIter->value); - } + for (dIter = stonith_resources; dIter; dIter = dIter->next) { + rc++; + *resources = lrmd_list_add(*resources, dIter->value); + } - stonith_key_value_freeall(stonith_resources, 1, 0); - return rc; + stonith_key_value_freeall(stonith_resources, 1, 0); + return rc; } static int -list_lsb_agents(lrmd_list_t **resources) +list_lsb_agents(lrmd_list_t ** resources) { - int rc = 0; - GListPtr gIter = NULL; - GList *agents = NULL; - - agents = resources_list_agents("lsb", NULL); - for (gIter = agents; gIter != NULL; gIter = gIter->next) { - *resources = lrmd_list_add(*resources, (const char *) gIter->data); - rc++; - } - g_list_free_full(agents, free); - return rc; + int rc = 0; + GListPtr gIter = NULL; + GList *agents = NULL; + + agents = resources_list_agents("lsb", NULL); + for (gIter = agents; gIter != NULL; gIter = gIter->next) { + *resources = lrmd_list_add(*resources, (const char *)gIter->data); + rc++; + } + g_list_free_full(agents, free); + return rc; } static int -list_service_agents(lrmd_list_t **resources) +list_service_agents(lrmd_list_t ** resources) { - int rc = 0; - GListPtr gIter = NULL; - GList *agents = NULL; - - agents = resources_list_agents("service", NULL); - for (gIter = agents; gIter != NULL; gIter = gIter->next) { - *resources = lrmd_list_add(*resources, (const char *) gIter->data); - rc++; - } - g_list_free_full(agents, free); - return rc; + int rc = 0; + GListPtr gIter = NULL; + GList *agents = NULL; + + agents = resources_list_agents("service", NULL); + for (gIter = agents; gIter != NULL; gIter = gIter->next) { + *resources = lrmd_list_add(*resources, (const char *)gIter->data); + rc++; + } + g_list_free_full(agents, free); + return rc; } static int -list_systemd_agents(lrmd_list_t **resources) +list_systemd_agents(lrmd_list_t ** resources) { - int rc = 0; - GListPtr gIter = NULL; - GList *agents = NULL; - - agents = resources_list_agents("systemd", NULL); - for (gIter = agents; gIter != NULL; gIter = gIter->next) { - *resources = lrmd_list_add(*resources, (const char *) gIter->data); - rc++; - } - g_list_free_full(agents, free); - return rc; + int rc = 0; + GListPtr gIter = NULL; + GList *agents = NULL; + + agents = resources_list_agents("systemd", NULL); + for (gIter = agents; gIter != NULL; gIter = gIter->next) { + *resources = lrmd_list_add(*resources, (const char *)gIter->data); + rc++; + } + g_list_free_full(agents, free); + return rc; } static int -list_ocf_agents(lrmd_list_t **resources, const char *list_provider) +list_ocf_agents(lrmd_list_t ** resources, const char *list_provider) { - int rc = 0; - char *provider = NULL; - GList *ocf_providers = NULL; - GList *agents = NULL; - GListPtr gIter = NULL; - GListPtr gIter2 = NULL; - - ocf_providers = resources_list_providers("ocf"); - - for (gIter = ocf_providers; gIter != NULL; gIter = gIter->next) { - provider = gIter->data; - - if (list_provider && !safe_str_eq(list_provider, provider)) { - continue; - } - agents = resources_list_agents("ocf", provider); - for (gIter2 = agents; gIter2 != NULL; gIter2 = gIter2->next) { - *resources = lrmd_list_add(*resources, (const char *) gIter2->data); - rc++; - } - g_list_free_full(agents, free); - } - - g_list_free_full(ocf_providers, free); - return rc; + int rc = 0; + char *provider = NULL; + GList *ocf_providers = NULL; + GList *agents = NULL; + GListPtr gIter = NULL; + GListPtr gIter2 = NULL; + + ocf_providers = resources_list_providers("ocf"); + + for (gIter = ocf_providers; gIter != NULL; gIter = gIter->next) { + provider = gIter->data; + + if (list_provider && !safe_str_eq(list_provider, provider)) { + continue; + } + agents = resources_list_agents("ocf", provider); + for (gIter2 = agents; gIter2 != NULL; gIter2 = gIter2->next) { + *resources = lrmd_list_add(*resources, (const char *)gIter2->data); + rc++; + } + g_list_free_full(agents, free); + } + + g_list_free_full(ocf_providers, free); + return rc; } static int -lrmd_api_list_agents(lrmd_t *lrmd, lrmd_list_t **resources, const char *class, const char *provider) +lrmd_api_list_agents(lrmd_t * lrmd, lrmd_list_t ** resources, const char *class, + const char *provider) { - int rc = lrmd_ok; - - if (safe_str_eq(class, "ocf")) { - rc += list_ocf_agents(resources, provider); - } else if (safe_str_eq(class, "lsb")) { - rc += list_lsb_agents(resources); - } else if (safe_str_eq(class, "systemd")) { - rc += list_systemd_agents(resources); - } else if (safe_str_eq(class, "service")) { - rc += list_service_agents(resources); - } else if (safe_str_eq(class, "stonith")) { - rc += list_stonith_agents(resources); - } else if (!class) { - rc += list_ocf_agents(resources, provider); - rc += list_systemd_agents(resources); - rc += list_lsb_agents(resources); - rc += list_stonith_agents(resources); - } else { - crm_err("Unknown class %s", class); - rc = lrmd_err_generic; - } - - return rc; + int rc = lrmd_ok; + + if (safe_str_eq(class, "ocf")) { + rc += list_ocf_agents(resources, provider); + } else if (safe_str_eq(class, "lsb")) { + rc += list_lsb_agents(resources); + } else if (safe_str_eq(class, "systemd")) { + rc += list_systemd_agents(resources); + } else if (safe_str_eq(class, "service")) { + rc += list_service_agents(resources); + } else if (safe_str_eq(class, "stonith")) { + rc += list_stonith_agents(resources); + } else if (!class) { + rc += list_ocf_agents(resources, provider); + rc += list_systemd_agents(resources); + rc += list_lsb_agents(resources); + rc += list_stonith_agents(resources); + } else { + crm_err("Unknown class %s", class); + rc = lrmd_err_generic; + } + + return rc; } static int does_provider_have_agent(const char *agent, const char *provider, const char *class) { - int found = 0; - GList *agents = NULL; - GListPtr gIter2 = NULL; - agents = resources_list_agents(class, provider); - for (gIter2 = agents; gIter2 != NULL; gIter2 = gIter2->next) { - if (safe_str_eq(agent, gIter2->data)) { - found = 1; - } - } - g_list_free_full(agents, free); - - return found; + int found = 0; + GList *agents = NULL; + GListPtr gIter2 = NULL; + + agents = resources_list_agents(class, provider); + for (gIter2 = agents; gIter2 != NULL; gIter2 = gIter2->next) { + if (safe_str_eq(agent, gIter2->data)) { + found = 1; + } + } + g_list_free_full(agents, free); + + return found; } static int -lrmd_api_list_ocf_providers(lrmd_t *lrmd, const char *agent, lrmd_list_t **providers) +lrmd_api_list_ocf_providers(lrmd_t * lrmd, const char *agent, lrmd_list_t ** providers) { - int rc = lrmd_ok; - char *provider = NULL; - GList *ocf_providers = NULL; - GListPtr gIter = NULL; - - ocf_providers = resources_list_providers("ocf"); - - for (gIter = ocf_providers; gIter != NULL; gIter = gIter->next) { - provider = gIter->data; - if (!agent || does_provider_have_agent(agent, provider, "ocf")) { - *providers = lrmd_list_add(*providers, (const char *) gIter->data); - rc++; - } - } + int rc = lrmd_ok; + char *provider = NULL; + GList *ocf_providers = NULL; + GListPtr gIter = NULL; + + ocf_providers = resources_list_providers("ocf"); - g_list_free_full(ocf_providers, free); + for (gIter = ocf_providers; gIter != NULL; gIter = gIter->next) { + provider = gIter->data; + if (!agent || does_provider_have_agent(agent, provider, "ocf")) { + *providers = lrmd_list_add(*providers, (const char *)gIter->data); + rc++; + } + } - return rc; + g_list_free_full(ocf_providers, free); + + return rc; } lrmd_t * lrmd_api_new(void) { - lrmd_t *new_lrmd = NULL; - lrmd_private_t *pvt = NULL; - - new_lrmd = calloc(1, sizeof(lrmd_t)); - pvt = calloc(1, sizeof(lrmd_private_t)); - new_lrmd->cmds = calloc(1, sizeof(lrmd_api_operations_t)); - - new_lrmd->private = pvt; - - new_lrmd->cmds->connect = lrmd_api_connect; - new_lrmd->cmds->disconnect = lrmd_api_disconnect; - new_lrmd->cmds->register_rsc = lrmd_api_register_rsc; - new_lrmd->cmds->unregister_rsc = lrmd_api_unregister_rsc; - new_lrmd->cmds->get_rsc_info = lrmd_api_get_rsc_info; - new_lrmd->cmds->set_callback = lrmd_api_set_callback; - new_lrmd->cmds->get_metadata = lrmd_api_get_metadata; - new_lrmd->cmds->exec = lrmd_api_exec; - new_lrmd->cmds->cancel = lrmd_api_cancel; - new_lrmd->cmds->list_agents = lrmd_api_list_agents; - new_lrmd->cmds->list_ocf_providers = lrmd_api_list_ocf_providers; - - if (!stonith_api) { - stonith_api = stonith_api_new(); - } - - return new_lrmd; + lrmd_t *new_lrmd = NULL; + lrmd_private_t *pvt = NULL; + + new_lrmd = calloc(1, sizeof(lrmd_t)); + pvt = calloc(1, sizeof(lrmd_private_t)); + new_lrmd->cmds = calloc(1, sizeof(lrmd_api_operations_t)); + + new_lrmd->private = pvt; + + new_lrmd->cmds->connect = lrmd_api_connect; + new_lrmd->cmds->disconnect = lrmd_api_disconnect; + new_lrmd->cmds->register_rsc = lrmd_api_register_rsc; + new_lrmd->cmds->unregister_rsc = lrmd_api_unregister_rsc; + new_lrmd->cmds->get_rsc_info = lrmd_api_get_rsc_info; + new_lrmd->cmds->set_callback = lrmd_api_set_callback; + new_lrmd->cmds->get_metadata = lrmd_api_get_metadata; + new_lrmd->cmds->exec = lrmd_api_exec; + new_lrmd->cmds->cancel = lrmd_api_cancel; + new_lrmd->cmds->list_agents = lrmd_api_list_agents; + new_lrmd->cmds->list_ocf_providers = lrmd_api_list_ocf_providers; + + if (!stonith_api) { + stonith_api = stonith_api_new(); + } + + return new_lrmd; } void lrmd_api_delete(lrmd_t * lrmd) { - lrmd->cmds->disconnect(lrmd); /* no-op if already disconnected */ - free(lrmd->cmds); - free(lrmd->private); - free(lrmd); + lrmd->cmds->disconnect(lrmd); /* no-op if already disconnected */ + free(lrmd->cmds); + free(lrmd->private); + free(lrmd); } diff --git a/lrmd/lrmd.c b/lrmd/lrmd.c index b66a4e857d..1231ab1f92 100644 --- a/lrmd/lrmd.c +++ b/lrmd/lrmd.c @@ -1,983 +1,971 @@ /* * Copyright (c) 2012 David Vossel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ #include #include #include #include #include #include #include #include #include #ifdef HAVE_SYS_TIMEB_H -#include +# include #endif GHashTable *rsc_list = NULL; GHashTable *client_list = NULL; typedef struct lrmd_cmd_s { - int timeout; - int interval; - int start_delay; + int timeout; + int interval; + int start_delay; - int call_id; - int exec_rc; - int lrmd_op_status; + int call_id; + int exec_rc; + int lrmd_op_status; - /* Timer ids, must be removed on cmd destruction. */ - int delay_id; - int stonith_recurring_id; + /* Timer ids, must be removed on cmd destruction. */ + int delay_id; + int stonith_recurring_id; - int rsc_deleted; + int rsc_deleted; - char *only_notify_client; - char *origin; - char *rsc_id; - char *action; - char *output; - char *userdata_str; + char *only_notify_client; + char *origin; + char *rsc_id; + char *action; + char *output; + char *userdata_str; #ifdef HAVE_SYS_TIMEB_H - /* Timestamp of when op ran */ - struct timeb t_run; - /* Timestamp of when op was queued */ - struct timeb t_queue; - /* Timestamp of last rc change */ - struct timeb t_rcchange; + /* Timestamp of when op ran */ + struct timeb t_run; + /* Timestamp of when op was queued */ + struct timeb t_queue; + /* Timestamp of last rc change */ + struct timeb t_rcchange; #endif - GHashTable *params; + GHashTable *params; } lrmd_cmd_t; -static void cmd_finalize(lrmd_cmd_t *cmd, lrmd_rsc_t *rsc); +static void cmd_finalize(lrmd_cmd_t * cmd, lrmd_rsc_t * rsc); static gboolean lrmd_rsc_dispatch(gpointer user_data); static lrmd_rsc_t * -build_rsc_from_xml(xmlNode *msg) +build_rsc_from_xml(xmlNode * msg) { - xmlNode *rsc_xml = get_xpath_object("//"F_LRMD_RSC, msg, LOG_ERR); - lrmd_rsc_t *rsc = NULL; + xmlNode *rsc_xml = get_xpath_object("//" F_LRMD_RSC, msg, LOG_ERR); + lrmd_rsc_t *rsc = NULL; - rsc = calloc(1, sizeof(lrmd_rsc_t)); - rsc->rsc_id = crm_element_value_copy(rsc_xml, F_LRMD_RSC_ID); - rsc->class = crm_element_value_copy(rsc_xml, F_LRMD_CLASS); - rsc->provider = crm_element_value_copy(rsc_xml, F_LRMD_PROVIDER); - rsc->type = crm_element_value_copy(rsc_xml, F_LRMD_TYPE); - rsc->work = mainloop_add_trigger(G_PRIORITY_HIGH, lrmd_rsc_dispatch, rsc); - return rsc; + rsc = calloc(1, sizeof(lrmd_rsc_t)); + rsc->rsc_id = crm_element_value_copy(rsc_xml, F_LRMD_RSC_ID); + rsc->class = crm_element_value_copy(rsc_xml, F_LRMD_CLASS); + rsc->provider = crm_element_value_copy(rsc_xml, F_LRMD_PROVIDER); + rsc->type = crm_element_value_copy(rsc_xml, F_LRMD_TYPE); + rsc->work = mainloop_add_trigger(G_PRIORITY_HIGH, lrmd_rsc_dispatch, rsc); + return rsc; } static lrmd_cmd_t * -create_lrmd_cmd(xmlNode *msg, lrmd_client_t *client) +create_lrmd_cmd(xmlNode * msg, lrmd_client_t * client) { - int call_options = 0; - xmlNode *rsc_xml = get_xpath_object("//"F_LRMD_RSC, msg, LOG_ERR); - lrmd_cmd_t *cmd = NULL; + int call_options = 0; + xmlNode *rsc_xml = get_xpath_object("//" F_LRMD_RSC, msg, LOG_ERR); + lrmd_cmd_t *cmd = NULL; - cmd = calloc(1, sizeof(lrmd_cmd_t)); + cmd = calloc(1, sizeof(lrmd_cmd_t)); - crm_element_value_int(msg, F_LRMD_CALLOPTS, &call_options); + crm_element_value_int(msg, F_LRMD_CALLOPTS, &call_options); - if (call_options & lrmd_opt_notify_orig_only) { - cmd->only_notify_client = crm_strdup(client->id); - } + if (call_options & lrmd_opt_notify_orig_only) { + cmd->only_notify_client = crm_strdup(client->id); + } - crm_element_value_int(msg, F_LRMD_CALLID, &cmd->call_id); - crm_element_value_int(rsc_xml, F_LRMD_RSC_INTERVAL, &cmd->interval); - crm_element_value_int(rsc_xml, F_LRMD_TIMEOUT, &cmd->timeout); - crm_element_value_int(rsc_xml, F_LRMD_RSC_START_DELAY, &cmd->start_delay); + crm_element_value_int(msg, F_LRMD_CALLID, &cmd->call_id); + crm_element_value_int(rsc_xml, F_LRMD_RSC_INTERVAL, &cmd->interval); + crm_element_value_int(rsc_xml, F_LRMD_TIMEOUT, &cmd->timeout); + crm_element_value_int(rsc_xml, F_LRMD_RSC_START_DELAY, &cmd->start_delay); - cmd->origin = crm_element_value_copy(rsc_xml, F_LRMD_ORIGIN); - cmd->action = crm_element_value_copy(rsc_xml, F_LRMD_RSC_ACTION); - cmd->userdata_str = crm_element_value_copy(rsc_xml, F_LRMD_RSC_USERDATA_STR); - cmd->rsc_id = crm_element_value_copy(rsc_xml, F_LRMD_RSC_ID); + cmd->origin = crm_element_value_copy(rsc_xml, F_LRMD_ORIGIN); + cmd->action = crm_element_value_copy(rsc_xml, F_LRMD_RSC_ACTION); + cmd->userdata_str = crm_element_value_copy(rsc_xml, F_LRMD_RSC_USERDATA_STR); + cmd->rsc_id = crm_element_value_copy(rsc_xml, F_LRMD_RSC_ID); - cmd->params = xml2list(rsc_xml); + cmd->params = xml2list(rsc_xml); - return cmd; + return cmd; } static void -free_lrmd_cmd(lrmd_cmd_t *cmd) -{ - if (cmd->stonith_recurring_id) { - g_source_remove(cmd->stonith_recurring_id); - } - if (cmd->delay_id) { - g_source_remove(cmd->delay_id); - } - if (cmd->params) { - g_hash_table_destroy(cmd->params); - } - free(cmd->origin); - free(cmd->action); - free(cmd->userdata_str); - free(cmd->rsc_id); - free(cmd->output); - free(cmd->only_notify_client); - free(cmd); +free_lrmd_cmd(lrmd_cmd_t * cmd) +{ + if (cmd->stonith_recurring_id) { + g_source_remove(cmd->stonith_recurring_id); + } + if (cmd->delay_id) { + g_source_remove(cmd->delay_id); + } + if (cmd->params) { + g_hash_table_destroy(cmd->params); + } + free(cmd->origin); + free(cmd->action); + free(cmd->userdata_str); + free(cmd->rsc_id); + free(cmd->output); + free(cmd->only_notify_client); + free(cmd); } static gboolean stonith_recurring_op_helper(gpointer data) { - lrmd_cmd_t *cmd = data; - lrmd_rsc_t *rsc = NULL; + lrmd_cmd_t *cmd = data; + lrmd_rsc_t *rsc = NULL; - cmd->stonith_recurring_id = 0; + cmd->stonith_recurring_id = 0; - rsc = cmd->rsc_id ? g_hash_table_lookup(rsc_list, cmd->rsc_id) : NULL; - CRM_ASSERT(rsc != NULL); + rsc = cmd->rsc_id ? g_hash_table_lookup(rsc_list, cmd->rsc_id) : NULL; + CRM_ASSERT(rsc != NULL); - /* take it out of recurring_ops list, and put it in the pending ops - * to be executed */ - rsc->recurring_ops = g_list_remove(rsc->recurring_ops, cmd); - rsc->pending_ops = g_list_append(rsc->pending_ops, cmd); + /* take it out of recurring_ops list, and put it in the pending ops + * to be executed */ + rsc->recurring_ops = g_list_remove(rsc->recurring_ops, cmd); + rsc->pending_ops = g_list_append(rsc->pending_ops, cmd); #ifdef HAVE_SYS_TIMEB_H - ftime(&cmd->t_queue); + ftime(&cmd->t_queue); #endif - mainloop_set_trigger(rsc->work); + mainloop_set_trigger(rsc->work); - return FALSE; + return FALSE; } static gboolean start_delay_helper(gpointer data) { - lrmd_cmd_t *cmd = data; - lrmd_rsc_t *rsc = NULL; + lrmd_cmd_t *cmd = data; + lrmd_rsc_t *rsc = NULL; - cmd->delay_id = 0; - rsc = cmd->rsc_id ? g_hash_table_lookup(rsc_list, cmd->rsc_id) : NULL; + cmd->delay_id = 0; + rsc = cmd->rsc_id ? g_hash_table_lookup(rsc_list, cmd->rsc_id) : NULL; - if (rsc) { - mainloop_set_trigger(rsc->work); - } + if (rsc) { + mainloop_set_trigger(rsc->work); + } - return FALSE; + return FALSE; } static void -schedule_lrmd_cmd(lrmd_rsc_t *rsc, lrmd_cmd_t *cmd) +schedule_lrmd_cmd(lrmd_rsc_t * rsc, lrmd_cmd_t * cmd) { - CRM_CHECK(cmd != NULL, return); - CRM_CHECK(rsc != NULL, return); + CRM_CHECK(cmd != NULL, return); + CRM_CHECK(rsc != NULL, return); - crm_trace("Scheduling %s on %s", cmd->action, rsc->rsc_id); - rsc->pending_ops = g_list_append(rsc->pending_ops, cmd); + crm_trace("Scheduling %s on %s", cmd->action, rsc->rsc_id); + rsc->pending_ops = g_list_append(rsc->pending_ops, cmd); #ifdef HAVE_SYS_TIMEB_H - ftime(&cmd->t_queue); + ftime(&cmd->t_queue); #endif - mainloop_set_trigger(rsc->work); + mainloop_set_trigger(rsc->work); - if (cmd->start_delay) { - cmd->delay_id = g_timeout_add(cmd->start_delay, start_delay_helper, cmd); - } + if (cmd->start_delay) { + cmd->delay_id = g_timeout_add(cmd->start_delay, start_delay_helper, cmd); + } } static void -send_reply(lrmd_client_t *client, int rc, int call_id) +send_reply(lrmd_client_t * client, int rc, int call_id) { - int send_rc = 0; - xmlNode *reply = NULL; + int send_rc = 0; + xmlNode *reply = NULL; - reply = create_xml_node(NULL, T_LRMD_REPLY); - crm_xml_add(reply, F_LRMD_ORIGIN, __FUNCTION__); - crm_xml_add_int(reply, F_LRMD_RC, rc); - crm_xml_add_int(reply, F_LRMD_CALLID, call_id); + reply = create_xml_node(NULL, T_LRMD_REPLY); + crm_xml_add(reply, F_LRMD_ORIGIN, __FUNCTION__); + crm_xml_add_int(reply, F_LRMD_RC, rc); + crm_xml_add_int(reply, F_LRMD_CALLID, call_id); - send_rc = crm_ipcs_send(client->channel, reply, FALSE); + send_rc = crm_ipcs_send(client->channel, reply, FALSE); - free_xml(reply); - if (send_rc < 0) { - crm_warn("LRMD reply to %s failed: %d", client->name, send_rc); - } + free_xml(reply); + if (send_rc < 0) { + crm_warn("LRMD reply to %s failed: %d", client->name, send_rc); + } } static void send_client_notify(gpointer key, gpointer value, gpointer user_data) { - xmlNode *update_msg = user_data; - lrmd_client_t *client = value; - - if (client == NULL) { - crm_err("Asked to send event to NULL client"); - return; - } else if (client->channel == NULL) { - crm_trace("Asked to send event to disconnected client"); - return; - } else if (client->name == NULL) { - crm_trace("Asked to send event to client with no name"); - return; - } + xmlNode *update_msg = user_data; + lrmd_client_t *client = value; + + if (client == NULL) { + crm_err("Asked to send event to NULL client"); + return; + } else if (client->channel == NULL) { + crm_trace("Asked to send event to disconnected client"); + return; + } else if (client->name == NULL) { + crm_trace("Asked to send event to client with no name"); + return; + } - if (crm_ipcs_send(client->channel, update_msg, TRUE) <= 0) { - crm_warn("Notification of client %s/%s failed", - client->name, client->id); - } + if (crm_ipcs_send(client->channel, update_msg, TRUE) <= 0) { + crm_warn("Notification of client %s/%s failed", client->name, client->id); + } } #ifdef HAVE_SYS_TIMEB_H static int time_diff_ms(struct timeb *now, struct timeb *old) { - int sec = difftime(now->time, old->time); - int ms = now->millitm - old->millitm; + int sec = difftime(now->time, old->time); + int ms = now->millitm - old->millitm; - if (old->time == 0) { - return 0; - } + if (old->time == 0) { + return 0; + } - return (sec * 1000) + ms; + return (sec * 1000) + ms; } #endif static void -send_cmd_complete_notify(lrmd_cmd_t *cmd) +send_cmd_complete_notify(lrmd_cmd_t * cmd) { #ifdef HAVE_SYS_TIMEB_H - struct timeb now = { 0, }; + struct timeb now = { 0, }; #endif - xmlNode *notify = NULL; - notify = create_xml_node(NULL, T_LRMD_NOTIFY); - - crm_xml_add(notify, F_LRMD_ORIGIN, __FUNCTION__); - crm_xml_add_int(notify, F_LRMD_TIMEOUT, cmd->timeout); - crm_xml_add_int(notify, F_LRMD_RSC_INTERVAL, cmd->interval); - crm_xml_add_int(notify, F_LRMD_RSC_START_DELAY, cmd->start_delay); - crm_xml_add_int(notify, F_LRMD_EXEC_RC, cmd->exec_rc); - crm_xml_add_int(notify, F_LRMD_OP_STATUS, cmd->lrmd_op_status); - crm_xml_add_int(notify, F_LRMD_CALLID, cmd->call_id); - crm_xml_add_int(notify, F_LRMD_RSC_DELETED, cmd->rsc_deleted); + xmlNode *notify = NULL; + + notify = create_xml_node(NULL, T_LRMD_NOTIFY); + + crm_xml_add(notify, F_LRMD_ORIGIN, __FUNCTION__); + crm_xml_add_int(notify, F_LRMD_TIMEOUT, cmd->timeout); + crm_xml_add_int(notify, F_LRMD_RSC_INTERVAL, cmd->interval); + crm_xml_add_int(notify, F_LRMD_RSC_START_DELAY, cmd->start_delay); + crm_xml_add_int(notify, F_LRMD_EXEC_RC, cmd->exec_rc); + crm_xml_add_int(notify, F_LRMD_OP_STATUS, cmd->lrmd_op_status); + crm_xml_add_int(notify, F_LRMD_CALLID, cmd->call_id); + crm_xml_add_int(notify, F_LRMD_RSC_DELETED, cmd->rsc_deleted); #ifdef HAVE_SYS_TIMEB_H - ftime(&now); - crm_xml_add_int(notify, F_LRMD_RSC_RUN_TIME, cmd->t_run.time); - crm_xml_add_int(notify, F_LRMD_RSC_RCCHANGE_TIME, cmd->t_rcchange.time); - crm_xml_add_int(notify, F_LRMD_RSC_EXEC_TIME, time_diff_ms(&now, &cmd->t_run)); - crm_xml_add_int(notify, F_LRMD_RSC_QUEUE_TIME, time_diff_ms(&cmd->t_run, &cmd->t_queue)); + ftime(&now); + crm_xml_add_int(notify, F_LRMD_RSC_RUN_TIME, cmd->t_run.time); + crm_xml_add_int(notify, F_LRMD_RSC_RCCHANGE_TIME, cmd->t_rcchange.time); + crm_xml_add_int(notify, F_LRMD_RSC_EXEC_TIME, time_diff_ms(&now, &cmd->t_run)); + crm_xml_add_int(notify, F_LRMD_RSC_QUEUE_TIME, time_diff_ms(&cmd->t_run, &cmd->t_queue)); #endif - crm_xml_add(notify, F_LRMD_OPERATION, LRMD_OP_RSC_EXEC); - crm_xml_add(notify, F_LRMD_RSC_ID, cmd->rsc_id); - crm_xml_add(notify, F_LRMD_RSC_ACTION, cmd->action); - crm_xml_add(notify, F_LRMD_RSC_USERDATA_STR, cmd->userdata_str); - crm_xml_add(notify, F_LRMD_RSC_OUTPUT, cmd->output); + crm_xml_add(notify, F_LRMD_OPERATION, LRMD_OP_RSC_EXEC); + crm_xml_add(notify, F_LRMD_RSC_ID, cmd->rsc_id); + crm_xml_add(notify, F_LRMD_RSC_ACTION, cmd->action); + crm_xml_add(notify, F_LRMD_RSC_USERDATA_STR, cmd->userdata_str); + crm_xml_add(notify, F_LRMD_RSC_OUTPUT, cmd->output); - if (cmd->params) { - char *key = NULL; - char *value = NULL; - GHashTableIter iter; + if (cmd->params) { + char *key = NULL; + char *value = NULL; + GHashTableIter iter; - xmlNode *args = create_xml_node(notify, XML_TAG_ATTRS); - g_hash_table_iter_init(&iter, cmd->params); - while (g_hash_table_iter_next(&iter, (gpointer *) & key, (gpointer *) & value)) { - hash2field((gpointer) key, (gpointer) value, args); - } - } + xmlNode *args = create_xml_node(notify, XML_TAG_ATTRS); - if (cmd->only_notify_client) { - lrmd_client_t *client = g_hash_table_lookup(client_list, cmd->only_notify_client); + g_hash_table_iter_init(&iter, cmd->params); + while (g_hash_table_iter_next(&iter, (gpointer *) & key, (gpointer *) & value)) { + hash2field((gpointer) key, (gpointer) value, args); + } + } - if (client) { - send_client_notify(client->id, client, notify); - } - } else { - g_hash_table_foreach(client_list, send_client_notify, notify); - } + if (cmd->only_notify_client) { + lrmd_client_t *client = g_hash_table_lookup(client_list, cmd->only_notify_client); - free_xml(notify); + if (client) { + send_client_notify(client->id, client, notify); + } + } else { + g_hash_table_foreach(client_list, send_client_notify, notify); + } + + free_xml(notify); } static void -send_generic_notify(int rc, xmlNode *request) +send_generic_notify(int rc, xmlNode * request) { - int call_id = 0; - xmlNode *notify = NULL; - xmlNode *rsc_xml = get_xpath_object("//"F_LRMD_RSC, request, LOG_ERR); - const char *rsc_id = crm_element_value(rsc_xml, F_LRMD_RSC_ID); - const char *op = crm_element_value(request, F_LRMD_OPERATION); + int call_id = 0; + xmlNode *notify = NULL; + xmlNode *rsc_xml = get_xpath_object("//" F_LRMD_RSC, request, LOG_ERR); + const char *rsc_id = crm_element_value(rsc_xml, F_LRMD_RSC_ID); + const char *op = crm_element_value(request, F_LRMD_OPERATION); - crm_element_value_int(request, F_LRMD_CALLID, &call_id); + crm_element_value_int(request, F_LRMD_CALLID, &call_id); - notify = create_xml_node(NULL, T_LRMD_NOTIFY); - crm_xml_add(notify, F_LRMD_ORIGIN, __FUNCTION__); - crm_xml_add_int(notify, F_LRMD_RC, rc); - crm_xml_add_int(notify, F_LRMD_CALLID, call_id); - crm_xml_add(notify, F_LRMD_OPERATION, op); - crm_xml_add(notify, F_LRMD_RSC_ID, rsc_id); + notify = create_xml_node(NULL, T_LRMD_NOTIFY); + crm_xml_add(notify, F_LRMD_ORIGIN, __FUNCTION__); + crm_xml_add_int(notify, F_LRMD_RC, rc); + crm_xml_add_int(notify, F_LRMD_CALLID, call_id); + crm_xml_add(notify, F_LRMD_OPERATION, op); + crm_xml_add(notify, F_LRMD_RSC_ID, rsc_id); - g_hash_table_foreach(client_list, send_client_notify, notify); + g_hash_table_foreach(client_list, send_client_notify, notify); - free_xml(notify); + free_xml(notify); } static void -cmd_finalize(lrmd_cmd_t *cmd, lrmd_rsc_t *rsc) -{ - crm_trace("Resource operation rsc:%s action:%s completed", cmd->rsc_id, cmd->action); - - if (rsc && (rsc->active == cmd)) { - rsc->active = NULL; - mainloop_set_trigger(rsc->work); - } - - if (!rsc) { - cmd->rsc_deleted = 1; - } - - send_cmd_complete_notify(cmd); - - - if (cmd->interval && (cmd->lrmd_op_status == PCMK_LRM_OP_CANCELLED)) { - if (rsc) { - rsc->recurring_ops = g_list_remove(rsc->recurring_ops, cmd); - rsc->pending_ops = g_list_remove(rsc->pending_ops, cmd); - } - free_lrmd_cmd(cmd); - } else if (cmd->interval == 0) { - if (rsc) { - rsc->pending_ops = g_list_remove(rsc->pending_ops, cmd); - } - free_lrmd_cmd(cmd); - } else { - /* Clear all the values pertaining just to the last iteration of a recurring op. */ - cmd->lrmd_op_status = 0; - memset(&cmd->t_run, 0, sizeof(cmd->t_run)); - memset(&cmd->t_queue, 0, sizeof(cmd->t_queue)); - free(cmd->output); - cmd->output = NULL; - } +cmd_finalize(lrmd_cmd_t * cmd, lrmd_rsc_t * rsc) +{ + crm_trace("Resource operation rsc:%s action:%s completed", cmd->rsc_id, cmd->action); + + if (rsc && (rsc->active == cmd)) { + rsc->active = NULL; + mainloop_set_trigger(rsc->work); + } + + if (!rsc) { + cmd->rsc_deleted = 1; + } + + send_cmd_complete_notify(cmd); + + if (cmd->interval && (cmd->lrmd_op_status == PCMK_LRM_OP_CANCELLED)) { + if (rsc) { + rsc->recurring_ops = g_list_remove(rsc->recurring_ops, cmd); + rsc->pending_ops = g_list_remove(rsc->pending_ops, cmd); + } + free_lrmd_cmd(cmd); + } else if (cmd->interval == 0) { + if (rsc) { + rsc->pending_ops = g_list_remove(rsc->pending_ops, cmd); + } + free_lrmd_cmd(cmd); + } else { + /* Clear all the values pertaining just to the last iteration of a recurring op. */ + cmd->lrmd_op_status = 0; + memset(&cmd->t_run, 0, sizeof(cmd->t_run)); + memset(&cmd->t_queue, 0, sizeof(cmd->t_queue)); + free(cmd->output); + cmd->output = NULL; + } } static int lsb2uniform_rc(const char *action, int rc) { - if (rc < 0) { - return PCMK_EXECRA_UNKNOWN_ERROR; - } - - /* status has different return codes that everything else. */ - if (!safe_str_eq(action, "status") && !safe_str_eq(action, "monitor")) { - if (rc > PCMK_LSB_NOT_RUNNING) { - return PCMK_EXECRA_UNKNOWN_ERROR; - } - return rc; - } - - switch (rc) { - case PCMK_LSB_STATUS_OK: - return PCMK_EXECRA_OK; - case PCMK_LSB_STATUS_NOT_INSTALLED: - return PCMK_EXECRA_NOT_INSTALLED; - case PCMK_LSB_STATUS_VAR_PID: - case PCMK_LSB_STATUS_VAR_LOCK: - case PCMK_LSB_STATUS_NOT_RUNNING: - return PCMK_EXECRA_NOT_RUNNING; - default: - return PCMK_EXECRA_UNKNOWN_ERROR; - } - - return PCMK_EXECRA_UNKNOWN_ERROR; + if (rc < 0) { + return PCMK_EXECRA_UNKNOWN_ERROR; + } + + /* status has different return codes that everything else. */ + if (!safe_str_eq(action, "status") && !safe_str_eq(action, "monitor")) { + if (rc > PCMK_LSB_NOT_RUNNING) { + return PCMK_EXECRA_UNKNOWN_ERROR; + } + return rc; + } + + switch (rc) { + case PCMK_LSB_STATUS_OK: + return PCMK_EXECRA_OK; + case PCMK_LSB_STATUS_NOT_INSTALLED: + return PCMK_EXECRA_NOT_INSTALLED; + case PCMK_LSB_STATUS_VAR_PID: + case PCMK_LSB_STATUS_VAR_LOCK: + case PCMK_LSB_STATUS_NOT_RUNNING: + return PCMK_EXECRA_NOT_RUNNING; + default: + return PCMK_EXECRA_UNKNOWN_ERROR; + } + + return PCMK_EXECRA_UNKNOWN_ERROR; } + static int ocf2uniform_rc(int rc) { - if (rc < 0 || rc > PCMK_OCF_FAILED_MASTER) { - return PCMK_EXECRA_UNKNOWN_ERROR; - } + if (rc < 0 || rc > PCMK_OCF_FAILED_MASTER) { + return PCMK_EXECRA_UNKNOWN_ERROR; + } - return rc; + return rc; } static int stonith2uniform_rc(const char *action, int rc) { - if (rc == st_err_unknown_device) { - if (safe_str_eq(action, "stop")) { - rc = PCMK_EXECRA_OK; - } else if (safe_str_eq(action, "start")) { - rc = PCMK_EXECRA_NOT_INSTALLED; - } else { - rc = PCMK_EXECRA_NOT_RUNNING; - } - } else if (rc != 0) { + if (rc == st_err_unknown_device) { + if (safe_str_eq(action, "stop")) { + rc = PCMK_EXECRA_OK; + } else if (safe_str_eq(action, "start")) { + rc = PCMK_EXECRA_NOT_INSTALLED; + } else { + rc = PCMK_EXECRA_NOT_RUNNING; + } + } else if (rc != 0) { rc = PCMK_EXECRA_UNKNOWN_ERROR; } return rc; } static int get_uniform_rc(const char *standard, const char *action, int rc) { - if (safe_str_eq(standard, "ocf")) { - return ocf2uniform_rc(rc); - } else if (safe_str_eq(standard, "stonith")) { - return stonith2uniform_rc(action, rc); - } else { - return lsb2uniform_rc(action, rc); - } + if (safe_str_eq(standard, "ocf")) { + return ocf2uniform_rc(rc); + } else if (safe_str_eq(standard, "stonith")) { + return stonith2uniform_rc(action, rc); + } else { + return lsb2uniform_rc(action, rc); + } } static void -action_complete(svc_action_t *action) +action_complete(svc_action_t * action) { - lrmd_rsc_t *rsc; - lrmd_cmd_t *cmd = action->cb_data; - - if (!cmd) { - crm_err("LRMD action (%s) completed does not match any known operations.", action->id); - return; - } + lrmd_rsc_t *rsc; + lrmd_cmd_t *cmd = action->cb_data; + if (!cmd) { + crm_err("LRMD action (%s) completed does not match any known operations.", action->id); + return; + } #ifdef HAVE_SYS_TIMEB_H - if (cmd->exec_rc != action->rc) { - ftime(&cmd->t_rcchange); - } + if (cmd->exec_rc != action->rc) { + ftime(&cmd->t_rcchange); + } #endif - cmd->exec_rc = get_uniform_rc(action->standard, cmd->action, action->rc); - cmd->lrmd_op_status = action->status; - rsc = cmd->rsc_id ? g_hash_table_lookup(rsc_list, cmd->rsc_id) : NULL; + cmd->exec_rc = get_uniform_rc(action->standard, cmd->action, action->rc); + cmd->lrmd_op_status = action->status; + rsc = cmd->rsc_id ? g_hash_table_lookup(rsc_list, cmd->rsc_id) : NULL; - if (action->stdout_data) { - cmd->output = crm_strdup(action->stdout_data); - } + if (action->stdout_data) { + cmd->output = crm_strdup(action->stdout_data); + } - cmd_finalize(cmd, rsc); + cmd_finalize(cmd, rsc); } static int -lrmd_rsc_execute_stonith(lrmd_rsc_t *rsc, lrmd_cmd_t *cmd) -{ - int rc = 0; - stonith_t *stonith_api = get_stonith_connection(); - - if (!stonith_api) { - cmd->exec_rc = get_uniform_rc("stonith", cmd->action, st_err_connection); - cmd->lrmd_op_status = PCMK_LRM_OP_ERROR; - cmd_finalize(cmd, rsc); - return lrmd_err_stonith_connection; - } - - if (safe_str_eq(cmd->action, "start")) { - char *key = NULL; - char *value = NULL; - stonith_key_value_t *device_params = NULL; - - if (cmd->params) { - GHashTableIter iter; - g_hash_table_iter_init(&iter, cmd->params); - while (g_hash_table_iter_next(&iter, (gpointer *) & key, (gpointer *) & value)) { - device_params = stonith_key_value_add(device_params, key, value); - } - } - - rc = stonith_api->cmds->register_device(stonith_api, - st_opt_sync_call, - cmd->rsc_id, - rsc->provider, - rsc->type, - device_params); - - stonith_key_value_freeall(device_params, 1, 1); - if (rc == 0) { - rc = stonith_api->cmds->call(stonith_api, - st_opt_sync_call, - cmd->rsc_id, - "monitor", - NULL, - cmd->timeout); - } - } else if (safe_str_eq(cmd->action, "stop")) { - rc = stonith_api->cmds->remove_device(stonith_api, st_opt_sync_call, cmd->rsc_id); - } else if (safe_str_eq(cmd->action, "monitor")) { - rc = stonith_api->cmds->call(stonith_api, - st_opt_sync_call, - cmd->rsc_id, - cmd->action, - NULL, - cmd->timeout); - } - - cmd->exec_rc = get_uniform_rc("stonith", cmd->action, rc); - - /* Attempt to map return codes to op status if possible */ - if (rc) { - switch (rc) { - case st_err_not_supported: - cmd->lrmd_op_status = PCMK_LRM_OP_NOTSUPPORTED; - break; - case st_err_timeout: - cmd->lrmd_op_status = PCMK_LRM_OP_TIMEOUT; - break; - default: - cmd->lrmd_op_status = PCMK_LRM_OP_ERROR; - } - } else { - cmd->lrmd_op_status = PCMK_LRM_OP_DONE; - } - - if (cmd->interval > 0) { - rsc->recurring_ops = g_list_append(rsc->recurring_ops, cmd); - cmd->stonith_recurring_id = g_timeout_add(cmd->interval, stonith_recurring_op_helper, cmd); - } - cmd_finalize(cmd, rsc); - - return rc; +lrmd_rsc_execute_stonith(lrmd_rsc_t * rsc, lrmd_cmd_t * cmd) +{ + int rc = 0; + stonith_t *stonith_api = get_stonith_connection(); + + if (!stonith_api) { + cmd->exec_rc = get_uniform_rc("stonith", cmd->action, st_err_connection); + cmd->lrmd_op_status = PCMK_LRM_OP_ERROR; + cmd_finalize(cmd, rsc); + return lrmd_err_stonith_connection; + } + + if (safe_str_eq(cmd->action, "start")) { + char *key = NULL; + char *value = NULL; + stonith_key_value_t *device_params = NULL; + + if (cmd->params) { + GHashTableIter iter; + + g_hash_table_iter_init(&iter, cmd->params); + while (g_hash_table_iter_next(&iter, (gpointer *) & key, (gpointer *) & value)) { + device_params = stonith_key_value_add(device_params, key, value); + } + } + + rc = stonith_api->cmds->register_device(stonith_api, + st_opt_sync_call, + cmd->rsc_id, + rsc->provider, rsc->type, device_params); + + stonith_key_value_freeall(device_params, 1, 1); + if (rc == 0) { + rc = stonith_api->cmds->call(stonith_api, + st_opt_sync_call, + cmd->rsc_id, "monitor", NULL, cmd->timeout); + } + } else if (safe_str_eq(cmd->action, "stop")) { + rc = stonith_api->cmds->remove_device(stonith_api, st_opt_sync_call, cmd->rsc_id); + } else if (safe_str_eq(cmd->action, "monitor")) { + rc = stonith_api->cmds->call(stonith_api, + st_opt_sync_call, + cmd->rsc_id, cmd->action, NULL, cmd->timeout); + } + + cmd->exec_rc = get_uniform_rc("stonith", cmd->action, rc); + + /* Attempt to map return codes to op status if possible */ + if (rc) { + switch (rc) { + case st_err_not_supported: + cmd->lrmd_op_status = PCMK_LRM_OP_NOTSUPPORTED; + break; + case st_err_timeout: + cmd->lrmd_op_status = PCMK_LRM_OP_TIMEOUT; + break; + default: + cmd->lrmd_op_status = PCMK_LRM_OP_ERROR; + } + } else { + cmd->lrmd_op_status = PCMK_LRM_OP_DONE; + } + + if (cmd->interval > 0) { + rsc->recurring_ops = g_list_append(rsc->recurring_ops, cmd); + cmd->stonith_recurring_id = g_timeout_add(cmd->interval, stonith_recurring_op_helper, cmd); + } + cmd_finalize(cmd, rsc); + + return rc; } static const char * -normalize_action_name(lrmd_rsc_t *rsc, const char *action) +normalize_action_name(lrmd_rsc_t * rsc, const char *action) { - if (safe_str_eq(action, "monitor") && - (safe_str_eq(rsc->class, "lsb") || - safe_str_eq(rsc->class, "service") || - safe_str_eq(rsc->class, "systemd"))) { - return "status"; - } - return action; + if (safe_str_eq(action, "monitor") && + (safe_str_eq(rsc->class, "lsb") || + safe_str_eq(rsc->class, "service") || safe_str_eq(rsc->class, "systemd"))) { + return "status"; + } + return action; } static void dup_attr(gpointer key, gpointer value, gpointer user_data) { - g_hash_table_replace(user_data, crm_strdup(key), crm_strdup(value)); + g_hash_table_replace(user_data, crm_strdup(key), crm_strdup(value)); } static int -lrmd_rsc_execute_service_lib(lrmd_rsc_t *rsc, lrmd_cmd_t *cmd) -{ - svc_action_t *action = NULL; - GHashTable *params_copy = NULL; - - crm_trace("Creating action, resource:%s action:%s class:%s provider:%s agent:%s", - rsc->rsc_id, - cmd->action, - rsc->class, - rsc->provider, - rsc->type); - - if (cmd->params) { - params_copy = g_hash_table_new_full(crm_str_hash, - g_str_equal, - g_hash_destroy_str, - g_hash_destroy_str); - - if (params_copy != NULL) { - g_hash_table_foreach(cmd->params, dup_attr, params_copy); - } - } - - action = resources_action_create(rsc->rsc_id, - rsc->class, - rsc->provider, - rsc->type, - normalize_action_name(rsc, cmd->action), - cmd->interval, - cmd->timeout, - params_copy); - - if (!action) { - crm_err("Failed to create action, action:%s on resource %s", cmd->action, rsc->rsc_id); - cmd->lrmd_op_status = PCMK_LRM_OP_ERROR; - goto exec_done; - } - - action->cb_data = cmd; - if (!services_action_async(action, action_complete)) { - services_action_free(action); - action = NULL; - cmd->lrmd_op_status = PCMK_LRM_OP_ERROR; - goto exec_done; - } - - if (cmd->interval) { - rsc->recurring_ops = g_list_append(rsc->recurring_ops, cmd); - } - - /* The cmd will be finalized by the action_complete callback after - * the service library is done with it */ - rsc->active = cmd; /* only one op at a time for a rsc */ - cmd = NULL; - -exec_done: - if (cmd) { - cmd_finalize(cmd, rsc); - } - return TRUE; +lrmd_rsc_execute_service_lib(lrmd_rsc_t * rsc, lrmd_cmd_t * cmd) +{ + svc_action_t *action = NULL; + GHashTable *params_copy = NULL; + + crm_trace("Creating action, resource:%s action:%s class:%s provider:%s agent:%s", + rsc->rsc_id, cmd->action, rsc->class, rsc->provider, rsc->type); + + if (cmd->params) { + params_copy = g_hash_table_new_full(crm_str_hash, + g_str_equal, g_hash_destroy_str, g_hash_destroy_str); + + if (params_copy != NULL) { + g_hash_table_foreach(cmd->params, dup_attr, params_copy); + } + } + + action = resources_action_create(rsc->rsc_id, + rsc->class, + rsc->provider, + rsc->type, + normalize_action_name(rsc, cmd->action), + cmd->interval, cmd->timeout, params_copy); + + if (!action) { + crm_err("Failed to create action, action:%s on resource %s", cmd->action, rsc->rsc_id); + cmd->lrmd_op_status = PCMK_LRM_OP_ERROR; + goto exec_done; + } + + action->cb_data = cmd; + if (!services_action_async(action, action_complete)) { + services_action_free(action); + action = NULL; + cmd->lrmd_op_status = PCMK_LRM_OP_ERROR; + goto exec_done; + } + + if (cmd->interval) { + rsc->recurring_ops = g_list_append(rsc->recurring_ops, cmd); + } + + /* The cmd will be finalized by the action_complete callback after + * the service library is done with it */ + rsc->active = cmd; /* only one op at a time for a rsc */ + cmd = NULL; + + exec_done: + if (cmd) { + cmd_finalize(cmd, rsc); + } + return TRUE; } static gboolean -lrmd_rsc_execute(lrmd_rsc_t *rsc) -{ - lrmd_cmd_t *cmd = NULL; - CRM_CHECK(rsc != NULL, return FALSE); - - if (rsc->active) { - crm_trace("%s is still active", rsc->rsc_id); - return TRUE; - } - - if (rsc->pending_ops) { - GList *first = rsc->pending_ops; - cmd = first->data; - if (cmd->delay_id) { - crm_trace("Command %s %s was asked to run too early, waiting for start_delay timeout of %dms", - cmd->rsc_id, cmd->action, cmd->start_delay); - return TRUE; - } - rsc->pending_ops = g_list_remove_link(rsc->pending_ops, first); - g_list_free_1(first); +lrmd_rsc_execute(lrmd_rsc_t * rsc) +{ + lrmd_cmd_t *cmd = NULL; + + CRM_CHECK(rsc != NULL, return FALSE); + + if (rsc->active) { + crm_trace("%s is still active", rsc->rsc_id); + return TRUE; + } + + if (rsc->pending_ops) { + GList *first = rsc->pending_ops; + + cmd = first->data; + if (cmd->delay_id) { + crm_trace + ("Command %s %s was asked to run too early, waiting for start_delay timeout of %dms", + cmd->rsc_id, cmd->action, cmd->start_delay); + return TRUE; + } + rsc->pending_ops = g_list_remove_link(rsc->pending_ops, first); + g_list_free_1(first); #ifdef HAVE_SYS_TIMEB_H - ftime(&cmd->t_run); - } + ftime(&cmd->t_run); + } #endif - if (!cmd) { - crm_trace("Nothing further to do for %s", rsc->rsc_id); - return TRUE; - } + if (!cmd) { + crm_trace("Nothing further to do for %s", rsc->rsc_id); + return TRUE; + } - if (safe_str_eq(rsc->class, "stonith")) { - lrmd_rsc_execute_stonith(rsc, cmd); - } else { - lrmd_rsc_execute_service_lib(rsc, cmd); - } + if (safe_str_eq(rsc->class, "stonith")) { + lrmd_rsc_execute_stonith(rsc, cmd); + } else { + lrmd_rsc_execute_service_lib(rsc, cmd); + } - return TRUE; + return TRUE; } static gboolean lrmd_rsc_dispatch(gpointer user_data) { - return lrmd_rsc_execute(user_data); + return lrmd_rsc_execute(user_data); } void free_rsc(gpointer data) { - GListPtr gIter = NULL; - lrmd_rsc_t *rsc = data; - int is_stonith = safe_str_eq(rsc->class, "stonith"); - - for (gIter = rsc->pending_ops; gIter != NULL; gIter = gIter->next) { - lrmd_cmd_t *cmd = gIter->data; - /* command was never executed */ - cmd->lrmd_op_status = PCMK_LRM_OP_CANCELLED; - cmd_finalize(cmd, NULL); - } - /* frees list, but not list elements. */ - g_list_free(rsc->pending_ops); - - for (gIter = rsc->recurring_ops; gIter != NULL; gIter = gIter->next) { - lrmd_cmd_t *cmd = gIter->data; - if (is_stonith) { - cmd->lrmd_op_status = PCMK_LRM_OP_CANCELLED; - cmd_finalize(cmd, NULL); - } else { - /* This command is already handed off to service library, - * let service library cancel it and tell us via the callback - * when it is cancelled. The rsc can be safely destroyed - * even if we are waiting for the cancel result */ - services_action_cancel(rsc->rsc_id, cmd->action, cmd->interval); - } - } - /* frees list, but not list elements. */ - g_list_free(rsc->recurring_ops); - - free(rsc->rsc_id); - free(rsc->class); - free(rsc->provider); - free(rsc->type); - mainloop_destroy_trigger(rsc->work); - - free(rsc); + GListPtr gIter = NULL; + lrmd_rsc_t *rsc = data; + int is_stonith = safe_str_eq(rsc->class, "stonith"); + + for (gIter = rsc->pending_ops; gIter != NULL; gIter = gIter->next) { + lrmd_cmd_t *cmd = gIter->data; + + /* command was never executed */ + cmd->lrmd_op_status = PCMK_LRM_OP_CANCELLED; + cmd_finalize(cmd, NULL); + } + /* frees list, but not list elements. */ + g_list_free(rsc->pending_ops); + + for (gIter = rsc->recurring_ops; gIter != NULL; gIter = gIter->next) { + lrmd_cmd_t *cmd = gIter->data; + + if (is_stonith) { + cmd->lrmd_op_status = PCMK_LRM_OP_CANCELLED; + cmd_finalize(cmd, NULL); + } else { + /* This command is already handed off to service library, + * let service library cancel it and tell us via the callback + * when it is cancelled. The rsc can be safely destroyed + * even if we are waiting for the cancel result */ + services_action_cancel(rsc->rsc_id, cmd->action, cmd->interval); + } + } + /* frees list, but not list elements. */ + g_list_free(rsc->recurring_ops); + + free(rsc->rsc_id); + free(rsc->class); + free(rsc->provider); + free(rsc->type); + mainloop_destroy_trigger(rsc->work); + + free(rsc); } static int -process_lrmd_signon(lrmd_client_t *client, xmlNode *request) +process_lrmd_signon(lrmd_client_t * client, xmlNode * request) { - xmlNode *reply = create_xml_node(NULL, "reply"); - crm_xml_add(reply, F_LRMD_OPERATION, CRM_OP_REGISTER); - crm_xml_add(reply, F_LRMD_CLIENTID, client->id); - crm_ipcs_send(client->channel, reply, FALSE); + xmlNode *reply = create_xml_node(NULL, "reply"); + + crm_xml_add(reply, F_LRMD_OPERATION, CRM_OP_REGISTER); + crm_xml_add(reply, F_LRMD_CLIENTID, client->id); + crm_ipcs_send(client->channel, reply, FALSE); - free_xml(reply); - return lrmd_ok; + free_xml(reply); + return lrmd_ok; } static int -process_lrmd_rsc_register(lrmd_client_t *client, xmlNode *request) +process_lrmd_rsc_register(lrmd_client_t * client, xmlNode * request) { - int rc = lrmd_ok; - lrmd_rsc_t *rsc = build_rsc_from_xml(request); - lrmd_rsc_t *dup = g_hash_table_lookup(rsc_list, rsc->rsc_id); + int rc = lrmd_ok; + lrmd_rsc_t *rsc = build_rsc_from_xml(request); + lrmd_rsc_t *dup = g_hash_table_lookup(rsc_list, rsc->rsc_id); - if (dup && - safe_str_eq(rsc->class, dup->class) && - safe_str_eq(rsc->provider, dup->provider) && - safe_str_eq(rsc->type, dup->type)) { + if (dup && + safe_str_eq(rsc->class, dup->class) && + safe_str_eq(rsc->provider, dup->provider) && safe_str_eq(rsc->type, dup->type)) { - crm_warn("Can't add, RSC '%s' already present in the rsc list (%d active resources)", - rsc->rsc_id, g_hash_table_size(rsc_list)); + crm_warn("Can't add, RSC '%s' already present in the rsc list (%d active resources)", + rsc->rsc_id, g_hash_table_size(rsc_list)); - free_rsc(rsc); - return rc; - } + free_rsc(rsc); + return rc; + } - g_hash_table_replace(rsc_list, rsc->rsc_id, rsc); - crm_info("Added '%s' to the rsc list (%d active resources)", - rsc->rsc_id, g_hash_table_size(rsc_list)); + g_hash_table_replace(rsc_list, rsc->rsc_id, rsc); + crm_info("Added '%s' to the rsc list (%d active resources)", + rsc->rsc_id, g_hash_table_size(rsc_list)); - return rc; + return rc; } static void -process_lrmd_get_rsc_info(lrmd_client_t *client, xmlNode *request) +process_lrmd_get_rsc_info(lrmd_client_t * client, xmlNode * request) { - int rc = lrmd_ok; - int send_rc = 0; - int call_id = 0; - xmlNode *rsc_xml = get_xpath_object("//"F_LRMD_RSC, request, LOG_ERR); - const char *rsc_id = crm_element_value(rsc_xml, F_LRMD_RSC_ID); - xmlNode *reply = NULL; - lrmd_rsc_t *rsc = NULL; + int rc = lrmd_ok; + int send_rc = 0; + int call_id = 0; + xmlNode *rsc_xml = get_xpath_object("//" F_LRMD_RSC, request, LOG_ERR); + const char *rsc_id = crm_element_value(rsc_xml, F_LRMD_RSC_ID); + xmlNode *reply = NULL; + lrmd_rsc_t *rsc = NULL; - crm_element_value_int(request, F_LRMD_CALLID, &call_id); + crm_element_value_int(request, F_LRMD_CALLID, &call_id); - if (!rsc_id) { - rc = lrmd_err_unknown_rsc; - goto get_rsc_done; - } + if (!rsc_id) { + rc = lrmd_err_unknown_rsc; + goto get_rsc_done; + } - if (!(rsc = g_hash_table_lookup(rsc_list, rsc_id))) { - crm_info("Resource '%s' not found (%d active resources)", - rsc_id, g_hash_table_size(rsc_list)); - rc = lrmd_err_unknown_rsc; - goto get_rsc_done; - } + if (!(rsc = g_hash_table_lookup(rsc_list, rsc_id))) { + crm_info("Resource '%s' not found (%d active resources)", + rsc_id, g_hash_table_size(rsc_list)); + rc = lrmd_err_unknown_rsc; + goto get_rsc_done; + } -get_rsc_done: + get_rsc_done: - reply = create_xml_node(NULL, T_LRMD_REPLY); - crm_xml_add(reply, F_LRMD_ORIGIN, __FUNCTION__); - crm_xml_add_int(reply, F_LRMD_RC, rc); - crm_xml_add_int(reply, F_LRMD_CALLID, call_id); + reply = create_xml_node(NULL, T_LRMD_REPLY); + crm_xml_add(reply, F_LRMD_ORIGIN, __FUNCTION__); + crm_xml_add_int(reply, F_LRMD_RC, rc); + crm_xml_add_int(reply, F_LRMD_CALLID, call_id); - if (rsc) { - crm_xml_add(reply, F_LRMD_RSC_ID, rsc->rsc_id); - crm_xml_add(reply, F_LRMD_CLASS, rsc->class); - crm_xml_add(reply, F_LRMD_PROVIDER, rsc->provider); - crm_xml_add(reply, F_LRMD_TYPE, rsc->type); - } + if (rsc) { + crm_xml_add(reply, F_LRMD_RSC_ID, rsc->rsc_id); + crm_xml_add(reply, F_LRMD_CLASS, rsc->class); + crm_xml_add(reply, F_LRMD_PROVIDER, rsc->provider); + crm_xml_add(reply, F_LRMD_TYPE, rsc->type); + } - send_rc = crm_ipcs_send(client->channel, reply, FALSE); + send_rc = crm_ipcs_send(client->channel, reply, FALSE); - if (send_rc < 0) { - crm_warn("LRMD reply to %s failed: %d", client->name, send_rc); - } + if (send_rc < 0) { + crm_warn("LRMD reply to %s failed: %d", client->name, send_rc); + } - free_xml(reply); + free_xml(reply); } static int -process_lrmd_rsc_unregister(lrmd_client_t *client, xmlNode *request) +process_lrmd_rsc_unregister(lrmd_client_t * client, xmlNode * request) { - int rc = lrmd_ok; - lrmd_rsc_t *rsc = NULL; - xmlNode *rsc_xml = get_xpath_object("//"F_LRMD_RSC, request, LOG_ERR); - const char *rsc_id = crm_element_value(rsc_xml, F_LRMD_RSC_ID); + int rc = lrmd_ok; + lrmd_rsc_t *rsc = NULL; + xmlNode *rsc_xml = get_xpath_object("//" F_LRMD_RSC, request, LOG_ERR); + const char *rsc_id = crm_element_value(rsc_xml, F_LRMD_RSC_ID); - if (!rsc_id) { - return lrmd_err_unknown_rsc; - } + if (!rsc_id) { + return lrmd_err_unknown_rsc; + } - if (!(rsc = g_hash_table_lookup(rsc_list, rsc_id))) { - crm_info("Resource '%s' not found (%d active resources)", - rsc_id, g_hash_table_size(rsc_list)); - return lrmd_err_unknown_rsc; - } + if (!(rsc = g_hash_table_lookup(rsc_list, rsc_id))) { + crm_info("Resource '%s' not found (%d active resources)", + rsc_id, g_hash_table_size(rsc_list)); + return lrmd_err_unknown_rsc; + } if (rsc->active) { /* let the caller know there are still active ops on this rsc to watch for */ rc = lrmd_pending; } - g_hash_table_remove(rsc_list, rsc_id); + g_hash_table_remove(rsc_list, rsc_id); - return rc; + return rc; } static int -process_lrmd_rsc_exec(lrmd_client_t *client, xmlNode *request) +process_lrmd_rsc_exec(lrmd_client_t * client, xmlNode * request) { - lrmd_rsc_t *rsc = NULL; - lrmd_cmd_t *cmd = NULL; - xmlNode *rsc_xml = get_xpath_object("//"F_LRMD_RSC, request, LOG_ERR); - const char *rsc_id = crm_element_value(rsc_xml, F_LRMD_RSC_ID); + lrmd_rsc_t *rsc = NULL; + lrmd_cmd_t *cmd = NULL; + xmlNode *rsc_xml = get_xpath_object("//" F_LRMD_RSC, request, LOG_ERR); + const char *rsc_id = crm_element_value(rsc_xml, F_LRMD_RSC_ID); - if (!rsc_id) { - return lrmd_err_missing; - } - if (!(rsc = g_hash_table_lookup(rsc_list, rsc_id))) { - return lrmd_err_unknown_rsc; - } + if (!rsc_id) { + return lrmd_err_missing; + } + if (!(rsc = g_hash_table_lookup(rsc_list, rsc_id))) { + return lrmd_err_unknown_rsc; + } - cmd = create_lrmd_cmd(request, client); - schedule_lrmd_cmd(rsc, cmd); + cmd = create_lrmd_cmd(request, client); + schedule_lrmd_cmd(rsc, cmd); - return cmd->call_id; + return cmd->call_id; } static int cancel_op(const char *rsc_id, const char *action, int interval) { - GListPtr gIter = NULL; - lrmd_rsc_t *rsc = g_hash_table_lookup(rsc_list, rsc_id); - - /* How to cancel an action. - * 1. Check pending ops list, if it hasn't been handed off - * to the service library or stonith recurring list remove - * it there and that will stop it. - * 2. If it isn't in the pending ops list, then its either a - * recurring op in the stonith recurring list, or the service - * library's recurring list. Stop it there - * 3. If not found in any lists, then this operation has either - * been executed already and is not a recurring operation, or - * never existed. - */ - if (!rsc) { - return lrmd_err_unknown_rsc; - } - - for (gIter = rsc->pending_ops; gIter != NULL; gIter = gIter->next) { - lrmd_cmd_t *cmd = gIter->data; - - if (safe_str_eq(cmd->action, action) && cmd->interval == interval) { - cmd->lrmd_op_status = PCMK_LRM_OP_CANCELLED; - cmd_finalize(cmd, rsc); - return lrmd_ok; - } - } - - if (safe_str_eq(rsc->class, "stonith")) { - /* The service library does not handle stonith operations. - * We have to handle recurring stonith opereations ourselves. */ - for (gIter = rsc->recurring_ops; gIter != NULL; gIter = gIter->next) { - lrmd_cmd_t *cmd = gIter->data; - - if (safe_str_eq(cmd->action, action) && cmd->interval == interval) { - cmd->lrmd_op_status = PCMK_LRM_OP_CANCELLED; - cmd_finalize(cmd, rsc); - return lrmd_ok; - } - } - } else if (services_action_cancel(rsc_id, normalize_action_name(rsc, action), interval) == TRUE) { - /* The service library will tell the action_complete callback function - * this action was cancelled, which will destroy the cmd and remove - * it from the recurring_op list. Do not do that in this function - * if the service library says it cancelled it. */ - return lrmd_ok; - } - - return lrmd_err_unknown_operation; + GListPtr gIter = NULL; + lrmd_rsc_t *rsc = g_hash_table_lookup(rsc_list, rsc_id); + + /* How to cancel an action. + * 1. Check pending ops list, if it hasn't been handed off + * to the service library or stonith recurring list remove + * it there and that will stop it. + * 2. If it isn't in the pending ops list, then its either a + * recurring op in the stonith recurring list, or the service + * library's recurring list. Stop it there + * 3. If not found in any lists, then this operation has either + * been executed already and is not a recurring operation, or + * never existed. + */ + if (!rsc) { + return lrmd_err_unknown_rsc; + } + + for (gIter = rsc->pending_ops; gIter != NULL; gIter = gIter->next) { + lrmd_cmd_t *cmd = gIter->data; + + if (safe_str_eq(cmd->action, action) && cmd->interval == interval) { + cmd->lrmd_op_status = PCMK_LRM_OP_CANCELLED; + cmd_finalize(cmd, rsc); + return lrmd_ok; + } + } + + if (safe_str_eq(rsc->class, "stonith")) { + /* The service library does not handle stonith operations. + * We have to handle recurring stonith opereations ourselves. */ + for (gIter = rsc->recurring_ops; gIter != NULL; gIter = gIter->next) { + lrmd_cmd_t *cmd = gIter->data; + + if (safe_str_eq(cmd->action, action) && cmd->interval == interval) { + cmd->lrmd_op_status = PCMK_LRM_OP_CANCELLED; + cmd_finalize(cmd, rsc); + return lrmd_ok; + } + } + } else if (services_action_cancel(rsc_id, normalize_action_name(rsc, action), interval) == TRUE) { + /* The service library will tell the action_complete callback function + * this action was cancelled, which will destroy the cmd and remove + * it from the recurring_op list. Do not do that in this function + * if the service library says it cancelled it. */ + return lrmd_ok; + } + + return lrmd_err_unknown_operation; } static int -process_lrmd_rsc_cancel(lrmd_client_t *client, xmlNode *request) +process_lrmd_rsc_cancel(lrmd_client_t * client, xmlNode * request) { - xmlNode *rsc_xml = get_xpath_object("//"F_LRMD_RSC, request, LOG_ERR); - const char *rsc_id = crm_element_value(rsc_xml, F_LRMD_RSC_ID); - const char *action = crm_element_value(rsc_xml, F_LRMD_RSC_ACTION); - int interval = 0; + xmlNode *rsc_xml = get_xpath_object("//" F_LRMD_RSC, request, LOG_ERR); + const char *rsc_id = crm_element_value(rsc_xml, F_LRMD_RSC_ID); + const char *action = crm_element_value(rsc_xml, F_LRMD_RSC_ACTION); + int interval = 0; - crm_element_value_int(rsc_xml, F_LRMD_RSC_INTERVAL, &interval); + crm_element_value_int(rsc_xml, F_LRMD_RSC_INTERVAL, &interval); - if (!rsc_id || !action) { - return lrmd_err_missing; - } + if (!rsc_id || !action) { + return lrmd_err_missing; + } - return cancel_op(rsc_id, action, interval); + return cancel_op(rsc_id, action, interval); } void -process_lrmd_message(lrmd_client_t *client, xmlNode *request) -{ - int rc = lrmd_ok; - int call_id = 0; - const char *op = crm_element_value(request, F_LRMD_OPERATION); - int do_reply = 0; - int do_notify = 0; - int exit = 0; - - crm_element_value_int(request, F_LRMD_CALLID, &call_id); - - if (crm_str_eq(op, CRM_OP_REGISTER, TRUE)) { - rc = process_lrmd_signon(client, request); - } else if (crm_str_eq(op, LRMD_OP_RSC_REG, TRUE)) { - rc = process_lrmd_rsc_register(client, request); - do_notify = 1; - do_reply = 1; - } else if (crm_str_eq(op, LRMD_OP_RSC_INFO, TRUE)) { - process_lrmd_get_rsc_info(client, request); - } else if (crm_str_eq(op, LRMD_OP_RSC_UNREG, TRUE)) { - rc = process_lrmd_rsc_unregister(client, request); - /* don't notify anyone about failed un-registers */ - if (rc == lrmd_ok || rc == lrmd_pending) { - do_notify = 1; - } - do_reply = 1; - } else if (crm_str_eq(op, LRMD_OP_RSC_EXEC, TRUE)) { - rc = process_lrmd_rsc_exec(client, request); - do_reply = 1; - } else if (crm_str_eq(op, LRMD_OP_RSC_CANCEL, TRUE)) { - rc = process_lrmd_rsc_cancel(client, request); - do_reply = 1; - } else if (crm_str_eq(op, CRM_OP_QUIT, TRUE)) { - do_reply = 1; - exit = 1; - } else { - rc = lrmd_err_unknown_operation; - do_reply = 1; - crm_err("Unknown %s from %s", op, client->name); - crm_log_xml_warn(request, "UnknownOp"); - } - - if (do_reply) { - send_reply(client, rc, call_id); - } - - if (do_notify) { - send_generic_notify(rc, request); - } - - if (exit) { - lrmd_shutdown(0); - } -} +process_lrmd_message(lrmd_client_t * client, xmlNode * request) +{ + int rc = lrmd_ok; + int call_id = 0; + const char *op = crm_element_value(request, F_LRMD_OPERATION); + int do_reply = 0; + int do_notify = 0; + int exit = 0; + + crm_element_value_int(request, F_LRMD_CALLID, &call_id); + + if (crm_str_eq(op, CRM_OP_REGISTER, TRUE)) { + rc = process_lrmd_signon(client, request); + } else if (crm_str_eq(op, LRMD_OP_RSC_REG, TRUE)) { + rc = process_lrmd_rsc_register(client, request); + do_notify = 1; + do_reply = 1; + } else if (crm_str_eq(op, LRMD_OP_RSC_INFO, TRUE)) { + process_lrmd_get_rsc_info(client, request); + } else if (crm_str_eq(op, LRMD_OP_RSC_UNREG, TRUE)) { + rc = process_lrmd_rsc_unregister(client, request); + /* don't notify anyone about failed un-registers */ + if (rc == lrmd_ok || rc == lrmd_pending) { + do_notify = 1; + } + do_reply = 1; + } else if (crm_str_eq(op, LRMD_OP_RSC_EXEC, TRUE)) { + rc = process_lrmd_rsc_exec(client, request); + do_reply = 1; + } else if (crm_str_eq(op, LRMD_OP_RSC_CANCEL, TRUE)) { + rc = process_lrmd_rsc_cancel(client, request); + do_reply = 1; + } else if (crm_str_eq(op, CRM_OP_QUIT, TRUE)) { + do_reply = 1; + exit = 1; + } else { + rc = lrmd_err_unknown_operation; + do_reply = 1; + crm_err("Unknown %s from %s", op, client->name); + crm_log_xml_warn(request, "UnknownOp"); + } + if (do_reply) { + send_reply(client, rc, call_id); + } + + if (do_notify) { + send_generic_notify(rc, request); + } + + if (exit) { + lrmd_shutdown(0); + } +} diff --git a/lrmd/lrmd_private.h b/lrmd/lrmd_private.h index 2e0dbf27e8..9ae9184f33 100644 --- a/lrmd/lrmd_private.h +++ b/lrmd/lrmd_private.h @@ -1,74 +1,74 @@ /* * Copyright (c) 2012 David Vossel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifndef LRMD_PVT__H -#define LRMD_PVT__H +# define LRMD_PVT__H -#include -#include -#include -#include +# include +# include +# include +# include GHashTable *rsc_list; GHashTable *client_list; typedef struct lrmd_rsc_s { - char *rsc_id; - char *class; - char *provider; - char *type; - - /* NEVER dereference this pointer, - * It simply exists as a switch to let us know - * when the currently active operation has completed */ - void *active; - - /* Operations in this list - * have not been executed yet. */ - GList *pending_ops; - /* Operations in this list are recurring operations - * that have been handed off from the pending ops list. */ - GList *recurring_ops; - - crm_trigger_t *work; + char *rsc_id; + char *class; + char *provider; + char *type; + + /* NEVER dereference this pointer, + * It simply exists as a switch to let us know + * when the currently active operation has completed */ + void *active; + + /* Operations in this list + * have not been executed yet. */ + GList *pending_ops; + /* Operations in this list are recurring operations + * that have been handed off from the pending ops list. */ + GList *recurring_ops; + + crm_trigger_t *work; } lrmd_rsc_t; typedef struct lrmd_client_s { - char *id; - char *name; + char *id; + char *name; - qb_ipcs_connection_t *channel; + qb_ipcs_connection_t *channel; - long long flags; + long long flags; } lrmd_client_t; -void process_lrmd_message(lrmd_client_t *client, xmlNode *request); +void process_lrmd_message(lrmd_client_t * client, xmlNode * request); void free_rsc(gpointer data); void lrmd_shutdown(int nsig); /* * \brief Don't worry about freeing this connection. It is * taken care of after mainloop exits by the main() function. */ stonith_t *get_stonith_connection(void); #endif diff --git a/lrmd/main.c b/lrmd/main.c index 2394e7ee8d..83ea7fd77e 100644 --- a/lrmd/main.c +++ b/lrmd/main.c @@ -1,255 +1,259 @@ /* * Copyright (c) 2012 David Vossel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ #include #include #include #include #include #include #include #include #include GMainLoop *mainloop = NULL; qb_ipcs_service_t *ipcs = NULL; stonith_t *stonith_api = NULL; - -stonith_t *get_stonith_connection(void) +stonith_t * +get_stonith_connection(void) { - if (stonith_api && stonith_api->state == stonith_disconnected) { - stonith_api_delete(stonith_api); - stonith_api = NULL; - } - - if (!stonith_api) { - int rc = 0; - int tries = 10; - stonith_api = stonith_api_new(); - do { - rc = stonith_api->cmds->connect(stonith_api, "lrmd", NULL); - if (rc == stonith_ok) { - break; - } - sleep(1); - tries--; - } while (tries); - - if (rc) { - crm_err("Unable to connect to stonith daemon to execute command. error: %s", stonith_error2string(rc)); - stonith_api_delete(stonith_api); - stonith_api = NULL; - } - } - return stonith_api; + if (stonith_api && stonith_api->state == stonith_disconnected) { + stonith_api_delete(stonith_api); + stonith_api = NULL; + } + + if (!stonith_api) { + int rc = 0; + int tries = 10; + + stonith_api = stonith_api_new(); + do { + rc = stonith_api->cmds->connect(stonith_api, "lrmd", NULL); + if (rc == stonith_ok) { + break; + } + sleep(1); + tries--; + } while (tries); + + if (rc) { + crm_err("Unable to connect to stonith daemon to execute command. error: %s", + stonith_error2string(rc)); + stonith_api_delete(stonith_api); + stonith_api = NULL; + } + } + return stonith_api; } static int32_t -lrmd_ipc_accept(qb_ipcs_connection_t *c, uid_t uid, gid_t gid) +lrmd_ipc_accept(qb_ipcs_connection_t * c, uid_t uid, gid_t gid) { - struct qb_ipcs_connection_stats stats = { 0, }; + struct qb_ipcs_connection_stats stats = { 0, }; - qb_ipcs_connection_stats_get(c, &stats, 1); - crm_info("Accepting client connection: %p pid=%d for uid=%d gid=%d", - c, stats.client_pid, uid, gid); - return 0; + qb_ipcs_connection_stats_get(c, &stats, 1); + crm_info("Accepting client connection: %p pid=%d for uid=%d gid=%d", + c, stats.client_pid, uid, gid); + return 0; } static void -lrmd_ipc_created(qb_ipcs_connection_t *c) +lrmd_ipc_created(qb_ipcs_connection_t * c) { - lrmd_client_t *new_client = NULL; + lrmd_client_t *new_client = NULL; - new_client = calloc(1, sizeof(lrmd_client_t)); - new_client->channel = c; + new_client = calloc(1, sizeof(lrmd_client_t)); + new_client->channel = c; - new_client->id = crm_generate_uuid(); - crm_trace("LRMD client connection established. %p id: %s", c, new_client->id); + new_client->id = crm_generate_uuid(); + crm_trace("LRMD client connection established. %p id: %s", c, new_client->id); - g_hash_table_insert(client_list, new_client->id, new_client); - qb_ipcs_context_set(c, new_client); + g_hash_table_insert(client_list, new_client->id, new_client); + qb_ipcs_context_set(c, new_client); } static int32_t -lrmd_ipc_dispatch(qb_ipcs_connection_t *c, void *data, size_t size) +lrmd_ipc_dispatch(qb_ipcs_connection_t * c, void *data, size_t size) { - xmlNode *request = crm_ipcs_recv(c, data, size); - lrmd_client_t *client = (lrmd_client_t *) qb_ipcs_context_get(c); + xmlNode *request = crm_ipcs_recv(c, data, size); + lrmd_client_t *client = (lrmd_client_t *) qb_ipcs_context_get(c); - CRM_CHECK(client != NULL, crm_err("Invalid client"); return FALSE); - CRM_CHECK(client->id != NULL, crm_err("Invalid client: %p", client); return FALSE); + CRM_CHECK(client != NULL, crm_err("Invalid client"); + return FALSE); + CRM_CHECK(client->id != NULL, crm_err("Invalid client: %p", client); + return FALSE); - if (!request) { - return 0; - } + if (!request) { + return 0; + } - if (!client->name) { - const char *value = crm_element_value(request, F_LRMD_CLIENTNAME); + if (!client->name) { + const char *value = crm_element_value(request, F_LRMD_CLIENTNAME); - if (value == NULL) { - client->name = crm_itoa(crm_ipcs_client_pid(c)); - } else { - client->name = crm_strdup(value); - } - } + if (value == NULL) { + client->name = crm_itoa(crm_ipcs_client_pid(c)); + } else { + client->name = crm_strdup(value); + } + } - crm_xml_add(request, F_LRMD_CLIENTID, client->id); - crm_xml_add(request, F_LRMD_CLIENTNAME, client->name); + crm_xml_add(request, F_LRMD_CLIENTID, client->id); + crm_xml_add(request, F_LRMD_CLIENTNAME, client->name); - process_lrmd_message(client, request); + process_lrmd_message(client, request); - free_xml(request); - return 0; + free_xml(request); + return 0; } static int32_t -lrmd_ipc_closed(qb_ipcs_connection_t *c) +lrmd_ipc_closed(qb_ipcs_connection_t * c) { - lrmd_client_t *client = (lrmd_client_t *) qb_ipcs_context_get(c); - int found = 0; + lrmd_client_t *client = (lrmd_client_t *) qb_ipcs_context_get(c); + int found = 0; - if (!client) { - crm_err("No client for ipc"); - return 0; - } + if (!client) { + crm_err("No client for ipc"); + return 0; + } - if (client->id) { - found = g_hash_table_remove(client_list, client->id); - } + if (client->id) { + found = g_hash_table_remove(client_list, client->id); + } - if (!found) { - crm_err("Asked to remove unknown client with id %d", client->id); - } + if (!found) { + crm_err("Asked to remove unknown client with id %d", client->id); + } - return 0; + return 0; } static void -lrmd_ipc_destroy(qb_ipcs_connection_t *c) +lrmd_ipc_destroy(qb_ipcs_connection_t * c) { - lrmd_client_t *client = (lrmd_client_t *) qb_ipcs_context_get(c); + lrmd_client_t *client = (lrmd_client_t *) qb_ipcs_context_get(c); - if (!client) { - crm_err("No client for ipc"); - return; - } + if (!client) { + crm_err("No client for ipc"); + return; + } - crm_info("LRMD client disconnecting %p - name: %s id: %s", c, client->name, client->id); + crm_info("LRMD client disconnecting %p - name: %s id: %s", c, client->name, client->id); - qb_ipcs_context_set(c, NULL); - free(client->name); - free(client->id); - free(client); + qb_ipcs_context_set(c, NULL); + free(client->name); + free(client->id); + free(client); } -static struct qb_ipcs_service_handlers lrmd_ipc_callbacks = -{ - .connection_accept = lrmd_ipc_accept, - .connection_created = lrmd_ipc_created, - .msg_process = lrmd_ipc_dispatch, - .connection_closed = lrmd_ipc_closed, - .connection_destroyed = lrmd_ipc_destroy +static struct qb_ipcs_service_handlers lrmd_ipc_callbacks = { + .connection_accept = lrmd_ipc_accept, + .connection_created = lrmd_ipc_created, + .msg_process = lrmd_ipc_dispatch, + .connection_closed = lrmd_ipc_closed, + .connection_destroyed = lrmd_ipc_destroy }; void lrmd_shutdown(int nsig) { - crm_info("Terminating with %d clients", g_hash_table_size(client_list)); - if (ipcs) { - mainloop_del_ipc_server(ipcs); - } - exit(0); + crm_info("Terminating with %d clients", g_hash_table_size(client_list)); + if (ipcs) { + mainloop_del_ipc_server(ipcs); + } + exit(0); } static int try_server_create(void) { - int tries = 10; - - /* - * This should complete on the first iteration. The only - * known reason for why this would fail is if another lrmd process - * already exists on the system. To avoid this situation - * we attempt to connect to the old lrmd process and shut it down - * using the client library. - */ - do { - ipcs = mainloop_add_ipc_server(CRM_SYSTEM_LRMD, QB_IPC_SHM, &lrmd_ipc_callbacks); - - if (ipcs == NULL) { - xmlNode *reply = NULL; - xmlNode *hello = create_xml_node(NULL, "lrmd_command"); - crm_ipc_t *ipc = crm_ipc_new("lrmd", 0); - - if (ipc && crm_ipc_connect(ipc)) { - crm_xml_add(hello, F_TYPE, T_LRMD); - crm_xml_add(hello, F_LRMD_OPERATION, CRM_OP_QUIT); - crm_xml_add(hello, F_LRMD_CLIENTNAME, "new_lrmd"); - - crm_ipc_send(ipc, hello, &reply, -1); - - crm_ipc_close(ipc); - crm_ipc_destroy(ipc); - } - free_xml(reply); - free_xml(hello); - - crm_err("New IPC server could not be created because another lrmd process exists, sending shutdown command to old lrmd process."); - } - - tries --; - } while (!ipcs && tries); - - return ipcs ? 0 : -1; + int tries = 10; + + /* + * This should complete on the first iteration. The only + * known reason for why this would fail is if another lrmd process + * already exists on the system. To avoid this situation + * we attempt to connect to the old lrmd process and shut it down + * using the client library. + */ + do { + ipcs = mainloop_add_ipc_server(CRM_SYSTEM_LRMD, QB_IPC_SHM, &lrmd_ipc_callbacks); + + if (ipcs == NULL) { + xmlNode *reply = NULL; + xmlNode *hello = create_xml_node(NULL, "lrmd_command"); + crm_ipc_t *ipc = crm_ipc_new("lrmd", 0); + + if (ipc && crm_ipc_connect(ipc)) { + crm_xml_add(hello, F_TYPE, T_LRMD); + crm_xml_add(hello, F_LRMD_OPERATION, CRM_OP_QUIT); + crm_xml_add(hello, F_LRMD_CLIENTNAME, "new_lrmd"); + + crm_ipc_send(ipc, hello, &reply, -1); + + crm_ipc_close(ipc); + crm_ipc_destroy(ipc); + } + free_xml(reply); + free_xml(hello); + + crm_err + ("New IPC server could not be created because another lrmd process exists, sending shutdown command to old lrmd process."); + } + + tries--; + } while (!ipcs && tries); + + return ipcs ? 0 : -1; } int -main(int argc, char ** argv) +main(int argc, char **argv) { - int rc = 0; + int rc = 0; - crm_log_init("lrmd", LOG_INFO, TRUE, FALSE, argc, argv, FALSE); + crm_log_init("lrmd", LOG_INFO, TRUE, FALSE, argc, argv, FALSE); rsc_list = g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, free_rsc); - client_list = g_hash_table_new(crm_str_hash, g_str_equal); - if (try_server_create()) { - crm_err("Failed to allocate lrmd server. shutting down"); - exit(-1); - } - - mainloop_add_signal(SIGTERM, lrmd_shutdown); - mainloop = g_main_new(FALSE); - crm_info("Starting"); - g_main_run(mainloop); - - mainloop_del_ipc_server(ipcs); - g_hash_table_destroy(client_list); - g_hash_table_destroy(rsc_list); - - if (stonith_api) { - stonith_api->cmds->disconnect(stonith_api); - stonith_api_delete(stonith_api); - } - - return rc; + client_list = g_hash_table_new(crm_str_hash, g_str_equal); + if (try_server_create()) { + crm_err("Failed to allocate lrmd server. shutting down"); + exit(-1); + } + + mainloop_add_signal(SIGTERM, lrmd_shutdown); + mainloop = g_main_new(FALSE); + crm_info("Starting"); + g_main_run(mainloop); + + mainloop_del_ipc_server(ipcs); + g_hash_table_destroy(client_list); + g_hash_table_destroy(rsc_list); + + if (stonith_api) { + stonith_api->cmds->disconnect(stonith_api); + stonith_api_delete(stonith_api); + } + + return rc; } diff --git a/lrmd/test.c b/lrmd/test.c index 64c7adf777..e33d6ab8a4 100644 --- a/lrmd/test.c +++ b/lrmd/test.c @@ -1,561 +1,553 @@ /* * Copyright (c) 2012 David Vossel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ #include #include #include #include #include #include #include #include #include /* *INDENT-OFF* */ static struct crm_option long_options[] = { {"help", 0, 0, '?'}, {"verbose", 0, 0, 'V', "\t\tPrint out logs and events to screen"}, {"quiet", 0, 0, 'Q', "\t\tSuppress all output to screen"}, /* just incase we have to add data to events, * we don't want break a billion regression tests. Instead * we'll create different versions */ {"listen", 1, 0, 'l', "\tListen for a specific event string"}, {"event-ver", 1, 0, 'e', "\tVersion of event to listen to"}, {"api-call", 1, 0, 'c', "\tDirectly relates to lrmd api functions"}, {"no-wait", 0, 0, 'w', "\tMake api call and do not wait for result."}, {"is-running", 0, 0, 'R', "\tDetermine if a resource is registered and running."}, {"-spacer-", 1, 0, '-', "\nParameters for api-call option"}, {"action", 1, 0, 'a'}, {"rsc-id", 1, 0, 'r'}, {"cancel-call-id", 1, 0, 'x'}, {"provider", 1, 0, 'P'}, {"class", 1, 0, 'C'}, {"type", 1, 0, 'T'}, {"interval", 1, 0, 'i'}, {"timeout", 1, 0, 't'}, {"start-delay", 1, 0, 's'}, {"param-key", 1, 0, 'k'}, {"param-val", 1, 0, 'v'}, {"-spacer-", 1, 0, '-'}, {0, 0, 0, 0} }; /* *INDENT-ON* */ cib_t *cib_conn = NULL; static int exec_call_id = 0; static int exec_call_opts = 0; extern void cleanup_alloc_calculations(pe_working_set_t * data_set); static struct { - int verbose; - int quiet; - int print; - int interval; - int timeout; - int start_delay; - int cancel_call_id; - int event_version; - int no_wait; - int is_running; - int no_connect; - const char *api_call; - const char *rsc_id; - const char *provider; - const char *class; - const char *type; - const char *action; - const char *listen; - lrmd_key_value_t *params; + int verbose; + int quiet; + int print; + int interval; + int timeout; + int start_delay; + int cancel_call_id; + int event_version; + int no_wait; + int is_running; + int no_connect; + const char *api_call; + const char *rsc_id; + const char *provider; + const char *class; + const char *type; + const char *action; + const char *listen; + lrmd_key_value_t *params; } options; GMainLoop *mainloop = NULL; lrmd_t *lrmd_conn = NULL; static char event_buf_v0[1024]; #define print_result(result) \ if (!options.quiet) { \ result; \ } \ #define report_event(event) \ snprintf(event_buf_v0, sizeof(event_buf_v0), "NEW_EVENT event_type:%s rsc_id:%s action:%s rc:%s op_status:%s", \ lrmd_event_type2str(event->type), \ event->rsc_id, \ event->op_type ? event->op_type : "none", \ lrmd_event_rc2str(event->rc), \ services_lrm_status_str(event->op_status)); \ crm_info("%s", event_buf_v0);; static void test_shutdown(int nsig) { - lrmd_api_delete(lrmd_conn); + lrmd_api_delete(lrmd_conn); } static void -read_events(lrmd_event_data_t *event) +read_events(lrmd_event_data_t * event) { - report_event(event); - if (options.listen) { - if (safe_str_eq(options.listen, event_buf_v0)) { - print_result(printf("LISTEN EVENT SUCCESSFUL\n")); - exit(0); - } - } - - if (exec_call_id && (event->call_id == exec_call_id)) { - if (event->op_status == 0 && event->rc == 0) { - print_result(printf("API-CALL SUCCESSFUL for 'exec'\n")); - } else { - print_result(printf("API-CALL FAILURE for 'exec', rc:%d lrmd_op_status:%s\n", - event->rc, - services_lrm_status_str(event->op_status))); - exit(-1); - } - - if (!options.listen) { - exit(0); - } - } + report_event(event); + if (options.listen) { + if (safe_str_eq(options.listen, event_buf_v0)) { + print_result(printf("LISTEN EVENT SUCCESSFUL\n")); + exit(0); + } + } + + if (exec_call_id && (event->call_id == exec_call_id)) { + if (event->op_status == 0 && event->rc == 0) { + print_result(printf("API-CALL SUCCESSFUL for 'exec'\n")); + } else { + print_result(printf("API-CALL FAILURE for 'exec', rc:%d lrmd_op_status:%s\n", + event->rc, services_lrm_status_str(event->op_status))); + exit(-1); + } + + if (!options.listen) { + exit(0); + } + } } static gboolean timeout_err(gpointer data) { - print_result(printf("LISTEN EVENT FAILURE - timeout occurred, never found.\n")); - exit(-1); + print_result(printf("LISTEN EVENT FAILURE - timeout occurred, never found.\n")); + exit(-1); - return FALSE; + return FALSE; } static void try_connect(void) { - int tries = 10; - int i = 0; - int rc = 0; - - - for (i = 0; i < tries; i++) { - rc = lrmd_conn->cmds->connect(lrmd_conn, "lrmd", NULL); - - if (!rc) { - crm_info("lrmd client connection established"); - return; - } else { - crm_info("lrmd client connection failed"); - } - sleep(1); - } - - print_result(printf("API CONNECTION FAILURE\n")); - exit(-1); + int tries = 10; + int i = 0; + int rc = 0; + + for (i = 0; i < tries; i++) { + rc = lrmd_conn->cmds->connect(lrmd_conn, "lrmd", NULL); + + if (!rc) { + crm_info("lrmd client connection established"); + return; + } else { + crm_info("lrmd client connection failed"); + } + sleep(1); + } + + print_result(printf("API CONNECTION FAILURE\n")); + exit(-1); } static gboolean start_test(gpointer user_data) { - int rc = 0; - - if (!options.no_connect) { - try_connect(); - } - lrmd_conn->cmds->set_callback(lrmd_conn, read_events); - - if (options.timeout) { - g_timeout_add(options.timeout, timeout_err, NULL); - } - - if (!options.api_call) { - return 0; - } - - if (safe_str_eq(options.api_call, "exec")) { - rc = lrmd_conn->cmds->exec(lrmd_conn, - options.rsc_id, - options.action, - NULL, - options.interval, - options.timeout, - options.start_delay, - exec_call_opts, - options.params); - - if (rc > 0) { - exec_call_id = rc; - print_result(printf("API-CALL 'exec' action pending, waiting on response\n")); - } - - } else if (safe_str_eq(options.api_call, "register_rsc")) { - rc = lrmd_conn->cmds->register_rsc(lrmd_conn, - options.rsc_id, - options.class, - options.provider, - options.type, - 0); - } else if (safe_str_eq(options.api_call, "get_rsc_info")) { - lrmd_rsc_info_t *rsc_info; - - rsc_info = lrmd_conn->cmds->get_rsc_info(lrmd_conn, options.rsc_id, 0); - - if (rsc_info) { - print_result(printf("RSC_INFO: id:%s class:%s provider:%s type:%s\n", - rsc_info->id, rsc_info->class, rsc_info->provider ? rsc_info->provider : "", rsc_info->type)); - lrmd_free_rsc_info(rsc_info); - rc = lrmd_ok; - } else { - rc = -1; - } - } else if (safe_str_eq(options.api_call, "unregister_rsc")) { - rc = lrmd_conn->cmds->unregister_rsc(lrmd_conn, - options.rsc_id, - 0); - } else if (safe_str_eq(options.api_call, "cancel")) { - rc = lrmd_conn->cmds->cancel(lrmd_conn, - options.rsc_id, - options.action, - options.interval); - } else if (safe_str_eq(options.api_call, "metadata")) { - char *output = NULL; - rc = lrmd_conn->cmds->get_metadata(lrmd_conn, - options.class, - options.provider, - options.type, &output, 0); - if (rc == lrmd_ok) { - print_result(printf("%s", output)); - free(output); - } - } else if (safe_str_eq(options.api_call, "list_agents")) { - lrmd_list_t *list = NULL; - lrmd_list_t *iter = NULL; - rc = lrmd_conn->cmds->list_agents(lrmd_conn, &list, options.class, options.provider); - - if (rc > 0) { - print_result(printf("%d agents found\n", rc)); - for (iter = list; iter != NULL; iter = iter->next) { - print_result(printf("%s\n", iter->val)); - } - lrmd_list_freeall(list); - rc = 0; - } else { - print_result(printf("API_CALL FAILURE - no agents found\n")); - rc = -1; - } - } else if (safe_str_eq(options.api_call, "list_ocf_providers")) { - lrmd_list_t *list = NULL; - lrmd_list_t *iter = NULL; - rc = lrmd_conn->cmds->list_ocf_providers(lrmd_conn, options.type, &list); - - if (rc > 0) { - print_result(printf("%d providers found\n", rc)); - for (iter = list; iter != NULL; iter = iter->next) { - print_result(printf("%s\n", iter->val)); - } - lrmd_list_freeall(list); - rc = 0; - } else { - print_result(printf("API_CALL FAILURE - no providers found\n")); - rc = -1; - } - } else if (options.api_call) { - print_result(printf("API-CALL FAILURE unknown action '%s'\n", options.action)); - exit(-1); - } - - if (rc < 0) { - print_result(printf("API-CALL FAILURE for '%s' api_rc:%d\n", options.api_call, rc)); - exit(-1); - } - - if (options.api_call && rc == lrmd_ok) { - print_result(printf("API-CALL SUCCESSFUL for '%s'\n", options.api_call)); - if (!options.listen) { - exit(0); - } - } - - if (options.no_wait) { - /* just make the call and exit regardless of anything else. */ - exit(0); - } - - return 0; + int rc = 0; + + if (!options.no_connect) { + try_connect(); + } + lrmd_conn->cmds->set_callback(lrmd_conn, read_events); + + if (options.timeout) { + g_timeout_add(options.timeout, timeout_err, NULL); + } + + if (!options.api_call) { + return 0; + } + + if (safe_str_eq(options.api_call, "exec")) { + rc = lrmd_conn->cmds->exec(lrmd_conn, + options.rsc_id, + options.action, + NULL, + options.interval, + options.timeout, + options.start_delay, exec_call_opts, options.params); + + if (rc > 0) { + exec_call_id = rc; + print_result(printf("API-CALL 'exec' action pending, waiting on response\n")); + } + + } else if (safe_str_eq(options.api_call, "register_rsc")) { + rc = lrmd_conn->cmds->register_rsc(lrmd_conn, + options.rsc_id, + options.class, options.provider, options.type, 0); + } else if (safe_str_eq(options.api_call, "get_rsc_info")) { + lrmd_rsc_info_t *rsc_info; + + rsc_info = lrmd_conn->cmds->get_rsc_info(lrmd_conn, options.rsc_id, 0); + + if (rsc_info) { + print_result(printf("RSC_INFO: id:%s class:%s provider:%s type:%s\n", + rsc_info->id, rsc_info->class, + rsc_info->provider ? rsc_info->provider : "", + rsc_info->type)); + lrmd_free_rsc_info(rsc_info); + rc = lrmd_ok; + } else { + rc = -1; + } + } else if (safe_str_eq(options.api_call, "unregister_rsc")) { + rc = lrmd_conn->cmds->unregister_rsc(lrmd_conn, options.rsc_id, 0); + } else if (safe_str_eq(options.api_call, "cancel")) { + rc = lrmd_conn->cmds->cancel(lrmd_conn, options.rsc_id, options.action, options.interval); + } else if (safe_str_eq(options.api_call, "metadata")) { + char *output = NULL; + + rc = lrmd_conn->cmds->get_metadata(lrmd_conn, + options.class, + options.provider, options.type, &output, 0); + if (rc == lrmd_ok) { + print_result(printf("%s", output)); + free(output); + } + } else if (safe_str_eq(options.api_call, "list_agents")) { + lrmd_list_t *list = NULL; + lrmd_list_t *iter = NULL; + + rc = lrmd_conn->cmds->list_agents(lrmd_conn, &list, options.class, options.provider); + + if (rc > 0) { + print_result(printf("%d agents found\n", rc)); + for (iter = list; iter != NULL; iter = iter->next) { + print_result(printf("%s\n", iter->val)); + } + lrmd_list_freeall(list); + rc = 0; + } else { + print_result(printf("API_CALL FAILURE - no agents found\n")); + rc = -1; + } + } else if (safe_str_eq(options.api_call, "list_ocf_providers")) { + lrmd_list_t *list = NULL; + lrmd_list_t *iter = NULL; + + rc = lrmd_conn->cmds->list_ocf_providers(lrmd_conn, options.type, &list); + + if (rc > 0) { + print_result(printf("%d providers found\n", rc)); + for (iter = list; iter != NULL; iter = iter->next) { + print_result(printf("%s\n", iter->val)); + } + lrmd_list_freeall(list); + rc = 0; + } else { + print_result(printf("API_CALL FAILURE - no providers found\n")); + rc = -1; + } + } else if (options.api_call) { + print_result(printf("API-CALL FAILURE unknown action '%s'\n", options.action)); + exit(-1); + } + + if (rc < 0) { + print_result(printf("API-CALL FAILURE for '%s' api_rc:%d\n", options.api_call, rc)); + exit(-1); + } + + if (options.api_call && rc == lrmd_ok) { + print_result(printf("API-CALL SUCCESSFUL for '%s'\n", options.api_call)); + if (!options.listen) { + exit(0); + } + } + + if (options.no_wait) { + /* just make the call and exit regardless of anything else. */ + exit(0); + } + + return 0; } static resource_t * find_rsc_or_clone(const char *rsc, pe_working_set_t * data_set) { - resource_t *the_rsc = pe_find_resource(data_set->resources, rsc); + resource_t *the_rsc = pe_find_resource(data_set->resources, rsc); - if (the_rsc == NULL) { - char *as_clone = crm_concat(rsc, "0", ':'); + if (the_rsc == NULL) { + char *as_clone = crm_concat(rsc, "0", ':'); - the_rsc = pe_find_resource(data_set->resources, as_clone); - free(as_clone); - } - return the_rsc; + the_rsc = pe_find_resource(data_set->resources, as_clone); + free(as_clone); + } + return the_rsc; } static int generate_params(void) { - int rc = 0; - pe_working_set_t data_set; - xmlNode *cib_xml_copy = NULL; - resource_t *rsc = NULL; - GHashTable *params = NULL; - GHashTable *meta = NULL; - GHashTableIter iter; - - if (options.params) { - return 0; - } - - set_working_set_defaults(&data_set); - - cib_conn = cib_new(); - rc = cib_conn->cmds->signon(cib_conn, "lrmd_test", cib_query); - if (rc != cib_ok) { - crm_err("Error signing on to the CIB service: %s\n", cib_error2string(rc)); - rc = -1; - goto param_gen_bail; - } - - cib_xml_copy = get_cib_copy(cib_conn); - - if (!cib_xml_copy) { - crm_err("Error retrieving cib copy."); - rc = -1; - goto param_gen_bail; - } - - if (cli_config_update(&cib_xml_copy, NULL, FALSE) == FALSE) { - crm_err("Error updating cib configuration"); - rc = -1; - goto param_gen_bail; - } - - data_set.input = cib_xml_copy; - data_set.now = new_ha_date(TRUE); - - cluster_status(&data_set); - if (options.rsc_id) { - rsc = find_rsc_or_clone(options.rsc_id, &data_set); - } - - if (!rsc) { - crm_err("Resource does not exist in config"); - rc = -1; - goto param_gen_bail; - } - - params = g_hash_table_new_full(crm_str_hash, - g_str_equal, g_hash_destroy_str, g_hash_destroy_str); - meta = g_hash_table_new_full(crm_str_hash, - g_str_equal, g_hash_destroy_str, g_hash_destroy_str); - - get_rsc_attributes(params, rsc, NULL, &data_set); - get_meta_attributes(meta, rsc, NULL, &data_set); - - if (params) { - char *key = NULL; - char *value = NULL; - - g_hash_table_iter_init(&iter, params); - while (g_hash_table_iter_next(&iter, (gpointer *) & key, (gpointer *) & value)) { - options.params = lrmd_key_value_add(options.params, key, value); - } - g_hash_table_destroy(params); - } - - if (meta) { - char *key = NULL; - char *value = NULL; - - g_hash_table_iter_init(&iter, meta); - while (g_hash_table_iter_next(&iter, (gpointer *) & key, (gpointer *) & value)) { - char *crm_name = crm_meta_name(key); - options.params = lrmd_key_value_add(options.params, crm_name, value); - free(crm_name); - } - g_hash_table_destroy(meta); - } - -param_gen_bail: - - cleanup_alloc_calculations(&data_set); - return rc; + int rc = 0; + pe_working_set_t data_set; + xmlNode *cib_xml_copy = NULL; + resource_t *rsc = NULL; + GHashTable *params = NULL; + GHashTable *meta = NULL; + GHashTableIter iter; + + if (options.params) { + return 0; + } + + set_working_set_defaults(&data_set); + + cib_conn = cib_new(); + rc = cib_conn->cmds->signon(cib_conn, "lrmd_test", cib_query); + if (rc != cib_ok) { + crm_err("Error signing on to the CIB service: %s\n", cib_error2string(rc)); + rc = -1; + goto param_gen_bail; + } + + cib_xml_copy = get_cib_copy(cib_conn); + + if (!cib_xml_copy) { + crm_err("Error retrieving cib copy."); + rc = -1; + goto param_gen_bail; + } + + if (cli_config_update(&cib_xml_copy, NULL, FALSE) == FALSE) { + crm_err("Error updating cib configuration"); + rc = -1; + goto param_gen_bail; + } + + data_set.input = cib_xml_copy; + data_set.now = new_ha_date(TRUE); + + cluster_status(&data_set); + if (options.rsc_id) { + rsc = find_rsc_or_clone(options.rsc_id, &data_set); + } + + if (!rsc) { + crm_err("Resource does not exist in config"); + rc = -1; + goto param_gen_bail; + } + + params = g_hash_table_new_full(crm_str_hash, + g_str_equal, g_hash_destroy_str, g_hash_destroy_str); + meta = g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str, g_hash_destroy_str); + + get_rsc_attributes(params, rsc, NULL, &data_set); + get_meta_attributes(meta, rsc, NULL, &data_set); + + if (params) { + char *key = NULL; + char *value = NULL; + + g_hash_table_iter_init(&iter, params); + while (g_hash_table_iter_next(&iter, (gpointer *) & key, (gpointer *) & value)) { + options.params = lrmd_key_value_add(options.params, key, value); + } + g_hash_table_destroy(params); + } + + if (meta) { + char *key = NULL; + char *value = NULL; + + g_hash_table_iter_init(&iter, meta); + while (g_hash_table_iter_next(&iter, (gpointer *) & key, (gpointer *) & value)) { + char *crm_name = crm_meta_name(key); + + options.params = lrmd_key_value_add(options.params, crm_name, value); + free(crm_name); + } + g_hash_table_destroy(meta); + } + + param_gen_bail: + + cleanup_alloc_calculations(&data_set); + return rc; } -int main(int argc, char ** argv) +int +main(int argc, char **argv) { - int option_index = 0; - int argerr = 0; - int flag; - char *key = NULL; - char *val = NULL; - crm_trigger_t *trig; - - crm_set_options(NULL, "mode [options]", long_options, - "Inject commands into the lrmd and watch for events\n"); - - while (1) { - flag = crm_get_option(argc, argv, &option_index); - if (flag == -1) - break; - - switch(flag) { - case '?': - crm_help(flag, EX_OK); - break; - case 'V': - options.verbose = 1; - break; - case 'Q': - options.quiet = 1; - options.verbose = 0; - break; - case 'e': - options.event_version = atoi(optarg); - break; - case 'l': - options.listen = optarg; - break; - case 'w': - options.no_wait = 1; - break; - case 'R': - options.is_running = 1; - break; - case 'c': - options.api_call = optarg; - break; - case 'a': - options.action = optarg; - break; - case 'r': - options.rsc_id = optarg; - break; - case 'x': - options.cancel_call_id = atoi(optarg); - break; - case 'P': - options.provider = optarg; - break; - case 'C': - options.class = optarg; - break; - case 'T': - options.type = optarg; - break; - case 'i': - options.interval = atoi(optarg); - break; - case 't': - options.timeout = atoi(optarg); - break; - case 's': - options.start_delay = atoi(optarg); - break; - case 'k': - key = optarg; - if (key && val) { - options.params = lrmd_key_value_add(options.params, key, val); - key = val = NULL; - } - break; - case 'v': - val = optarg; - if (key && val) { - options.params = lrmd_key_value_add(options.params, key, val); - key = val = NULL; - } - break; - default: - ++argerr; - break; - } - } - - if (argerr) { - crm_help('?', EX_USAGE); - } - if (optind > argc) { - ++argerr; - } - - - if (!options.listen && - (safe_str_eq(options.api_call, "metadata") || - safe_str_eq(options.api_call, "list_agents") || - safe_str_eq(options.api_call, "list_ocf_providers"))) { - options.no_connect = 1; - } - - crm_log_init("lrmd_ctest", LOG_INFO, TRUE, options.verbose ? TRUE : FALSE, argc, argv, FALSE); - - if (options.is_running) { - if (!options.timeout) { - options.timeout = 30000; - } - options.interval = 0; - if (!options.rsc_id) { - crm_err("rsc-id must be given when is-running is used"); - exit(-1); - } - - if (generate_params()) { - print_result(printf("Failed to retrieve rsc parameters from cib, can not determine if rsc is running.\n")); - exit(-1); - } - options.api_call = "exec"; - options.action = "monitor"; - exec_call_opts = lrmd_opt_notify_orig_only; - } - - - /* if we can't perform an api_call or listen for events, - * there is nothing to do */ - if (!options.api_call && !options.listen) { - crm_err("Nothing to be done. Please specify 'api-call' and/or 'listen'"); - return 0; - } - - lrmd_conn = lrmd_api_new(); - trig = mainloop_add_trigger(G_PRIORITY_HIGH, start_test, NULL); - mainloop_set_trigger(trig); - mainloop_add_signal(SIGTERM, test_shutdown); - - crm_info("Starting"); - mainloop = g_main_new(FALSE); - g_main_run(mainloop); - lrmd_api_delete(lrmd_conn); - - if (cib_conn != NULL) { - cib_conn->cmds->signoff(cib_conn); - cib_delete(cib_conn); - } - - return 0; + int option_index = 0; + int argerr = 0; + int flag; + char *key = NULL; + char *val = NULL; + crm_trigger_t *trig; + + crm_set_options(NULL, "mode [options]", long_options, + "Inject commands into the lrmd and watch for events\n"); + + while (1) { + flag = crm_get_option(argc, argv, &option_index); + if (flag == -1) + break; + + switch (flag) { + case '?': + crm_help(flag, EX_OK); + break; + case 'V': + options.verbose = 1; + break; + case 'Q': + options.quiet = 1; + options.verbose = 0; + break; + case 'e': + options.event_version = atoi(optarg); + break; + case 'l': + options.listen = optarg; + break; + case 'w': + options.no_wait = 1; + break; + case 'R': + options.is_running = 1; + break; + case 'c': + options.api_call = optarg; + break; + case 'a': + options.action = optarg; + break; + case 'r': + options.rsc_id = optarg; + break; + case 'x': + options.cancel_call_id = atoi(optarg); + break; + case 'P': + options.provider = optarg; + break; + case 'C': + options.class = optarg; + break; + case 'T': + options.type = optarg; + break; + case 'i': + options.interval = atoi(optarg); + break; + case 't': + options.timeout = atoi(optarg); + break; + case 's': + options.start_delay = atoi(optarg); + break; + case 'k': + key = optarg; + if (key && val) { + options.params = lrmd_key_value_add(options.params, key, val); + key = val = NULL; + } + break; + case 'v': + val = optarg; + if (key && val) { + options.params = lrmd_key_value_add(options.params, key, val); + key = val = NULL; + } + break; + default: + ++argerr; + break; + } + } + + if (argerr) { + crm_help('?', EX_USAGE); + } + if (optind > argc) { + ++argerr; + } + + if (!options.listen && + (safe_str_eq(options.api_call, "metadata") || + safe_str_eq(options.api_call, "list_agents") || + safe_str_eq(options.api_call, "list_ocf_providers"))) { + options.no_connect = 1; + } + + crm_log_init("lrmd_ctest", LOG_INFO, TRUE, options.verbose ? TRUE : FALSE, argc, argv, FALSE); + + if (options.is_running) { + if (!options.timeout) { + options.timeout = 30000; + } + options.interval = 0; + if (!options.rsc_id) { + crm_err("rsc-id must be given when is-running is used"); + exit(-1); + } + + if (generate_params()) { + print_result(printf + ("Failed to retrieve rsc parameters from cib, can not determine if rsc is running.\n")); + exit(-1); + } + options.api_call = "exec"; + options.action = "monitor"; + exec_call_opts = lrmd_opt_notify_orig_only; + } + + /* if we can't perform an api_call or listen for events, + * there is nothing to do */ + if (!options.api_call && !options.listen) { + crm_err("Nothing to be done. Please specify 'api-call' and/or 'listen'"); + return 0; + } + + lrmd_conn = lrmd_api_new(); + trig = mainloop_add_trigger(G_PRIORITY_HIGH, start_test, NULL); + mainloop_set_trigger(trig); + mainloop_add_signal(SIGTERM, test_shutdown); + + crm_info("Starting"); + mainloop = g_main_new(FALSE); + g_main_run(mainloop); + lrmd_api_delete(lrmd_conn); + + if (cib_conn != NULL) { + cib_conn->cmds->signoff(cib_conn); + cib_delete(cib_conn); + } + + return 0; }