mirror of
https://github.com/Icinga/icinga2.git
synced 2025-07-27 07:34:15 +02:00
Implemented environment-based macros.
This commit is contained in:
parent
f8851aa79d
commit
ee37e0cace
@ -32,6 +32,8 @@ AC_LANG_CPLUSPLUS
|
|||||||
AC_PROG_CC
|
AC_PROG_CC
|
||||||
AC_LANG_C
|
AC_LANG_C
|
||||||
|
|
||||||
|
AC_FUNC_VFORK
|
||||||
|
|
||||||
LT_INIT([dlopen disable-static win32-dll])
|
LT_INIT([dlopen disable-static win32-dll])
|
||||||
LT_CONFIG_LTDL_DIR([third-party/ltdl])
|
LT_CONFIG_LTDL_DIR([third-party/ltdl])
|
||||||
LTDL_INIT
|
LTDL_INIT
|
||||||
|
@ -43,3 +43,7 @@ String Convert::ToString(long val)
|
|||||||
return cs.str();
|
return cs.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String Convert::ToString(const Value& val)
|
||||||
|
{
|
||||||
|
return static_cast<String>(val);
|
||||||
|
}
|
||||||
|
@ -35,6 +35,7 @@ public:
|
|||||||
static double ToDouble(const String& val);
|
static double ToDouble(const String& val);
|
||||||
static bool ToBool(const String& val);
|
static bool ToBool(const String& val);
|
||||||
static String ToString(long val);
|
static String ToString(long val);
|
||||||
|
static String ToString(const Value& val);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Convert(void);
|
Convert(void);
|
||||||
|
@ -255,4 +255,3 @@ cJSON *Dictionary::ToJson(void) const
|
|||||||
|
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,10 +19,6 @@
|
|||||||
|
|
||||||
#include "i2-base.h"
|
#include "i2-base.h"
|
||||||
|
|
||||||
#ifndef _MSC_VER
|
|
||||||
# include "popen_noshell.h"
|
|
||||||
#endif /* _MSC_VER */
|
|
||||||
|
|
||||||
using namespace icinga;
|
using namespace icinga;
|
||||||
|
|
||||||
bool Process::m_ThreadCreated = false;
|
bool Process::m_ThreadCreated = false;
|
||||||
@ -30,8 +26,9 @@ boost::mutex Process::m_Mutex;
|
|||||||
deque<Process::Ptr> Process::m_Tasks;
|
deque<Process::Ptr> Process::m_Tasks;
|
||||||
condition_variable Process::m_TasksCV;
|
condition_variable Process::m_TasksCV;
|
||||||
|
|
||||||
Process::Process(const String& command)
|
Process::Process(const String& command, const Dictionary::Ptr& environment)
|
||||||
: AsyncTask<Process, ProcessResult>(), m_Command(command), m_UsePopen(false)
|
: AsyncTask<Process, ProcessResult>(), m_Command(command),
|
||||||
|
m_Environment(environment), m_FP(NULL)
|
||||||
{
|
{
|
||||||
assert(Application::IsMainThread());
|
assert(Application::IsMainThread());
|
||||||
|
|
||||||
@ -130,29 +127,127 @@ void Process::WorkerThreadProc(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Process::Spawn(const String& command, const Dictionary::Ptr& env)
|
||||||
|
{
|
||||||
|
vector<String> args;
|
||||||
|
args.push_back("sh");
|
||||||
|
args.push_back("-c");
|
||||||
|
args.push_back(command);
|
||||||
|
|
||||||
|
return Spawn(args, env);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Process::Spawn(const vector<String>& args, const Dictionary::Ptr& extraEnv)
|
||||||
|
{
|
||||||
|
assert(m_FP == NULL);
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#error "TODO: implement"
|
||||||
|
#else /* _MSC_VER */
|
||||||
|
int fds[2];
|
||||||
|
|
||||||
|
if (pipe(fds) < 0)
|
||||||
|
BOOST_THROW_EXCEPTION(PosixException("pipe() failed.", errno));
|
||||||
|
|
||||||
|
char **argv = new char *[args.size() + 1];
|
||||||
|
|
||||||
|
for (int i = 0; i < args.size(); i++)
|
||||||
|
argv[i] = strdup(args[i].CStr());
|
||||||
|
|
||||||
|
argv[args.size()] = NULL;
|
||||||
|
|
||||||
|
int envc = 0;
|
||||||
|
|
||||||
|
/* count existing environment variables */
|
||||||
|
while (environ[envc] != NULL)
|
||||||
|
envc++;
|
||||||
|
|
||||||
|
char **envp = new char *[envc + (extraEnv ? extraEnv->GetLength() : 0) + 1];
|
||||||
|
|
||||||
|
for (int i = 0; i < envc; i++)
|
||||||
|
envp[i] = environ[i];
|
||||||
|
|
||||||
|
if (extraEnv) {
|
||||||
|
String key;
|
||||||
|
Value value;
|
||||||
|
int index = envc;
|
||||||
|
BOOST_FOREACH(tie(key, value), extraEnv) {
|
||||||
|
String kv = key + "=" + Convert::ToString(value);
|
||||||
|
envp[index] = strdup(kv.CStr());
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
envp[envc + (extraEnv ? extraEnv->GetLength() : 0)] = NULL;
|
||||||
|
|
||||||
|
#ifdef HAVE_VFORK
|
||||||
|
m_Pid = vfork();
|
||||||
|
#else /* HAVE_VFORK */
|
||||||
|
m_Pid = fork();
|
||||||
|
#endif /* HAVE_VFORK */
|
||||||
|
|
||||||
|
if (m_Pid < 0)
|
||||||
|
BOOST_THROW_EXCEPTION(PosixException("fork() failed.", errno));
|
||||||
|
|
||||||
|
if (m_Pid == 0) {
|
||||||
|
/* child */
|
||||||
|
if (dup2(fds[1], STDOUT_FILENO) < 0 || dup2(fds[1], STDERR_FILENO) < 0) {
|
||||||
|
perror("dup2() failed.");
|
||||||
|
_exit(128);
|
||||||
|
}
|
||||||
|
|
||||||
|
(void) close(fds[1]);
|
||||||
|
|
||||||
|
if (execvpe(argv[0], argv, envp) < 0) {
|
||||||
|
perror("execvpe() failed.");
|
||||||
|
_exit(128);
|
||||||
|
}
|
||||||
|
|
||||||
|
_exit(128);
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < args.size(); i++)
|
||||||
|
free(argv[i]);
|
||||||
|
|
||||||
|
delete [] argv;
|
||||||
|
|
||||||
|
if (extraEnv) {
|
||||||
|
for (int i = envc; i < envc + extraEnv->GetLength(); i++)
|
||||||
|
free(envp[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete [] envp;
|
||||||
|
|
||||||
|
/* parent */
|
||||||
|
(void) close(fds[1]);
|
||||||
|
|
||||||
|
m_FP = fdopen(fds[0], "r");
|
||||||
|
|
||||||
|
if (m_FP == NULL)
|
||||||
|
BOOST_THROW_EXCEPTION(PosixException("fdopen() failed.", errno));
|
||||||
|
}
|
||||||
|
#endif /* _MSC_VER */
|
||||||
|
}
|
||||||
|
|
||||||
|
int Process::WaitPid(void)
|
||||||
|
{
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
return _pclose(m_FP);
|
||||||
|
#else /* _MSC_VER */
|
||||||
|
fclose(m_FP);
|
||||||
|
|
||||||
|
int status;
|
||||||
|
if (waitpid(m_Pid, &status, 0) != m_Pid)
|
||||||
|
BOOST_THROW_EXCEPTION(PosixException("waitpid() failed.", errno));
|
||||||
|
|
||||||
|
return status;
|
||||||
|
#endif /* _MSC_VER */
|
||||||
|
}
|
||||||
|
|
||||||
void Process::InitTask(void)
|
void Process::InitTask(void)
|
||||||
{
|
{
|
||||||
m_Result.ExecutionStart = Utility::GetTime();
|
m_Result.ExecutionStart = Utility::GetTime();
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
Spawn(m_Command, m_Environment);
|
||||||
m_FP = _popen(m_Command.CStr(), "r");
|
|
||||||
#else /* _MSC_VER */
|
|
||||||
if (!m_UsePopen) {
|
|
||||||
m_PCloseArg = new popen_noshell_pass_to_pclose;
|
|
||||||
|
|
||||||
m_FP = popen_noshell_compat(m_Command.CStr(), "r",
|
|
||||||
(popen_noshell_pass_to_pclose *)m_PCloseArg);
|
|
||||||
|
|
||||||
if (m_FP == NULL)
|
|
||||||
m_UsePopen = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_UsePopen)
|
|
||||||
m_FP = popen(m_Command.CStr(), "r");
|
|
||||||
#endif /* _MSC_VER */
|
|
||||||
|
|
||||||
if (m_FP == NULL)
|
|
||||||
BOOST_THROW_EXCEPTION(runtime_error("Could not create process."));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Process::RunTask(void)
|
bool Process::RunTask(void)
|
||||||
@ -169,18 +264,8 @@ bool Process::RunTask(void)
|
|||||||
String output = m_OutputStream.str();
|
String output = m_OutputStream.str();
|
||||||
|
|
||||||
int status, exitcode;
|
int status, exitcode;
|
||||||
#ifdef _MSC_VER
|
|
||||||
status = _pclose(m_FP);
|
|
||||||
#else /* _MSC_VER */
|
|
||||||
if (m_UsePopen) {
|
|
||||||
status = pclose(m_FP);
|
|
||||||
} else {
|
|
||||||
status = pclose_noshell((popen_noshell_pass_to_pclose *)m_PCloseArg);
|
|
||||||
delete (popen_noshell_pass_to_pclose *)m_PCloseArg;
|
|
||||||
}
|
|
||||||
#endif /* _MSC_VER */
|
|
||||||
|
|
||||||
m_Result.ExecutionEnd = Utility::GetTime();
|
status = WaitPid();
|
||||||
|
|
||||||
#ifndef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
if (WIFEXITED(status)) {
|
if (WIFEXITED(status)) {
|
||||||
@ -206,6 +291,7 @@ bool Process::RunTask(void)
|
|||||||
}
|
}
|
||||||
#endif /* _MSC_VER */
|
#endif /* _MSC_VER */
|
||||||
|
|
||||||
|
m_Result.ExecutionEnd = Utility::GetTime();
|
||||||
m_Result.ExitStatus = exitcode;
|
m_Result.ExitStatus = exitcode;
|
||||||
m_Result.Output = output;
|
m_Result.Output = output;
|
||||||
|
|
||||||
|
@ -50,19 +50,20 @@ public:
|
|||||||
|
|
||||||
static const deque<Process::Ptr>::size_type MaxTasksPerThread = 512;
|
static const deque<Process::Ptr>::size_type MaxTasksPerThread = 512;
|
||||||
|
|
||||||
Process(const String& command);
|
Process(const String& command, const Dictionary::Ptr& environment = Dictionary::Ptr());
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static bool m_ThreadCreated;
|
static bool m_ThreadCreated;
|
||||||
|
|
||||||
String m_Command;
|
String m_Command;
|
||||||
|
Dictionary::Ptr m_Environment;
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
pid_t m_Pid;
|
||||||
|
#endif /* _WIN32 */
|
||||||
FILE *m_FP;
|
FILE *m_FP;
|
||||||
|
|
||||||
stringstream m_OutputStream;
|
stringstream m_OutputStream;
|
||||||
bool m_UsePopen;
|
|
||||||
#ifndef _MSC_VER
|
|
||||||
void *m_PCloseArg;
|
|
||||||
#endif /* _MSC_VER */
|
|
||||||
|
|
||||||
ProcessResult m_Result;
|
ProcessResult m_Result;
|
||||||
|
|
||||||
@ -78,6 +79,10 @@ private:
|
|||||||
bool RunTask(void);
|
bool RunTask(void);
|
||||||
|
|
||||||
int GetFD(void) const;
|
int GetFD(void) const;
|
||||||
|
|
||||||
|
void Spawn(const String& command, const Dictionary::Ptr& extraEnv);
|
||||||
|
void Spawn(const vector<String>& args, const Dictionary::Ptr& extraEnv);
|
||||||
|
int WaitPid(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -56,3 +56,21 @@ String MacroProcessor::ResolveMacros(const String& str, const vector<Dictionary:
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Dictionary::Ptr MacroProcessor::MakeEnvironment(const vector<Dictionary::Ptr>& dicts)
|
||||||
|
{
|
||||||
|
Dictionary::Ptr result = boost::make_shared<Dictionary>();
|
||||||
|
|
||||||
|
BOOST_REVERSE_FOREACH(const Dictionary::Ptr& dict, dicts) {
|
||||||
|
String key;
|
||||||
|
Value value;
|
||||||
|
BOOST_FOREACH(tie(key, value), dict) {
|
||||||
|
if (!value.IsScalar())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
result->Set(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
@ -32,6 +32,7 @@ class I2_ICINGA_API MacroProcessor
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static String ResolveMacros(const String& str, const vector<Dictionary::Ptr>& macroDicts);
|
static String ResolveMacros(const String& str, const vector<Dictionary::Ptr>& macroDicts);
|
||||||
|
static Dictionary::Ptr MakeEnvironment(const vector<Dictionary::Ptr>& macroDicts);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ void PluginCheckTask::ScriptFunc(const ScriptTask::Ptr& task, const vector<Value
|
|||||||
macroDicts.push_back(IcingaApplication::GetInstance()->GetMacros());
|
macroDicts.push_back(IcingaApplication::GetInstance()->GetMacros());
|
||||||
String command = MacroProcessor::ResolveMacros(checkCommand, macroDicts);
|
String command = MacroProcessor::ResolveMacros(checkCommand, macroDicts);
|
||||||
|
|
||||||
Process::Ptr process = boost::make_shared<Process>(command);
|
Process::Ptr process = boost::make_shared<Process>(command, MacroProcessor::MakeEnvironment(macroDicts));
|
||||||
|
|
||||||
PluginCheckTask ct(task, process);
|
PluginCheckTask ct(task, process);
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ void PluginNotificationTask::ScriptFunc(const ScriptTask::Ptr& task, const vecto
|
|||||||
macroDicts.push_back(IcingaApplication::GetInstance()->GetMacros());
|
macroDicts.push_back(IcingaApplication::GetInstance()->GetMacros());
|
||||||
String command = MacroProcessor::ResolveMacros(notificationCommand, macroDicts);
|
String command = MacroProcessor::ResolveMacros(notificationCommand, macroDicts);
|
||||||
|
|
||||||
Process::Ptr process = boost::make_shared<Process>(command);
|
Process::Ptr process = boost::make_shared<Process>(command, MacroProcessor::MakeEnvironment(macroDicts));
|
||||||
|
|
||||||
PluginNotificationTask ct(task, process, notification->GetService()->GetName(), command);
|
PluginNotificationTask ct(task, process, notification->GetService()->GetName(), command);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user