16 #include <sys/types.h>    48 static int operations = 0;
    49 static GHashTable *recurring_actions = NULL;
    53 static GList *blocked_ops = NULL;
    56 static GList *inflight_ops = NULL;
    58 static void handle_blocked_ops(
void);
    93 init_recurring_actions(
void)
    95     if (recurring_actions == NULL) {
   108 static inline gboolean
   113            g_list_find(inflight_ops, op) != NULL;
   129 expand_resource_class(
const char *rsc, 
const char *standard, 
const char *agent)
   131     char *expanded_class = NULL;
   137             crm_debug(
"Found %s agent %s for %s", found_class, agent, rsc);
   138             expanded_class = strdup(found_class);
   140             crm_info(
"Assuming resource class lsb for agent %s for %s",
   145         expanded_class = strdup(standard);
   148     return expanded_class;
   178 required_argument_missing(uint32_t ra_caps, 
const char *
name,
   179                           const char *standard, 
const char *provider,
   180                           const char *agent, 
const char *
action)
   182     if (pcmk__str_empty(
name)) {
   183         crm_info(
"Cannot create operation without resource name (bug?)");
   187     if (pcmk__str_empty(standard)) {
   188         crm_info(
"Cannot create operation for %s without resource class (bug?)",
   194         && pcmk__str_empty(provider)) {
   195         crm_info(
"Cannot create operation for %s resource %s "   196                  "without provider (bug?)", standard, 
name);
   200     if (pcmk__str_empty(agent)) {
   201         crm_info(
"Cannot create operation for %s without agent name (bug?)",
   206     if (pcmk__str_empty(
action)) {
   207         crm_info(
"Cannot create operation for %s without action name (bug?)",
   217                       const char *standard, 
const char *provider,
   218                       const char *agent, 
const char *
action)
   221     if (op->
rsc == NULL) {
   225     op->
agent = strdup(agent);
   226     if (op->
agent == NULL) {
   230     op->
standard = expand_resource_class(
name, standard, agent);
   255                         const char *provider, 
const char *agent,
   266         if (params != NULL) {
   267             g_hash_table_destroy(params);
   280     } 
else if (params != NULL) {
   281         g_hash_table_destroy(params);
   285     if (required_argument_missing(ra_caps, 
name, standard, provider, agent,
   289                              "Required agent or action information missing");
   295     if (copy_action_arguments(op, ra_caps, 
name, standard, provider, agent,
   297         crm_crit(
"Cannot prepare %s action for %s: %s",
   327         crm_info(
"Cannot prepare %s operation for %s: %s",
   336                         const char *provider, 
const char *agent,
   343     if (op == NULL || op->
rc != 0) {
   375     for (
int cur_arg = 1; args[cur_arg - 1] != NULL; cur_arg++) {
   378             crm_info(
"Cannot prepare action for '%s': Too many arguments",
   385         op->
opaque->
args[cur_arg] = strdup(args[cur_arg - 1]);
   387             crm_crit(
"Cannot prepare action for '%s': %s",
   414                       GHashTable *params, 
int sequence, 
void *cb_data)
   424     action->sequence = sequence;
   425     action->cb_data = cb_data;
   447     CRM_CHECK((op != NULL) && (user != NULL), 
return -EINVAL);
   467     action->synchronous = 
false;
   468     action->opaque->callback = cb;
   481 services_set_op_pending(
svc_action_t *op, DBusPendingCall *pending)
   483     if (op->
opaque->pending && (op->
opaque->pending != pending)) {
   489         dbus_pending_call_unref(op->
opaque->pending);
   491     op->
opaque->pending = pending;
   493         crm_trace(
"Updated pending %s DBus call (%p)", op->
id, pending);
   503     if ((op == NULL) || (op->
opaque == NULL)) {
   508     if(op->
opaque->timerid != 0) {
   510         g_source_remove(op->
opaque->timerid);
   515         if (dbus_pending_call_get_completed(op->
opaque->pending)) {
   517             crm_warn(
"Result of %s op %s was unhandled",
   520             crm_debug(
"Will ignore any result of canceled %s op %s",
   523         dbus_pending_call_cancel(op->
opaque->pending);
   524         services_set_op_pending(op, NULL);
   578         crm_warn(
"Treating result from unknown standard '%s' as OCF",
   579                  ((standard == NULL)? 
"unspecified" : standard));
   597     CRM_CHECK(g_list_find(inflight_ops, op) == NULL, 
return);
   598     CRM_CHECK(g_list_find(blocked_ops, op) == NULL, 
return);
   600               || (g_hash_table_lookup(recurring_actions, op->
id) == NULL),
   630         g_hash_table_destroy(op->
params);
   642     if (recurring_actions) {
   643         g_hash_table_remove(recurring_actions, op->
id);
   666     gboolean cancelled = FALSE;
   671     init_recurring_actions();
   672     op = g_hash_table_lookup(recurring_actions, 
id);
   690         crm_info(
"Terminating in-flight op %s[%d] early because it was cancelled",
   693         if (cancelled == FALSE) {
   694             crm_err(
"Termination of %s[%d] failed", 
id, op->
pid);
   701     if (inflight_systemd_or_upstart(op)) {
   702         inflight_ops = g_list_remove(inflight_ops, op);
   721     blocked_ops = g_list_remove(blocked_ops, op);
   737     init_recurring_actions();
   738     op = g_hash_table_lookup(recurring_actions, 
id);
   746     if (op->
pid || inflight_systemd_or_upstart(op)) {
   773     dup = g_hash_table_lookup(recurring_actions, op->
id);
   775     if (dup && (dup != op)) {
   845         inflight_ops = g_list_append(inflight_ops, op);
   859     inflight_ops = g_list_remove(inflight_ops, op);
   860     blocked_ops = g_list_remove(blocked_ops, op);
   863     handle_blocked_ops();
   874     if (action_callback != NULL) {
   877     if (action_fork_callback != NULL) {
   882         init_recurring_actions();
   883         if (handle_duplicate_recurring(op)) {
   888         g_hash_table_replace(recurring_actions, op->
id, op);
   893         blocked_ops = g_list_append(blocked_ops, op);
   907 static gboolean processing_blocked_ops = FALSE;
   915     for (gIter = inflight_ops; gIter != NULL; gIter = gIter->next) {
   926 handle_blocked_ops(
void)
   928     GList *executed_ops = NULL;
   932     if (processing_blocked_ops) {
   937     processing_blocked_ops = TRUE;
   941     for (gIter = blocked_ops; gIter != NULL; gIter = gIter->next) {
   946         executed_ops = g_list_append(executed_ops, op);
   954     for (gIter = executed_ops; gIter != NULL; gIter = gIter->next) {
   956         blocked_ops = g_list_remove(blocked_ops, op);
   958     g_list_free(executed_ops);
   960     processing_blocked_ops = FALSE;
   974     const char *
class = op->standard;
   976     if (op->
agent == NULL) {
   977         crm_info(
"Meta-data requested without specifying agent");
   984         crm_info(
"Meta-data requested for agent %s without specifying class",
   988                              "Agent standard not specified");
   996         crm_info(
"Meta-data requested for %s, but could not determine class",
  1000                              "Agent standard could not be determined");
  1016     return execute_action(op);
  1039         rc = (execute_metadata_action(op) == 
pcmk_rc_ok);
  1063     GList *standards = NULL;
  1073         if (agents != NULL) {
  1074             standards = g_list_append(standards,
  1076             g_list_free_full(agents, free);
  1085         if (agents != NULL) {
  1086             standards = g_list_append(standards,
  1088             g_list_free_full(agents, free);
  1097         if (agents != NULL) {
  1098             standards = g_list_append(standards,
  1100             g_list_free_full(agents, free);
  1121     if ((standard == NULL)
  1128         if (standard == NULL) {
  1132                 result = g_list_concat(tmp1, tmp2);
  1139             result = g_list_concat(tmp1, tmp2);
  1147             result = g_list_concat(tmp1, tmp2);
  1177     GList *standards = NULL;
  1178     GList *providers = NULL;
  1180     gboolean rc = FALSE;
  1181     gboolean has_providers = FALSE;
  1184     for (iter = standards; iter != NULL; iter = iter->next) {
  1198     if (has_providers == TRUE && provider != NULL) {
  1200         for (iter = providers; iter != NULL; iter = iter->next) {
  1206     } 
else if (has_providers == FALSE && provider == NULL) {
  1256     g_list_free(standards);
  1257     g_list_free(providers);
  1278     action->rc = agent_status;
  1279     action->status = exec_status;
  1281     if (!pcmk__str_eq(
action->opaque->exit_reason, reason,
  1283         free(
action->opaque->exit_reason);
  1284         action->opaque->exit_reason = (reason == NULL)? NULL : strdup(reason);
  1302                         const char *format, ...)
  1306     char *reason = NULL;
  1312     action->rc = agent_status;
  1313     action->status = exec_status;
  1315     if (format != NULL) {
  1316         va_start(ap, format);
  1317         len = vasprintf(&reason, format, ap);
  1321     free(
action->opaque->exit_reason);
  1322     action->opaque->exit_reason = reason;
  1338         free(
action->opaque->exit_reason);
  1339         action->opaque->exit_reason = NULL;
  1358         return "Fence agent";
  1361         return "Alert agent";
  1363         return "Resource agent";
  1378     return action->opaque->exit_reason;
  1394     char *output = 
action->stdout_data;
  1396     action->stdout_data = NULL;
  1413     char *output = 
action->stderr_data;
  1415     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)
 
int services__nagios_prepare(svc_action_t *op)
 
char * services__grab_stdout(svc_action_t *action)
 
mainloop_io_t * stderr_gsource
 
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)
 
const char * services__exit_reason(svc_action_t *action)
 
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)
 
#define PCMK_RESOURCE_CLASS_SYSTEMD
 
int timeout
Action timeout (in milliseconds) 
 
char * strerror(int errnum)
 
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__generic_error(svc_action_t *op)
 
int services__get_lsb_metadata(const char *type, char **output)
 
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. 
 
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)
 
Action completed, result is known. 
 
const char * services__action_kind(svc_action_t *action)
 
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)
 
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. 
 
char * pcmk__op_key(const char *rsc_id, const char *op_type, guint interval_ms)
Generate an operation key (RESOURCE_ACTION_INTERVAL) 
 
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. 
 
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)
 
void services_untrack_op(svc_action_t *op)
 
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. 
 
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
 
#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)