DaemonUtility#ValidateConfigFiles(): re-try unknown zones once they may have become known

refs #7530
This commit is contained in:
Alexander A. Klimov 2019-09-27 17:17:11 +02:00
parent f0fcfdf910
commit eacdb3dac7

View File

@ -8,6 +8,7 @@
#include "config/configcompiler.hpp" #include "config/configcompiler.hpp"
#include "config/configcompilercontext.hpp" #include "config/configcompilercontext.hpp"
#include "config/configitembuilder.hpp" #include "config/configitembuilder.hpp"
#include <set>
using namespace icinga; using namespace icinga;
@ -27,7 +28,7 @@ static bool ExecuteExpression(Expression *expression)
return true; return true;
} }
static void IncludeZoneDirRecursive(const String& path, const String& package, bool& success) static bool IncludeZoneDirRecursive(const String& path, const String& package, bool& success)
{ {
String zoneName = Utility::BaseName(path); String zoneName = Utility::BaseName(path);
@ -35,9 +36,7 @@ static void IncludeZoneDirRecursive(const String& path, const String& package, b
* to not include this specific synced zones directory. * to not include this specific synced zones directory.
*/ */
if(!ConfigItem::GetByTypeAndName(Type::GetByName("Zone"), zoneName)) { if(!ConfigItem::GetByTypeAndName(Type::GetByName("Zone"), zoneName)) {
Log(LogWarning, "config") return false;
<< "Ignoring directory '" << path << "' for unknown zone '" << zoneName << "'.";
return;
} }
/* register this zone path for cluster config sync */ /* register this zone path for cluster config sync */
@ -48,9 +47,11 @@ static void IncludeZoneDirRecursive(const String& path, const String& package, b
DictExpression expr(std::move(expressions)); DictExpression expr(std::move(expressions));
if (!ExecuteExpression(&expr)) if (!ExecuteExpression(&expr))
success = false; success = false;
return true;
} }
static void IncludeNonLocalZone(const String& zonePath, const String& package, bool& success) static bool IncludeNonLocalZone(const String& zonePath, const String& package, bool& success)
{ {
/* Note: This include function must not call RegisterZoneDir(). /* Note: This include function must not call RegisterZoneDir().
* We do not need to copy it for cluster config sync. */ * We do not need to copy it for cluster config sync. */
@ -61,9 +62,7 @@ static void IncludeNonLocalZone(const String& zonePath, const String& package, b
* to not include this specific synced zones directory. * to not include this specific synced zones directory.
*/ */
if(!ConfigItem::GetByTypeAndName(Type::GetByName("Zone"), zoneName)) { if(!ConfigItem::GetByTypeAndName(Type::GetByName("Zone"), zoneName)) {
Log(LogWarning, "config") return false;
<< "Ignoring directory '" << zonePath << "' for unknown zone '" << zoneName << "'.";
return;
} }
/* Check whether this node already has an authoritative config version /* Check whether this node already has an authoritative config version
@ -72,7 +71,7 @@ static void IncludeNonLocalZone(const String& zonePath, const String& package, b
if (ConfigCompiler::HasZoneConfigAuthority(zoneName) || Utility::PathExists(zonePath + "/.authoritative")) { if (ConfigCompiler::HasZoneConfigAuthority(zoneName) || Utility::PathExists(zonePath + "/.authoritative")) {
Log(LogNotice, "config") Log(LogNotice, "config")
<< "Ignoring non local config include for zone '" << zoneName << "': We already have an authoritative copy included."; << "Ignoring non local config include for zone '" << zoneName << "': We already have an authoritative copy included.";
return; return true;
} }
std::vector<std::unique_ptr<Expression> > expressions; std::vector<std::unique_ptr<Expression> > expressions;
@ -80,6 +79,8 @@ static void IncludeNonLocalZone(const String& zonePath, const String& package, b
DictExpression expr(std::move(expressions)); DictExpression expr(std::move(expressions));
if (!ExecuteExpression(&expr)) if (!ExecuteExpression(&expr))
success = false; success = false;
return true;
} }
static void IncludePackage(const String& packagePath, bool& success) static void IncludePackage(const String& packagePath, bool& success)
@ -129,8 +130,29 @@ bool DaemonUtility::ValidateConfigFiles(const std::vector<std::string>& configs,
/* Only load zone directory if we're not in staging validation. */ /* Only load zone directory if we're not in staging validation. */
if (!systemNS->Contains("ZonesStageVarDir")) { if (!systemNS->Contains("ZonesStageVarDir")) {
String zonesEtcDir = Configuration::ZonesDir; String zonesEtcDir = Configuration::ZonesDir;
if (!zonesEtcDir.IsEmpty() && Utility::PathExists(zonesEtcDir)) if (!zonesEtcDir.IsEmpty() && Utility::PathExists(zonesEtcDir)) {
Utility::Glob(zonesEtcDir + "/*", std::bind(&IncludeZoneDirRecursive, _1, "_etc", std::ref(success)), GlobDirectory); std::set<String> zoneEtcDirs;
Utility::Glob(zonesEtcDir + "/*", [&zoneEtcDirs](const String& zoneEtcDir) { zoneEtcDirs.emplace(zoneEtcDir); }, GlobDirectory);
bool hasSuccess = true;
while (!zoneEtcDirs.empty() && hasSuccess) {
hasSuccess = false;
for (auto& zoneEtcDir : zoneEtcDirs) {
if (IncludeZoneDirRecursive(zoneEtcDir, "_etc", success)) {
zoneEtcDirs.erase(zoneEtcDir);
hasSuccess = true;
break;
}
}
}
for (auto& zoneEtcDir : zoneEtcDirs) {
Log(LogWarning, "config")
<< "Ignoring directory '" << zoneEtcDir << "' for unknown zone '" << Utility::BaseName(zoneEtcDir) << "'.";
}
}
if (!success) if (!success)
return false; return false;
@ -157,8 +179,29 @@ bool DaemonUtility::ValidateConfigFiles(const std::vector<std::string>& configs,
} }
if (Utility::PathExists(zonesVarDir)) if (Utility::PathExists(zonesVarDir)) {
Utility::Glob(zonesVarDir + "/*", std::bind(&IncludeNonLocalZone, _1, "_cluster", std::ref(success)), GlobDirectory); std::set<String> zoneVarDirs;
Utility::Glob(zonesVarDir + "/*", [&zoneVarDirs](const String& zoneVarDir) { zoneVarDirs.emplace(zoneVarDir); }, GlobDirectory);
bool hasSuccess = true;
while (!zoneVarDirs.empty() && hasSuccess) {
hasSuccess = false;
for (auto& zoneVarDir : zoneVarDirs) {
if (IncludeNonLocalZone(zoneVarDir, "_cluster", success)) {
zoneVarDirs.erase(zoneVarDir);
hasSuccess = true;
break;
}
}
}
for (auto& zoneEtcDir : zoneVarDirs) {
Log(LogWarning, "config")
<< "Ignoring directory '" << zoneEtcDir << "' for unknown zone '" << Utility::BaseName(zoneEtcDir) << "'.";
}
}
if (!success) if (!success)
return false; return false;