Add livestatus component.

This commit is contained in:
Gunnar Beutner 2013-03-10 03:09:01 +01:00
parent 375746d710
commit 27505536f9
20 changed files with 726 additions and 7 deletions

View File

@ -6,5 +6,6 @@ SUBDIRS = \
compat \
delegation \
demo \
livestatus \
notification \
replication

View File

@ -0,0 +1,37 @@
## Process this file with automake to produce Makefile.in
pkglib_LTLIBRARIES = \
livestatus.la
livestatus_la_SOURCES = \
livestatuscomponent.cpp \
livestatuscomponent.h \
livestatusconnection.cpp \
livestatusconnection.h \
livestatusquery.cpp \
livestatusquery.h \
livestatustable.cpp \
livestatustable.h \
i2-livestatus.h
livestatus_la_CPPFLAGS = \
$(BOOST_CPPFLAGS) \
-I${top_srcdir}/lib/base \
-I${top_srcdir}/lib/config \
-I${top_srcdir}/lib/remoting \
-I${top_srcdir}/lib/icinga
livestatus_la_LDFLAGS = \
$(BOOST_LDFLAGS) \
-module \
-no-undefined \
@RELEASE_INFO@ \
@VERSION_INFO@
livestatus_la_LIBADD = \
$(BOOST_SIGNALS_LIB) \
$(BOOST_THREAD_LIB) \
${top_builddir}/lib/base/libbase.la \
${top_builddir}/lib/config/libconfig.la \
${top_builddir}/lib/remoting/libremoting.la \
${top_builddir}/lib/icinga/libicinga.la

View File

@ -0,0 +1,38 @@
/******************************************************************************
* Icinga 2 *
* Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/) *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software Foundation *
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
******************************************************************************/
#ifndef I2LIVESTATUS_H
#define I2LIVESTATUS_H
/**
* @defgroup livestatus Livestatus component
*
* The livestatus component implements livestatus queries.
*/
#include <i2-base.h>
#include <i2-remoting.h>
#include <i2-icinga.h>
#include "livestatusconnection.h"
#include "livestatusquery.h"
#include "livestatustable.h"
#include "livestatuscomponent.h"
#endif /* I2LIVESTATUS_H */

View File

@ -0,0 +1,167 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{2E6C1133-730F-4875-A72C-B455B1DD4C5C}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>demo</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>$(SolutionDir)\lib\base;$(SolutionDir)\lib\remoting;$(SolutionDir)\lib\icinga;$(SolutionDir)\lib\config;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)$(Platform)\$(Configuration)\;$(LibraryPath)</LibraryPath>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>$(SolutionDir)\lib\base;$(SolutionDir)\lib\remoting;$(SolutionDir)\lib\icinga;$(SolutionDir)\lib\config;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)$(Platform)\$(Configuration)\;$(LibraryPath)</LibraryPath>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>$(SolutionDir)\lib\base;$(SolutionDir)\lib\remoting;$(SolutionDir)\lib\icinga;$(SolutionDir)\lib\config;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)$(Platform)\$(Configuration)\;$(LibraryPath)</LibraryPath>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>$(SolutionDir)\lib\base;$(SolutionDir)\lib\remoting;$(SolutionDir)\lib\icinga;$(SolutionDir)\lib\config;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)$(Platform)\$(Configuration)\;$(LibraryPath)</LibraryPath>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;DEMO_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>Level3</WarningLevel>
<MinimalRebuild>false</MinimalRebuild>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>base.lib;remoting.lib;icinga.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;DEMO_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>Level3</WarningLevel>
<MinimalRebuild>false</MinimalRebuild>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>base.lib;remoting.lib;icinga.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;DEMO_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>Level3</WarningLevel>
<MinimalRebuild>false</MinimalRebuild>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>base.lib;remoting.lib;icinga.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;DEMO_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>Level3</WarningLevel>
<MinimalRebuild>false</MinimalRebuild>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>base.lib;remoting.lib;icinga.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="democomponent.h" />
<ClInclude Include="i2-demo.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="democomponent.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClInclude Include="democomponent.h">
<Filter>Headerdateien</Filter>
</ClInclude>
<ClInclude Include="i2-demo.h">
<Filter>Headerdateien</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="Headerdateien">
<UniqueIdentifier>{11a495bf-a705-4766-b3d3-9b5db266a6ef}</UniqueIdentifier>
</Filter>
<Filter Include="Quelldateien">
<UniqueIdentifier>{1fb6337f-a17f-46ea-9316-2d800a94b53d}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="democomponent.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -0,0 +1,74 @@
/******************************************************************************
* Icinga 2 *
* Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/) *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software Foundation *
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
******************************************************************************/
#include "i2-livestatus.h"
using namespace icinga;
REGISTER_COMPONENT("livestatus", LivestatusComponent);
/**
* Starts the component.
*/
void LivestatusComponent::Start(void)
{
UnixSocket::Ptr socket = boost::make_shared<UnixSocket>();
socket->OnNewClient.connect(boost::bind(&LivestatusComponent::NewClientHandler, this, _2));
socket->Bind(GetSocketPath());
socket->Listen();
socket->Start();
m_Listener = socket;
}
/**
* Stops the component.
*/
void LivestatusComponent::Stop(void)
{
}
String LivestatusComponent::GetSocketPath(void) const
{
DynamicObject::Ptr config = GetConfig();
Value socketPath = config->Get("socket_path");
if (socketPath.IsEmpty())
return Application::GetLocalStateDir() + "/run/icinga2/livestatus";
else
return socketPath;
}
void LivestatusComponent::NewClientHandler(const Socket::Ptr& client)
{
Logger::Write(LogInformation, "livestatus", "Client connected");
LivestatusConnection::Ptr lconnection = boost::make_shared<LivestatusConnection>(client);
lconnection->OnClosed.connect(boost::bind(&LivestatusComponent::ClientClosedHandler, this, _1));
m_Connections.insert(lconnection);
client->Start();
}
void LivestatusComponent::ClientClosedHandler(const Connection::Ptr& connection)
{
LivestatusConnection::Ptr lconnection = static_pointer_cast<LivestatusConnection>(connection);
Logger::Write(LogInformation, "livestatus", "Client disconnected");
m_Connections.erase(lconnection);
}

View File

@ -0,0 +1,47 @@
/******************************************************************************
* Icinga 2 *
* Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/) *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software Foundation *
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
******************************************************************************/
#ifndef LIVESTATUSCOMPONENT_H
#define LIVESTATUSCOMPONENT_H
namespace icinga
{
/**
* @ingroup livestatus
*/
class LivestatusComponent : public IComponent
{
public:
virtual void Start(void);
virtual void Stop(void);
String GetSocketPath(void) const;
private:
Socket::Ptr m_Listener;
set<LivestatusConnection::Ptr> m_Connections;
void NewClientHandler(const Socket::Ptr& client);
void ClientClosedHandler(const Connection::Ptr& connection);
};
}
#endif /* LIVESTATUSCOMPONENT_H */

View File

@ -0,0 +1,36 @@
/******************************************************************************
* Icinga 2 *
* Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/) *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software Foundation *
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
******************************************************************************/
#include "i2-livestatus.h"
using namespace icinga;
LivestatusConnection::LivestatusConnection(const Stream::Ptr& stream)
: Connection(stream)
{ }
void LivestatusConnection::ProcessData(void)
{
LivestatusQuery::Ptr query = LivestatusQuery::ParseQuery(GetStream());
if (!query)
return;
query->Execute(GetStream());
}

View File

@ -0,0 +1,40 @@
/******************************************************************************
* Icinga 2 *
* Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/) *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software Foundation *
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
******************************************************************************/
#ifndef LIVESTATUSCONNECTION_H
#define LIVESTATUSCONNECTION_H
namespace icinga
{
class LivestatusConnection : public Connection
{
public:
typedef shared_ptr<LivestatusConnection> Ptr;
typedef weak_ptr<LivestatusConnection> WeakPtr;
LivestatusConnection(const Stream::Ptr& stream);
protected:
virtual void ProcessData(void);
};
}
#endif /* LIVESTATUSCONNECTION_H */

View File

@ -0,0 +1,126 @@
/******************************************************************************
* Icinga 2 *
* Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/) *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software Foundation *
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
******************************************************************************/
#include "i2-livestatus.h"
using namespace icinga;
LivestatusQuery::LivestatusQuery(void)
: m_KeepAlive(false), m_ColumnHeaders(true), m_Limit(-1)
{ }
LivestatusQuery::Ptr LivestatusQuery::ParseQuery(const Stream::Ptr& stream)
{
LivestatusQuery::Ptr query = boost::make_shared<LivestatusQuery>();
String line;
if (!stream->ReadLine(&line))
return LivestatusQuery::Ptr();
size_t sp_index = line.FindFirstOf(" ");
if (sp_index == String::NPos)
BOOST_THROW_EXCEPTION(runtime_error("Livestatus header must contain a verb."));
String verb = line.SubStr(0, sp_index);
String target = line.SubStr(sp_index + 1);
query->m_Verb = verb;
if (query->m_Verb == "COMMAND") {
query->m_Command = target;
} else if (query->m_Verb == "GET") {
query->m_Table = target;
} else {
BOOST_THROW_EXCEPTION(runtime_error("Unknown livestatus verb: " + query->m_Verb));
}
while (!stream->IsEOF() && stream->ReadLine(&line)) {
/* Empty line means we've reached the end of this query. */
if (line.GetLength() == 0)
return query;
size_t col_index = line.FindFirstOf(":");
String header = line.SubStr(0, col_index);
String params = line.SubStr(col_index + 2);
if (header == "ResponseHeader")
query->m_ResponseHeader = params;
}
/* Check if we've reached EOF. */
if (!stream->IsConnected())
return query;
/* Query isn't complete yet. */
return LivestatusQuery::Ptr();
}
void LivestatusQuery::ExecuteGetHelper(const Stream::Ptr& stream)
{
}
void LivestatusQuery::ExecuteCommandHelper(const Stream::Ptr& stream)
{
try {
Logger::Write(LogInformation, "livestatus", "Executing command: " + m_Command);
ExternalCommandProcessor::Execute(m_Command);
} catch (const std::exception& ex) {
SendResponse(stream, 452, diagnostic_information(ex));
}
}
void LivestatusQuery::ExecuteErrorHelper(const Stream::Ptr& stream)
{
PrintFixed16(stream, m_ErrorCode, m_ErrorMessage);
}
void LivestatusQuery::SendResponse(const Stream::Ptr& stream, int code, const String& data)
{
if (m_ResponseHeader == "fixed16")
PrintFixed16(stream, code, data);
else if (code == 200)
stream->Write(data.CStr(), data.GetLength());
}
void LivestatusQuery::PrintFixed16(const Stream::Ptr& stream, int code, const String& data)
{
ASSERT(code >= 100 && code <= 999);
String sCode = Convert::ToString(code);
String sLength = Convert::ToString(data.GetLength());
String header = sCode + String(16 - 3 - sLength.GetLength() - 1, ' ') + sLength + "\n";
stream->Write(header.CStr(), header.GetLength());
}
void LivestatusQuery::Execute(const Stream::Ptr& stream)
{
Logger::Write(LogInformation, "livestatus", "Executing livestatus query: " + m_Verb);
if (m_Verb == "GET")
ExecuteGetHelper(stream);
else if (m_Verb == "COMMAND")
ExecuteCommandHelper(stream);
else if (m_Verb == "ERROR")
ExecuteErrorHelper(stream);
else
BOOST_THROW_EXCEPTION(runtime_error("Invalid livestatus query verb."));
}

View File

@ -0,0 +1,75 @@
/******************************************************************************
* Icinga 2 *
* Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/) *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software Foundation *
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
******************************************************************************/
#ifndef LIVESTATUSQUERY_H
#define LIVESTATUSQUERY_H
namespace icinga
{
/**
* @ingroup livestatus
*/
class LivestatusQuery : public Object
{
public:
typedef shared_ptr<LivestatusQuery> Ptr;
typedef weak_ptr<LivestatusQuery> WeakPtr;
static LivestatusQuery::Ptr ParseQuery(const Stream::Ptr& stream);
void Execute(const Stream::Ptr& stream);
private:
String m_Verb;
bool m_KeepAlive;
/* Parameters for GET queries. */
String m_Table;
vector<String> m_Columns;
String m_OutputFormat;
bool m_ColumnHeaders;
int m_Limit;
String m_ResponseHeader;
/* Parameters for COMMAND queries. */
String m_Command;
/* Parameters for invalid queries. */
int m_ErrorCode;
String m_ErrorMessage;
LivestatusQuery(void);
void ExecuteGetHelper(const Stream::Ptr& stream);
void ExecuteCommandHelper(const Stream::Ptr& stream);
void ExecuteErrorHelper(const Stream::Ptr& stream);
void SendResponse(const Stream::Ptr& stream, int code, const String& data);
void PrintFixed16(const Stream::Ptr& stream, int code, const String& data);
friend Ptr boost::make_shared<LivestatusQuery>(void);
};
}
#endif /* LIVESTATUSQUERY_H */

View File

View File

@ -108,6 +108,7 @@ components/checker/Makefile
components/compat/Makefile
components/delegation/Makefile
components/demo/Makefile
components/livestatus/Makefile
components/notification/Makefile
components/replication/Makefile
docs/Doxyfile

View File

@ -130,6 +130,7 @@ using std::type_info;
#include <boost/signals2.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/join.hpp>
#include <boost/algorithm/string/compare.hpp>
#include <boost/thread.hpp>
#include <boost/variant.hpp>

View File

@ -35,6 +35,10 @@ String::String(const std::string& data)
: m_Data(data)
{ }
String::String(size_t n, char c)
: m_Data(n, c)
{ }
String::String(const String& other)
: m_Data(other.m_Data)
{ }
@ -124,6 +128,11 @@ void String::Replace(size_t first, size_t second, const String& str)
m_Data.replace(first, second, str);
}
String Join(const vector<String>& strings, const char *delim)
{
return boost::algorithm::join(strings, delim);
}
void String::Trim(void)
{
boost::algorithm::trim(m_Data);
@ -257,4 +266,3 @@ String::ConstIterator icinga::range_end(const String& x)
{
return x.End();
}

View File

@ -34,9 +34,13 @@ public:
typedef std::string::iterator Iterator;
typedef std::string::const_iterator ConstIterator;
typedef std::string::iterator iterator;
typedef std::string::const_iterator const_iterator;
String(void);
String(const char *data);
String(const std::string& data);
String(size_t n, char c);
template<typename InputIterator>
String(InputIterator begin, InputIterator end)
@ -66,7 +70,7 @@ public:
size_t GetLength(void) const;
size_t FindFirstOf(const char *s, size_t pos = 0) const;
String SubStr(size_t first, size_t len) const;
String SubStr(size_t first, size_t len = NPos) const;
void Replace(size_t first, size_t second, const String& str);
template<typename Predicate>
@ -77,11 +81,19 @@ public:
return tokens;
}
static String Join(const vector<String>& strings, const char *delim);
void Trim(void);
void swap(String& str);
Iterator erase(Iterator first, Iterator last);
template<typename InputIterator>
void insert(Iterator p, InputIterator first, InputIterator last)
{
m_Data.insert(p, first, last);
}
Iterator Begin(void);
ConstIterator Begin(void) const;
Iterator End(void);

View File

@ -392,9 +392,13 @@ size_t Socket::Read(void *buffer, size_t size)
throw new logic_error("Socket does not support Read().");
}
if (m_RecvQueue->GetAvailableBytes() == 0)
if (m_RecvQueue->GetAvailableBytes() == 0) {
CheckException();
if (!IsConnected())
SetEOF(true);
}
return m_RecvQueue->Read(buffer, size);
}
@ -516,9 +520,12 @@ void Socket::HandleReadableClient(void)
#endif /* _WIN32 */
break;
if (rc <= 0)
if (rc < 0)
BOOST_THROW_EXCEPTION(SocketException("recv() failed", GetError()));
if (rc == 0)
SetEOF(true);
m_RecvQueue->Write(data, rc);
new_data = true;
@ -586,7 +593,7 @@ bool Socket::WantsToRead(void) const
*/
bool Socket::WantsToReadClient(void) const
{
return true;
return !IsEOF();
}
/**

View File

@ -22,7 +22,7 @@
using namespace icinga;
Stream::Stream(void)
: m_Connected(false)
: m_Connected(false), m_EOF(false)
{ }
Stream::~Stream(void)
@ -40,6 +40,16 @@ bool Stream::IsConnected(void) const
return m_Connected;
}
/**
* @threadsafety Always.
*/
bool Stream::IsEOF(void) const
{
ObjectLock olock(this);
return m_EOF;
}
/**
* @threadsafety Always.
*/
@ -56,6 +66,17 @@ void Stream::SetConnected(bool connected)
OnClosed(GetSelf());
}
/**
* @threadsafety Always.
*/
void Stream::SetEOF(bool eof)
{
{
ObjectLock olock(this);
m_EOF = eof;
}
}
/**
* Checks whether an exception is available for this stream and re-throws
* the exception if there is one.
@ -119,9 +140,10 @@ bool Stream::ReadLine(String *line, size_t maxLength)
size_t rc = Peek(buffer, maxLength);
for (int i = 0; i < rc; i++) {
for (size_t i = 0; i < rc; i++) {
if (buffer[i] == '\n') {
*line = String(buffer, &(buffer[i]));
boost::algorithm::trim_right(*line);
Read(NULL, rc);

View File

@ -81,6 +81,7 @@ public:
virtual void Close(void);
bool IsConnected(void) const;
bool IsEOF(void) const;
bool ReadLine(String *line, size_t maxLength = 4096);
@ -93,12 +94,14 @@ public:
protected:
void SetConnected(bool connected);
void SetEOF(bool eof);
void SetException(boost::exception_ptr exception);
private:
bool m_Running;
bool m_Connected;
bool m_EOF;
boost::exception_ptr m_Exception;
};