16 #include <sys/types.h>
47 static int operations = 0;
48 static GHashTable *recurring_actions = NULL;
52 static GList *blocked_ops = NULL;
55 static GList *inflight_ops = NULL;
57 static void handle_blocked_ops(
void);
92 init_recurring_actions(
void)
94 if (recurring_actions == NULL) {
107 static inline gboolean
112 g_list_find(inflight_ops, op) != NULL;
128 expand_resource_class(
const char *rsc,
const char *standard,
const char *agent)
130 char *expanded_class = NULL;
136 crm_debug(
"Found %s agent %s for %s", found_class, agent, rsc);
137 expanded_class = strdup(found_class);
139 crm_info(
"Assuming resource class lsb for agent %s for %s",
144 expanded_class = strdup(standard);
147 return expanded_class;
160 dup_file_path(
const char *filename,
const char *dirname)
162 return (*filename ==
'/')? strdup(filename)
169 const char *provider,
const char *agent,
174 uint32_t ra_caps = 0;
181 if (pcmk__str_empty(name)) {
182 crm_err(
"Cannot create operation without resource name");
186 if (pcmk__str_empty(standard)) {
187 crm_err(
"Cannot create operation for %s without resource class", name);
193 && pcmk__str_empty(provider)) {
194 crm_err(
"Cannot create operation for %s without provider", name);
198 if (pcmk__str_empty(agent)) {
199 crm_err(
"Cannot create operation for %s without agent name", name);
203 if (pcmk__str_empty(action)) {
204 crm_err(
"Cannot create operation for %s without operation name", name);
214 op->
rsc = strdup(name);
217 op->
standard = expand_resource_class(name, standard, agent);
218 op->
agent = strdup(agent);
226 op->
action = strdup(
"status");
228 op->
action = strdup(action);
246 if (pcmk__str_empty(dirs)) {
252 for (dir = strtok(dirs,
":"); dir != NULL; dir = strtok(NULL,
":")) {
254 if (stat(buf, &st) == 0) {
300 static int args_size =
sizeof(op->
opaque->
args) /
sizeof(
char *);
302 g_hash_table_iter_init(&iter, op->
params);
304 while (g_hash_table_iter_next(&iter, (gpointer *) & key, (gpointer *) & value) &&
305 index <= args_size - 3) {
317 g_hash_table_destroy(op->
params);
328 g_hash_table_destroy(params);
336 const char *provider,
const char *agent,
341 provider, agent, action, interval_ms, timeout,
343 if (op == NULL || op->
rc != 0) {
355 unsigned int cur_arg;
357 op = calloc(1,
sizeof(*op));
363 for (cur_arg = 1; args && args[cur_arg - 1]; cur_arg++) {
364 op->
opaque->
args[cur_arg] = strdup(args[cur_arg - 1]);
367 crm_err(
"svc_action_t args list not long enough for '%s' execution request.", exec);
391 GHashTable *params,
int sequence,
void *cb_data)
397 action->
id = strdup(
id);
422 CRM_CHECK((op != NULL) && (user != NULL),
return -EINVAL);
454 services_set_op_pending(
svc_action_t *op, DBusPendingCall *pending)
456 if (op->
opaque->pending && (op->
opaque->pending != pending)) {
462 dbus_pending_call_unref(op->
opaque->pending);
464 op->
opaque->pending = pending;
466 crm_trace(
"Updated pending %s DBus call (%p)", op->
id, pending);
476 if ((op == NULL) || (op->
opaque == NULL)) {
481 if(op->
opaque->timerid != 0) {
483 g_source_remove(op->
opaque->timerid);
488 if (dbus_pending_call_get_completed(op->
opaque->pending)) {
490 crm_warn(
"Result of %s op %s was unhandled",
493 crm_debug(
"Will ignore any result of canceled %s op %s",
496 dbus_pending_call_cancel(op->
opaque->pending);
497 services_set_op_pending(op, NULL);
525 CRM_CHECK(g_list_find(inflight_ops, op) == NULL,
return);
526 CRM_CHECK(g_list_find(blocked_ops, op) == NULL,
return);
528 || (g_hash_table_lookup(recurring_actions, op->
id) == NULL),
557 g_hash_table_destroy(op->
params);
569 if (recurring_actions) {
570 g_hash_table_remove(recurring_actions, op->
id);
593 gboolean cancelled = FALSE;
598 init_recurring_actions();
599 op = g_hash_table_lookup(recurring_actions,
id);
617 crm_info(
"Terminating in-flight op %s[%d] early because it was cancelled",
620 if (cancelled == FALSE) {
621 crm_err(
"Termination of %s[%d] failed",
id, op->
pid);
628 if (inflight_systemd_or_upstart(op)) {
629 inflight_ops = g_list_remove(inflight_ops, op);
647 blocked_ops = g_list_remove(blocked_ops, op);
663 init_recurring_actions();
664 op = g_hash_table_lookup(recurring_actions,
id);
672 if (op->
pid || inflight_systemd_or_upstart(op)) {
699 dup = g_hash_table_lookup(recurring_actions, op->
id);
701 if (dup && (dup != op)) {
724 inline static gboolean
759 inflight_ops = g_list_append(inflight_ops, op);
773 inflight_ops = g_list_remove(inflight_ops, op);
774 blocked_ops = g_list_remove(blocked_ops, op);
777 handle_blocked_ops();
786 if (action_callback) {
789 if (action_fork_callback) {
794 init_recurring_actions();
795 if (handle_duplicate_recurring(op) == TRUE) {
800 g_hash_table_replace(recurring_actions, op->
id, op);
805 blocked_ops = g_list_append(blocked_ops, op);
809 return action_exec_helper(op);
819 static gboolean processing_blocked_ops = FALSE;
827 for (gIter = inflight_ops; gIter != NULL; gIter = gIter->next) {
838 handle_blocked_ops(
void)
840 GList *executed_ops = NULL;
843 gboolean res = FALSE;
845 if (processing_blocked_ops) {
850 processing_blocked_ops = TRUE;
854 for (gIter = blocked_ops; gIter != NULL; gIter = gIter->next) {
859 executed_ops = g_list_append(executed_ops, op);
860 res = action_exec_helper(op);
869 for (gIter = executed_ops; gIter != NULL; gIter = gIter->next) {
871 blocked_ops = g_list_remove(blocked_ops, op);
873 g_list_free(executed_ops);
875 processing_blocked_ops = FALSE;
881 const char *
class = op->standard;
883 if (op->
agent == NULL) {
884 crm_err(
"meta-data requested without specifying agent");
889 crm_err(
"meta-data requested for agent %s without specifying class",
899 crm_err(
"meta-data requested for %s, but could not determine class",
914 return action_exec_helper(op);
937 rc = action_get_metadata(op);
939 rc = action_exec_helper(op);
961 GList *standards = NULL;
962 GList *agents = NULL;
971 standards = g_list_append(standards,
973 g_list_free_full(agents, free);
980 standards = g_list_append(standards,
982 g_list_free_full(agents, free);
989 standards = g_list_append(standards,
991 g_list_free_full(agents, free);
1011 if ((standard == NULL)
1018 if (standard == NULL) {
1022 result = g_list_concat(tmp1, tmp2);
1029 result = g_list_concat(tmp1, tmp2);
1037 result = g_list_concat(tmp1, tmp2);
1067 GList *standards = NULL;
1068 GList *providers = NULL;
1070 gboolean
rc = FALSE;
1071 gboolean has_providers = FALSE;
1074 for (iter = standards; iter != NULL; iter = iter->next) {
1088 if (has_providers == TRUE && provider != NULL) {
1090 for (iter = providers; iter != NULL; iter = iter->next) {
1096 }
else if (has_providers == FALSE && provider == NULL) {
1146 g_list_free(standards);
1147 g_list_free(providers);
gboolean services_action_cancel(const char *name, const char *action, guint interval_ms)
Cancel a recurring action.
#define CRM_CHECK(expr, failure_action)
void services_action_free(svc_action_t *op)
gboolean services__ocf_agent_exists(const char *provider, const char *agent)
gboolean services_action_kick(const char *name, const char *action, guint interval_ms)
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)
mainloop_io_t * stderr_gsource
const char * resources_find_service_class(const char *agent)
Find first service class that can provide a specified agent.
GList * resources_os_list_ocf_agents(const char *provider)
GList * resources_os_list_ocf_providers(void)
#define PCMK_RESOURCE_CLASS_SYSTEMD
gboolean recurring_action_timer(gpointer data)
svc_action_t * services_action_create_generic(const char *exec, const char *args[])
void(* fork_callback)(svc_action_t *op)
int services__get_nagios_metadata(const char *type, char **output)
gboolean services_action_async_fork_notify(svc_action_t *op, void(*action_callback)(svc_action_t *), void(*action_fork_callback)(svc_action_t *))
GList * services_os_get_directory_list(const char *root, gboolean files, gboolean executable)
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.
int crm_user_lookup(const char *name, uid_t *uid, gid_t *gid)
gboolean services_os_action_execute(svc_action_t *op)
gboolean upstart_job_exec(svc_action_t *op)
gboolean is_op_blocked(const char *rsc)
Wrappers for and extensions to glib mainloop.
char * services__lsb_agent_path(const char *agent)
int services__get_lsb_metadata(const char *type, char **output)
void services_action_cleanup(svc_action_t *op)
GList * services__list_lsb_agents(void)
enum svc_action_flags flags
#define crm_warn(fmt, args...)
#define PCMK_RESOURCE_CLASS_OCF
gboolean cancel_recurring_action(svc_action_t *op)
svc_action_private_t * opaque
GList * upstart_job_listall(void)
#define crm_debug(fmt, args...)
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 operation_finalize(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.
gboolean services_action_sync(svc_action_t *op)
gboolean systemd_unit_exists(const char *name)
#define PCMK_RESOURCE_CLASS_SERVICE
#define crm_trace(fmt, args...)
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
void(* callback)(svc_action_t *op)
gboolean services__nagios_agent_exists(const char *name)
GList * resources_list_providers(const char *standard)
Get a list of providers.
char * pcmk__op_key(const char *rsc_id, const char *op_type, guint interval_ms)
Generate an operation key (RESOURCE_ACTION_INTERVAL)
GList * systemd_unit_listall(void)
int services_action_user(svc_action_t *op, const char *user)
Set the user and group that an action will execute as.
void services_add_inflight_op(svc_action_t *op)
void services_untrack_op(svc_action_t *op)
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
#define PCMK_RESOURCE_CLASS_NAGIOS
#define PCMK_RESOURCE_CLASS_LSB
#define NAGIOS_PLUGIN_DIR
GList * resources_list_standards(void)
#define crm_err(fmt, args...)
GList * get_directory_list(const char *root, gboolean files, gboolean executable)
Get a list of files or directories in a given path.
#define PCMK_RESOURCE_CLASS_UPSTART
GList * services__list_nagios_agents(void)
void services__handle_exec_error(svc_action_t *op, int error)
gboolean resources_agent_exists(const char *standard, const char *provider, const char *agent)
GList * resources_list_agents(const char *standard, const char *provider)
Get a list of resource agents.
mainloop_io_t * stdout_gsource
#define XML_ATTR_CRM_VERSION
gboolean services_alert_async(svc_action_t *action, void(*cb)(svc_action_t *op))
Execute an alert agent action.
void mainloop_del_fd(mainloop_io_t *client)
uint32_t pcmk_get_ra_caps(const char *standard)
Get capabilities of a resource agent standard.
gboolean services_action_async(svc_action_t *op, void(*action_callback)(svc_action_t *))
gboolean systemd_unit_exec(svc_action_t *op)
#define crm_info(fmt, args...)
bool services__lsb_agent_exists(const char *agent)