static void IncludeNonLocalZone(const String& zonePath, const String& package, bool& success)
{
- String etcPath = Application::GetZonesDir() + "/" + Utility::BaseName(zonePath);
+ /* Note: This include function must not call RegisterZoneDir().
+ * We do not need to copy it for cluster config sync. */
- if (Utility::PathExists(etcPath) || Utility::PathExists(zonePath + "/.authoritative"))
+ String zoneName = Utility::BaseName(zonePath);
+
+ /* Check whether this node already has an authoritative config version
+ * from zones.d in etc or api package directory, or a local marker file)
+ */
+ if (ConfigCompiler::HasZoneConfigAuthority(zoneName) || Utility::PathExists(zonePath + "/.authoritative")) {
+ Log(LogWarning, "config")
+ << "Ignoring non local config include for zone '" << zoneName << "': We already have an authoritative copy included.";
return;
+ }
- IncludeZoneDirRecursive(zonePath, package, success);
+ std::vector<Expression *> expressions;
+ Utility::GlobRecursive(zonePath, "*.conf", boost::bind(&ConfigCompiler::CollectIncludes, boost::ref(expressions), _1, zoneName, package), GlobFile);
+ DictExpression expr(expressions);
+ if (!ExecuteExpression(&expr))
+ success = false;
}
static void IncludePackage(const String& packagePath, bool& success)
{
+ /* Note: Package includes will register their zones
+ * for config sync inside their generated config. */
String packageName = Utility::BaseName(packagePath);
-
+
if (Utility::PathExists(packagePath + "/include.conf")) {
Expression *expr = ConfigCompiler::CompileFile(packagePath + "/include.conf",
String(), packageName);
-
+
if (!ExecuteExpression(expr))
success = false;
-
+
delete expr;
}
}
}
}
- /* Load cluster config files - this should probably be in libremote but
- * unfortunately moving it there is somewhat non-trivial. */
+ /* Load cluster config files from /etc/icinga2/zones.d.
+ * This should probably be in libremote but
+ * unfortunately moving it there is somewhat non-trivial. */
success = true;
String zonesEtcDir = Application::GetZonesDir();
if (!success)
return false;
- String zonesVarDir = Application::GetLocalStateDir() + "/lib/icinga2/api/zones";
- if (Utility::PathExists(zonesVarDir))
- Utility::Glob(zonesVarDir + "/*", boost::bind(&IncludeNonLocalZone, _1, "_cluster", boost::ref(success)), GlobDirectory);
+ /* Load package config files - they may contain additional zones which
+ * are authoritative on this node and are checked in HasZoneConfigAuthority(). */
+ String packagesVarDir = Application::GetLocalStateDir() + "/lib/icinga2/api/packages";
+ if (Utility::PathExists(packagesVarDir))
+ Utility::Glob(packagesVarDir + "/*", boost::bind(&IncludePackage, _1, boost::ref(success)), GlobDirectory);
if (!success)
return false;
- String packagesVarDir = Application::GetLocalStateDir() + "/lib/icinga2/api/packages";
- if (Utility::PathExists(packagesVarDir))
- Utility::Glob(packagesVarDir + "/*", boost::bind(&IncludePackage, _1, boost::ref(success)), GlobDirectory);
+ /* Load cluster synchronized configuration files */
+ String zonesVarDir = Application::GetLocalStateDir() + "/lib/icinga2/api/zones";
+ if (Utility::PathExists(zonesVarDir))
+ Utility::Glob(zonesVarDir + "/*", boost::bind(&IncludeNonLocalZone, _1, "_cluster", boost::ref(success)), GlobDirectory);
if (!success)
return false;
REGISTER_APIFUNCTION(Update, config, &ApiListener::ConfigUpdateHandler);
-bool ApiListener::IsConfigMaster(const Zone::Ptr& zone)
-{
- std::vector<ZoneFragment> zoneDirs = ConfigCompiler::GetZoneDirs(zone->GetName());
-
- std::vector<String> paths;
- BOOST_FOREACH(const ZoneFragment& zf, zoneDirs) {
- paths.push_back(zf.Path);
- }
-
- Log(LogNotice, "ApiListener")
- << "Registered config directories for zone '" << zone->GetName() << "': " << Utility::NaturalJoin(paths);
-
- return zoneDirs.size() > 0;
-}
-
void ApiListener::ConfigGlobHandler(Dictionary::Ptr& config, const String& path, const String& file)
{
CONTEXT("Creating config update for file '" + file + "'");
}
}
+ if (newConfig->GetLength() == 0)
+ return;
+
String oldDir = Application::GetLocalStateDir() + "/lib/icinga2/api/zones/" + zone->GetName();
Log(LogInformation, "ApiListener")
- << "Copying zone configuration files for zone '" << zone->GetName() << "' to '" << oldDir << "'.";
+ << "Copying " << newConfig->GetLength() << " zone configuration files for zone '" << zone->GetName() << "' to '" << oldDir << "'.";
Utility::MkDir(oldDir, 0700);
void ApiListener::SyncZoneDirs(void) const
{
BOOST_FOREACH(const Zone::Ptr& zone, ConfigType::GetObjectsByType<Zone>()) {
- if (!IsConfigMaster(zone)) {
- Log(LogWarning, "ApiListener")
- << "Not syncing config update for zone '" << zone->GetName() << "' because we do not have an authoritative version of the zone's config.";
- continue;
- }
-
try {
SyncZoneDir(zone);
} catch (const std::exception&) {
continue;
}
- if (IsConfigMaster(zone)) {
+ if (ConfigCompiler::HasZoneConfigAuthority(kv.first)) {
Log(LogWarning, "ApiListener")
<< "Ignoring config update for zone '" << kv.first << "' because we have an authoritative version of the zone's config.";
continue;