16 #include <sys/types.h> 51 static int operations = 0;
52 static GHashTable *recurring_actions = NULL;
56 static GList *blocked_ops = NULL;
59 static GList *inflight_ops = NULL;
61 static void handle_blocked_ops(
void);
98 init_recurring_actions(
void)
100 if (recurring_actions == NULL) {
113 static inline gboolean
118 g_list_find(inflight_ops, op) != NULL;
134 expand_resource_class(
const char *rsc,
const char *standard,
const char *agent)
136 char *expanded_class = NULL;
138 #if PCMK__ENABLE_SERVICE 142 if (found_class != NULL) {
143 crm_debug(
"Found %s agent %s for %s", found_class, agent, rsc);
146 const char *default_standard = NULL;
150 #elif SUPPORT_SYSTEMD 152 #elif SUPPORT_UPSTART 155 #error No standards supported for service alias (configure script bug) 157 crm_info(
"Assuming resource class %s for agent %s for %s",
158 default_standard, agent, rsc);
164 if (expanded_class == NULL) {
167 return expanded_class;
197 required_argument_missing(uint32_t ra_caps,
const char *
name,
198 const char *standard,
const char *provider,
199 const char *agent,
const char *
action)
201 if (pcmk__str_empty(
name)) {
202 crm_info(
"Cannot create operation without resource name (bug?)");
206 if (pcmk__str_empty(standard)) {
207 crm_info(
"Cannot create operation for %s without resource class (bug?)",
213 && pcmk__str_empty(provider)) {
214 crm_info(
"Cannot create operation for %s resource %s " 215 "without provider (bug?)", standard,
name);
219 if (pcmk__str_empty(agent)) {
220 crm_info(
"Cannot create operation for %s without agent name (bug?)",
225 if (pcmk__str_empty(
action)) {
226 crm_info(
"Cannot create operation for %s without action name (bug?)",
236 const char *standard,
const char *provider,
237 const char *agent,
const char *
action)
240 if (op->
rsc == NULL) {
244 op->
agent = strdup(agent);
245 if (op->
agent == NULL) {
249 op->
standard = expand_resource_class(
name, standard, agent);
274 const char *provider,
const char *agent,
284 crm_crit(
"Cannot prepare action: %s", strerror(ENOMEM));
285 if (params != NULL) {
286 g_hash_table_destroy(params);
299 }
else if (params != NULL) {
300 g_hash_table_destroy(params);
304 if (required_argument_missing(ra_caps,
name, standard, provider, agent,
308 "Required agent or action information missing");
314 if (copy_action_arguments(op, ra_caps,
name, standard, provider, agent,
316 crm_crit(
"Cannot prepare %s action for %s: %s",
347 crm_info(
"Cannot prepare %s operation for %s: %s",
356 const char *provider,
const char *agent,
363 if (op == NULL || op->
rc != 0) {
385 crm_crit(
"Cannot prepare action for '%s': %s", exec, strerror(ENOMEM));
395 for (
int cur_arg = 1; args[cur_arg - 1] != NULL; cur_arg++) {
398 crm_info(
"Cannot prepare action for '%s': Too many arguments",
405 op->
opaque->
args[cur_arg] = strdup(args[cur_arg - 1]);
407 crm_crit(
"Cannot prepare action for '%s': %s",
408 exec, strerror(ENOMEM));
434 GHashTable *params,
int sequence,
void *cb_data)
442 action->sequence = sequence;
443 action->cb_data = cb_data;
465 CRM_CHECK((op != NULL) && (user != NULL),
return -EINVAL);
485 action->synchronous =
false;
486 action->opaque->callback = cb;
499 services_set_op_pending(
svc_action_t *op, DBusPendingCall *pending)
501 if (op->
opaque->pending && (op->
opaque->pending != pending)) {
507 dbus_pending_call_unref(op->
opaque->pending);
509 op->
opaque->pending = pending;
511 crm_trace(
"Updated pending %s DBus call (%p)", op->
id, pending);
521 if ((op == NULL) || (op->
opaque == NULL)) {
526 if(op->
opaque->timerid != 0) {
528 g_source_remove(op->
opaque->timerid);
533 if (dbus_pending_call_get_completed(op->
opaque->pending)) {
535 crm_warn(
"Result of %s op %s was unhandled",
538 crm_debug(
"Will ignore any result of canceled %s op %s",
541 dbus_pending_call_cancel(op->
opaque->pending);
542 services_set_op_pending(op, NULL);
598 crm_warn(
"Treating result from unknown standard '%s' as OCF",
599 ((standard == NULL)?
"unspecified" : standard));
617 CRM_CHECK(g_list_find(inflight_ops, op) == NULL,
return);
618 CRM_CHECK(g_list_find(blocked_ops, op) == NULL,
return);
620 || (g_hash_table_lookup(recurring_actions, op->
id) == NULL),
650 g_hash_table_destroy(op->
params);
662 if (recurring_actions) {
663 g_hash_table_remove(recurring_actions, op->
id);
686 gboolean cancelled = FALSE;
691 init_recurring_actions();
692 op = g_hash_table_lookup(recurring_actions,
id);
710 crm_info(
"Terminating in-flight op %s[%d] early because it was cancelled",
713 if (cancelled == FALSE) {
714 crm_err(
"Termination of %s[%d] failed",
id, op->
pid);
721 if (inflight_systemd_or_upstart(op)) {
722 inflight_ops = g_list_remove(inflight_ops, op);
741 blocked_ops = g_list_remove(blocked_ops, op);
757 init_recurring_actions();
758 op = g_hash_table_lookup(recurring_actions,
id);
766 if (op->
pid || inflight_systemd_or_upstart(op)) {
793 dup = g_hash_table_lookup(recurring_actions, op->
id);
795 if (dup && (dup != op)) {
865 inflight_ops = g_list_append(inflight_ops, op);
879 inflight_ops = g_list_remove(inflight_ops, op);
880 blocked_ops = g_list_remove(blocked_ops, op);
883 handle_blocked_ops();
894 if (action_callback != NULL) {
897 if (action_fork_callback != NULL) {
902 init_recurring_actions();
903 if (handle_duplicate_recurring(op)) {
908 g_hash_table_replace(recurring_actions, op->
id, op);
913 blocked_ops = g_list_append(blocked_ops, op);
927 static gboolean processing_blocked_ops = FALSE;
935 for (gIter = inflight_ops; gIter != NULL; gIter = gIter->next) {
946 handle_blocked_ops(
void)
948 GList *executed_ops = NULL;
952 if (processing_blocked_ops) {
957 processing_blocked_ops = TRUE;
961 for (gIter = blocked_ops; gIter != NULL; gIter = gIter->next) {
966 executed_ops = g_list_append(executed_ops, op);
974 for (gIter = executed_ops; gIter != NULL; gIter = gIter->next) {
976 blocked_ops = g_list_remove(blocked_ops, op);
978 g_list_free(executed_ops);
980 processing_blocked_ops = FALSE;
994 const char *
class = op->standard;
996 if (op->
agent == NULL) {
997 crm_info(
"Meta-data requested without specifying agent");
1003 if (
class == NULL) {
1004 crm_info(
"Meta-data requested for agent %s without specifying class",
1008 "Agent standard not specified");
1012 #if PCMK__ENABLE_SERVICE 1016 if (
class == NULL) {
1017 crm_info(
"Meta-data requested for %s, but could not determine class",
1021 "Agent standard could not be determined");
1026 #if PCMK__ENABLE_LSB 1040 return execute_action(op);
1063 rc = (execute_metadata_action(op) ==
pcmk_rc_ok);
1087 GList *standards = NULL;
1091 #if PCMK__ENABLE_SERVICE 1095 #if PCMK__ENABLE_LSB 1103 if (agents != NULL) {
1104 standards = g_list_append(standards,
1106 g_list_free_full(agents, free);
1115 if (agents != NULL) {
1116 standards = g_list_append(standards,
1118 g_list_free_full(agents, free);
1127 if (agents != NULL) {
1128 standards = g_list_append(standards,
1130 g_list_free_full(agents, free);
1151 if ((standard == NULL)
1161 if (standard == NULL) {
1165 result = g_list_concat(tmp1, tmp2);
1169 #if PCMK__ENABLE_LSB 1177 result = g_list_concat(tmp1, tmp2);
1185 result = g_list_concat(tmp1, tmp2);
1193 #if PCMK__ENABLE_LSB 1217 GList *standards = NULL;
1218 GList *providers = NULL;
1220 gboolean rc = FALSE;
1221 gboolean has_providers = FALSE;
1224 for (iter = standards; iter != NULL; iter = iter->next) {
1238 if (has_providers == TRUE && provider != NULL) {
1240 for (iter = providers; iter != NULL; iter = iter->next) {
1246 }
else if (has_providers == FALSE && provider == NULL) {
1254 #if PCMK__ENABLE_SERVICE 1256 #if PCMK__ENABLE_LSB 1282 #if PCMK__ENABLE_LSB 1307 g_list_free(standards);
1308 g_list_free(providers);
1329 action->rc = agent_status;
1330 action->status = exec_status;
1332 if (!pcmk__str_eq(
action->opaque->exit_reason, reason,
1334 free(
action->opaque->exit_reason);
1335 action->opaque->exit_reason = (reason == NULL)? NULL : strdup(reason);
1353 const char *format, ...)
1357 char *reason = NULL;
1363 action->rc = agent_status;
1364 action->status = exec_status;
1366 if (format != NULL) {
1367 va_start(ap, format);
1368 len = vasprintf(&reason, format, ap);
1372 free(
action->opaque->exit_reason);
1373 action->opaque->exit_reason = reason;
1389 free(
action->opaque->exit_reason);
1390 action->opaque->exit_reason = NULL;
1409 return "Fence agent";
1412 return "Alert agent";
1414 return "Resource agent";
1429 return action->opaque->exit_reason;
1445 char *output =
action->stdout_data;
1447 action->stdout_data = NULL;
1464 char *output =
action->stderr_data;
1466 action->stderr_data = NULL;
int rc
Exit status of action (set by library upon completion)
#define CRM_CHECK(expr, failure_action)
void(* callback)(svc_action_t *op)
int services__execute_systemd(svc_action_t *op)
ocf_exitcode
Exit status codes for resource agents.
#define crm_crit(fmt, args...)
guint interval_ms
Action interval for recurring resource actions, otherwise 0.
GList * resources_list_providers(const char *standard)
Get a list of providers.
gboolean services_action_async_fork_notify(svc_action_t *op, void(*action_callback)(svc_action_t *), void(*action_fork_callback)(svc_action_t *))
Run an action asynchronously, with callback after process is forked.
#define PCMK_RESOURCE_CLASS_SERVICE
char * standard
Resource standard for resource actions, otherwise NULL.
bool pcmk__strcase_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
gboolean upstart_job_exists(const char *name)
gboolean mainloop_child_kill(pid_t pid)
enum ocf_exitcode services__upstart2ocf(int exit_status)
#define PCMK__OP_FMT
printf-style format to create operation key from resource, action, interval
int services__nagios_prepare(svc_action_t *op)
char * services__grab_stdout(svc_action_t *action)
mainloop_io_t * stderr_gsource
#define PCMK_ACTION_META_DATA
#define PCMK_ACTION_MONITOR
gboolean recurring_action_timer(gpointer data)
int services__get_nagios_metadata(const char *type, char **output)
GList * services_os_get_directory_list(const char *root, gboolean files, gboolean executable)
int services__generic_error(const svc_action_t *op)
gboolean services_action_async(svc_action_t *op, void(*action_callback)(svc_action_t *))
Request asynchronous execution of an action.
#define PCMK_RESOURCE_CLASS_OCF
char * rsc
XML ID of resource being executed for resource actions, otherwise NULL.
int crm_user_lookup(const char *name, uid_t *uid, gid_t *gid)
const char * services__action_kind(const svc_action_t *action)
#define PCMK_RESOURCE_CLASS_SYSTEMD
int timeout
Action timeout (in milliseconds)
Execution failed, do not retry on node.
gboolean resources_agent_exists(const char *standard, const char *provider, const char *agent)
Check whether a resource agent exists on the local host.
gboolean is_op_blocked(const char *rsc)
Wrappers for and extensions to glib mainloop.
svc_action_t * services_action_create_generic(const char *exec, const char *args[])
Request execution of an arbitrary command.
int services__get_lsb_metadata(const char *type, char **output)
#define PCMK__ENABLE_SERVICE
#define PCMK_ACTION_STATUS
GList * services__list_lsb_agents(void)
enum svc_action_flags flags
Flag group of enum svc_action_flags.
#define crm_warn(fmt, args...)
#define PCMK_RESOURCE_CLASS_UPSTART
void services__set_cancelled(svc_action_t *action)
gboolean cancel_recurring_action(svc_action_t *op)
GList * resources_os_list_ocf_providers(void)
svc_action_private_t * opaque
This field should be treated as internal to Pacemaker.
GList * upstart_job_listall(void)
#define crm_debug(fmt, args...)
Used only to initialize variables.
void services_untrack_op(const svc_action_t *op)
char * stdout_data
Action stdout (set by library)
svc_action_t * services_alert_create(const char *id, const char *exec, int timeout, GHashTable *params, int sequence, void *cb_data)
Create an alert agent action.
gboolean systemd_unit_exists(const char *name)
#define crm_trace(fmt, args...)
#define PCMK_RESOURCE_CLASS_STONITH
int services__finalize_async_op(svc_action_t *op)
int services__ocf_prepare(svc_action_t *op)
Object for executing external actions.
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
gboolean services_alert_async(svc_action_t *action, void(*cb)(svc_action_t *op))
Execute an alert agent action.
char * agent
Resource agent name for resource actions, otherwise NULL.
gboolean services__nagios_agent_exists(const char *name)
Wrappers for and extensions to libxml2.
Action completed, result is known.
int services__lsb_prepare(svc_action_t *op)
int pcmk_legacy2rc(int legacy_rc)
Execution failed, do not retry anywhere.
gboolean services_action_sync(svc_action_t *op)
char * pcmk__op_key(const char *rsc_id, const char *op_type, guint interval_ms)
Generate an operation key (RESOURCE_ACTION_INTERVAL)
#define pcmk__str_copy(str)
int services__upstart_prepare(svc_action_t *op)
svc_action_t * services__create_resource_action(const char *name, const char *standard, const char *provider, const char *agent, const char *action, guint interval_ms, int timeout, GHashTable *params, enum svc_action_flags flags)
Create a new resource action.
int services__execute_upstart(svc_action_t *op)
GList * systemd_unit_listall(void)
const char * resources_find_service_class(const char *agent)
Find first service class that can provide a specified agent.
#define pcmk__assert(expr)
GList * resources_list_agents(const char *standard, const char *provider)
Get a list of resource agents.
enum ocf_exitcode services__lsb2ocf(const char *action, int exit_status)
void services_add_inflight_op(svc_action_t *op)
int services__systemd_prepare(svc_action_t *op)
GList * resources_list_standards(void)
char * action
Name of action being executed for resource actions, otherwise NULL.
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
GList * get_directory_list(const char *root, gboolean files, gboolean executable)
Get a list of files or directories in a given path.
pcmk__action_result_t result
svc_action_t * resources_action_create(const char *name, const char *standard, const char *provider, const char *agent, const char *action, guint interval_ms, int timeout, GHashTable *params, enum svc_action_flags flags)
Create a new resource action.
#define crm_err(fmt, args...)
enum ocf_exitcode services__systemd2ocf(int exit_status)
char * services__grab_stderr(svc_action_t *action)
int status
Execution status (enum pcmk_exec_status set by library)
#define PCMK_RESOURCE_CLASS_LSB
GList * services__list_nagios_agents(void)
void services__handle_exec_error(svc_action_t *op, int error)
int services_action_user(svc_action_t *op, const char *user)
Set the user and group that an action will execute as.
#define pcmk__mem_assert(ptr)
void services__set_result(svc_action_t *action, int agent_status, enum pcmk_exec_status exec_status, const char *reason)
mainloop_io_t * stdout_gsource
enum ocf_exitcode services__ocf2ocf(int exit_status)
void mainloop_del_fd(mainloop_io_t *client)
GList * resources_os_list_ocf_agents(const char *provider)
void * cb_data
For caller's use (not used by library)
uint32_t pcmk_get_ra_caps(const char *standard)
Get capabilities of a resource agent standard.
void services_action_cleanup(svc_action_t *op)
pcmk_exec_status
Execution status.
void services__format_result(svc_action_t *action, int agent_status, enum pcmk_exec_status exec_status, const char *format,...)
#define PCMK_RESOURCE_CLASS_ALERT
const char * services__exit_reason(const svc_action_t *action)
#define PCMK_RESOURCE_CLASS_NAGIOS
void services_action_free(svc_action_t *op)
enum ocf_exitcode services_result2ocf(const char *standard, const char *action, int exit_status)
gboolean services__ocf_agent_exists(const char *provider, const char *agent)
char * provider
Resource provider for resource actions that require it, otherwise NULL.
void(* fork_callback)(svc_action_t *op)
Execution failed, may be retried.
#define crm_info(fmt, args...)
gboolean services_action_cancel(const char *name, const char *action, guint interval_ms)
Cancel a recurring action.
enum ocf_exitcode services__nagios2ocf(int exit_status)
gboolean services_action_kick(const char *name, const char *action, guint interval_ms)
Reschedule a recurring action for immediate execution.
bool services__lsb_agent_exists(const char *agent)
int services__execute_file(svc_action_t *op)
char * stderr_data
Action stderr (set by library)