mirror of https://github.com/Icinga/icinga2.git
Implemented rudimentary service checks.
This commit is contained in:
parent
01c2da2853
commit
31407fd07f
|
@ -21,12 +21,14 @@
|
|||
|
||||
using namespace icinga;
|
||||
|
||||
ConfigObject::ConfigObject(Dictionary::Ptr properties)
|
||||
: m_Properties(properties), m_Tags(make_shared<Dictionary>())
|
||||
ConfigObject::ConfigObject(Dictionary::Ptr properties, const ConfigObject::Set::Ptr& container)
|
||||
: m_Container(container ? container : GetAllObjects()),
|
||||
m_Properties(properties), m_Tags(make_shared<Dictionary>())
|
||||
{ }
|
||||
|
||||
ConfigObject::ConfigObject(string type, string name)
|
||||
: m_Properties(make_shared<Dictionary>()), m_Tags(make_shared<Dictionary>())
|
||||
ConfigObject::ConfigObject(string type, string name, const ConfigObject::Set::Ptr& container)
|
||||
: m_Container(container ? container : GetAllObjects()),
|
||||
m_Properties(make_shared<Dictionary>()), m_Tags(make_shared<Dictionary>())
|
||||
{
|
||||
SetProperty("__type", type);
|
||||
SetProperty("__name", name);
|
||||
|
@ -90,13 +92,13 @@ void ConfigObject::Commit(void)
|
|||
ConfigObject::Ptr dobj = GetObject(GetType(), GetName());
|
||||
ConfigObject::Ptr self = static_pointer_cast<ConfigObject>(shared_from_this());
|
||||
assert(!dobj || dobj == self);
|
||||
GetAllObjects()->CheckObject(self);
|
||||
m_Container->CheckObject(self);
|
||||
}
|
||||
|
||||
void ConfigObject::Unregister(void)
|
||||
{
|
||||
ConfigObject::Ptr self = static_pointer_cast<ConfigObject>(shared_from_this());
|
||||
GetAllObjects()->RemoveObject(self);
|
||||
m_Container->RemoveObject(self);
|
||||
}
|
||||
|
||||
ObjectSet<ConfigObject::Ptr>::Ptr ConfigObject::GetAllObjects(void)
|
||||
|
@ -174,4 +176,4 @@ bool ConfigObject::TypeGetter(const ConfigObject::Ptr& object, string *key)
|
|||
ConfigObject::TMap::Range ConfigObject::GetObjects(string type)
|
||||
{
|
||||
return GetObjectsByType()->GetRange(type);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,8 +33,8 @@ public:
|
|||
typedef ObjectMap<string, ConfigObject::Ptr> TMap;
|
||||
typedef ObjectSet<ConfigObject::Ptr> Set;
|
||||
|
||||
ConfigObject(Dictionary::Ptr properties);
|
||||
ConfigObject(string type, string name);
|
||||
ConfigObject(Dictionary::Ptr properties, const Set::Ptr& container = Set::Ptr());
|
||||
ConfigObject(string type, string name, const Set::Ptr& container = Set::Ptr());
|
||||
|
||||
void SetProperties(Dictionary::Ptr config);
|
||||
Dictionary::Ptr GetProperties(void) const;
|
||||
|
@ -89,6 +89,7 @@ public:
|
|||
static function<bool (ConfigObject::Ptr)> MakeTypePredicate(string type);
|
||||
|
||||
private:
|
||||
Set::Ptr m_Container;
|
||||
Dictionary::Ptr m_Properties;
|
||||
Dictionary::Ptr m_Tags;
|
||||
|
||||
|
|
|
@ -94,17 +94,14 @@ RequestMessage ConfigRpcComponent::MakeObjectMessage(const ConfigObject::Ptr& ob
|
|||
params.SetProperty("type", object->GetType());
|
||||
|
||||
if (includeProperties)
|
||||
params.SetProperty("properties", object);
|
||||
params.SetProperty("properties", object->GetProperties());
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
bool ConfigRpcComponent::ShouldReplicateObject(const ConfigObject::Ptr& object)
|
||||
{
|
||||
long replicate;
|
||||
if (!object->GetProperty("replicate", &replicate))
|
||||
return true;
|
||||
return (replicate != 0);
|
||||
return (!object->IsLocal());
|
||||
}
|
||||
|
||||
int ConfigRpcComponent::FetchObjectsHandler(const NewRequestEventArgs& ea)
|
||||
|
|
|
@ -122,7 +122,10 @@ void ConfigItem::Commit(void)
|
|||
|
||||
m_ConfigObject = dobj;
|
||||
|
||||
dobj->Commit();
|
||||
if (dobj->IsAbstract())
|
||||
dobj->Unregister();
|
||||
else
|
||||
dobj->Commit();
|
||||
|
||||
ConfigItem::Ptr ci = GetObject(GetType(), GetName());
|
||||
ConfigItem::Ptr self = static_pointer_cast<ConfigItem>(shared_from_this());
|
||||
|
|
|
@ -5,3 +5,28 @@ local object application "icinga" {
|
|||
local object component "demo" {
|
||||
|
||||
}
|
||||
|
||||
object host "localhost" {
|
||||
|
||||
}
|
||||
|
||||
abstract object service "nagios-service" {
|
||||
check_type = "nagios",
|
||||
|
||||
macros = {
|
||||
plugindir = "/usr/local/icinga/libexec"
|
||||
}
|
||||
}
|
||||
|
||||
abstract object service "ping" inherits "nagios-service" {
|
||||
check_type = "nagios",
|
||||
check_command = "$plugindir$/check_ping -H $address$"
|
||||
}
|
||||
|
||||
object service "localhost-ping" inherits "ping" {
|
||||
host_name = "localhost",
|
||||
|
||||
macros += {
|
||||
address = "localhost"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
#include "i2-icinga.h"
|
||||
|
||||
using namespace icinga;
|
||||
|
||||
map<string, CheckTask::Factory> CheckTask::m_Types;
|
||||
|
||||
void CheckTask::RegisterType(string type, Factory factory)
|
||||
{
|
||||
m_Types[type] = factory;
|
||||
}
|
||||
|
||||
CheckTask::Ptr CheckTask::CreateTask(const Service& service)
|
||||
{
|
||||
map<string, CheckTask::Factory>::iterator it;
|
||||
|
||||
it = m_Types.find(service.GetCheckType());
|
||||
|
||||
if (it == m_Types.end())
|
||||
throw runtime_error("Invalid check type specified for service '" + service.GetName() + "'");
|
||||
|
||||
return it->second(service);
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
#ifndef CHECKTASK_H
|
||||
#define CHECKTASK_H
|
||||
|
||||
namespace icinga
|
||||
{
|
||||
|
||||
enum CheckState
|
||||
{
|
||||
StateOK,
|
||||
StateWarning,
|
||||
StateCritical,
|
||||
StateUnreachable,
|
||||
StateUncheckable,
|
||||
StateUnknown
|
||||
};
|
||||
|
||||
struct CheckResult
|
||||
{
|
||||
time_t StartTime;
|
||||
time_t EndTime;
|
||||
|
||||
CheckState State;
|
||||
string Output;
|
||||
Dictionary::Ptr PerformanceData;
|
||||
};
|
||||
|
||||
class CheckTask : public Object
|
||||
{
|
||||
public:
|
||||
typedef shared_ptr<CheckTask> Ptr;
|
||||
typedef weak_ptr<CheckTask> WeakPtr;
|
||||
|
||||
typedef function<CheckTask::Ptr(const Service&)> Factory;
|
||||
|
||||
virtual CheckResult Execute(void) const = 0;
|
||||
|
||||
static void RegisterType(string type, Factory factory);
|
||||
static CheckTask::Ptr CreateTask(const Service& service);
|
||||
|
||||
private:
|
||||
static map<string, Factory> m_Types;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* CHECKTASK_H */
|
|
@ -0,0 +1,23 @@
|
|||
#include "i2-icinga.h"
|
||||
|
||||
using namespace icinga;
|
||||
|
||||
string ConfigObjectAdapter::GetType(void) const
|
||||
{
|
||||
return m_ConfigObject->GetType();
|
||||
}
|
||||
|
||||
string ConfigObjectAdapter::GetName(void) const
|
||||
{
|
||||
return m_ConfigObject->GetName();
|
||||
}
|
||||
|
||||
bool ConfigObjectAdapter::IsLocal(void) const
|
||||
{
|
||||
return m_ConfigObject->IsLocal();
|
||||
}
|
||||
|
||||
ConfigObject::Ptr ConfigObjectAdapter::GetConfigObject() const
|
||||
{
|
||||
return m_ConfigObject;
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
#ifndef CONFIGOBJECTADAPTER_H
|
||||
#define CONFIGOBJECTADAPTER_H
|
||||
|
||||
namespace icinga
|
||||
{
|
||||
|
||||
class I2_ICINGA_API ConfigObjectAdapter
|
||||
{
|
||||
public:
|
||||
ConfigObjectAdapter(const ConfigObject::Ptr& configObject)
|
||||
: m_ConfigObject(configObject)
|
||||
{ }
|
||||
|
||||
string GetType(void) const;
|
||||
string GetName(void) const;
|
||||
|
||||
bool IsLocal(void) const;
|
||||
|
||||
protected:
|
||||
ConfigObject::Ptr GetConfigObject() const;
|
||||
|
||||
private:
|
||||
ConfigObject::Ptr m_ConfigObject;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* CONFIGOBJECTADAPTER_H */
|
|
@ -0,0 +1,23 @@
|
|||
#include "i2-icinga.h"
|
||||
|
||||
using namespace icinga;
|
||||
|
||||
string Host::GetDisplayName(void) const
|
||||
{
|
||||
string value;
|
||||
|
||||
if (GetConfigObject()->GetProperty("displayname", &value))
|
||||
return value;
|
||||
|
||||
return GetName();
|
||||
}
|
||||
|
||||
Host Host::GetByName(string name)
|
||||
{
|
||||
ConfigObject::Ptr configObject = ConfigObject::GetObject("host", name);
|
||||
|
||||
if (!configObject)
|
||||
throw invalid_argument("Host '" + name + "' does not exist.");
|
||||
|
||||
return Host(configObject);
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef HOST_H
|
||||
#define HOST_H
|
||||
|
||||
namespace icinga
|
||||
{
|
||||
|
||||
class I2_ICINGA_API Host : public ConfigObjectAdapter
|
||||
{
|
||||
public:
|
||||
Host(const ConfigObject::Ptr& configObject)
|
||||
: ConfigObjectAdapter(configObject)
|
||||
{ }
|
||||
|
||||
static Host GetByName(string name);
|
||||
|
||||
string GetDisplayName(void) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* HOST_H */
|
|
@ -44,4 +44,12 @@
|
|||
#include "icingaapplication.h"
|
||||
#include "icingacomponent.h"
|
||||
|
||||
#include "configobjectadapter.h"
|
||||
#include "host.h"
|
||||
#include "service.h"
|
||||
|
||||
#include "macroprocessor.h"
|
||||
#include "checktask.h"
|
||||
#include "nagioschecktask.h"
|
||||
|
||||
#endif /* I2ICINGA_H */
|
||||
|
|
|
@ -11,20 +11,32 @@
|
|||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="checktask.cpp" />
|
||||
<ClCompile Include="configobjectadapter.cpp" />
|
||||
<ClCompile Include="endpoint.cpp" />
|
||||
<ClCompile Include="endpointmanager.cpp" />
|
||||
<ClCompile Include="host.cpp" />
|
||||
<ClCompile Include="icingaapplication.cpp" />
|
||||
<ClCompile Include="icingacomponent.cpp" />
|
||||
<ClCompile Include="jsonrpcendpoint.cpp" />
|
||||
<ClCompile Include="macroprocessor.cpp" />
|
||||
<ClCompile Include="nagioschecktask.cpp" />
|
||||
<ClCompile Include="service.cpp" />
|
||||
<ClCompile Include="virtualendpoint.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="checktask.h" />
|
||||
<ClInclude Include="configobjectadapter.h" />
|
||||
<ClInclude Include="endpoint.h" />
|
||||
<ClInclude Include="endpointmanager.h" />
|
||||
<ClInclude Include="host.h" />
|
||||
<ClInclude Include="i2-icinga.h" />
|
||||
<ClInclude Include="icingaapplication.h" />
|
||||
<ClInclude Include="icingacomponent.h" />
|
||||
<ClInclude Include="jsonrpcendpoint.h" />
|
||||
<ClInclude Include="macroprocessor.h" />
|
||||
<ClInclude Include="nagioschecktask.h" />
|
||||
<ClInclude Include="service.h" />
|
||||
<ClInclude Include="virtualendpoint.h" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
|
|
|
@ -91,6 +91,18 @@ int IcingaApplication::Main(const vector<string>& args)
|
|||
m_EndpointManager->SetSSLContext(sslContext);
|
||||
}
|
||||
|
||||
CheckTask::RegisterType("nagios", NagiosCheckTask::CreateTask);
|
||||
|
||||
ConfigObject::TMap::Range range = ConfigObject::GetObjects("service");
|
||||
|
||||
for (ConfigObject::TMap::Iterator it = range.first; it != range.second; it++) {
|
||||
ConfigObject::Ptr obj = it->second;
|
||||
|
||||
Service svc = Service(obj);
|
||||
CheckTask::Ptr ct = CheckTask::CreateTask(svc);
|
||||
CheckResult cr = ct->Execute();
|
||||
}
|
||||
|
||||
/* create the primary RPC listener */
|
||||
string service = GetService();
|
||||
if (!service.empty())
|
||||
|
@ -117,7 +129,7 @@ int IcingaApplication::NewComponentHandler(const ObjectSetEventArgs<ConfigObject
|
|||
|
||||
/* don't allow replicated config objects */
|
||||
if (!object->IsLocal())
|
||||
return 0;
|
||||
throw runtime_error("'component' objects must be 'local'");
|
||||
|
||||
string path;
|
||||
if (!object->GetProperty("path", &path)) {
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
#include "i2-icinga.h"
|
||||
|
||||
using namespace icinga;
|
||||
|
||||
string MacroProcessor::ResolveMacros(string str, Dictionary::Ptr macros)
|
||||
{
|
||||
string::size_type offset, pos_first, pos_second;
|
||||
|
||||
offset = 0;
|
||||
|
||||
while ((pos_first = str.find_first_of('$', offset)) != string::npos) {
|
||||
pos_second = str.find_first_of('$', pos_first + 1);
|
||||
|
||||
if (pos_second == string::npos)
|
||||
throw runtime_error("Closing $ not found in macro format string.");
|
||||
|
||||
string name = str.substr(pos_first + 1, pos_second - pos_first - 1);
|
||||
string value;
|
||||
if (!macros || !macros->GetProperty(name, &value))
|
||||
throw runtime_error("Macro '" + name + "' is not defined.");
|
||||
|
||||
str.replace(pos_first, pos_second - pos_first + 1, value);
|
||||
|
||||
offset = pos_first + value.size();
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
#ifndef MACROPROCESSOR_H
|
||||
#define MACROPROCESSOR_H
|
||||
|
||||
namespace icinga
|
||||
{
|
||||
|
||||
class MacroProcessor
|
||||
{
|
||||
public:
|
||||
static string ResolveMacros(string str, Dictionary::Ptr macros);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* MACROPROCESSOR_H */
|
|
@ -0,0 +1,85 @@
|
|||
#include "i2-icinga.h"
|
||||
|
||||
using namespace icinga;
|
||||
|
||||
NagiosCheckTask::NagiosCheckTask(const Service& service)
|
||||
{
|
||||
string checkCommand = service.GetCheckCommand();
|
||||
m_Command = MacroProcessor::ResolveMacros(checkCommand, service.GetMacros());
|
||||
}
|
||||
|
||||
CheckResult NagiosCheckTask::Execute(void) const
|
||||
{
|
||||
CheckResult cr;
|
||||
FILE *fp;
|
||||
|
||||
time(&cr.StartTime);
|
||||
|
||||
string command = m_Command + " 2>&1";
|
||||
|
||||
#ifdef _MSC_VER
|
||||
fp = _popen(command.c_str(), "r");
|
||||
#else /* _MSC_VER */
|
||||
fp = popen(command.c_str(), "r");
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
stringstream output;
|
||||
|
||||
while (!feof(fp)) {
|
||||
char buffer[128];
|
||||
size_t read = fread(buffer, 1, sizeof(buffer), fp);
|
||||
|
||||
if (read == 0)
|
||||
break;
|
||||
|
||||
output << string(buffer, buffer + read);
|
||||
}
|
||||
|
||||
cr.Output = output.str();
|
||||
|
||||
int status, exitstatus;
|
||||
#ifdef _MSC_VER
|
||||
status = _pclose(fp);
|
||||
#else /* _MSC_VER */
|
||||
status = pclose(fp);
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
#ifndef _MSC_VER
|
||||
if (WIFEXITED(status)) {
|
||||
exitcode = WEXITSTATUS(status);
|
||||
#else /* _MSC_VER */
|
||||
exitstatus = status;
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
switch (exitstatus) {
|
||||
case 0:
|
||||
cr.State = StateOK;
|
||||
break;
|
||||
case 1:
|
||||
cr.State = StateWarning;
|
||||
break;
|
||||
case 2:
|
||||
cr.State = StateCritical;
|
||||
break;
|
||||
default:
|
||||
cr.State = StateUnknown;
|
||||
break;
|
||||
}
|
||||
#ifndef _MSC_VER
|
||||
} else if (WIFSIGNALED(status)) {
|
||||
cr.Output = "Process was terminated by signal " + WTERMSIG(status);
|
||||
cr.Status = StateUnknown;
|
||||
}
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
time(&cr.EndTime);
|
||||
|
||||
return cr;
|
||||
}
|
||||
|
||||
CheckTask::Ptr NagiosCheckTask::CreateTask(const Service& service)
|
||||
{
|
||||
assert(service.GetCheckType() == "nagios");
|
||||
|
||||
return make_shared<NagiosCheckTask>(service);
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
#ifndef NAGIOSCHECKTASK_H
|
||||
#define NAGIOSCHECKTASK_H
|
||||
|
||||
namespace icinga
|
||||
{
|
||||
|
||||
class NagiosCheckTask : public CheckTask
|
||||
{
|
||||
public:
|
||||
NagiosCheckTask(const Service& service);
|
||||
|
||||
virtual CheckResult Execute(void) const;
|
||||
|
||||
static CheckTask::Ptr CreateTask(const Service& service);
|
||||
|
||||
private:
|
||||
string m_Command;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* NAGIOSCHECKTASK_H */
|
|
@ -0,0 +1,64 @@
|
|||
#include "i2-icinga.h"
|
||||
|
||||
using namespace icinga;
|
||||
|
||||
string Service::GetDisplayName(void) const
|
||||
{
|
||||
string value;
|
||||
|
||||
if (GetConfigObject()->GetProperty("displayname", &value))
|
||||
return value;
|
||||
|
||||
return GetName();
|
||||
}
|
||||
|
||||
Host Service::GetHost(void) const
|
||||
{
|
||||
string hostname;
|
||||
if (!GetConfigObject()->GetProperty("host_name", &hostname))
|
||||
throw runtime_error("Service object is missing the 'host_name' property.");
|
||||
|
||||
return Host::GetByName(hostname);
|
||||
}
|
||||
|
||||
Dictionary::Ptr Service::GetMacros(void) const
|
||||
{
|
||||
Dictionary::Ptr macros;
|
||||
GetConfigObject()->GetProperty("macros", ¯os);
|
||||
return macros;
|
||||
}
|
||||
|
||||
string Service::GetCheckType(void) const
|
||||
{
|
||||
string value = "nagios";
|
||||
GetConfigObject()->GetProperty("check_type", &value);
|
||||
return value;
|
||||
}
|
||||
|
||||
string Service::GetCheckCommand(void) const
|
||||
{
|
||||
string value;
|
||||
GetConfigObject()->GetProperty("check_command", &value);
|
||||
return value;
|
||||
}
|
||||
|
||||
long Service::GetMaxCheckAttempts(void) const
|
||||
{
|
||||
long value = 1;
|
||||
GetConfigObject()->GetProperty("max_check_attempts", &value);
|
||||
return value;
|
||||
}
|
||||
|
||||
long Service::GetCheckInterval(void) const
|
||||
{
|
||||
long value = 1;
|
||||
GetConfigObject()->GetProperty("check_interval", &value);
|
||||
return value;
|
||||
}
|
||||
|
||||
long Service::GetRetryInterval(void) const
|
||||
{
|
||||
long value = 1;
|
||||
GetConfigObject()->GetProperty("retry_interval", &value);
|
||||
return value;
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
#ifndef SERVICE_H
|
||||
#define SERVICE_H
|
||||
|
||||
namespace icinga
|
||||
{
|
||||
|
||||
class I2_ICINGA_API Service : public ConfigObjectAdapter
|
||||
{
|
||||
public:
|
||||
Service(const ConfigObject::Ptr& configObject)
|
||||
: ConfigObjectAdapter(configObject)
|
||||
{ }
|
||||
|
||||
string GetDisplayName(void) const;
|
||||
Host GetHost(void) const;
|
||||
Dictionary::Ptr GetMacros(void) const;
|
||||
string GetCheckType(void) const;
|
||||
string GetCheckCommand(void) const;
|
||||
long GetMaxCheckAttempts(void) const;
|
||||
long GetCheckInterval(void) const;
|
||||
long GetRetryInterval(void) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* SERVICE_H */
|
Loading…
Reference in New Issue