|
|
c54a00 |
From 06ef8406cf224af6b94dc4672c9b6caa15133f89 Mon Sep 17 00:00:00 2001
|
|
|
c54a00 |
From: Klaus Wenninger <klaus.wenninger@aon.at>
|
|
|
c54a00 |
Date: Thu, 14 Feb 2019 13:27:46 +0100
|
|
|
c54a00 |
Subject: [PATCH] use common service interface for fence-agents and RAs
|
|
|
c54a00 |
|
|
|
c54a00 |
---
|
|
|
c54a00 |
include/crm/services.h | 5 +-
|
|
|
c54a00 |
lib/Makefile.am | 3 +-
|
|
|
c54a00 |
lib/fencing/Makefile.am | 1 +
|
|
|
c54a00 |
lib/fencing/st_client.c | 459 +++++++++-------------------------------
|
|
|
c54a00 |
lib/services/services_linux.c | 93 ++++++++
|
|
|
c54a00 |
lib/services/services_private.h | 2 +
|
|
|
c54a00 |
6 files changed, 203 insertions(+), 360 deletions(-)
|
|
|
c54a00 |
|
|
|
c54a00 |
diff --git a/include/crm/services.h b/include/crm/services.h
|
|
|
c54a00 |
index 0186e66..eddafc3 100644
|
|
|
c54a00 |
--- a/include/crm/services.h
|
|
|
c54a00 |
+++ b/include/crm/services.h
|
|
|
c54a00 |
@@ -170,7 +170,10 @@ typedef struct svc_action_s {
|
|
|
c54a00 |
char *agent;
|
|
|
c54a00 |
|
|
|
c54a00 |
int timeout;
|
|
|
c54a00 |
- GHashTable *params; /* used by OCF agents and alert agents */
|
|
|
c54a00 |
+ GHashTable *params; /* used for setting up environment for ocf-ra &
|
|
|
c54a00 |
+ alert agents
|
|
|
c54a00 |
+ and to be sent via stdin for fence-agents
|
|
|
c54a00 |
+ */
|
|
|
c54a00 |
|
|
|
c54a00 |
int rc;
|
|
|
c54a00 |
int pid;
|
|
|
c54a00 |
diff --git a/lib/Makefile.am b/lib/Makefile.am
|
|
|
c54a00 |
index 5563819..d73bf2e 100644
|
|
|
c54a00 |
--- a/lib/Makefile.am
|
|
|
c54a00 |
+++ b/lib/Makefile.am
|
|
|
c54a00 |
@@ -39,11 +39,10 @@ clean-local:
|
|
|
c54a00 |
rm -f *.pc
|
|
|
c54a00 |
|
|
|
c54a00 |
## Subdirectories...
|
|
|
c54a00 |
-SUBDIRS = gnu common pengine transition cib fencing services lrmd cluster
|
|
|
c54a00 |
+SUBDIRS = gnu common pengine transition cib services fencing lrmd cluster
|
|
|
c54a00 |
DIST_SUBDIRS = $(SUBDIRS) ais
|
|
|
c54a00 |
|
|
|
c54a00 |
if BUILD_CS_PLUGIN
|
|
|
c54a00 |
SUBDIRS += ais
|
|
|
c54a00 |
endif
|
|
|
c54a00 |
|
|
|
c54a00 |
-
|
|
|
c54a00 |
diff --git a/lib/fencing/Makefile.am b/lib/fencing/Makefile.am
|
|
|
c54a00 |
index c3f4ea2..e447627 100644
|
|
|
c54a00 |
--- a/lib/fencing/Makefile.am
|
|
|
c54a00 |
+++ b/lib/fencing/Makefile.am
|
|
|
c54a00 |
@@ -15,6 +15,7 @@ libstonithd_la_CFLAGS = $(CFLAGS_HARDENED_LIB)
|
|
|
c54a00 |
libstonithd_la_LDFLAGS += $(LDFLAGS_HARDENED_LIB)
|
|
|
c54a00 |
|
|
|
c54a00 |
libstonithd_la_LIBADD = $(top_builddir)/lib/common/libcrmcommon.la
|
|
|
c54a00 |
+libstonithd_la_LIBADD += $(top_builddir)/lib/services/libcrmservice.la
|
|
|
c54a00 |
|
|
|
c54a00 |
libstonithd_la_SOURCES = st_client.c st_rhcs.c
|
|
|
c54a00 |
if BUILD_LHA_SUPPORT
|
|
|
c54a00 |
diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c
|
|
|
c54a00 |
index 3898d45..1c56cf4 100644
|
|
|
c54a00 |
--- a/lib/fencing/st_client.c
|
|
|
c54a00 |
+++ b/lib/fencing/st_client.c
|
|
|
c54a00 |
@@ -22,6 +22,7 @@
|
|
|
c54a00 |
#include <stdio.h>
|
|
|
c54a00 |
#include <string.h>
|
|
|
c54a00 |
#include <ctype.h>
|
|
|
c54a00 |
+#include <libgen.h>
|
|
|
c54a00 |
|
|
|
c54a00 |
#include <sys/stat.h>
|
|
|
c54a00 |
#include <sys/types.h>
|
|
|
c54a00 |
@@ -48,23 +49,18 @@ struct stonith_action_s {
|
|
|
c54a00 |
char *agent;
|
|
|
c54a00 |
char *action;
|
|
|
c54a00 |
char *victim;
|
|
|
c54a00 |
- char *args;
|
|
|
c54a00 |
+ GHashTable *args;
|
|
|
c54a00 |
int timeout;
|
|
|
c54a00 |
int async;
|
|
|
c54a00 |
void *userdata;
|
|
|
c54a00 |
void (*done_cb) (GPid pid, gint status, const char *output, gpointer user_data);
|
|
|
c54a00 |
|
|
|
c54a00 |
- /*! internal async track data */
|
|
|
c54a00 |
- int fd_stdout;
|
|
|
c54a00 |
- int fd_stderr;
|
|
|
c54a00 |
- int last_timeout_signo;
|
|
|
c54a00 |
+ svc_action_t *svc_action;
|
|
|
c54a00 |
|
|
|
c54a00 |
/*! internal timing information */
|
|
|
c54a00 |
time_t initial_start_time;
|
|
|
c54a00 |
int tries;
|
|
|
c54a00 |
int remaining_timeout;
|
|
|
c54a00 |
- guint timer_sigterm;
|
|
|
c54a00 |
- guint timer_sigkill;
|
|
|
c54a00 |
int max_retries;
|
|
|
c54a00 |
|
|
|
c54a00 |
/* device output data */
|
|
|
c54a00 |
@@ -448,13 +444,11 @@ stonith_api_register_level(stonith_t * st, int options, const char *node, int le
|
|
|
c54a00 |
}
|
|
|
c54a00 |
|
|
|
c54a00 |
static void
|
|
|
c54a00 |
-append_arg(const char *key, const char *value, char **args)
|
|
|
c54a00 |
+append_arg(const char *key, const char *value, GHashTable **args)
|
|
|
c54a00 |
{
|
|
|
c54a00 |
- int len = 3; /* =, \n, \0 */
|
|
|
c54a00 |
- int last = 0;
|
|
|
c54a00 |
-
|
|
|
c54a00 |
CRM_CHECK(key != NULL, return);
|
|
|
c54a00 |
CRM_CHECK(value != NULL, return);
|
|
|
c54a00 |
+ CRM_CHECK(args != NULL, return);
|
|
|
c54a00 |
|
|
|
c54a00 |
if (strstr(key, "pcmk_")) {
|
|
|
c54a00 |
return;
|
|
|
c54a00 |
@@ -464,15 +458,13 @@ append_arg(const char *key, const char *value, char **args)
|
|
|
c54a00 |
return;
|
|
|
c54a00 |
}
|
|
|
c54a00 |
|
|
|
c54a00 |
- len += strlen(key);
|
|
|
c54a00 |
- len += strlen(value);
|
|
|
c54a00 |
- if (*args != NULL) {
|
|
|
c54a00 |
- last = strlen(*args);
|
|
|
c54a00 |
+ if (!*args) {
|
|
|
c54a00 |
+ *args = crm_str_table_new();
|
|
|
c54a00 |
}
|
|
|
c54a00 |
|
|
|
c54a00 |
- *args = realloc_safe(*args, last + len);
|
|
|
c54a00 |
+ CRM_CHECK(*args != NULL, return);
|
|
|
c54a00 |
crm_trace("Appending: %s=%s", key, value);
|
|
|
c54a00 |
- sprintf((*args) + last, "%s=%s\n", key, value);
|
|
|
c54a00 |
+ g_hash_table_replace(*args, strdup(key), strdup(value));
|
|
|
c54a00 |
}
|
|
|
c54a00 |
|
|
|
c54a00 |
static void
|
|
|
c54a00 |
@@ -489,7 +481,7 @@ append_config_arg(gpointer key, gpointer value, gpointer user_data)
|
|
|
c54a00 |
}
|
|
|
c54a00 |
|
|
|
c54a00 |
static void
|
|
|
c54a00 |
-append_host_specific_args(const char *victim, const char *map, GHashTable * params, char **arg_list)
|
|
|
c54a00 |
+append_host_specific_args(const char *victim, const char *map, GHashTable * params, GHashTable **args)
|
|
|
c54a00 |
{
|
|
|
c54a00 |
char *name = NULL;
|
|
|
c54a00 |
int last = 0, lpc = 0, max = 0;
|
|
|
c54a00 |
@@ -497,7 +489,7 @@ append_host_specific_args(const char *victim, const char *map, GHashTable * para
|
|
|
c54a00 |
if (map == NULL) {
|
|
|
c54a00 |
/* The best default there is for now... */
|
|
|
c54a00 |
crm_debug("Using default arg map: port=uname");
|
|
|
c54a00 |
- append_arg("port", victim, arg_list);
|
|
|
c54a00 |
+ append_arg("port", victim, args);
|
|
|
c54a00 |
return;
|
|
|
c54a00 |
}
|
|
|
c54a00 |
|
|
|
c54a00 |
@@ -540,7 +532,7 @@ append_host_specific_args(const char *victim, const char *map, GHashTable * para
|
|
|
c54a00 |
|
|
|
c54a00 |
if (value) {
|
|
|
c54a00 |
crm_debug("Setting '%s'='%s' (%s) for %s", name, value, param, victim);
|
|
|
c54a00 |
- append_arg(name, value, arg_list);
|
|
|
c54a00 |
+ append_arg(name, value, args);
|
|
|
c54a00 |
|
|
|
c54a00 |
} else {
|
|
|
c54a00 |
crm_err("No node attribute '%s' for '%s'", name, victim);
|
|
|
c54a00 |
@@ -560,12 +552,12 @@ append_host_specific_args(const char *victim, const char *map, GHashTable * para
|
|
|
c54a00 |
free(name);
|
|
|
c54a00 |
}
|
|
|
c54a00 |
|
|
|
c54a00 |
-static char *
|
|
|
c54a00 |
+static GHashTable *
|
|
|
c54a00 |
make_args(const char *agent, const char *action, const char *victim, uint32_t victim_nodeid, GHashTable * device_args,
|
|
|
c54a00 |
GHashTable * port_map)
|
|
|
c54a00 |
{
|
|
|
c54a00 |
char buffer[512];
|
|
|
c54a00 |
- char *arg_list = NULL;
|
|
|
c54a00 |
+ GHashTable *arg_list = NULL;
|
|
|
c54a00 |
const char *value = NULL;
|
|
|
c54a00 |
|
|
|
c54a00 |
CRM_CHECK(action != NULL, return NULL);
|
|
|
c54a00 |
@@ -653,66 +645,6 @@ make_args(const char *agent, const char *action, const char *victim, uint32_t vi
|
|
|
c54a00 |
return arg_list;
|
|
|
c54a00 |
}
|
|
|
c54a00 |
|
|
|
c54a00 |
-static gboolean
|
|
|
c54a00 |
-st_child_term(gpointer data)
|
|
|
c54a00 |
-{
|
|
|
c54a00 |
- int rc = 0;
|
|
|
c54a00 |
- stonith_action_t *track = data;
|
|
|
c54a00 |
-
|
|
|
c54a00 |
- crm_info("Child %d timed out, sending SIGTERM", track->pid);
|
|
|
c54a00 |
- track->timer_sigterm = 0;
|
|
|
c54a00 |
- track->last_timeout_signo = SIGTERM;
|
|
|
c54a00 |
- rc = kill(-track->pid, SIGTERM);
|
|
|
c54a00 |
- if (rc < 0) {
|
|
|
c54a00 |
- crm_perror(LOG_ERR, "Couldn't send SIGTERM to %d", track->pid);
|
|
|
c54a00 |
- }
|
|
|
c54a00 |
- return FALSE;
|
|
|
c54a00 |
-}
|
|
|
c54a00 |
-
|
|
|
c54a00 |
-static gboolean
|
|
|
c54a00 |
-st_child_kill(gpointer data)
|
|
|
c54a00 |
-{
|
|
|
c54a00 |
- int rc = 0;
|
|
|
c54a00 |
- stonith_action_t *track = data;
|
|
|
c54a00 |
-
|
|
|
c54a00 |
- crm_info("Child %d timed out, sending SIGKILL", track->pid);
|
|
|
c54a00 |
- track->timer_sigkill = 0;
|
|
|
c54a00 |
- track->last_timeout_signo = SIGKILL;
|
|
|
c54a00 |
- rc = kill(-track->pid, SIGKILL);
|
|
|
c54a00 |
- if (rc < 0) {
|
|
|
c54a00 |
- crm_perror(LOG_ERR, "Couldn't send SIGKILL to %d", track->pid);
|
|
|
c54a00 |
- }
|
|
|
c54a00 |
- return FALSE;
|
|
|
c54a00 |
-}
|
|
|
c54a00 |
-
|
|
|
c54a00 |
-static void
|
|
|
c54a00 |
-stonith_action_clear_tracking_data(stonith_action_t * action)
|
|
|
c54a00 |
-{
|
|
|
c54a00 |
- if (action->timer_sigterm > 0) {
|
|
|
c54a00 |
- g_source_remove(action->timer_sigterm);
|
|
|
c54a00 |
- action->timer_sigterm = 0;
|
|
|
c54a00 |
- }
|
|
|
c54a00 |
- if (action->timer_sigkill > 0) {
|
|
|
c54a00 |
- g_source_remove(action->timer_sigkill);
|
|
|
c54a00 |
- action->timer_sigkill = 0;
|
|
|
c54a00 |
- }
|
|
|
c54a00 |
- if (action->fd_stdout) {
|
|
|
c54a00 |
- close(action->fd_stdout);
|
|
|
c54a00 |
- action->fd_stdout = 0;
|
|
|
c54a00 |
- }
|
|
|
c54a00 |
- if (action->fd_stderr) {
|
|
|
c54a00 |
- close(action->fd_stderr);
|
|
|
c54a00 |
- action->fd_stderr = 0;
|
|
|
c54a00 |
- }
|
|
|
c54a00 |
- free(action->output);
|
|
|
c54a00 |
- action->output = NULL;
|
|
|
c54a00 |
- free(action->error);
|
|
|
c54a00 |
- action->error = NULL;
|
|
|
c54a00 |
- action->rc = 0;
|
|
|
c54a00 |
- action->pid = 0;
|
|
|
c54a00 |
- action->last_timeout_signo = 0;
|
|
|
c54a00 |
-}
|
|
|
c54a00 |
-
|
|
|
c54a00 |
/*!
|
|
|
c54a00 |
* \internal
|
|
|
c54a00 |
* \brief Free all memory used by a stonith action
|
|
|
c54a00 |
@@ -723,11 +655,17 @@ void
|
|
|
c54a00 |
stonith__destroy_action(stonith_action_t *action)
|
|
|
c54a00 |
{
|
|
|
c54a00 |
if (action) {
|
|
|
c54a00 |
- stonith_action_clear_tracking_data(action);
|
|
|
c54a00 |
free(action->agent);
|
|
|
c54a00 |
- free(action->args);
|
|
|
c54a00 |
+ if (action->args) {
|
|
|
c54a00 |
+ g_hash_table_destroy(action->args);
|
|
|
c54a00 |
+ }
|
|
|
c54a00 |
free(action->action);
|
|
|
c54a00 |
free(action->victim);
|
|
|
c54a00 |
+ if (action->svc_action) {
|
|
|
c54a00 |
+ services_action_free(action->svc_action);
|
|
|
c54a00 |
+ }
|
|
|
c54a00 |
+ free(action->output);
|
|
|
c54a00 |
+ free(action->error);
|
|
|
c54a00 |
free(action);
|
|
|
c54a00 |
}
|
|
|
c54a00 |
}
|
|
|
c54a00 |
@@ -809,38 +747,6 @@ stonith_action_create(const char *agent,
|
|
|
c54a00 |
return action;
|
|
|
c54a00 |
}
|
|
|
c54a00 |
|
|
|
c54a00 |
-#define READ_MAX 500
|
|
|
c54a00 |
-static char *
|
|
|
c54a00 |
-read_output(int fd)
|
|
|
c54a00 |
-{
|
|
|
c54a00 |
- char buffer[READ_MAX];
|
|
|
c54a00 |
- char *output = NULL;
|
|
|
c54a00 |
- int len = 0;
|
|
|
c54a00 |
- int more = 0;
|
|
|
c54a00 |
-
|
|
|
c54a00 |
- if (!fd) {
|
|
|
c54a00 |
- return NULL;
|
|
|
c54a00 |
- }
|
|
|
c54a00 |
-
|
|
|
c54a00 |
- do {
|
|
|
c54a00 |
- errno = 0;
|
|
|
c54a00 |
- memset(&buffer, 0, READ_MAX);
|
|
|
c54a00 |
- more = read(fd, buffer, READ_MAX - 1);
|
|
|
c54a00 |
-
|
|
|
c54a00 |
- if (more > 0) {
|
|
|
c54a00 |
- buffer[more] = 0; /* Make sure it's nul-terminated for logging
|
|
|
c54a00 |
- * 'more' is always less than our buffer size
|
|
|
c54a00 |
- */
|
|
|
c54a00 |
- output = realloc_safe(output, len + more + 1);
|
|
|
c54a00 |
- snprintf(output + len, more + 1, "%s", buffer);
|
|
|
c54a00 |
- len += more;
|
|
|
c54a00 |
- }
|
|
|
c54a00 |
-
|
|
|
c54a00 |
- } while (more == (READ_MAX - 1) || (more < 0 && errno == EINTR));
|
|
|
c54a00 |
-
|
|
|
c54a00 |
- return output;
|
|
|
c54a00 |
-}
|
|
|
c54a00 |
-
|
|
|
c54a00 |
static gboolean
|
|
|
c54a00 |
update_remaining_timeout(stonith_action_t * action)
|
|
|
c54a00 |
{
|
|
|
c54a00 |
@@ -860,58 +766,51 @@ update_remaining_timeout(stonith_action_t * action)
|
|
|
c54a00 |
return action->remaining_timeout ? TRUE : FALSE;
|
|
|
c54a00 |
}
|
|
|
c54a00 |
|
|
|
c54a00 |
-static void
|
|
|
c54a00 |
-stonith_action_async_done(mainloop_child_t * p, pid_t pid, int core, int signo, int exitcode)
|
|
|
c54a00 |
-{
|
|
|
c54a00 |
- stonith_action_t *action = mainloop_child_userdata(p);
|
|
|
c54a00 |
-
|
|
|
c54a00 |
- if (action->timer_sigterm > 0) {
|
|
|
c54a00 |
- g_source_remove(action->timer_sigterm);
|
|
|
c54a00 |
- action->timer_sigterm = 0;
|
|
|
c54a00 |
- }
|
|
|
c54a00 |
- if (action->timer_sigkill > 0) {
|
|
|
c54a00 |
- g_source_remove(action->timer_sigkill);
|
|
|
c54a00 |
- action->timer_sigkill = 0;
|
|
|
c54a00 |
- }
|
|
|
c54a00 |
+static int
|
|
|
c54a00 |
+svc_action_to_errno(svc_action_t *svc_action) {
|
|
|
c54a00 |
+ int rv = pcmk_ok;
|
|
|
c54a00 |
|
|
|
c54a00 |
- action->output = read_output(action->fd_stdout);
|
|
|
c54a00 |
- action->error = read_output(action->fd_stderr);
|
|
|
c54a00 |
+ if (svc_action->rc > 0) {
|
|
|
c54a00 |
+ /* Try to provide a useful error code based on the fence agent's
|
|
|
c54a00 |
+ * error output.
|
|
|
c54a00 |
+ */
|
|
|
c54a00 |
+ if (svc_action->rc == PCMK_OCF_TIMEOUT) {
|
|
|
c54a00 |
+ rv = -ETIME;
|
|
|
c54a00 |
|
|
|
c54a00 |
- if (action->last_timeout_signo) {
|
|
|
c54a00 |
- action->rc = -ETIME;
|
|
|
c54a00 |
- crm_notice("Child process %d performing action '%s' timed out with signal %d",
|
|
|
c54a00 |
- pid, action->action, action->last_timeout_signo);
|
|
|
c54a00 |
+ } else if (svc_action->stderr_data == NULL) {
|
|
|
c54a00 |
+ rv = -ENODATA;
|
|
|
c54a00 |
|
|
|
c54a00 |
- } else if (signo) {
|
|
|
c54a00 |
- action->rc = -ECONNABORTED;
|
|
|
c54a00 |
- crm_notice("Child process %d performing action '%s' timed out with signal %d",
|
|
|
c54a00 |
- pid, action->action, signo);
|
|
|
c54a00 |
+ } else if (strstr(svc_action->stderr_data, "imed out")) {
|
|
|
c54a00 |
+ /* Some agents have their own internal timeouts */
|
|
|
c54a00 |
+ rv = -ETIME;
|
|
|
c54a00 |
|
|
|
c54a00 |
- } else {
|
|
|
c54a00 |
- crm_debug("Child process %d performing action '%s' exited with rc %d",
|
|
|
c54a00 |
- pid, action->action, exitcode);
|
|
|
c54a00 |
- if (exitcode > 0) {
|
|
|
c54a00 |
- /* Try to provide a useful error code based on the fence agent's
|
|
|
c54a00 |
- * error output.
|
|
|
c54a00 |
- */
|
|
|
c54a00 |
- if (action->error == NULL) {
|
|
|
c54a00 |
- exitcode = -ENODATA;
|
|
|
c54a00 |
-
|
|
|
c54a00 |
- } else if (strstr(action->error, "imed out")) {
|
|
|
c54a00 |
- /* Some agents have their own internal timeouts */
|
|
|
c54a00 |
- exitcode = -ETIMEDOUT;
|
|
|
c54a00 |
-
|
|
|
c54a00 |
- } else if (strstr(action->error, "Unrecognised action")) {
|
|
|
c54a00 |
- exitcode = -EOPNOTSUPP;
|
|
|
c54a00 |
+ } else if (strstr(svc_action->stderr_data, "Unrecognised action")) {
|
|
|
c54a00 |
+ rv = -EOPNOTSUPP;
|
|
|
c54a00 |
|
|
|
c54a00 |
- } else {
|
|
|
c54a00 |
- exitcode = -pcmk_err_generic;
|
|
|
c54a00 |
- }
|
|
|
c54a00 |
+ } else {
|
|
|
c54a00 |
+ rv = -pcmk_err_generic;
|
|
|
c54a00 |
}
|
|
|
c54a00 |
- action->rc = exitcode;
|
|
|
c54a00 |
}
|
|
|
c54a00 |
+ return rv;
|
|
|
c54a00 |
+}
|
|
|
c54a00 |
|
|
|
c54a00 |
- log_action(action, pid);
|
|
|
c54a00 |
+static void
|
|
|
c54a00 |
+stonith_action_async_done(svc_action_t *svc_action)
|
|
|
c54a00 |
+{
|
|
|
c54a00 |
+ stonith_action_t *action = (stonith_action_t *) svc_action->cb_data;
|
|
|
c54a00 |
+
|
|
|
c54a00 |
+ action->rc = svc_action_to_errno(svc_action);
|
|
|
c54a00 |
+ action->output = svc_action->stdout_data;
|
|
|
c54a00 |
+ svc_action->stdout_data = NULL;
|
|
|
c54a00 |
+ action->error = svc_action->stderr_data;
|
|
|
c54a00 |
+ svc_action->stderr_data = NULL;
|
|
|
c54a00 |
+
|
|
|
c54a00 |
+ svc_action->params = NULL;
|
|
|
c54a00 |
+
|
|
|
c54a00 |
+ crm_debug("Child process %d performing action '%s' exited with rc %d",
|
|
|
c54a00 |
+ action->pid, action->action, svc_action->rc);
|
|
|
c54a00 |
+
|
|
|
c54a00 |
+ log_action(action, action->pid);
|
|
|
c54a00 |
|
|
|
c54a00 |
if (action->rc != pcmk_ok && update_remaining_timeout(action)) {
|
|
|
c54a00 |
int rc = internal_stonith_action_execute(action);
|
|
|
c54a00 |
@@ -921,28 +820,21 @@ stonith_action_async_done(mainloop_child_t * p, pid_t pid, int core, int signo,
|
|
|
c54a00 |
}
|
|
|
c54a00 |
|
|
|
c54a00 |
if (action->done_cb) {
|
|
|
c54a00 |
- action->done_cb(pid, action->rc, action->output, action->userdata);
|
|
|
c54a00 |
+ action->done_cb(action->pid, action->rc, action->output, action->userdata);
|
|
|
c54a00 |
}
|
|
|
c54a00 |
|
|
|
c54a00 |
+ action->svc_action = NULL; // don't remove our caller
|
|
|
c54a00 |
stonith__destroy_action(action);
|
|
|
c54a00 |
}
|
|
|
c54a00 |
|
|
|
c54a00 |
static int
|
|
|
c54a00 |
internal_stonith_action_execute(stonith_action_t * action)
|
|
|
c54a00 |
{
|
|
|
c54a00 |
- int pid, status = 0, len, rc = -EPROTO;
|
|
|
c54a00 |
- int ret;
|
|
|
c54a00 |
- int total = 0;
|
|
|
c54a00 |
- int p_read_fd, p_write_fd; /* parent read/write file descriptors */
|
|
|
c54a00 |
- int c_read_fd, c_write_fd; /* child read/write file descriptors */
|
|
|
c54a00 |
- int c_stderr_fd, p_stderr_fd; /* parent/child side file descriptors for stderr */
|
|
|
c54a00 |
- int fd1[2];
|
|
|
c54a00 |
- int fd2[2];
|
|
|
c54a00 |
- int fd3[2];
|
|
|
c54a00 |
+ int rc = -EPROTO;
|
|
|
c54a00 |
int is_retry = 0;
|
|
|
c54a00 |
-
|
|
|
c54a00 |
- /* clear any previous tracking data */
|
|
|
c54a00 |
- stonith_action_clear_tracking_data(action);
|
|
|
c54a00 |
+ svc_action_t *svc_action = NULL;
|
|
|
c54a00 |
+ static int stonith_sequence = 0;
|
|
|
c54a00 |
+ char *buffer = NULL;
|
|
|
c54a00 |
|
|
|
c54a00 |
if (!action->tries) {
|
|
|
c54a00 |
action->initial_start_time = time(NULL);
|
|
|
c54a00 |
@@ -955,207 +847,60 @@ internal_stonith_action_execute(stonith_action_t * action)
|
|
|
c54a00 |
is_retry = 1;
|
|
|
c54a00 |
}
|
|
|
c54a00 |
|
|
|
c54a00 |
- c_read_fd = c_write_fd = p_read_fd = p_write_fd = c_stderr_fd = p_stderr_fd = -1;
|
|
|
c54a00 |
-
|
|
|
c54a00 |
if (action->args == NULL || action->agent == NULL)
|
|
|
c54a00 |
goto fail;
|
|
|
c54a00 |
- len = strlen(action->args);
|
|
|
c54a00 |
-
|
|
|
c54a00 |
- if (pipe(fd1))
|
|
|
c54a00 |
- goto fail;
|
|
|
c54a00 |
- p_read_fd = fd1[0];
|
|
|
c54a00 |
- c_write_fd = fd1[1];
|
|
|
c54a00 |
-
|
|
|
c54a00 |
- if (pipe(fd2))
|
|
|
c54a00 |
- goto fail;
|
|
|
c54a00 |
- c_read_fd = fd2[0];
|
|
|
c54a00 |
- p_write_fd = fd2[1];
|
|
|
c54a00 |
-
|
|
|
c54a00 |
- if (pipe(fd3))
|
|
|
c54a00 |
- goto fail;
|
|
|
c54a00 |
- p_stderr_fd = fd3[0];
|
|
|
c54a00 |
- c_stderr_fd = fd3[1];
|
|
|
c54a00 |
-
|
|
|
c54a00 |
- crm_debug("forking");
|
|
|
c54a00 |
- pid = fork();
|
|
|
c54a00 |
- if (pid < 0) {
|
|
|
c54a00 |
- rc = -ECHILD;
|
|
|
c54a00 |
- goto fail;
|
|
|
c54a00 |
- }
|
|
|
c54a00 |
-
|
|
|
c54a00 |
- if (!pid) {
|
|
|
c54a00 |
- /* child */
|
|
|
c54a00 |
- setpgid(0, 0);
|
|
|
c54a00 |
-
|
|
|
c54a00 |
- close(1);
|
|
|
c54a00 |
- /* coverity[leaked_handle] False positive */
|
|
|
c54a00 |
- if (dup(c_write_fd) < 0)
|
|
|
c54a00 |
- goto fail;
|
|
|
c54a00 |
- close(2);
|
|
|
c54a00 |
- /* coverity[leaked_handle] False positive */
|
|
|
c54a00 |
- if (dup(c_stderr_fd) < 0)
|
|
|
c54a00 |
- goto fail;
|
|
|
c54a00 |
- close(0);
|
|
|
c54a00 |
- /* coverity[leaked_handle] False positive */
|
|
|
c54a00 |
- if (dup(c_read_fd) < 0)
|
|
|
c54a00 |
- goto fail;
|
|
|
c54a00 |
-
|
|
|
c54a00 |
- /* keep c_stderr_fd open so parent can report all errors. */
|
|
|
c54a00 |
- /* keep c_write_fd open so hostlist can be sent to parent. */
|
|
|
c54a00 |
- close(c_read_fd);
|
|
|
c54a00 |
- close(p_read_fd);
|
|
|
c54a00 |
- close(p_write_fd);
|
|
|
c54a00 |
- close(p_stderr_fd);
|
|
|
c54a00 |
-
|
|
|
c54a00 |
- /* keep retries from executing out of control */
|
|
|
c54a00 |
- if (is_retry) {
|
|
|
c54a00 |
- sleep(1);
|
|
|
c54a00 |
- }
|
|
|
c54a00 |
- execlp(action->agent, action->agent, NULL);
|
|
|
c54a00 |
- exit(EXIT_FAILURE);
|
|
|
c54a00 |
- }
|
|
|
c54a00 |
|
|
|
c54a00 |
- /* parent */
|
|
|
c54a00 |
- action->pid = pid;
|
|
|
c54a00 |
- ret = crm_set_nonblocking(p_read_fd);
|
|
|
c54a00 |
- if (ret < 0) {
|
|
|
c54a00 |
- crm_notice("Could not set output of %s to be non-blocking: %s "
|
|
|
c54a00 |
- CRM_XS " rc=%d",
|
|
|
c54a00 |
- action->agent, pcmk_strerror(rc), rc);
|
|
|
c54a00 |
+ buffer = crm_strdup_printf(RH_STONITH_DIR "/%s", basename(action->agent));
|
|
|
c54a00 |
+ svc_action = services_action_create_generic(buffer, NULL);
|
|
|
c54a00 |
+ free(buffer);
|
|
|
c54a00 |
+ svc_action->timeout = 1000 * action->remaining_timeout;
|
|
|
c54a00 |
+ svc_action->standard = strdup(PCMK_RESOURCE_CLASS_STONITH);
|
|
|
c54a00 |
+ svc_action->id = crm_strdup_printf("%s_%s_%d", basename(action->agent),
|
|
|
c54a00 |
+ action->action, action->tries);
|
|
|
c54a00 |
+ svc_action->agent = strdup(action->agent);
|
|
|
c54a00 |
+ svc_action->sequence = stonith_sequence++;
|
|
|
c54a00 |
+ svc_action->params = action->args;
|
|
|
c54a00 |
+ svc_action->cb_data = (void *) action;
|
|
|
c54a00 |
+
|
|
|
c54a00 |
+ /* keep retries from executing out of control and free previous results */
|
|
|
c54a00 |
+ if (is_retry) {
|
|
|
c54a00 |
+ free(action->output);
|
|
|
c54a00 |
+ action->output = NULL;
|
|
|
c54a00 |
+ free(action->error);
|
|
|
c54a00 |
+ action->error = NULL;
|
|
|
c54a00 |
+ sleep(1);
|
|
|
c54a00 |
}
|
|
|
c54a00 |
- ret = crm_set_nonblocking(p_stderr_fd);
|
|
|
c54a00 |
- if (ret < 0) {
|
|
|
c54a00 |
- crm_notice("Could not set error output of %s to be non-blocking: %s "
|
|
|
c54a00 |
- CRM_XS " rc=%d",
|
|
|
c54a00 |
- action->agent, pcmk_strerror(rc), rc);
|
|
|
c54a00 |
- }
|
|
|
c54a00 |
-
|
|
|
c54a00 |
- errno = 0;
|
|
|
c54a00 |
- do {
|
|
|
c54a00 |
- crm_debug("sending args");
|
|
|
c54a00 |
- ret = write(p_write_fd, action->args + total, len - total);
|
|
|
c54a00 |
- if (ret > 0) {
|
|
|
c54a00 |
- total += ret;
|
|
|
c54a00 |
- }
|
|
|
c54a00 |
-
|
|
|
c54a00 |
- } while (errno == EINTR && total < len);
|
|
|
c54a00 |
-
|
|
|
c54a00 |
- if (total != len) {
|
|
|
c54a00 |
- crm_perror(LOG_ERR, "Sent %d not %d bytes", total, len);
|
|
|
c54a00 |
- if (ret >= 0) {
|
|
|
c54a00 |
- rc = -ECOMM;
|
|
|
c54a00 |
- }
|
|
|
c54a00 |
- goto fail;
|
|
|
c54a00 |
- }
|
|
|
c54a00 |
-
|
|
|
c54a00 |
- close(p_write_fd); p_write_fd = -1;
|
|
|
c54a00 |
|
|
|
c54a00 |
- /* async */
|
|
|
c54a00 |
if (action->async) {
|
|
|
c54a00 |
- action->fd_stdout = p_read_fd;
|
|
|
c54a00 |
- action->fd_stderr = p_stderr_fd;
|
|
|
c54a00 |
- mainloop_child_add(pid, 0/* Move the timeout here? */, action->action, action, stonith_action_async_done);
|
|
|
c54a00 |
- crm_trace("Op: %s on %s, pid: %d, timeout: %ds", action->action, action->agent, pid,
|
|
|
c54a00 |
- action->remaining_timeout);
|
|
|
c54a00 |
- action->last_timeout_signo = 0;
|
|
|
c54a00 |
- if (action->remaining_timeout) {
|
|
|
c54a00 |
- action->timer_sigterm =
|
|
|
c54a00 |
- g_timeout_add(1000 * action->remaining_timeout, st_child_term, action);
|
|
|
c54a00 |
- action->timer_sigkill =
|
|
|
c54a00 |
- g_timeout_add(1000 * (action->remaining_timeout + 5), st_child_kill, action);
|
|
|
c54a00 |
+ /* async */
|
|
|
c54a00 |
+ if(services_action_async(svc_action, &stonith_action_async_done) == FALSE) {
|
|
|
c54a00 |
+ services_action_free(svc_action);
|
|
|
c54a00 |
+ svc_action = NULL;
|
|
|
c54a00 |
} else {
|
|
|
c54a00 |
- crm_err("No timeout set for stonith operation %s with device %s",
|
|
|
c54a00 |
- action->action, action->agent);
|
|
|
c54a00 |
+ action->pid = svc_action->pid;
|
|
|
c54a00 |
+ action->svc_action = svc_action;
|
|
|
c54a00 |
+ rc = 0;
|
|
|
c54a00 |
}
|
|
|
c54a00 |
|
|
|
c54a00 |
- close(c_write_fd);
|
|
|
c54a00 |
- close(c_read_fd);
|
|
|
c54a00 |
- close(c_stderr_fd);
|
|
|
c54a00 |
- return 0;
|
|
|
c54a00 |
-
|
|
|
c54a00 |
} else {
|
|
|
c54a00 |
/* sync */
|
|
|
c54a00 |
- int timeout = action->remaining_timeout + 1;
|
|
|
c54a00 |
- pid_t p = 0;
|
|
|
c54a00 |
-
|
|
|
c54a00 |
- while (action->remaining_timeout < 0 || timeout > 0) {
|
|
|
c54a00 |
- p = waitpid(pid, &status, WNOHANG);
|
|
|
c54a00 |
- if (p > 0) {
|
|
|
c54a00 |
- break;
|
|
|
c54a00 |
- }
|
|
|
c54a00 |
- sleep(1);
|
|
|
c54a00 |
- timeout--;
|
|
|
c54a00 |
- }
|
|
|
c54a00 |
-
|
|
|
c54a00 |
- if (timeout == 0) {
|
|
|
c54a00 |
- int killrc = kill(-pid, SIGKILL);
|
|
|
c54a00 |
-
|
|
|
c54a00 |
- if (killrc && errno != ESRCH) {
|
|
|
c54a00 |
- crm_err("kill(%d, KILL) failed: %s (%d)", pid, pcmk_strerror(errno), errno);
|
|
|
c54a00 |
- }
|
|
|
c54a00 |
- /*
|
|
|
c54a00 |
- * From sigprocmask(2):
|
|
|
c54a00 |
- * It is not possible to block SIGKILL or SIGSTOP. Attempts to do so are silently ignored.
|
|
|
c54a00 |
- *
|
|
|
c54a00 |
- * This makes it safe to skip WNOHANG here
|
|
|
c54a00 |
- */
|
|
|
c54a00 |
- p = waitpid(pid, &status, 0);
|
|
|
c54a00 |
- }
|
|
|
c54a00 |
-
|
|
|
c54a00 |
- if (p <= 0) {
|
|
|
c54a00 |
- crm_perror(LOG_ERR, "waitpid(%d)", pid);
|
|
|
c54a00 |
-
|
|
|
c54a00 |
- } else if (p != pid) {
|
|
|
c54a00 |
- crm_err("Waited for %d, got %d", pid, p);
|
|
|
c54a00 |
- }
|
|
|
c54a00 |
-
|
|
|
c54a00 |
- action->output = read_output(p_read_fd);
|
|
|
c54a00 |
- action->error = read_output(p_stderr_fd);
|
|
|
c54a00 |
-
|
|
|
c54a00 |
- action->rc = -ECONNABORTED;
|
|
|
c54a00 |
-
|
|
|
c54a00 |
- log_action(action, pid);
|
|
|
c54a00 |
-
|
|
|
c54a00 |
- rc = action->rc;
|
|
|
c54a00 |
- if (timeout == 0) {
|
|
|
c54a00 |
- action->rc = -ETIME;
|
|
|
c54a00 |
- } else if (WIFEXITED(status)) {
|
|
|
c54a00 |
- crm_debug("result = %d", WEXITSTATUS(status));
|
|
|
c54a00 |
- action->rc = -WEXITSTATUS(status);
|
|
|
c54a00 |
+ if (services_action_sync(svc_action)) {
|
|
|
c54a00 |
rc = 0;
|
|
|
c54a00 |
-
|
|
|
c54a00 |
- } else if (WIFSIGNALED(status)) {
|
|
|
c54a00 |
- crm_err("call %s for %s exited due to signal %d", action->action, action->agent,
|
|
|
c54a00 |
- WTERMSIG(status));
|
|
|
c54a00 |
-
|
|
|
c54a00 |
+ action->rc = svc_action_to_errno(svc_action);
|
|
|
c54a00 |
+ action->output = svc_action->stdout_data;
|
|
|
c54a00 |
+ svc_action->stdout_data = NULL;
|
|
|
c54a00 |
+ action->error = svc_action->stderr_data;
|
|
|
c54a00 |
+ svc_action->stderr_data = NULL;
|
|
|
c54a00 |
} else {
|
|
|
c54a00 |
- crm_err("call %s for %s returned unexpected status %#x",
|
|
|
c54a00 |
- action->action, action->agent, status);
|
|
|
c54a00 |
+ action->rc = -ECONNABORTED;
|
|
|
c54a00 |
+ rc = action->rc;
|
|
|
c54a00 |
}
|
|
|
c54a00 |
- }
|
|
|
c54a00 |
|
|
|
c54a00 |
- fail:
|
|
|
c54a00 |
-
|
|
|
c54a00 |
- if (p_read_fd >= 0) {
|
|
|
c54a00 |
- close(p_read_fd);
|
|
|
c54a00 |
- }
|
|
|
c54a00 |
- if (p_write_fd >= 0) {
|
|
|
c54a00 |
- close(p_write_fd);
|
|
|
c54a00 |
- }
|
|
|
c54a00 |
- if (p_stderr_fd >= 0) {
|
|
|
c54a00 |
- close(p_stderr_fd);
|
|
|
c54a00 |
- }
|
|
|
c54a00 |
-
|
|
|
c54a00 |
- if (c_read_fd >= 0) {
|
|
|
c54a00 |
- close(c_read_fd);
|
|
|
c54a00 |
- }
|
|
|
c54a00 |
- if (c_write_fd >= 0) {
|
|
|
c54a00 |
- close(c_write_fd);
|
|
|
c54a00 |
- }
|
|
|
c54a00 |
- if (c_stderr_fd >= 0) {
|
|
|
c54a00 |
- close(c_stderr_fd);
|
|
|
c54a00 |
+ svc_action->params = NULL;
|
|
|
c54a00 |
+ services_action_free(svc_action);
|
|
|
c54a00 |
}
|
|
|
c54a00 |
|
|
|
c54a00 |
+ fail:
|
|
|
c54a00 |
return rc;
|
|
|
c54a00 |
}
|
|
|
c54a00 |
|
|
|
c54a00 |
diff --git a/lib/services/services_linux.c b/lib/services/services_linux.c
|
|
|
c54a00 |
index a413484..d79c16d 100644
|
|
|
c54a00 |
--- a/lib/services/services_linux.c
|
|
|
c54a00 |
+++ b/lib/services/services_linux.c
|
|
|
c54a00 |
@@ -195,6 +195,39 @@ add_action_env_vars(const svc_action_t *op)
|
|
|
c54a00 |
}
|
|
|
c54a00 |
}
|
|
|
c54a00 |
|
|
|
c54a00 |
+static void
|
|
|
c54a00 |
+pipe_in_single_parameter(gpointer key, gpointer value, gpointer user_data)
|
|
|
c54a00 |
+{
|
|
|
c54a00 |
+ svc_action_t *op = user_data;
|
|
|
c54a00 |
+ char *buffer = crm_strdup_printf("%s=%s\n", (char *)key, (char *) value);
|
|
|
c54a00 |
+ int ret, total = 0, len = strlen(buffer);
|
|
|
c54a00 |
+
|
|
|
c54a00 |
+ do {
|
|
|
c54a00 |
+ errno = 0;
|
|
|
c54a00 |
+ ret = write(op->opaque->stdin_fd, buffer + total, len - total);
|
|
|
c54a00 |
+ if (ret > 0) {
|
|
|
c54a00 |
+ total += ret;
|
|
|
c54a00 |
+ }
|
|
|
c54a00 |
+
|
|
|
c54a00 |
+ } while ((errno == EINTR) && (total < len));
|
|
|
c54a00 |
+ free(buffer);
|
|
|
c54a00 |
+}
|
|
|
c54a00 |
+
|
|
|
c54a00 |
+/*!
|
|
|
c54a00 |
+ * \internal
|
|
|
c54a00 |
+ * \brief Pipe parameters in via stdin for action
|
|
|
c54a00 |
+ *
|
|
|
c54a00 |
+ * \param[in] op Action to use
|
|
|
c54a00 |
+ */
|
|
|
c54a00 |
+static void
|
|
|
c54a00 |
+pipe_in_action_stdin_parameters(const svc_action_t *op)
|
|
|
c54a00 |
+{
|
|
|
c54a00 |
+ crm_debug("sending args");
|
|
|
c54a00 |
+ if (op->params) {
|
|
|
c54a00 |
+ g_hash_table_foreach(op->params, pipe_in_single_parameter, (gpointer) op);
|
|
|
c54a00 |
+ }
|
|
|
c54a00 |
+}
|
|
|
c54a00 |
+
|
|
|
c54a00 |
gboolean
|
|
|
c54a00 |
recurring_action_timer(gpointer data)
|
|
|
c54a00 |
{
|
|
|
c54a00 |
@@ -284,6 +317,10 @@ operation_finished(mainloop_child_t * p, pid_t pid, int core, int signo, int exi
|
|
|
c54a00 |
op->opaque->stdout_gsource = NULL;
|
|
|
c54a00 |
}
|
|
|
c54a00 |
|
|
|
c54a00 |
+ if (op->opaque->stdin_fd >= 0) {
|
|
|
c54a00 |
+ close(op->opaque->stdin_fd);
|
|
|
c54a00 |
+ }
|
|
|
c54a00 |
+
|
|
|
c54a00 |
if (signo) {
|
|
|
c54a00 |
if (mainloop_child_timeout(p)) {
|
|
|
c54a00 |
crm_warn("%s - timed out after %dms", prefix, op->timeout);
|
|
|
c54a00 |
@@ -605,6 +642,9 @@ action_synced_wait(svc_action_t * op, sigset_t *mask)
|
|
|
c54a00 |
|
|
|
c54a00 |
close(op->opaque->stdout_fd);
|
|
|
c54a00 |
close(op->opaque->stderr_fd);
|
|
|
c54a00 |
+ if (op->opaque->stdin_fd >= 0) {
|
|
|
c54a00 |
+ close(op->opaque->stdin_fd);
|
|
|
c54a00 |
+ }
|
|
|
c54a00 |
|
|
|
c54a00 |
#ifdef HAVE_SYS_SIGNALFD_H
|
|
|
c54a00 |
close(sfd);
|
|
|
c54a00 |
@@ -618,6 +658,7 @@ services_os_action_execute(svc_action_t * op)
|
|
|
c54a00 |
{
|
|
|
c54a00 |
int stdout_fd[2];
|
|
|
c54a00 |
int stderr_fd[2];
|
|
|
c54a00 |
+ int stdin_fd[2] = {-1, -1};
|
|
|
c54a00 |
int rc;
|
|
|
c54a00 |
struct stat st;
|
|
|
c54a00 |
sigset_t *pmask;
|
|
|
c54a00 |
@@ -683,6 +724,25 @@ services_os_action_execute(svc_action_t * op)
|
|
|
c54a00 |
return FALSE;
|
|
|
c54a00 |
}
|
|
|
c54a00 |
|
|
|
c54a00 |
+ if (safe_str_eq(op->standard, PCMK_RESOURCE_CLASS_STONITH)) {
|
|
|
c54a00 |
+ if (pipe(stdin_fd) < 0) {
|
|
|
c54a00 |
+ rc = errno;
|
|
|
c54a00 |
+
|
|
|
c54a00 |
+ close(stdout_fd[0]);
|
|
|
c54a00 |
+ close(stdout_fd[1]);
|
|
|
c54a00 |
+ close(stderr_fd[0]);
|
|
|
c54a00 |
+ close(stderr_fd[1]);
|
|
|
c54a00 |
+
|
|
|
c54a00 |
+ crm_err("pipe(stdin_fd) failed. '%s': %s (%d)", op->opaque->exec, pcmk_strerror(rc), rc);
|
|
|
c54a00 |
+
|
|
|
c54a00 |
+ services_handle_exec_error(op, rc);
|
|
|
c54a00 |
+ if (!op->synchronous) {
|
|
|
c54a00 |
+ return operation_finalize(op);
|
|
|
c54a00 |
+ }
|
|
|
c54a00 |
+ return FALSE;
|
|
|
c54a00 |
+ }
|
|
|
c54a00 |
+ }
|
|
|
c54a00 |
+
|
|
|
c54a00 |
if (op->synchronous) {
|
|
|
c54a00 |
#ifdef HAVE_SYS_SIGNALFD_H
|
|
|
c54a00 |
sigemptyset(&mask);
|
|
|
c54a00 |
@@ -730,6 +790,10 @@ services_os_action_execute(svc_action_t * op)
|
|
|
c54a00 |
close(stdout_fd[1]);
|
|
|
c54a00 |
close(stderr_fd[0]);
|
|
|
c54a00 |
close(stderr_fd[1]);
|
|
|
c54a00 |
+ if (stdin_fd[0] >= 0) {
|
|
|
c54a00 |
+ close(stdin_fd[0]);
|
|
|
c54a00 |
+ close(stdin_fd[1]);
|
|
|
c54a00 |
+ }
|
|
|
c54a00 |
|
|
|
c54a00 |
crm_err("Could not execute '%s': %s (%d)", op->opaque->exec, pcmk_strerror(rc), rc);
|
|
|
c54a00 |
services_handle_exec_error(op, rc);
|
|
|
c54a00 |
@@ -743,6 +807,9 @@ services_os_action_execute(svc_action_t * op)
|
|
|
c54a00 |
case 0: /* Child */
|
|
|
c54a00 |
close(stdout_fd[0]);
|
|
|
c54a00 |
close(stderr_fd[0]);
|
|
|
c54a00 |
+ if (stdin_fd[1] >= 0) {
|
|
|
c54a00 |
+ close(stdin_fd[1]);
|
|
|
c54a00 |
+ }
|
|
|
c54a00 |
if (STDOUT_FILENO != stdout_fd[1]) {
|
|
|
c54a00 |
if (dup2(stdout_fd[1], STDOUT_FILENO) != STDOUT_FILENO) {
|
|
|
c54a00 |
crm_err("dup2() failed (stdout)");
|
|
|
c54a00 |
@@ -755,6 +822,13 @@ services_os_action_execute(svc_action_t * op)
|
|
|
c54a00 |
}
|
|
|
c54a00 |
close(stderr_fd[1]);
|
|
|
c54a00 |
}
|
|
|
c54a00 |
+ if ((stdin_fd[0] >= 0) &&
|
|
|
c54a00 |
+ (STDIN_FILENO != stdin_fd[0])) {
|
|
|
c54a00 |
+ if (dup2(stdin_fd[0], STDIN_FILENO) != STDIN_FILENO) {
|
|
|
c54a00 |
+ crm_err("dup2() failed (stdin)");
|
|
|
c54a00 |
+ }
|
|
|
c54a00 |
+ close(stdin_fd[0]);
|
|
|
c54a00 |
+ }
|
|
|
c54a00 |
|
|
|
c54a00 |
if (op->synchronous) {
|
|
|
c54a00 |
sigchld_cleanup();
|
|
|
c54a00 |
@@ -767,6 +841,9 @@ services_os_action_execute(svc_action_t * op)
|
|
|
c54a00 |
/* Only the parent reaches here */
|
|
|
c54a00 |
close(stdout_fd[1]);
|
|
|
c54a00 |
close(stderr_fd[1]);
|
|
|
c54a00 |
+ if (stdin_fd[0] >= 0) {
|
|
|
c54a00 |
+ close(stdin_fd[0]);
|
|
|
c54a00 |
+ }
|
|
|
c54a00 |
|
|
|
c54a00 |
op->opaque->stdout_fd = stdout_fd[0];
|
|
|
c54a00 |
rc = crm_set_nonblocking(op->opaque->stdout_fd);
|
|
|
c54a00 |
@@ -784,6 +861,22 @@ services_os_action_execute(svc_action_t * op)
|
|
|
c54a00 |
pcmk_strerror(rc), rc);
|
|
|
c54a00 |
}
|
|
|
c54a00 |
|
|
|
c54a00 |
+ op->opaque->stdin_fd = stdin_fd[1];
|
|
|
c54a00 |
+ if (op->opaque->stdin_fd >= 0) {
|
|
|
c54a00 |
+ // using buffer behind non-blocking-fd here - that could be improved
|
|
|
c54a00 |
+ // as long as no other standard uses stdin_fd assume stonith
|
|
|
c54a00 |
+ rc = crm_set_nonblocking(op->opaque->stdin_fd);
|
|
|
c54a00 |
+ if (rc < 0) {
|
|
|
c54a00 |
+ crm_warn("Could not set child input non-blocking: %s "
|
|
|
c54a00 |
+ CRM_XS " fd=%d,rc=%d",
|
|
|
c54a00 |
+ pcmk_strerror(rc), op->opaque->stdin_fd, rc);
|
|
|
c54a00 |
+ }
|
|
|
c54a00 |
+ pipe_in_action_stdin_parameters(op);
|
|
|
c54a00 |
+ // as long as we are handling parameters directly in here just close
|
|
|
c54a00 |
+ close(op->opaque->stdin_fd);
|
|
|
c54a00 |
+ op->opaque->stdin_fd = -1;
|
|
|
c54a00 |
+ }
|
|
|
c54a00 |
+
|
|
|
c54a00 |
if (op->synchronous) {
|
|
|
c54a00 |
action_synced_wait(op, pmask);
|
|
|
c54a00 |
sigchld_cleanup();
|
|
|
c54a00 |
diff --git a/lib/services/services_private.h b/lib/services/services_private.h
|
|
|
c54a00 |
index 0676c6f..9735da7 100644
|
|
|
c54a00 |
--- a/lib/services/services_private.h
|
|
|
c54a00 |
+++ b/lib/services/services_private.h
|
|
|
c54a00 |
@@ -42,6 +42,8 @@ struct svc_action_private_s {
|
|
|
c54a00 |
|
|
|
c54a00 |
int stdout_fd;
|
|
|
c54a00 |
mainloop_io_t *stdout_gsource;
|
|
|
c54a00 |
+
|
|
|
c54a00 |
+ int stdin_fd;
|
|
|
c54a00 |
#if SUPPORT_DBUS
|
|
|
c54a00 |
DBusPendingCall* pending;
|
|
|
c54a00 |
unsigned timerid;
|
|
|
c54a00 |
--
|
|
|
c54a00 |
1.8.3.1
|
|
|
c54a00 |
|