14 #include <sys/types.h> 38 static int operations = 0;
39 static GHashTable *recurring_actions = NULL;
43 static GList *blocked_ops = NULL;
46 static GList *inflight_ops = NULL;
48 static void handle_blocked_ops(
void);
83 init_recurring_actions(
void)
85 if (recurring_actions == NULL) {
86 recurring_actions = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
99 static inline gboolean
104 && (g_list_find(inflight_ops, op) != NULL);
120 expand_resource_class(
const char *rsc,
const char *standard,
const char *agent)
122 char *expanded_class = NULL;
128 crm_debug(
"Found %s agent %s for %s", found_class, agent, rsc);
129 expanded_class = strdup(found_class);
131 crm_info(
"Assuming resource class lsb for agent %s for %s",
136 expanded_class = strdup(standard);
139 return expanded_class;
151 dup_file_path(
const char *filename,
const char *dirname)
153 return (*filename ==
'/')? strdup(filename)
159 const char *provider,
const char *agent,
160 const char *action, guint interval_ms,
int timeout,
171 if (crm_strlen_zero(name)) {
172 crm_err(
"Cannot create operation without resource name");
176 if (crm_strlen_zero(standard)) {
177 crm_err(
"Cannot create operation for %s without resource class", name);
183 crm_err(
"Cannot create operation for %s without provider", name);
187 if (crm_strlen_zero(agent)) {
188 crm_err(
"Cannot create operation for %s without agent name", name);
192 if (crm_strlen_zero(action)) {
193 crm_err(
"Cannot create operation for %s without operation name", name);
203 op->
rsc = strdup(name);
206 op->
standard = expand_resource_class(name, standard, agent);
207 op->
agent = strdup(agent);
213 op->
action = strdup(
"status");
215 op->
action = strdup(action);
260 static int args_size =
sizeof(op->
opaque->
args) /
sizeof(
char *);
262 g_hash_table_iter_init(&iter, op->
params);
264 while (g_hash_table_iter_next(&iter, (gpointer *) & key, (gpointer *) & value) &&
265 index <= args_size - 3) {
277 g_hash_table_destroy(op->
params);
287 g_hash_table_destroy(params);
293 g_hash_table_destroy(params);
304 unsigned int cur_arg;
306 op = calloc(1,
sizeof(*op));
312 for (cur_arg = 1; args && args[cur_arg - 1]; cur_arg++) {
313 op->
opaque->
args[cur_arg] = strdup(args[cur_arg - 1]);
316 crm_err(
"svc_action_t args list not long enough for '%s' execution request.", exec);
340 GHashTable *params,
int sequence,
void *cb_data)
346 action->
id = strdup(
id);
371 CRM_CHECK((op != NULL) && (user != NULL),
return -EINVAL);
376 set_alert_env(gpointer key, gpointer value, gpointer user_data)
381 rc =
setenv(key, value, 1);
388 (
char*)key, (value? (
char*)value :
""));
390 crm_trace(
"setenv %s=%s", (
char*)key, (value? (
char*)value :
""));
395 unset_alert_env(gpointer key, gpointer value, gpointer user_data)
397 if (unsetenv(key) < 0) {
418 gboolean responsible;
423 g_hash_table_foreach(action->
params, set_alert_env, NULL);
427 g_hash_table_foreach(action->
params, unset_alert_env, NULL);
441 services_set_op_pending(
svc_action_t *op, DBusPendingCall *pending)
443 if (op->
opaque->pending && (op->
opaque->pending != pending)) {
449 dbus_pending_call_unref(op->
opaque->pending);
451 op->
opaque->pending = pending;
453 crm_trace(
"Updated pending %s DBus call (%p)", op->
id, pending);
468 if(op->
opaque->timerid != 0) {
470 g_source_remove(op->
opaque->timerid);
476 if(dbus_pending_call_get_completed(op->
opaque->pending)) {
479 dbus_pending_call_cancel(op->
opaque->pending);
480 dbus_pending_call_unref(op->
opaque->pending);
481 op->
opaque->pending = NULL;
509 CRM_CHECK(g_list_find(inflight_ops, op) == NULL,
return);
510 CRM_CHECK(g_list_find(blocked_ops, op) == NULL,
return);
512 || (g_hash_table_lookup(recurring_actions, op->
id) == NULL),
541 g_hash_table_destroy(op->
params);
553 if (recurring_actions) {
554 g_hash_table_remove(recurring_actions, op->
id);
577 gboolean cancelled = FALSE;
582 init_recurring_actions();
583 op = g_hash_table_lookup(recurring_actions,
id);
601 crm_info(
"Terminating in-flight op %s (pid %d) early because it was cancelled",
604 if (cancelled == FALSE) {
605 crm_err(
"Termination of %s (pid %d) failed",
id, op->
pid);
615 if (inflight_systemd_or_upstart(op)) {
616 crm_info(
"Will cancel %s op %s when in-flight instance completes",
628 blocked_ops = g_list_remove(blocked_ops, op);
643 init_recurring_actions();
644 op = g_hash_table_lookup(recurring_actions,
id);
652 if (op->
pid || inflight_systemd_or_upstart(op)) {
679 dup = g_hash_table_lookup(recurring_actions, op->
id);
681 if (dup && (dup != op)) {
704 inline static gboolean
739 inflight_ops = g_list_append(inflight_ops, op);
753 inflight_ops = g_list_remove(inflight_ops, op);
754 blocked_ops = g_list_remove(blocked_ops, op);
757 handle_blocked_ops();
764 if (action_callback) {
769 init_recurring_actions();
770 if (handle_duplicate_recurring(op) == TRUE) {
775 g_hash_table_replace(recurring_actions, op->
id, op);
779 blocked_ops = g_list_append(blocked_ops, op);
783 return action_exec_helper(op);
787 static gboolean processing_blocked_ops = FALSE;
795 for (gIter = inflight_ops; gIter != NULL; gIter = gIter->next) {
806 handle_blocked_ops(
void)
808 GList *executed_ops = NULL;
811 gboolean res = FALSE;
813 if (processing_blocked_ops) {
818 processing_blocked_ops = TRUE;
822 for (gIter = blocked_ops; gIter != NULL; gIter = gIter->next) {
827 executed_ops = g_list_append(executed_ops, op);
828 res = action_exec_helper(op);
837 for (gIter = executed_ops; gIter != NULL; gIter = gIter->next) {
839 blocked_ops = g_list_remove(blocked_ops, op);
841 g_list_free(executed_ops);
843 processing_blocked_ops = FALSE;
848 nagios_get_metadata(
const char *
type,
char **output)
851 FILE *file_strm = NULL;
852 int start = 0, length = 0, read_len = 0;
856 file_strm = fopen(metadata_file,
"r");
857 if (file_strm == NULL) {
858 crm_err(
"Metadata file %s does not exist", metadata_file);
864 start = ftell(file_strm);
865 fseek(file_strm, 0L, SEEK_END);
866 length = ftell(file_strm);
867 fseek(file_strm, 0L, start);
873 crm_info(
"%s was not valid", metadata_file);
879 crm_trace(
"Reading %d bytes from file", length);
880 *output = calloc(1, (length + 1));
881 read_len = fread(*output, 1, length, file_strm);
882 if (read_len != length) {
883 crm_err(
"Calculated and read bytes differ: %d vs. %d",
900 const char *
class = op->standard;
902 if (op->
agent == NULL) {
903 crm_err(
"meta-data requested without specifying agent");
908 crm_err(
"meta-data requested for agent %s without specifying class",
918 crm_err(
"meta-data requested for %s, but could not determine class",
933 return action_exec_helper(op);
956 rc = action_get_metadata(op);
958 rc = action_exec_helper(op);
980 GList *standards = NULL;
981 GList *agents = NULL;
990 standards = g_list_append(standards,
992 g_list_free_full(agents, free);
999 standards = g_list_append(standards,
1001 g_list_free_full(agents, free);
1008 standards = g_list_append(standards,
1010 g_list_free_full(agents, free);
1030 if ((standard == NULL)
1037 if (standard == NULL) {
1041 result = g_list_concat(tmp1, tmp2);
1048 result = g_list_concat(tmp1, tmp2);
1056 result = g_list_concat(tmp1, tmp2);
#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)
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 *))
int crm_user_lookup(const char *name, uid_t *uid, gid_t *gid)
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.
char * services__lsb_agent_path(const char *agent)
svc_action_t * services_action_create_generic(const char *exec, const char *args[])
int services__get_lsb_metadata(const char *type, char **output)
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...)
gboolean operation_finalize(svc_action_t *op)
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 PCMK_RESOURCE_CLASS_SERVICE
#define crm_trace(fmt, args...)
int setenv(const char *name, const char *value, int why)
gboolean services_alert_async(svc_action_t *action, void(*cb)(svc_action_t *op))
Execute an alert agent action.
uint32_t pcmk_get_ra_caps(const char *standard)
Get capabilities of a resource agent standard.
gboolean services_action_sync(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.
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 crm_perror(level, fmt, args...)
Log a system error message.
#define NAGIOS_PLUGIN_DIR
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...)
#define PCMK_RESOURCE_CLASS_UPSTART
int services_action_user(svc_action_t *op, const char *user)
Set the user and group that an action will execute as.
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)
#define safe_str_eq(a, b)
void services_action_free(svc_action_t *op)
char * crm_strdup_printf(char const *format,...) __attribute__((__format__(__printf__
gboolean systemd_unit_exec(svc_action_t *op)
#define crm_info(fmt, args...)
#define NAGIOS_METADATA_DIR
char * generate_op_key(const char *rsc_id, const char *op_type, guint interval_ms)
Generate an operation key.
gboolean services_action_cancel(const char *name, const char *action, guint interval_ms)
Cancel a recurring action.
gboolean services_action_kick(const char *name, const char *action, guint interval_ms)
bool services__lsb_agent_exists(const char *agent)
enum crm_ais_msg_types type