mirror of https://github.com/Icinga/icinga2.git
parent
cb2e38ae0d
commit
0d36cc8d5f
|
@ -516,6 +516,7 @@ Variable |Description
|
|||
--------------------|-------------------
|
||||
PrefixDir |**Read-only.** Contains the installation prefix that was specified with cmake -DCMAKE_INSTALL_PREFIX. Defaults to "/usr/local".
|
||||
SysconfDir |**Read-only.** Contains the path of the sysconf directory. Defaults to PrefixDir + "/etc".
|
||||
ZonesDir |**Read-only.** Contains the path of the zones.d directory. Defaults to SysconfDir + "/zones.d".
|
||||
LocalStateDir |**Read-only.** Contains the path of the local state directory. Defaults to PrefixDir + "/var".
|
||||
PkgDataDir |**Read-only.** Contains the path of the package data directory. Defaults to PrefixDir + "/share/icinga2".
|
||||
StatePath |**Read-write.** Contains the path of the Icinga 2 state file. Defaults to LocalStateDir + "/lib/icinga2/icinga2.state".
|
||||
|
|
|
@ -56,6 +56,7 @@ install_if_not_exists(icinga2/features-available/syslog.conf ${CMAKE_INSTALL_SYS
|
|||
install_if_not_exists(icinga2/scripts/check_kernel ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/scripts)
|
||||
install_if_not_exists(icinga2/scripts/mail-host-notification.sh ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/scripts)
|
||||
install_if_not_exists(icinga2/scripts/mail-service-notification.sh ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/scripts)
|
||||
install_if_not_exists(icinga2/zones.d/README ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/zones.d)
|
||||
install_if_not_exists(logrotate.d/icinga2 ${CMAKE_INSTALL_SYSCONFDIR}/logrotate.d)
|
||||
|
||||
install(CODE "file(MAKE_DIRECTORY \"\$ENV{DESTDIR}${CMAKE_INSTALL_FULL_SYSCONFDIR}/icinga2/pki\")")
|
||||
|
|
|
@ -65,6 +65,27 @@ static String LoadAppType(const String& typeSpec)
|
|||
return typeSpec.SubStr(index + 1);
|
||||
}
|
||||
|
||||
static void IncludeDirRecursive(const String& path)
|
||||
{
|
||||
Utility::GlobRecursive(path, "*.conf", &ConfigCompiler::CompileFile, GlobFile);
|
||||
}
|
||||
|
||||
static void IncludeNonLocalZone(const String& zonePath)
|
||||
{
|
||||
String etcPath = Application::GetZonesDir() + "/" + Utility::BaseName(zonePath);
|
||||
|
||||
#ifndef _WIN32
|
||||
struct stat statbuf;
|
||||
if (lstat(etcPath.CStr(), &statbuf) >= 0)
|
||||
#else /* _WIN32 */
|
||||
struct _stat statbuf;
|
||||
if (_stat(etcPath.CStr(), &statbuf) >= 0)
|
||||
#endif /* _WIN32 */
|
||||
return;
|
||||
|
||||
IncludeDirRecursive(zonePath);
|
||||
}
|
||||
|
||||
static bool LoadConfigFiles(const String& appType)
|
||||
{
|
||||
ConfigCompilerContext::GetInstance()->Reset();
|
||||
|
@ -75,6 +96,12 @@ static bool LoadConfigFiles(const String& appType)
|
|||
}
|
||||
}
|
||||
|
||||
IncludeDirRecursive(Application::GetZonesDir());
|
||||
Utility::Glob(Application::GetLocalStateDir() + "/lib/icinga2/api/zones/*", &IncludeNonLocalZone, GlobDirectory);
|
||||
|
||||
/* Load cluster config files - this should probably be in libremote but
|
||||
* unfortunately moving it there is somewhat non-trivial. */
|
||||
|
||||
String name, fragment;
|
||||
BOOST_FOREACH(boost::tie(name, fragment), ConfigFragmentRegistry::GetInstance()->GetItems()) {
|
||||
ConfigCompiler::CompileText(name, fragment);
|
||||
|
@ -265,6 +292,7 @@ int Main(void)
|
|||
}
|
||||
#endif /* _WIN32 */
|
||||
|
||||
Application::DeclareZonesDir(Application::GetSysconfDir() + "/icinga2/zones.d");
|
||||
Application::DeclareApplicationType("icinga/IcingaApplication");
|
||||
|
||||
po::options_description desc("Supported options");
|
||||
|
|
|
@ -790,6 +790,26 @@ String Application::GetLocalStateDir(void)
|
|||
return ScriptVariable::Get("LocalStateDir");
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the path of the zones dir.
|
||||
*
|
||||
* @param path The new path.
|
||||
*/
|
||||
void Application::DeclareZonesDir(const String& path)
|
||||
{
|
||||
ScriptVariable::Set("ZonesDir", path, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the path for the local state dir.
|
||||
*
|
||||
* @returns The path.
|
||||
*/
|
||||
String Application::GetZonesDir(void)
|
||||
{
|
||||
return ScriptVariable::Get("ZonesDir");
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the path for the local state dir.
|
||||
*
|
||||
|
|
|
@ -79,6 +79,9 @@ public:
|
|||
static String GetSysconfDir(void);
|
||||
static void DeclareSysconfDir(const String& path);
|
||||
|
||||
static String GetZonesDir(void);
|
||||
static void DeclareZonesDir(const String& path);
|
||||
|
||||
static String GetLocalStateDir(void);
|
||||
static void DeclareLocalStateDir(const String& path);
|
||||
|
||||
|
|
|
@ -22,9 +22,9 @@ mkclass_target(zone.ti zone.th)
|
|||
mkembedconfig_target(remote-type.conf remote-type.cpp)
|
||||
|
||||
add_library(remote SHARED
|
||||
apiclient.cpp apifunction.cpp apilistener.cpp apilistener.th authority.cpp
|
||||
endpoint.cpp endpoint.th jsonrpc.cpp messageorigin.cpp remote-type.cpp
|
||||
zone.cpp zone.th
|
||||
apiclient.cpp apifunction.cpp apilistener.cpp apilistener-sync.cpp
|
||||
apilistener.th authority.cpp endpoint.cpp endpoint.th jsonrpc.cpp
|
||||
messageorigin.cpp remote-type.cpp zone.cpp zone.th
|
||||
)
|
||||
|
||||
include_directories(${Boost_INCLUDE_DIRS})
|
||||
|
@ -46,4 +46,6 @@ install(
|
|||
#install(CODE "file(MAKE_DIRECTORY \"\$ENV{DESTDIR}${CMAKE_INSTALL_FULL_LOCALSTATEDIR}/lib/icinga2/api\")")
|
||||
install(CODE "file(MAKE_DIRECTORY \"\$ENV{DESTDIR}${CMAKE_INSTALL_FULL_LOCALSTATEDIR}/lib/icinga2/api/log\")")
|
||||
install(CODE "file(MAKE_DIRECTORY \"\$ENV{DESTDIR}${CMAKE_INSTALL_FULL_LOCALSTATEDIR}/lib/icinga2/api/repository\")")
|
||||
install(CODE "file(MAKE_DIRECTORY \"\$ENV{DESTDIR}${CMAKE_INSTALL_FULL_LOCALSTATEDIR}/lib/icinga2/api/zones\")")
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
/******************************************************************************
|
||||
* Icinga 2 *
|
||||
* Copyright (C) 2012-2014 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 "remote/apilistener.h"
|
||||
#include "base/dynamictype.h"
|
||||
#include "base/logger_fwd.h"
|
||||
#include <boost/foreach.hpp>
|
||||
#include <fstream>
|
||||
|
||||
using namespace icinga;
|
||||
|
||||
bool ApiListener::IsConfigMaster(const Zone::Ptr& zone) const
|
||||
{
|
||||
String path = Application::GetZonesDir() + "/" + zone->GetName();
|
||||
|
||||
#ifndef _WIN32
|
||||
struct stat statbuf;
|
||||
return (lstat(path.CStr(), &statbuf) >= 0);
|
||||
#else /* _WIN32 */
|
||||
struct _stat statbuf;
|
||||
return (_stat(path.CStr(), &statbuf) >= 0);
|
||||
#endif /* _WIN32 */
|
||||
}
|
||||
|
||||
void ApiListener::ConfigGlobHandler(const Dictionary::Ptr& config, const String& path, const String& file)
|
||||
{
|
||||
CONTEXT("Creating config update for file '" + file + "'");
|
||||
|
||||
std::ifstream fp(file.CStr());
|
||||
if (!fp)
|
||||
return;
|
||||
|
||||
String content((std::istreambuf_iterator<char>(fp)), std::istreambuf_iterator<char>());
|
||||
config->Set(file.SubStr(path.GetLength()), content);
|
||||
}
|
||||
|
||||
void ApiListener::SyncZoneDir(const Zone::Ptr& zone) const
|
||||
{
|
||||
Log(LogInformation, "remote", "Syncing zone: " + zone->GetName());
|
||||
|
||||
String dirNew = Application::GetZonesDir() + "/" + zone->GetName();
|
||||
String dirOld = Application::GetLocalStateDir() + "/lib/icinga2/api/zones/" + zone->GetName();
|
||||
|
||||
#ifndef _WIN32
|
||||
if (mkdir(dirOld.CStr(), 0700) < 0 && errno != EEXIST) {
|
||||
#else /*_ WIN32 */
|
||||
if (mkdir(dirOld.CStr()) < 0 && errno != EEXIST) {
|
||||
#endif /* _WIN32 */
|
||||
BOOST_THROW_EXCEPTION(posix_error()
|
||||
<< boost::errinfo_api_function("mkdir")
|
||||
<< boost::errinfo_errno(errno)
|
||||
<< boost::errinfo_file_name(dirOld));
|
||||
}
|
||||
|
||||
Dictionary::Ptr configNew = make_shared<Dictionary>();
|
||||
Utility::GlobRecursive(dirNew, "*.conf", boost::bind(&ApiListener::ConfigGlobHandler, configNew, dirNew, _1), GlobFile);
|
||||
|
||||
Dictionary::Ptr configOld = make_shared<Dictionary>();
|
||||
Utility::GlobRecursive(dirOld, "*.conf", boost::bind(&ApiListener::ConfigGlobHandler, configOld, dirOld, _1), GlobFile);
|
||||
|
||||
BOOST_FOREACH(const Dictionary::Pair& kv, configNew) {
|
||||
if (configOld->Get(kv.first) != kv.second) {
|
||||
String path = dirOld + "/" + kv.first;
|
||||
Log(LogInformation, "remote", "Updating configuration file: " + path);
|
||||
|
||||
std::ofstream fp(path.CStr(), std::ofstream::out | std::ostream::trunc);
|
||||
fp << kv.second;
|
||||
fp.close();
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_FOREACH(const Dictionary::Pair& kv, configOld) {
|
||||
if (!configNew->Contains(kv.first)) {
|
||||
String path = dirOld + "/" + kv.first;
|
||||
(void) unlink(path.CStr());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ApiListener::SyncZoneDirs(void) const
|
||||
{
|
||||
BOOST_FOREACH(const Zone::Ptr& zone, DynamicType::GetObjects<Zone>()) {
|
||||
if (!IsConfigMaster(zone))
|
||||
continue;
|
||||
|
||||
SyncZoneDir(zone);
|
||||
}
|
||||
|
||||
bool configChange = false;
|
||||
|
||||
// TODO: remove configuration files for zones which don't exist anymore (i.e. don't have a Zone object)
|
||||
|
||||
if (configChange) {
|
||||
Log(LogInformation, "remote", "Restarting after configuration change.");
|
||||
Application::RequestRestart();
|
||||
}
|
||||
}
|
|
@ -53,6 +53,8 @@ void ApiListener::OnConfigLoaded(void)
|
|||
|
||||
if (!Endpoint::GetByName(GetIdentity()))
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error("Endpoint object for '" + GetIdentity() + "' is missing."));
|
||||
|
||||
SyncZoneDirs();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -100,6 +100,12 @@ private:
|
|||
void CloseLogFile(void);
|
||||
static void LogGlobHandler(std::vector<int>& files, const String& file);
|
||||
void ReplayLog(const ApiClient::Ptr& client);
|
||||
|
||||
void SyncZoneDirs(void) const;
|
||||
void SyncZoneDir(const Zone::Ptr& zone) const;
|
||||
bool IsConfigMaster(const Zone::Ptr& zone) const;
|
||||
static void ConfigGlobHandler(const Dictionary::Ptr& config, const String& path, const String& file);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "base/dynamicobject.h"
|
||||
#include "base/application.h"
|
||||
|
||||
namespace icinga
|
||||
{
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
%attribute %string "crl_path",
|
||||
|
||||
%attribute %string "bind_host",
|
||||
%attribute %string "bind_port"
|
||||
%attribute %string "bind_port",
|
||||
}
|
||||
|
||||
%type Endpoint {
|
||||
|
|
Loading…
Reference in New Issue