summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEd Tanous <edtanous@google.com>2021-10-19 22:20:45 +0300
committerEd Tanous <edtanous@google.com>2021-10-19 22:44:03 +0300
commit3fafa370cca70187fbfc897267919209766a170b (patch)
treeb68aa4a61f631e916d3fd5836194d8be970f45ac
parent27ea7db1c2a40bdb3402a9ffda335d2876f604fb (diff)
downloadbmcweb-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.build1
-rw-r--r--meson_options.txt1
-rw-r--r--redfish-core/include/gzfile.hpp178
-rw-r--r--redfish-core/include/redfish.hpp6
-rw-r--r--redfish-core/lib/log_services.hpp223
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/")