14 #include <sys/types.h> 39 static int operations = 0;
40 static GHashTable *recurring_actions = NULL;
44 static GList *blocked_ops = NULL;
47 static GList *inflight_ops = NULL;
49 static void handle_blocked_ops(
void);
55 action, interval, timeout, NULL, 0);
72 if (rc > 0 && stat(path, &st) == 0) {
94 init_recurring_actions(
void)
96 if (recurring_actions == NULL) {
97 recurring_actions = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
110 static inline gboolean
115 && (g_list_find(inflight_ops, op) != NULL);
131 expand_resource_class(
const char *rsc,
const char *standard,
const char *agent)
133 char *expanded_class = NULL;
139 crm_debug(
"Found %s agent %s for %s", found_class, agent, rsc);
140 expanded_class = strdup(found_class);
142 crm_info(
"Assuming resource class lsb for agent %s for %s",
147 expanded_class = strdup(standard);
150 return expanded_class;
155 const char *agent,
const char *action,
int interval,
int timeout,
165 if (crm_strlen_zero(name)) {
166 crm_err(
"Cannot create operation without resource name");
170 if (crm_strlen_zero(standard)) {
171 crm_err(
"Cannot create operation for %s without resource class", name);
176 && crm_strlen_zero(provider)) {
177 crm_err(
"Cannot create OCF operation for %s without provider", name);
181 if (crm_strlen_zero(agent)) {
182 crm_err(
"Cannot create operation for %s without agent name", name);
186 if (crm_strlen_zero(action)) {
187 crm_err(
"Cannot create operation for %s without operation name", name);
197 op->
rsc = strdup(name);
200 op->
standard = expand_resource_class(name, standard, agent);
201 op->
agent = strdup(agent);
213 op->
action = strdup(action);
221 crm_err(
"Internal error: cannot create agent path");
228 if (op->
agent[0] ==
'/') {
233 crm_err(
"Internal error: cannot create agent path");
239 #if SUPPORT_HEARTBEAT 246 if (op->
agent[0] ==
'/') {
250 }
else if (asprintf(&op->
opaque->
exec,
"%s/%s", HB_RA_DIR, op->
agent) == -1) {
251 crm_err(
"Internal error: cannot create agent path");
259 for (index = 1; index <=
MAX_ARGC - 3; index++ ) {
260 snprintf(buf_tmp,
sizeof(buf_tmp),
"%d", index);
261 value_tmp = g_hash_table_lookup(params, buf_tmp);
262 if (value_tmp == NULL) {
267 op->
opaque->
args[param_num++] = strdup(value_tmp);
287 if (op->
agent[0] ==
'/') {
293 crm_err(
"Internal error: cannot create agent path");
302 op->
opaque->
args[index] = strdup(
"--version");
309 static int args_size =
sizeof(op->
opaque->
args) /
sizeof(
char *);
311 g_hash_table_iter_init(&iter, params);
313 while (g_hash_table_iter_next(&iter, (gpointer *) & key, (gpointer *) & value) &&
314 index <= args_size - 3) {
316 char *long_opt = NULL;
323 long_opt = calloc(1, len);
324 sprintf(long_opt,
"--%s", key);
325 long_opt[len - 1] = 0;
341 g_hash_table_destroy(params);
347 g_hash_table_destroy(params);
358 unsigned int cur_arg;
360 op = calloc(1,
sizeof(*op));
366 for (cur_arg = 1; args && args[cur_arg - 1]; cur_arg++) {
367 op->
opaque->
args[cur_arg] = strdup(args[cur_arg - 1]);
370 crm_err(
"svc_action_t args list not long enough for '%s' execution request.", exec);
387 services_set_op_pending(
svc_action_t *op, DBusPendingCall *pending)
389 if (op->
opaque->pending && (op->
opaque->pending != pending)) {
395 dbus_pending_call_unref(op->
opaque->pending);
397 op->
opaque->pending = pending;
399 crm_trace(
"Updated pending %s DBus call (%p)", op->
id, pending);
414 if(op->
opaque->timerid != 0) {
416 g_source_remove(op->
opaque->timerid);
422 if(dbus_pending_call_get_completed(op->
opaque->pending)) {
425 dbus_pending_call_cancel(op->
opaque->pending);
426 dbus_pending_call_unref(op->
opaque->pending);
427 op->
opaque->pending = NULL;
455 CRM_CHECK(g_list_find(inflight_ops, op) == NULL,
return);
456 CRM_CHECK(g_list_find(blocked_ops, op) == NULL,
return);
458 || (g_hash_table_lookup(recurring_actions, op->
id) == NULL),
487 g_hash_table_destroy(op->
params);
499 if (recurring_actions) {
500 g_hash_table_remove(recurring_actions, op->
id);
523 gboolean cancelled = FALSE;
528 init_recurring_actions();
529 op = g_hash_table_lookup(recurring_actions,
id);
547 crm_info(
"Terminating in-flight op %s (pid %d) early because it was cancelled",
550 if (cancelled == FALSE) {
551 crm_err(
"Termination of %s (pid %d) failed",
id, op->
pid);
561 if (inflight_systemd_or_upstart(op)) {
562 crm_info(
"Will cancel %s op %s when in-flight instance completes",
574 blocked_ops = g_list_remove(blocked_ops, op);
589 init_recurring_actions();
590 op = g_hash_table_lookup(recurring_actions,
id);
598 if (op->
pid || inflight_systemd_or_upstart(op)) {
625 dup = g_hash_table_lookup(recurring_actions, op->
id);
627 if (dup && (dup != op)) {
650 inline static gboolean
685 inflight_ops = g_list_append(inflight_ops, op);
699 inflight_ops = g_list_remove(inflight_ops, op);
700 blocked_ops = g_list_remove(blocked_ops, op);
703 handle_blocked_ops();
710 if (action_callback) {
715 init_recurring_actions();
716 if (handle_duplicate_recurring(op) == TRUE) {
721 g_hash_table_replace(recurring_actions, op->
id, op);
725 blocked_ops = g_list_append(blocked_ops, op);
729 return action_exec_helper(op);
733 static gboolean processing_blocked_ops = FALSE;
741 for (gIter = inflight_ops; gIter != NULL; gIter = gIter->next) {
752 handle_blocked_ops(
void)
754 GList *executed_ops = NULL;
757 gboolean res = FALSE;
759 if (processing_blocked_ops) {
764 processing_blocked_ops = TRUE;
768 for (gIter = blocked_ops; gIter != NULL; gIter = gIter->next) {
773 executed_ops = g_list_append(executed_ops, op);
774 res = action_exec_helper(op);
783 for (gIter = executed_ops; gIter != NULL; gIter = gIter->next) {
785 blocked_ops = g_list_remove(blocked_ops, op);
787 g_list_free(executed_ops);
789 processing_blocked_ops = FALSE;
803 rc = action_exec_helper(op);
826 #if SUPPORT_HEARTBEAT 828 resources_os_list_hb_agents(
void)
837 GList *standards = NULL;
838 GList *agents = NULL;
847 standards = g_list_append(standards,
849 g_list_free_full(agents, free);
856 standards = g_list_append(standards,
858 g_list_free_full(agents, free);
865 standards = g_list_append(standards,
867 g_list_free_full(agents, free);
871 #if SUPPORT_HEARTBEAT 891 if ((standard == NULL)
898 if (standard == NULL) {
902 result = g_list_concat(tmp1, tmp2);
909 result = g_list_concat(tmp1, tmp2);
917 result = g_list_concat(tmp1, tmp2);
927 #if SUPPORT_HEARTBEAT 929 return resources_os_list_hb_agents();
gboolean services_action_cancel(const char *name, const char *action, int interval)
Cancel a recurring action.
#define CRM_CHECK(expr, failure_action)
void(* callback)(svc_action_t *op)
GList * resources_list_providers(const char *standard)
Get a list of providers.
gboolean upstart_job_exists(const char *name)
gboolean mainloop_child_kill(pid_t pid)
svc_action_t * resources_action_create(const char *name, const char *standard, const char *provider, const char *agent, const char *action, int interval, int timeout, GHashTable *params, enum svc_action_flags flags)
Create a new resource action.
mainloop_io_t * stderr_gsource
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)
GList * services_os_get_directory_list(const char *root, gboolean files, gboolean executable)
gboolean services_action_async(svc_action_t *op, void(*action_callback)(svc_action_t *))
gboolean services_os_action_execute(svc_action_t *op)
G_GNUC_INTERNAL GList * resources_os_list_nagios_agents(void)
gboolean upstart_job_exec(svc_action_t *op)
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[])
GList * resources_os_list_lsb_agents(void)
enum svc_action_flags flags
#define crm_warn(fmt, args...)
GList * services_list(void)
#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...)
gboolean operation_finalize(svc_action_t *op)
gboolean systemd_unit_exists(const char *name)
#define PCMK_RESOURCE_CLASS_SERVICE
#define crm_trace(fmt, args...)
gboolean services_action_sync(svc_action_t *op)
#define SUPPORT_HEARTBEAT
gboolean services_action_kick(const char *name, const char *action, int interval)
GList * systemd_unit_listall(void)
const char * resources_find_service_class(const char *agent)
GList * resources_list_agents(const char *standard, const char *provider)
Get a list of resource agents.
void services_add_inflight_op(svc_action_t *op)
GList * resources_list_standards(void)
void services_untrack_op(svc_action_t *op)
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_NAGIOS
#define PCMK_RESOURCE_CLASS_LSB
#define NAGIOS_PLUGIN_DIR
#define crm_err(fmt, args...)
#define PCMK_RESOURCE_CLASS_UPSTART
#define PCMK_RESOURCE_CLASS_HB
mainloop_io_t * stdout_gsource
#define XML_ATTR_CRM_VERSION
void mainloop_del_fd(mainloop_io_t *client)
void services_action_cleanup(svc_action_t *op)
char * generate_op_key(const char *rsc_id, const char *op_type, int interval)
Generate an operation key.
#define safe_str_eq(a, b)
void services_action_free(svc_action_t *op)
gboolean systemd_unit_exec(svc_action_t *op)
#define crm_info(fmt, args...)
svc_action_t * services_action_create(const char *name, const char *action, int interval, int timeout)