using namespace icinga;
-String NodeUtility::GetRepositoryPath(void)
-{
- return Application::GetLocalStateDir() + "/lib/icinga2/api/repository";
-}
-
-String NodeUtility::GetNodeRepositoryFile(const String& name)
-{
- return GetRepositoryPath() + "/" + SHA256(name) + ".repo";
-}
-
-String NodeUtility::GetNodeSettingsFile(const String& name)
-{
- return GetRepositoryPath() + "/" + SHA256(name) + ".settings";
-}
-
-void NodeUtility::CreateRepositoryPath(const String& path)
-{
- if (!Utility::PathExists(path))
- Utility::MkDirP(path, 0750);
-
- String user = ScriptGlobal::Get("RunAsUser");
- String group = ScriptGlobal::Get("RunAsGroup");
-
- if (!Utility::SetFileOwnership(path, user, group)) {
- Log(LogWarning, "cli")
- << "Cannot set ownership for user '" << user << "' group '" << group << "' on path '" << path << "'. Verify it yourself!";
- }
-}
-
-std::vector<String> NodeUtility::GetNodeCompletionSuggestions(const String& word)
-{
- std::vector<String> suggestions;
-
- for (const Dictionary::Ptr& node : GetNodes()) {
- String node_name = node->Get("endpoint");
-
- if (node_name.Find(word) == 0)
- suggestions.push_back(node_name);
- }
-
- return suggestions;
-}
-
-void NodeUtility::PrintNodes(std::ostream& fp)
-{
- bool first = true;
-
- for (const Dictionary::Ptr& node : GetNodes()) {
- if (first)
- first = false;
- else
- fp << "\n";
-
- fp << "Node '"
- << ConsoleColorTag(Console_ForegroundBlue | Console_Bold) << node->Get("endpoint") << ConsoleColorTag(Console_Normal)
- << "' (";
-
- Dictionary::Ptr settings = node->Get("settings");
-
- if (settings) {
- String host = settings->Get("host");
- String port = settings->Get("port");
- double log_duration = settings->Get("log_duration");
-
- if (!host.IsEmpty() && !port.IsEmpty())
- fp << "host: " << host << ", port: " << port << ", ";
-
- fp << "log duration: " << Utility::FormatDuration(log_duration) << ", ";
- }
-
- fp << "last seen: " << Utility::FormatDateTime("%c", node->Get("seen")) << ")\n";
-
- PrintNodeRepository(fp, node->Get("repository"));
- }
-}
-
-void NodeUtility::PrintNodeRepository(std::ostream& fp, const Dictionary::Ptr& repository)
-{
- if (!repository)
- return;
-
- ObjectLock olock(repository);
- for (const Dictionary::Pair& kv : repository) {
- fp << std::setw(4) << " "
- << "* Host '" << ConsoleColorTag(Console_ForegroundGreen | Console_Bold) << kv.first << ConsoleColorTag(Console_Normal) << "'\n";
-
- Array::Ptr services = kv.second;
- ObjectLock xlock(services);
- for (const String& service : services) {
- fp << std::setw(8) << " " << "* Service '" << ConsoleColorTag(Console_ForegroundGreen | Console_Bold) << service << ConsoleColorTag(Console_Normal) << "'\n";
- }
- }
-}
-
-void NodeUtility::PrintNodesJson(std::ostream& fp)
-{
- Dictionary::Ptr result = new Dictionary();
-
- for (const Dictionary::Ptr& node : GetNodes()) {
- result->Set(node->Get("endpoint"), node);
- }
-
- fp << JsonEncode(result);
-}
-
-void NodeUtility::AddNode(const String& name)
-{
- String path = GetNodeRepositoryFile(name);
-
- if (Utility::PathExists(path) ) {
- Log(LogInformation, "cli")
- << "Node '" << name << "' exists already.";
- }
-
- Dictionary::Ptr node = new Dictionary();
-
- node->Set("seen", Utility::GetTime());
- node->Set("endpoint", name);
- node->Set("zone", name);
- node->Set("repository", Empty);
-
- CreateRepositoryPath();
- Utility::SaveJsonFile(path, 0600, node);
-}
-
-void NodeUtility::AddNodeSettings(const String& name, const String& host,
- const String& port, double log_duration)
-{
- Dictionary::Ptr settings = new Dictionary();
-
- settings->Set("host", host);
- settings->Set("port", port);
- settings->Set("log_duration", log_duration);
-
- CreateRepositoryPath();
- Utility::SaveJsonFile(GetNodeSettingsFile(name), 0600, settings);
-}
-
-void NodeUtility::RemoveNode(const String& name)
-{
- String repoPath = GetNodeRepositoryFile(name);
-
- if (!Utility::PathExists(repoPath))
- return;
-
- if (unlink(repoPath.CStr()) < 0) {
- Log(LogCritical, "cli")
- << "Cannot remove file '" << repoPath
- << "'. Failed with error code " << errno << ", \"" << Utility::FormatErrorNumber(errno) + "\".";
- BOOST_THROW_EXCEPTION(posix_error()
- << boost::errinfo_api_function("unlink")
- << boost::errinfo_errno(errno)
- << boost::errinfo_file_name(repoPath));
- }
-
- String settingsPath = GetNodeSettingsFile(name);
-
- if (Utility::PathExists(settingsPath)) {
- if (unlink(settingsPath.CStr()) < 0) {
- Log(LogCritical, "cli")
- << "Cannot remove file '" << settingsPath
- << "'. Failed with error code " << errno << ", \"" << Utility::FormatErrorNumber(errno) + "\".";
- BOOST_THROW_EXCEPTION(posix_error()
- << boost::errinfo_api_function("unlink")
- << boost::errinfo_errno(errno)
- << boost::errinfo_file_name(settingsPath));
- }
- }
-}
-
-std::vector<Dictionary::Ptr> NodeUtility::GetNodes(void)
-{
- std::vector<Dictionary::Ptr> nodes;
-
- Utility::Glob(GetRepositoryPath() + "/*.repo",
- boost::bind(&NodeUtility::CollectNodes, _1, boost::ref(nodes)), GlobFile);
-
- return nodes;
-}
-
-Dictionary::Ptr NodeUtility::LoadNodeFile(const String& node_file)
-{
- Dictionary::Ptr node = Utility::LoadJsonFile(node_file);
-
- if (!node)
- return Dictionary::Ptr();
-
- String settingsFile = GetNodeSettingsFile(node->Get("endpoint"));
-
- if (Utility::PathExists(settingsFile))
- node->Set("settings", Utility::LoadJsonFile(settingsFile));
- else
- node->Remove("settings");
-
- return node;
-}
-
-void NodeUtility::CollectNodes(const String& node_file, std::vector<Dictionary::Ptr>& nodes)
-{
- Dictionary::Ptr node;
-
- try {
- node = LoadNodeFile(node_file);
- } catch (const std::exception&) {
- return;
- }
-
- if (!node)
- return;
-
- nodes.push_back(node);
-}
-
/*
* Node Setup helpers
*/
return true;
}
-/*
- * Black/Whitelist helpers
- */
-String NodeUtility::GetBlackAndWhiteListPath(const String& type)
-{
- return NodeUtility::GetRepositoryPath() + "/" + type + ".list";
-}
-
-Array::Ptr NodeUtility::GetBlackAndWhiteList(const String& type)
-{
- String list_path = GetBlackAndWhiteListPath(type);
-
- Array::Ptr lists = new Array();
-
- if (Utility::PathExists(list_path)) {
- lists = Utility::LoadJsonFile(list_path);
- }
-
- return lists;
-}
-
-int NodeUtility::UpdateBlackAndWhiteList(const String& type, const String& zone_filter, const String& host_filter, const String& service_filter)
-{
- Array::Ptr lists = GetBlackAndWhiteList(type);
-
- {
- ObjectLock olock(lists);
-
- for (const Dictionary::Ptr& filter : lists) {
-
- if (filter->Get("zone") == zone_filter) {
- if (filter->Get("host") == host_filter && service_filter.IsEmpty()) {
- Log(LogWarning, "cli")
- << "Found zone filter '" << zone_filter << "' with host filter '" << host_filter << "'. Bailing out.";
- return 1;
- } else if (filter->Get("host") == host_filter && filter->Get("service") == service_filter) {
- Log(LogWarning, "cli")
- << "Found zone filter '" << zone_filter << "' with host filter '" << host_filter << "' and service filter '"
- << service_filter << "'. Bailing out.";
- return 1;
- }
- }
- }
- }
-
- Dictionary::Ptr new_filter = new Dictionary();
-
- new_filter->Set("zone", zone_filter);
- new_filter->Set("host", host_filter);
- new_filter->Set("service", service_filter);
-
- lists->Add(new_filter);
-
- String list_path = GetBlackAndWhiteListPath(type);
- CreateRepositoryPath();
- Utility::SaveJsonFile(list_path, 0600, lists);
-
- return 0;
-}
-
-int NodeUtility::RemoveBlackAndWhiteList(const String& type, const String& zone_filter, const String& host_filter, const String& service_filter)
-{
- Array::Ptr lists = GetBlackAndWhiteList(type);
-
- std::vector<int> remove_filters;
- int remove_idx = 0;
- {
- ObjectLock olock(lists);
-
- for (const Dictionary::Ptr& filter : lists) {
-
- if (filter->Get("zone") == zone_filter) {
- if (filter->Get("host") == host_filter && service_filter.IsEmpty()) {
- Log(LogInformation, "cli")
- << "Found zone filter '" << zone_filter << "' with host filter '" << host_filter << "'. Removing from " << type << ".";
- remove_filters.push_back(remove_idx);
- } else if (filter->Get("host") == host_filter && filter->Get("service") == service_filter) {
- Log(LogInformation, "cli")
- << "Found zone filter '" << zone_filter << "' with host filter '" << host_filter << "' and service filter '"
- << service_filter << "'. Removing from " << type << ".";
- remove_filters.push_back(remove_idx);
- }
- }
-
- remove_idx++;
- }
- }
-
- /* if there are no matches for reomval, throw an error */
- if (remove_filters.empty()) {
- Log(LogCritical, "cli", "Cannot remove filter!");
- return 1;
- }
-
- for (int remove : remove_filters) {
- lists->Remove(remove);
- }
-
- String list_path = GetBlackAndWhiteListPath(type);
- CreateRepositoryPath();
- Utility::SaveJsonFile(list_path, 0600, lists);
-
- return 0;
-}
-
-int NodeUtility::PrintBlackAndWhiteList(std::ostream& fp, const String& type)
-{
- Array::Ptr lists = GetBlackAndWhiteList(type);
-
- if (lists->GetLength() == 0)
- return 0;
-
- fp << "Listing all " << type << " entries:\n";
-
- ObjectLock olock(lists);
- for (const Dictionary::Ptr& filter : lists) {
- fp << type << " filter for Node: '" << filter->Get("zone") << "' Host: '"
- << filter->Get("host") << "' Service: '" << filter->Get("service") << "'.\n";
- }
-
- return 0;
-}
-
-bool NodeUtility::CheckAgainstBlackAndWhiteList(const String& type, const String& zone, const String& host, const String& service)
-{
- Array::Ptr lists = GetBlackAndWhiteList(type);
-
- Log(LogNotice, "cli")
- << "Checking object against " << type << ".";
-
- ObjectLock olock(lists);
- for (const Dictionary::Ptr& filter : lists) {
- String zone_filter = filter->Get("zone");
- String host_filter = filter->Get("host");
- String service_filter;
-
- if (filter->Contains("service"))
- service_filter = filter->Get("service");
-
- Log(LogNotice, "cli")
- << "Checking Node '" << zone << "' =~ '" << zone_filter << "', host '" << host << "' =~ '" << host_filter
- << "', service '" << service << "' =~ '" << service_filter << "'.";
-
- if (Utility::Match(zone_filter, zone)) {
- Log(LogNotice, "cli")
- << "Node '" << zone << "' matches filter '" << zone_filter << "'";
-
- if (Utility::Match(host_filter, host)) {
- Log(LogNotice, "cli")
- << "Host '" << host << "' matches filter '" << host_filter << "'";
-
- /* no service filter means host match */
- if (service_filter.IsEmpty())
- return true;
-
- if (Utility::Match(service_filter, service)) {
- Log(LogNotice, "cli")
- << "Host '" << service << "' matches filter '" << service_filter << "'";
- return true;
- }
- }
- }
- }
-
- return false;
-}
/*
* We generally don't overwrite files without backup before