diff options
author | Ed Tanous <edtanous@google.com> | 2021-10-19 22:20:45 +0300 |
---|---|---|
committer | Ed Tanous <edtanous@google.com> | 2021-10-19 22:44:03 +0300 |
commit | 3fafa370cca70187fbfc897267919209766a170b (patch) | |
tree | b68aa4a61f631e916d3fd5836194d8be970f45ac | |
parent | 27ea7db1c2a40bdb3402a9ffda335d2876f604fb (diff) | |
download | bmcweb-3fafa370cca70187fbfc897267919209766a170b.tar.xz |
Revert "Redfish: Support Host Log Entries"
This commit appears to cause 500 errors on systems that don't have
host-logger installed. Reverting for now to get the codebase back to
stable; To the author, please fix the error and resubmit.
The bump that failed is here:
https://gerrit.openbmc-project.xyz/c/openbmc/openbmc/+/47933
This reverts commit bf888502a247d8374c70e7ceddc9862bf0ad88bd.
Change-Id: I346178f079245f96e2c1e03720490dcbcf19427b
Signed-off-by: Ed Tanous <edtanous@google.com>
-rw-r--r-- | meson.build | 1 | ||||
-rw-r--r-- | meson_options.txt | 1 | ||||
-rw-r--r-- | redfish-core/include/gzfile.hpp | 178 | ||||
-rw-r--r-- | redfish-core/include/redfish.hpp | 6 | ||||
-rw-r--r-- | redfish-core/lib/log_services.hpp | 223 |
5 files changed, 0 insertions, 409 deletions
diff --git a/meson.build b/meson.build index 0bcf3661fb..76731129fe 100644 --- a/meson.build +++ b/meson.build @@ -77,7 +77,6 @@ feature_map = { 'redfish' : '-DBMCWEB_ENABLE_REDFISH', 'redfish-bmc-journal' : '-DBMCWEB_ENABLE_REDFISH_BMC_JOURNAL', 'redfish-cpu-log' : '-DBMCWEB_ENABLE_REDFISH_CPU_LOG', - 'redfish-host-logger' : '-DBMCWEB_ENABLE_REDFISH_HOST_LOGGER', 'redfish-dbus-log' : '-DBMCWEB_ENABLE_REDFISH_DBUS_LOG_ENTRIES', 'redfish-provisioning-feature' : '-DBMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE', 'redfish-dump-log' : '-DBMCWEB_ENABLE_REDFISH_DUMP_LOG', diff --git a/meson_options.txt b/meson_options.txt index 6c0f6434c4..ada1957e8b 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -19,7 +19,6 @@ option('redfish-bmc-journal', type : 'feature', value : 'disabled', description option('redfish-cpu-log', type : 'feature', value : 'disabled', description : '''Enable CPU log service transactions through Redfish. Paths are under \'/redfish/v1/Systems/system/LogServices/Crashdump'.''') option('redfish-dump-log', type : 'feature', value : 'disabled', description : 'Enable Dump log service transactions through Redfish. Paths are under \'/redfish/v1/Systems/system/LogServices/Dump\'and \'/redfish/v1/Managers/bmc/LogServices/Dump\'') option('redfish-dbus-log', type : 'feature', value : 'disabled', description : 'Enable DBUS log service transactions through Redfish. Paths are under \'/redfish/v1/Systems/system/LogServices/EventLog/Entries\'') -option('redfish-host-logger', type : 'feature', value : 'enabled', description : 'Enable host log service transactions based on phosphor-hostlogger through Redfish. Paths are under \'/redfish/v1/Systems/system/LogServices/HostLogger\'') option('redfish-provisioning-feature', type : 'feature', value : 'disabled', description : 'Enable provisioning feature support in redfish. Paths are under \'/redfish/v1/Systems/system/\'') option('bmcweb-logging', type : 'feature', value : 'disabled', description : 'Enable output the extended debug logs') option('basic-auth', type : 'feature', value : 'enabled', description : '''Enable basic authentication''') diff --git a/redfish-core/include/gzfile.hpp b/redfish-core/include/gzfile.hpp deleted file mode 100644 index 9f1b5dbdfe..0000000000 --- a/redfish-core/include/gzfile.hpp +++ /dev/null @@ -1,178 +0,0 @@ -#pragma once - -#include <zlib.h> - -#include <array> -#include <filesystem> -#include <vector> - -class GzFileReader -{ - public: - bool gzGetLines(std::vector<std::string>& logEntries, - const std::string& filename) - { - gzFile logStream = gzopen(filename.c_str(), "r"); - if (!logStream) - { - BMCWEB_LOG_ERROR << "Can't open gz file: " << filename << '\n'; - return false; - } - - std::string wholeFile; - if (!readFile(wholeFile, logStream)) - { - gzclose(logStream); - return false; - } - std::string newLastMessage; - std::vector<std::string> parseLogs = - hostLogEntryParser(wholeFile, newLastMessage); - - // If file doesn't contain any "\r" or "\n", parseLogs should be empty. - if (parseLogs.empty()) - { - lastMessage.insert(lastMessage.end(), - std::make_move_iterator(newLastMessage.begin()), - std::make_move_iterator(newLastMessage.end())); - } - else - { - if (!lastMessage.empty()) - { - parseLogs.front() = lastMessage + parseLogs.front(); - lastMessage.clear(); - } - if (!newLastMessage.empty()) - { - lastMessage = std::move(newLastMessage); - } - logEntries.insert(logEntries.end(), - std::make_move_iterator(parseLogs.begin()), - std::make_move_iterator(parseLogs.end())); - } - gzclose(logStream); - return true; - } - - std::string getLastMessage() - { - return lastMessage; - } - - private: - std::string lastMessage; - std::string lastDelimiter; - size_t totalFilesSize = 0; - - void printErrorMessage(gzFile logStream) - { - int errNum = 0; - const char* errMsg = gzerror(logStream, &errNum); - - BMCWEB_LOG_ERROR << "Error reading gz compressed data.\n" - << "Error Message: " << errMsg << '\n' - << "Error Number: " << errNum; - } - - bool readFile(std::string& wholeFile, gzFile logStream) - { - // Assume we have 8 files, and the max size of each file is - // 16k, so define the max size as 256kb (double of 8 files * - // 16kb) - constexpr size_t maxTotalFilesSize = 262144; - constexpr int bufferLimitSize = 1024; - do - { - std::string bufferStr; - bufferStr.resize(bufferLimitSize); - - int bytesRead = gzread(logStream, bufferStr.data(), - static_cast<unsigned int>(bufferStr.size())); - // On errors, gzread() shall return a value less than 0. - if (bytesRead < 0) - { - printErrorMessage(logStream); - return false; - } - bufferStr.resize(static_cast<size_t>(bytesRead)); - totalFilesSize += bufferStr.size(); - if (totalFilesSize > maxTotalFilesSize) - { - BMCWEB_LOG_ERROR << "File size exceeds maximum allowed size of " - << maxTotalFilesSize; - return false; - } - wholeFile.insert(wholeFile.end(), - std::make_move_iterator(bufferStr.begin()), - std::make_move_iterator(bufferStr.end())); - } while (!gzeof(logStream)); - - return true; - } - - std::vector<std::string> hostLogEntryParser(const std::string& wholeFile, - std::string& newLastMessage) - { - std::vector<std::string> logEntries; - - // It may contain several log entry in one line, and - // the end of each log entry will be '\r\n' or '\r'. - // So we need to go through and split string by '\n' and '\r' - size_t pos = wholeFile.find_first_of("\n\r"); - size_t initialPos = 0; - - while (pos != std::string::npos) - { - std::string logEntry = - wholeFile.substr(initialPos, pos - initialPos); - // Since there might be consecutive delimiters like "\r\n", we need - // to filter empty strings. - if (!logEntry.empty()) - { - logEntries.push_back(logEntry); - } - else - { - // Handle consecutive delimiter. '\r\n' act as a single - // delimiter, the other case like '\n\n', '\n\r' or '\r\r' will - // push back a "\n" as a log. - std::string delimiters; - if (pos > 0) - { - delimiters = wholeFile.substr(pos - 1, 2); - } - // Handle consecutive delimiter but spilt between two files. - if (pos == 0 && !(lastDelimiter.empty())) - { - delimiters = lastDelimiter + wholeFile.substr(0, 1); - } - if (delimiters != "\r\n") - { - logEntries.emplace_back("\n"); - } - } - initialPos = pos + 1; - pos = wholeFile.find_first_of("\n\r", initialPos); - } - - // Store the last message - if (initialPos < wholeFile.size()) - { - newLastMessage = wholeFile.substr(initialPos); - } - // If consecutive delimiter spilt by file, the last character of the - // file must be the delimiter. - else if (initialPos == wholeFile.size()) - { - lastDelimiter = wholeFile.substr(initialPos - 1, 1); - } - return logEntries; - } - - public: - GzFileReader() = default; - ~GzFileReader() = default; - GzFileReader(const GzFileReader&) = delete; - GzFileReader& operator=(const GzFileReader&) = delete; -}; diff --git a/redfish-core/include/redfish.hpp b/redfish-core/include/redfish.hpp index 247933232e..0a97150433 100644 --- a/redfish-core/include/redfish.hpp +++ b/redfish-core/include/redfish.hpp @@ -161,12 +161,6 @@ class RedfishService requestRoutesDBusEventLogEntryDownload(app); #endif -#ifdef BMCWEB_ENABLE_REDFISH_HOST_LOGGER - requestRoutesSystemHostLogger(app); - requestRoutesSystemHostLoggerCollection(app); - requestRoutesSystemHostLoggerLogEntry(app); -#endif - requestRoutesMessageRegistryFileCollection(app); requestRoutesMessageRegistryFile(app); requestRoutesMessageRegistry(app); diff --git a/redfish-core/lib/log_services.hpp b/redfish-core/lib/log_services.hpp index 065a4d1a79..2c9ae3a9ce 100644 --- a/redfish-core/lib/log_services.hpp +++ b/redfish-core/lib/log_services.hpp @@ -15,9 +15,7 @@ */ #pragma once -#include "gzfile.hpp" #include "http_utility.hpp" -#include "human_sort.hpp" #include "registries.hpp" #include "registries/base_message_registry.hpp" #include "registries/openbmc_message_registry.hpp" @@ -977,12 +975,6 @@ inline void requestRoutesSystemLogServiceCollection(App& app) {{"@odata.id", "/redfish/v1/Systems/system/LogServices/Crashdump"}}); #endif - -#ifdef BMCWEB_ENABLE_REDFISH_HOST_LOGGER - logServiceArray.push_back( - {{"@odata.id", - "/redfish/v1/Systems/system/LogServices/HostLogger"}}); -#endif asyncResp->res.jsonValue["Members@odata.count"] = logServiceArray.size(); @@ -1825,221 +1817,6 @@ inline void requestRoutesDBusEventLogEntryDownload(App& app) }); } -constexpr const char* hostLoggerFolderPath = "/var/log/console"; -inline bool - getHostLoggerFiles(const std::string& hostLoggerFilePath, - std::vector<std::filesystem::path>& hostLoggerFiles) -{ - std::error_code ec; - std::filesystem::directory_iterator logPath(hostLoggerFilePath, ec); - if (ec) - { - BMCWEB_LOG_ERROR << ec.message(); - return false; - } - for (const std::filesystem::directory_entry& it : logPath) - { - std::string filename = it.path().filename(); - // Prefix of each log files is "log". Find the file and save the - // path - if (boost::starts_with(filename, "log")) - { - hostLoggerFiles.emplace_back(it.path()); - } - } - // As the log files rotate, they are appended with a ".#" that is higher for - // the older logs. Since we start from oldest logs, sort the name in - // descending order. - std::sort(hostLoggerFiles.rbegin(), hostLoggerFiles.rend(), - AlphanumLess<std::string>()); - - return true; -} - -inline bool - getHostLoggerEntries(std::vector<std::filesystem::path>& hostLoggerFiles, - std::vector<std::string>& logEntries) -{ - GzFileReader logFile; - - // Go though all log files and expose host log into logEntries - for (const std::filesystem::path& it : hostLoggerFiles) - { - if (!logFile.gzGetLines(logEntries, it.string())) - { - BMCWEB_LOG_ERROR << "fail to expose host logs"; - return false; - } - } - // Get lastMessage from constructor by getter - std::string lastMessage = logFile.getLastMessage(); - if (!lastMessage.empty()) - { - logEntries.push_back(lastMessage); - } - return true; -} - -inline void fillHostLoggerEntryJson(const std::string& logEntryID, - const std::string& msg, - nlohmann::json& logEntryJson) -{ - // Fill in the log entry with the gathered data. - logEntryJson = { - {"@odata.type", "#LogEntry.v1_4_0.LogEntry"}, - {"@odata.id", - "/redfish/v1/Systems/system/LogServices/HostLogger/Entries/" + - logEntryID}, - {"Name", "Host Logger Entry"}, - {"Id", logEntryID}, - {"Message", msg}, - {"EntryType", "Oem"}, - {"Severity", "OK"}, - {"OemRecordFormat", "Host Logger Entry"}}; -} - -inline void requestRoutesSystemHostLogger(App& app) -{ - BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/LogServices/HostLogger/") - .privileges(redfish::privileges::getLogService) - .methods(boost::beast::http::verb::get)( - [](const crow::Request&, - const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { - asyncResp->res.jsonValue["@odata.id"] = - "/redfish/v1/Systems/system/LogServices/HostLogger"; - asyncResp->res.jsonValue["@odata.type"] = - "#LogService.v1_1_0.LogService"; - asyncResp->res.jsonValue["Name"] = "Host Logger Service"; - asyncResp->res.jsonValue["Description"] = "Host Logger Service"; - asyncResp->res.jsonValue["Id"] = "HostLogger"; - asyncResp->res.jsonValue["Entries"] = { - {"@odata.id", "/redfish/v1/Systems/system/LogServices/" - "HostLogger/Entries"}}; - }); -} - -inline void requestRoutesSystemHostLoggerCollection(App& app) -{ - BMCWEB_ROUTE(app, - "/redfish/v1/Systems/system/LogServices/HostLogger/Entries/") - .privileges(redfish::privileges::getLogEntry) - .methods(boost::beast::http::verb::get)( - [](const crow::Request& req, - const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { - uint64_t skip = 0; - uint64_t top = maxEntriesPerPage; // Show max 1000 entries by - // default, allow range 1 to - // 1000 entries per page. - if (!getSkipParam(asyncResp, req, skip)) - { - return; - } - if (!getTopParam(asyncResp, req, top)) - { - return; - } - asyncResp->res.jsonValue["@odata.id"] = - "/redfish/v1/Systems/system/LogServices/HostLogger/Entries"; - asyncResp->res.jsonValue["@odata.type"] = - "#LogEntryCollection.LogEntryCollection"; - asyncResp->res.jsonValue["Name"] = "HostLogger Entries"; - asyncResp->res.jsonValue["Description"] = - "Collection of HostLogger Entries"; - nlohmann::json& logEntryArray = - asyncResp->res.jsonValue["Members"]; - logEntryArray = nlohmann::json::array(); - - std::vector<std::filesystem::path> hostLoggerFiles; - if (!getHostLoggerFiles(hostLoggerFolderPath, hostLoggerFiles)) - { - BMCWEB_LOG_ERROR << "fail to get host log file path"; - messages::internalError(asyncResp->res); - return; - } - - std::vector<std::string> logEntries; - if (!getHostLoggerEntries(hostLoggerFiles, logEntries)) - { - messages::internalError(asyncResp->res); - return; - } - - for (uint64_t id = skip; - id < std::min<uint64_t>(skip + top, logEntries.size()); - id++) - { - logEntryArray.push_back({}); - nlohmann::json& hostLogEntry = logEntryArray.back(); - fillHostLoggerEntryJson(std::to_string(id), - logEntries[static_cast<size_t>(id)], - hostLogEntry); - } - - asyncResp->res.jsonValue["Members@odata.count"] = - logEntries.size(); - if (skip + top < logEntries.size()) - { - asyncResp->res.jsonValue["Members@odata.nextLink"] = - "/redfish/v1/Systems/system/LogServices/HostLogger/" - "Entries?skip=" + - std::to_string(skip + top); - } - }); -} - -inline void requestRoutesSystemHostLoggerLogEntry(App& app) -{ - BMCWEB_ROUTE( - app, "/redfish/v1/Systems/system/LogServices/HostLogger/Entries/<str>/") - .privileges(redfish::privileges::getLogEntry) - .methods(boost::beast::http::verb::get)( - [](const crow::Request&, - const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, - const std::string& param) { - const std::string& targetID = param; - - std::vector<std::filesystem::path> hostLoggerFiles; - if (!getHostLoggerFiles(hostLoggerFolderPath, hostLoggerFiles)) - { - BMCWEB_LOG_ERROR << "fail to get host log file path"; - messages::internalError(asyncResp->res); - return; - } - - std::vector<std::string> logEntries; - if (!getHostLoggerEntries(hostLoggerFiles, logEntries)) - { - messages::internalError(asyncResp->res); - return; - } - - uint64_t idInt = 0; - auto [ptr, ec] = std::from_chars( - targetID.data(), targetID.data() + targetID.size(), idInt); - if (ec == std::errc::invalid_argument) - { - messages::resourceMissingAtURI(asyncResp->res, targetID); - return; - } - if (ec == std::errc::result_out_of_range) - { - messages::resourceMissingAtURI(asyncResp->res, targetID); - return; - } - - if (idInt < logEntries.size()) - { - fillHostLoggerEntryJson( - targetID, logEntries[static_cast<size_t>(idInt)], - asyncResp->res.jsonValue); - return; - } - - // Requested ID was not found - messages::resourceMissingAtURI(asyncResp->res, targetID); - }); -} - inline void requestRoutesBMCLogServiceCollection(App& app) { BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/LogServices/") |