summaryrefslogtreecommitdiff
path: root/redfish-core/lib/log_services.hpp
diff options
context:
space:
mode:
authorJohn Edward Broadbent <jebr@google.com>2021-04-09 01:57:16 +0300
committerEd Tanous <ed@tanous.net>2021-06-03 21:18:02 +0300
commit7e860f1550c8686eec42f7a75bc5f2ef51e756ad (patch)
tree989da47a8427bc1a60119f480e2523151b1433aa /redfish-core/lib/log_services.hpp
parenteb75770c6c4369984cb150ded4f5ace410ed24a9 (diff)
downloadbmcweb-7e860f1550c8686eec42f7a75bc5f2ef51e756ad.tar.xz
Remove Redfish Node class
Reduces the total number of lines and will allow for easier testing of the redfish responses. A main purpose of the node class was to set app.routeDynamic(). However now app.routeDynamic can handle the complexity that was once in critical to node. The macro app.routeDynamic() provides a shorter cleaner interface to the unerlying app.routeDyanic call. The old pattern set permissions for 6 interfaces (get, head, patch, put, delete_, and post) even if only one interface is created. That pattern creates unneeded code that can be safely removed with no effect. Unit test for the responses would have to mock the node the class in order to fully test responses. see https://github.com/openbmc/bmcweb/issues/181 The following files still need node to be extracted. virtual_media.hpp account_service.hpp redfish_sessions.hpp ethernet.hpp The files above use a pattern that is not trivial to address. Often their responses call an async lambda capturing the inherited class. ie (https://github.com/openbmc/bmcweb/blob/ffed87b5ad1797ca966d030e7f979770 28d258fa/redfish-core/lib/account_service.hpp#L1393) At a later point I plan to remove node from the files above. Tested: I ran the docker unit test with the following command. WORKSPACE=$(pwd) UNIT_TEST_PKG=bmcweb ./openbmc-build-scripts/run-unit-test-docker.sh I ran the validator and this change did not create any issues. python3 RedfishServiceValidator.py -c config.ini Signed-off-by: John Edward Broadbent <jebr@google.com> Signed-off-by: Ed Tanous <edtanous@google.com> Change-Id: I147a0289c52cb4198345b1ad9bfe6fdddf57f3df
Diffstat (limited to 'redfish-core/lib/log_services.hpp')
-rw-r--r--redfish-core/lib/log_services.hpp3516
1 files changed, 1555 insertions, 1961 deletions
diff --git a/redfish-core/lib/log_services.hpp b/redfish-core/lib/log_services.hpp
index efed76463b..b04d0f9bcd 100644
--- a/redfish-core/lib/log_services.hpp
+++ b/redfish-core/lib/log_services.hpp
@@ -15,7 +15,6 @@
*/
#pragma once
-#include "node.hpp"
#include "registries.hpp"
#include "registries/base_message_registry.hpp"
#include "registries/openbmc_message_registry.hpp"
@@ -24,6 +23,7 @@
#include <systemd/sd-journal.h>
#include <unistd.h>
+#include <app.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/beast/core/span.hpp>
@@ -129,9 +129,9 @@ inline std::string translateSeverityDbusToRedfish(const std::string& s)
return "";
}
-static int getJournalMetadata(sd_journal* journal,
- const std::string_view& field,
- std::string_view& contents)
+inline static int getJournalMetadata(sd_journal* journal,
+ const std::string_view& field,
+ std::string_view& contents)
{
const char* data = nullptr;
size_t length = 0;
@@ -149,9 +149,9 @@ static int getJournalMetadata(sd_journal* journal,
return ret;
}
-static int getJournalMetadata(sd_journal* journal,
- const std::string_view& field, const int& base,
- long int& contents)
+inline static int getJournalMetadata(sd_journal* journal,
+ const std::string_view& field,
+ const int& base, long int& contents)
{
int ret = 0;
std::string_view metadata;
@@ -165,7 +165,8 @@ static int getJournalMetadata(sd_journal* journal,
return ret;
}
-static bool getEntryTimestamp(sd_journal* journal, std::string& entryTimestamp)
+inline static bool getEntryTimestamp(sd_journal* journal,
+ std::string& entryTimestamp)
{
int ret = 0;
uint64_t timestamp = 0;
@@ -231,8 +232,8 @@ static bool getTopParam(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
return true;
}
-static bool getUniqueEntryID(sd_journal* journal, std::string& entryID,
- const bool firstEntry = true)
+inline static bool getUniqueEntryID(sd_journal* journal, std::string& entryID,
+ const bool firstEntry = true)
{
int ret = 0;
static uint64_t prevTs = 0;
@@ -311,7 +312,7 @@ static bool getUniqueEntryID(const std::string& logEntry, std::string& entryID,
return true;
}
-static bool
+inline static bool
getTimestampFromID(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::string& entryID, uint64_t& timestamp,
uint64_t& index)
@@ -864,7 +865,7 @@ inline void clearDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
dumpType});
}
-static void parseCrashdumpParameters(
+inline static void parseCrashdumpParameters(
const std::vector<std::pair<std::string, VariantType>>& params,
std::string& filename, std::string& timestamp, std::string& logfile)
{
@@ -901,171 +902,144 @@ static void parseCrashdumpParameters(
}
constexpr char const* postCodeIface = "xyz.openbmc_project.State.Boot.PostCode";
-class SystemLogServiceCollection : public Node
+inline void requestRoutesSystemLogServiceCollection(App& app)
{
- public:
- SystemLogServiceCollection(App& app) :
- Node(app, "/redfish/v1/Systems/system/LogServices/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
/**
* Functions triggers appropriate requests on DBus
*/
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
- // Collections don't include the static data added by SubRoute because
- // it has a duplicate entry for members
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogServiceCollection.LogServiceCollection";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Systems/system/LogServices";
- asyncResp->res.jsonValue["Name"] = "System Log Services Collection";
- asyncResp->res.jsonValue["Description"] =
- "Collection of LogServices for this Computer System";
- nlohmann::json& logServiceArray = asyncResp->res.jsonValue["Members"];
- logServiceArray = nlohmann::json::array();
- logServiceArray.push_back(
- {{"@odata.id", "/redfish/v1/Systems/system/LogServices/EventLog"}});
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/LogServices/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+
+ {
+ // Collections don't include the static data added by SubRoute
+ // because it has a duplicate entry for members
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogServiceCollection.LogServiceCollection";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Systems/system/LogServices";
+ asyncResp->res.jsonValue["Name"] =
+ "System Log Services Collection";
+ asyncResp->res.jsonValue["Description"] =
+ "Collection of LogServices for this Computer System";
+ nlohmann::json& logServiceArray =
+ asyncResp->res.jsonValue["Members"];
+ logServiceArray = nlohmann::json::array();
+ logServiceArray.push_back(
+ {{"@odata.id",
+ "/redfish/v1/Systems/system/LogServices/EventLog"}});
#ifdef BMCWEB_ENABLE_REDFISH_DUMP_LOG
- logServiceArray.push_back(
- {{"@odata.id", "/redfish/v1/Systems/system/LogServices/Dump"}});
+ logServiceArray.push_back(
+ {{"@odata.id",
+ "/redfish/v1/Systems/system/LogServices/Dump"}});
#endif
#ifdef BMCWEB_ENABLE_REDFISH_CPU_LOG
- logServiceArray.push_back(
- {{"@odata.id",
- "/redfish/v1/Systems/system/LogServices/Crashdump"}});
+ logServiceArray.push_back(
+ {{"@odata.id",
+ "/redfish/v1/Systems/system/LogServices/Crashdump"}});
#endif
- asyncResp->res.jsonValue["Members@odata.count"] =
- logServiceArray.size();
+ asyncResp->res.jsonValue["Members@odata.count"] =
+ logServiceArray.size();
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code ec,
- const std::vector<std::string>& subtreePath) {
- if (ec)
- {
- BMCWEB_LOG_ERROR << ec;
- return;
- }
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code ec,
+ const std::vector<std::string>& subtreePath) {
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR << ec;
+ return;
+ }
- for (auto& pathStr : subtreePath)
- {
- if (pathStr.find("PostCode") != std::string::npos)
- {
- nlohmann::json& logServiceArrayLocal =
- asyncResp->res.jsonValue["Members"];
- logServiceArrayLocal.push_back(
- {{"@odata.id", "/redfish/v1/Systems/system/"
- "LogServices/PostCodes"}});
- asyncResp->res.jsonValue["Members@odata.count"] =
- logServiceArrayLocal.size();
- return;
- }
- }
- },
- "xyz.openbmc_project.ObjectMapper",
- "/xyz/openbmc_project/object_mapper",
- "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "/", 0,
- std::array<const char*, 1>{postCodeIface});
- }
-};
+ for (auto& pathStr : subtreePath)
+ {
+ if (pathStr.find("PostCode") != std::string::npos)
+ {
+ nlohmann::json& logServiceArrayLocal =
+ asyncResp->res.jsonValue["Members"];
+ logServiceArrayLocal.push_back(
+ {{"@odata.id", "/redfish/v1/Systems/system/"
+ "LogServices/PostCodes"}});
+ asyncResp->res
+ .jsonValue["Members@odata.count"] =
+ logServiceArrayLocal.size();
+ return;
+ }
+ }
+ },
+ "xyz.openbmc_project.ObjectMapper",
+ "/xyz/openbmc_project/object_mapper",
+ "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "/",
+ 0, std::array<const char*, 1>{postCodeIface});
+ });
+}
-class EventLogService : public Node
+inline void requestRoutesEventLogService(App& app)
{
- public:
- EventLogService(App& app) :
- Node(app, "/redfish/v1/Systems/system/LogServices/EventLog/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Systems/system/LogServices/EventLog";
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogService.v1_1_0.LogService";
- asyncResp->res.jsonValue["Name"] = "Event Log Service";
- asyncResp->res.jsonValue["Description"] = "System Event Log Service";
- asyncResp->res.jsonValue["Id"] = "EventLog";
- asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull";
- asyncResp->res.jsonValue["Entries"] = {
- {"@odata.id",
- "/redfish/v1/Systems/system/LogServices/EventLog/Entries"}};
- asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"] = {
-
- {"target", "/redfish/v1/Systems/system/LogServices/EventLog/"
- "Actions/LogService.ClearLog"}};
- }
-};
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/LogServices/EventLog/")
+ .privileges({"Login"})
+ .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/EventLog";
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogService.v1_1_0.LogService";
+ asyncResp->res.jsonValue["Name"] = "Event Log Service";
+ asyncResp->res.jsonValue["Description"] =
+ "System Event Log Service";
+ asyncResp->res.jsonValue["Id"] = "EventLog";
+ asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull";
+ asyncResp->res.jsonValue["Entries"] = {
+ {"@odata.id",
+ "/redfish/v1/Systems/system/LogServices/EventLog/Entries"}};
+ asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"] = {
+
+ {"target", "/redfish/v1/Systems/system/LogServices/EventLog/"
+ "Actions/LogService.ClearLog"}};
+ });
+}
-class JournalEventLogClear : public Node
+inline void requestRoutesJournalEventLogClear(App& app)
{
- public:
- JournalEventLogClear(App& app) :
- Node(app, "/redfish/v1/Systems/system/LogServices/EventLog/Actions/"
- "LogService.ClearLog/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
-
- private:
- void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
-
- // Clear the EventLog by deleting the log files
- std::vector<std::filesystem::path> redfishLogFiles;
- if (getRedfishLogFiles(redfishLogFiles))
- {
- for (const std::filesystem::path& file : redfishLogFiles)
- {
- std::error_code ec;
- std::filesystem::remove(file, ec);
- }
- }
-
- // Reload rsyslog so it knows to start new log files
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code ec) {
- if (ec)
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/LogServices/EventLog/Actions/"
+ "LogService.ClearLog/")
+ .privileges({"ConfigureComponents"})
+ .methods(boost::beast::http::verb::post)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ // Clear the EventLog by deleting the log files
+ std::vector<std::filesystem::path> redfishLogFiles;
+ if (getRedfishLogFiles(redfishLogFiles))
{
- BMCWEB_LOG_ERROR << "Failed to reload rsyslog: " << ec;
- messages::internalError(asyncResp->res);
- return;
+ for (const std::filesystem::path& file : redfishLogFiles)
+ {
+ std::error_code ec;
+ std::filesystem::remove(file, ec);
+ }
}
- messages::success(asyncResp->res);
- },
- "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager", "ReloadUnit", "rsyslog.service",
- "replace");
- }
-};
+ // Reload rsyslog so it knows to start new log files
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code ec) {
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR << "Failed to reload rsyslog: "
+ << ec;
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ messages::success(asyncResp->res);
+ },
+ "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager", "ReloadUnit",
+ "rsyslog.service", "replace");
+ });
+}
static int fillEventLogEntryJson(const std::string& logEntryID,
const std::string& logEntry,
@@ -1164,800 +1138,718 @@ static int fillEventLogEntryJson(const std::string& logEntryID,
return 0;
}
-class JournalEventLogEntryCollection : public Node
+inline void requestRoutesJournalEventLogEntryCollection(App& app)
{
- public:
- JournalEventLogEntryCollection(App& app) :
- Node(app, "/redfish/v1/Systems/system/LogServices/EventLog/Entries/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>&) override
- {
- uint64_t skip = 0;
- uint64_t top = maxEntriesPerPage; // Show max entries by default
- if (!getSkipParam(asyncResp, req, skip))
- {
- return;
- }
- if (!getTopParam(asyncResp, req, top))
- {
- return;
- }
- // Collections don't include the static data added by SubRoute because
- // it has a duplicate entry for members
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogEntryCollection.LogEntryCollection";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Systems/system/LogServices/EventLog/Entries";
- asyncResp->res.jsonValue["Name"] = "System Event Log Entries";
- asyncResp->res.jsonValue["Description"] =
- "Collection of System Event Log Entries";
-
- nlohmann::json& logEntryArray = asyncResp->res.jsonValue["Members"];
- logEntryArray = nlohmann::json::array();
- // Go through the log files and create a unique ID for each entry
- std::vector<std::filesystem::path> redfishLogFiles;
- getRedfishLogFiles(redfishLogFiles);
- uint64_t entryCount = 0;
- std::string logEntry;
-
- // Oldest logs are in the last file, so start there and loop backwards
- for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend();
- it++)
- {
- std::ifstream logStream(*it);
- if (!logStream.is_open())
- {
- continue;
- }
-
- // Reset the unique ID on the first entry
- bool firstEntry = true;
- while (std::getline(logStream, logEntry))
- {
- entryCount++;
- // Handle paging using skip (number of entries to skip from the
- // start) and top (number of entries to display)
- if (entryCount <= skip || entryCount > skip + top)
- {
- continue;
- }
-
- std::string idStr;
- if (!getUniqueEntryID(logEntry, idStr, firstEntry))
+ BMCWEB_ROUTE(app,
+ "/redfish/v1/Systems/system/LogServices/EventLog/Entries/")
+ .privileges({"Login"})
+ .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 entries by default
+ if (!getSkipParam(asyncResp, req, skip))
{
- continue;
- }
-
- if (firstEntry)
- {
- firstEntry = false;
+ return;
}
-
- logEntryArray.push_back({});
- nlohmann::json& bmcLogEntry = logEntryArray.back();
- if (fillEventLogEntryJson(idStr, logEntry, bmcLogEntry) != 0)
+ if (!getTopParam(asyncResp, req, top))
{
- messages::internalError(asyncResp->res);
return;
}
- }
- }
- asyncResp->res.jsonValue["Members@odata.count"] = entryCount;
- if (skip + top < entryCount)
- {
- asyncResp->res.jsonValue["Members@odata.nextLink"] =
- "/redfish/v1/Systems/system/LogServices/EventLog/"
- "Entries?$skip=" +
- std::to_string(skip + top);
- }
- }
-};
-
-class JournalEventLogEntry : public Node
-{
- public:
- JournalEventLogEntry(App& app) :
- Node(app,
- "/redfish/v1/Systems/system/LogServices/EventLog/Entries/<str>/",
- std::string())
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
+ // Collections don't include the static data added by SubRoute
+ // because it has a duplicate entry for members
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogEntryCollection.LogEntryCollection";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Systems/system/LogServices/EventLog/Entries";
+ asyncResp->res.jsonValue["Name"] = "System Event Log Entries";
+ asyncResp->res.jsonValue["Description"] =
+ "Collection of System Event Log Entries";
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&,
- const std::vector<std::string>& params) override
- {
+ nlohmann::json& logEntryArray =
+ asyncResp->res.jsonValue["Members"];
+ logEntryArray = nlohmann::json::array();
+ // Go through the log files and create a unique ID for each
+ // entry
+ std::vector<std::filesystem::path> redfishLogFiles;
+ getRedfishLogFiles(redfishLogFiles);
+ uint64_t entryCount = 0;
+ std::string logEntry;
+
+ // Oldest logs are in the last file, so start there and loop
+ // backwards
+ for (auto it = redfishLogFiles.rbegin();
+ it < redfishLogFiles.rend(); it++)
+ {
+ std::ifstream logStream(*it);
+ if (!logStream.is_open())
+ {
+ continue;
+ }
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- const std::string& targetID = params[0];
+ // Reset the unique ID on the first entry
+ bool firstEntry = true;
+ while (std::getline(logStream, logEntry))
+ {
+ entryCount++;
+ // Handle paging using skip (number of entries to skip
+ // from the start) and top (number of entries to
+ // display)
+ if (entryCount <= skip || entryCount > skip + top)
+ {
+ continue;
+ }
- // Go through the log files and check the unique ID for each entry to
- // find the target entry
- std::vector<std::filesystem::path> redfishLogFiles;
- getRedfishLogFiles(redfishLogFiles);
- std::string logEntry;
+ std::string idStr;
+ if (!getUniqueEntryID(logEntry, idStr, firstEntry))
+ {
+ continue;
+ }
- // Oldest logs are in the last file, so start there and loop backwards
- for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend();
- it++)
- {
- std::ifstream logStream(*it);
- if (!logStream.is_open())
- {
- continue;
- }
+ if (firstEntry)
+ {
+ firstEntry = false;
+ }
- // Reset the unique ID on the first entry
- bool firstEntry = true;
- while (std::getline(logStream, logEntry))
- {
- std::string idStr;
- if (!getUniqueEntryID(logEntry, idStr, firstEntry))
- {
- continue;
+ logEntryArray.push_back({});
+ nlohmann::json& bmcLogEntry = logEntryArray.back();
+ if (fillEventLogEntryJson(idStr, logEntry,
+ bmcLogEntry) != 0)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ }
}
-
- if (firstEntry)
+ asyncResp->res.jsonValue["Members@odata.count"] = entryCount;
+ if (skip + top < entryCount)
{
- firstEntry = false;
+ asyncResp->res.jsonValue["Members@odata.nextLink"] =
+ "/redfish/v1/Systems/system/LogServices/EventLog/"
+ "Entries?$skip=" +
+ std::to_string(skip + top);
}
+ });
+}
- if (idStr == targetID)
+inline void requestRoutesJournalEventLogEntry(App& app)
+{
+ BMCWEB_ROUTE(
+ app, "/redfish/v1/Systems/system/LogServices/EventLog/Entries/<str>/")
+ .privileges({"Login"})
+ .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;
+
+ // Go through the log files and check the unique ID for each
+ // entry to find the target entry
+ std::vector<std::filesystem::path> redfishLogFiles;
+ getRedfishLogFiles(redfishLogFiles);
+ std::string logEntry;
+
+ // Oldest logs are in the last file, so start there and loop
+ // backwards
+ for (auto it = redfishLogFiles.rbegin();
+ it < redfishLogFiles.rend(); it++)
{
- if (fillEventLogEntryJson(idStr, logEntry,
- asyncResp->res.jsonValue) != 0)
+ std::ifstream logStream(*it);
+ if (!logStream.is_open())
{
- messages::internalError(asyncResp->res);
- return;
+ continue;
}
- return;
- }
- }
- }
- // Requested ID was not found
- messages::resourceMissingAtURI(asyncResp->res, targetID);
- }
-};
-class DBusEventLogEntryCollection : public Node
-{
- public:
- DBusEventLogEntryCollection(App& app) :
- Node(app, "/redfish/v1/Systems/system/LogServices/EventLog/Entries/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
+ // Reset the unique ID on the first entry
+ bool firstEntry = true;
+ while (std::getline(logStream, logEntry))
+ {
+ std::string idStr;
+ if (!getUniqueEntryID(logEntry, idStr, firstEntry))
+ {
+ continue;
+ }
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
+ if (firstEntry)
+ {
+ firstEntry = false;
+ }
- // Collections don't include the static data added by SubRoute because
- // it has a duplicate entry for members
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogEntryCollection.LogEntryCollection";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Systems/system/LogServices/EventLog/Entries";
- asyncResp->res.jsonValue["Name"] = "System Event Log Entries";
- asyncResp->res.jsonValue["Description"] =
- "Collection of System Event Log Entries";
-
- // DBus implementation of EventLog/Entries
- // Make call to Logging Service to find all log entry objects
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code ec,
- GetManagedObjectsType& resp) {
- if (ec)
- {
- // TODO Handle for specific error code
- BMCWEB_LOG_ERROR
- << "getLogEntriesIfaceData resp_handler got error "
- << ec;
- messages::internalError(asyncResp->res);
- return;
+ if (idStr == targetID)
+ {
+ if (fillEventLogEntryJson(
+ idStr, logEntry,
+ asyncResp->res.jsonValue) != 0)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ return;
+ }
+ }
}
- nlohmann::json& entriesArray =
- asyncResp->res.jsonValue["Members"];
- entriesArray = nlohmann::json::array();
- for (auto& objectPath : resp)
- {
- uint32_t* id = nullptr;
- std::time_t timestamp{};
- std::time_t updateTimestamp{};
- std::string* severity = nullptr;
- std::string* message = nullptr;
- std::string* filePath = nullptr;
- bool resolved = false;
- for (auto& interfaceMap : objectPath.second)
+ // Requested ID was not found
+ messages::resourceMissingAtURI(asyncResp->res, targetID);
+ });
+}
+
+inline void requestRoutesDBusEventLogEntryCollection(App& app)
+{
+ BMCWEB_ROUTE(app,
+ "/redfish/v1/Systems/system/LogServices/EventLog/Entries/")
+ .privileges({"Login"})
+ .methods(
+ boost::beast::http::verb::
+ get)([](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ // Collections don't include the static data added by SubRoute
+ // because it has a duplicate entry for members
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogEntryCollection.LogEntryCollection";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Systems/system/LogServices/EventLog/Entries";
+ asyncResp->res.jsonValue["Name"] = "System Event Log Entries";
+ asyncResp->res.jsonValue["Description"] =
+ "Collection of System Event Log Entries";
+
+ // DBus implementation of EventLog/Entries
+ // Make call to Logging Service to find all log entry objects
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code ec,
+ GetManagedObjectsType& resp) {
+ if (ec)
{
- if (interfaceMap.first ==
- "xyz.openbmc_project.Logging.Entry")
+ // TODO Handle for specific error code
+ BMCWEB_LOG_ERROR
+ << "getLogEntriesIfaceData resp_handler got error "
+ << ec;
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ nlohmann::json& entriesArray =
+ asyncResp->res.jsonValue["Members"];
+ entriesArray = nlohmann::json::array();
+ for (auto& objectPath : resp)
+ {
+ uint32_t* id = nullptr;
+ std::time_t timestamp{};
+ std::time_t updateTimestamp{};
+ std::string* severity = nullptr;
+ std::string* message = nullptr;
+ std::string* filePath = nullptr;
+ bool resolved = false;
+ for (auto& interfaceMap : objectPath.second)
{
- for (auto& propertyMap : interfaceMap.second)
+ if (interfaceMap.first ==
+ "xyz.openbmc_project.Logging.Entry")
{
- if (propertyMap.first == "Id")
- {
- id = std::get_if<uint32_t>(
- &propertyMap.second);
- }
- else if (propertyMap.first == "Timestamp")
+ for (auto& propertyMap : interfaceMap.second)
{
- const uint64_t* millisTimeStamp =
- std::get_if<uint64_t>(
+ if (propertyMap.first == "Id")
+ {
+ id = std::get_if<uint32_t>(
&propertyMap.second);
- if (millisTimeStamp != nullptr)
+ }
+ else if (propertyMap.first == "Timestamp")
{
- timestamp = crow::utility::getTimestamp(
- *millisTimeStamp);
+ const uint64_t* millisTimeStamp =
+ std::get_if<uint64_t>(
+ &propertyMap.second);
+ if (millisTimeStamp != nullptr)
+ {
+ timestamp =
+ crow::utility::getTimestamp(
+ *millisTimeStamp);
+ }
}
- }
- else if (propertyMap.first == "UpdateTimestamp")
- {
- const uint64_t* millisTimeStamp =
- std::get_if<uint64_t>(
+ else if (propertyMap.first ==
+ "UpdateTimestamp")
+ {
+ const uint64_t* millisTimeStamp =
+ std::get_if<uint64_t>(
+ &propertyMap.second);
+ if (millisTimeStamp != nullptr)
+ {
+ updateTimestamp =
+ crow::utility::getTimestamp(
+ *millisTimeStamp);
+ }
+ }
+ else if (propertyMap.first == "Severity")
+ {
+ severity = std::get_if<std::string>(
&propertyMap.second);
- if (millisTimeStamp != nullptr)
+ }
+ else if (propertyMap.first == "Message")
{
- updateTimestamp =
- crow::utility::getTimestamp(
- *millisTimeStamp);
+ message = std::get_if<std::string>(
+ &propertyMap.second);
+ }
+ else if (propertyMap.first == "Resolved")
+ {
+ bool* resolveptr = std::get_if<bool>(
+ &propertyMap.second);
+ if (resolveptr == nullptr)
+ {
+ messages::internalError(
+ asyncResp->res);
+ return;
+ }
+ resolved = *resolveptr;
}
}
- else if (propertyMap.first == "Severity")
- {
- severity = std::get_if<std::string>(
- &propertyMap.second);
- }
- else if (propertyMap.first == "Message")
+ if (id == nullptr || message == nullptr ||
+ severity == nullptr)
{
- message = std::get_if<std::string>(
- &propertyMap.second);
+ messages::internalError(asyncResp->res);
+ return;
}
- else if (propertyMap.first == "Resolved")
+ }
+ else if (interfaceMap.first ==
+ "xyz.openbmc_project.Common.FilePath")
+ {
+ for (auto& propertyMap : interfaceMap.second)
{
- bool* resolveptr =
- std::get_if<bool>(&propertyMap.second);
- if (resolveptr == nullptr)
+ if (propertyMap.first == "Path")
{
- messages::internalError(asyncResp->res);
- return;
+ filePath = std::get_if<std::string>(
+ &propertyMap.second);
}
- resolved = *resolveptr;
}
}
- if (id == nullptr || message == nullptr ||
- severity == nullptr)
- {
- messages::internalError(asyncResp->res);
- return;
- }
}
- else if (interfaceMap.first ==
- "xyz.openbmc_project.Common.FilePath")
+ // Object path without the
+ // xyz.openbmc_project.Logging.Entry interface, ignore
+ // and continue.
+ if (id == nullptr || message == nullptr ||
+ severity == nullptr)
{
- for (auto& propertyMap : interfaceMap.second)
- {
- if (propertyMap.first == "Path")
- {
- filePath = std::get_if<std::string>(
- &propertyMap.second);
- }
- }
+ continue;
+ }
+ entriesArray.push_back({});
+ nlohmann::json& thisEntry = entriesArray.back();
+ thisEntry["@odata.type"] = "#LogEntry.v1_8_0.LogEntry";
+ thisEntry["@odata.id"] =
+ "/redfish/v1/Systems/system/"
+ "LogServices/EventLog/Entries/" +
+ std::to_string(*id);
+ thisEntry["Name"] = "System Event Log Entry";
+ thisEntry["Id"] = std::to_string(*id);
+ thisEntry["Message"] = *message;
+ thisEntry["Resolved"] = resolved;
+ thisEntry["EntryType"] = "Event";
+ thisEntry["Severity"] =
+ translateSeverityDbusToRedfish(*severity);
+ thisEntry["Created"] =
+ crow::utility::getDateTime(timestamp);
+ thisEntry["Modified"] =
+ crow::utility::getDateTime(updateTimestamp);
+ if (filePath != nullptr)
+ {
+ thisEntry["AdditionalDataURI"] =
+ "/redfish/v1/Systems/system/LogServices/"
+ "EventLog/"
+ "Entries/" +
+ std::to_string(*id) + "/attachment";
}
}
- // Object path without the xyz.openbmc_project.Logging.Entry
- // interface, ignore and continue.
- if (id == nullptr || message == nullptr ||
- severity == nullptr)
- {
- continue;
- }
- entriesArray.push_back({});
- nlohmann::json& thisEntry = entriesArray.back();
- thisEntry["@odata.type"] = "#LogEntry.v1_8_0.LogEntry";
- thisEntry["@odata.id"] = "/redfish/v1/Systems/system/"
- "LogServices/EventLog/Entries/" +
- std::to_string(*id);
- thisEntry["Name"] = "System Event Log Entry";
- thisEntry["Id"] = std::to_string(*id);
- thisEntry["Message"] = *message;
- thisEntry["Resolved"] = resolved;
- thisEntry["EntryType"] = "Event";
- thisEntry["Severity"] =
- translateSeverityDbusToRedfish(*severity);
- thisEntry["Created"] =
- crow::utility::getDateTime(timestamp);
- thisEntry["Modified"] =
- crow::utility::getDateTime(updateTimestamp);
- if (filePath != nullptr)
- {
- thisEntry["AdditionalDataURI"] =
- "/redfish/v1/Systems/system/LogServices/EventLog/"
- "Entries/" +
- std::to_string(*id) + "/attachment";
- }
- }
- std::sort(entriesArray.begin(), entriesArray.end(),
- [](const nlohmann::json& left,
- const nlohmann::json& right) {
- return (left["Id"] <= right["Id"]);
- });
- asyncResp->res.jsonValue["Members@odata.count"] =
- entriesArray.size();
- },
- "xyz.openbmc_project.Logging", "/xyz/openbmc_project/logging",
- "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
- }
-};
+ std::sort(entriesArray.begin(), entriesArray.end(),
+ [](const nlohmann::json& left,
+ const nlohmann::json& right) {
+ return (left["Id"] <= right["Id"]);
+ });
+ asyncResp->res.jsonValue["Members@odata.count"] =
+ entriesArray.size();
+ },
+ "xyz.openbmc_project.Logging", "/xyz/openbmc_project/logging",
+ "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
+ });
+}
-class DBusEventLogEntry : public Node
+inline void requestRoutesDBusEventLogEntry(App& app)
{
- public:
- DBusEventLogEntry(App& app) :
- Node(app,
- "/redfish/v1/Systems/system/LogServices/EventLog/Entries/<str>/",
- std::string())
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
+ BMCWEB_ROUTE(
+ app, "/redfish/v1/Systems/system/LogServices/EventLog/Entries/<str>/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& param)
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&,
- const std::vector<std::string>& params) override
- {
-
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- std::string entryID = params[0];
- dbus::utility::escapePathForDbus(entryID);
-
- // DBus implementation of EventLog/Entries
- // Make call to Logging Service to find all log entry objects
- crow::connections::systemBus->async_method_call(
- [asyncResp, entryID](const boost::system::error_code ec,
- GetManagedPropertyType& resp) {
- if (ec.value() == EBADR)
- {
- messages::resourceNotFound(asyncResp->res, "EventLogEntry",
- entryID);
- return;
- }
- if (ec)
- {
- BMCWEB_LOG_ERROR
- << "EventLogEntry (DBus) resp_handler got error " << ec;
- messages::internalError(asyncResp->res);
- return;
- }
- uint32_t* id = nullptr;
- std::time_t timestamp{};
- std::time_t updateTimestamp{};
- std::string* severity = nullptr;
- std::string* message = nullptr;
- std::string* filePath = nullptr;
- bool resolved = false;
-
- for (auto& propertyMap : resp)
- {
- if (propertyMap.first == "Id")
- {
- id = std::get_if<uint32_t>(&propertyMap.second);
- }
- else if (propertyMap.first == "Timestamp")
- {
- const uint64_t* millisTimeStamp =
- std::get_if<uint64_t>(&propertyMap.second);
- if (millisTimeStamp != nullptr)
+ {
+ std::string entryID = param;
+ dbus::utility::escapePathForDbus(entryID);
+
+ // DBus implementation of EventLog/Entries
+ // Make call to Logging Service to find all log entry objects
+ crow::connections::systemBus->async_method_call(
+ [asyncResp, entryID](const boost::system::error_code ec,
+ GetManagedPropertyType& resp) {
+ if (ec.value() == EBADR)
{
- timestamp =
- crow::utility::getTimestamp(*millisTimeStamp);
+ messages::resourceNotFound(
+ asyncResp->res, "EventLogEntry", entryID);
+ return;
}
- }
- else if (propertyMap.first == "UpdateTimestamp")
- {
- const uint64_t* millisTimeStamp =
- std::get_if<uint64_t>(&propertyMap.second);
- if (millisTimeStamp != nullptr)
+ if (ec)
{
- updateTimestamp =
- crow::utility::getTimestamp(*millisTimeStamp);
+ BMCWEB_LOG_ERROR << "EventLogEntry (DBus) "
+ "resp_handler got error "
+ << ec;
+ messages::internalError(asyncResp->res);
+ return;
}
- }
- else if (propertyMap.first == "Severity")
- {
- severity =
- std::get_if<std::string>(&propertyMap.second);
- }
- else if (propertyMap.first == "Message")
- {
- message = std::get_if<std::string>(&propertyMap.second);
- }
- else if (propertyMap.first == "Resolved")
- {
- bool* resolveptr =
- std::get_if<bool>(&propertyMap.second);
- if (resolveptr == nullptr)
+ uint32_t* id = nullptr;
+ std::time_t timestamp{};
+ std::time_t updateTimestamp{};
+ std::string* severity = nullptr;
+ std::string* message = nullptr;
+ std::string* filePath = nullptr;
+ bool resolved = false;
+
+ for (auto& propertyMap : resp)
+ {
+ if (propertyMap.first == "Id")
+ {
+ id = std::get_if<uint32_t>(&propertyMap.second);
+ }
+ else if (propertyMap.first == "Timestamp")
+ {
+ const uint64_t* millisTimeStamp =
+ std::get_if<uint64_t>(&propertyMap.second);
+ if (millisTimeStamp != nullptr)
+ {
+ timestamp = crow::utility::getTimestamp(
+ *millisTimeStamp);
+ }
+ }
+ else if (propertyMap.first == "UpdateTimestamp")
+ {
+ const uint64_t* millisTimeStamp =
+ std::get_if<uint64_t>(&propertyMap.second);
+ if (millisTimeStamp != nullptr)
+ {
+ updateTimestamp =
+ crow::utility::getTimestamp(
+ *millisTimeStamp);
+ }
+ }
+ else if (propertyMap.first == "Severity")
+ {
+ severity = std::get_if<std::string>(
+ &propertyMap.second);
+ }
+ else if (propertyMap.first == "Message")
+ {
+ message = std::get_if<std::string>(
+ &propertyMap.second);
+ }
+ else if (propertyMap.first == "Resolved")
+ {
+ bool* resolveptr =
+ std::get_if<bool>(&propertyMap.second);
+ if (resolveptr == nullptr)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ resolved = *resolveptr;
+ }
+ else if (propertyMap.first == "Path")
+ {
+ filePath = std::get_if<std::string>(
+ &propertyMap.second);
+ }
+ }
+ if (id == nullptr || message == nullptr ||
+ severity == nullptr)
{
messages::internalError(asyncResp->res);
return;
}
- resolved = *resolveptr;
- }
- else if (propertyMap.first == "Path")
- {
- filePath =
- std::get_if<std::string>(&propertyMap.second);
- }
- }
- if (id == nullptr || message == nullptr || severity == nullptr)
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogEntry.v1_8_0.LogEntry";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Systems/system/LogServices/EventLog/"
+ "Entries/" +
+ std::to_string(*id);
+ asyncResp->res.jsonValue["Name"] =
+ "System Event Log Entry";
+ asyncResp->res.jsonValue["Id"] = std::to_string(*id);
+ asyncResp->res.jsonValue["Message"] = *message;
+ asyncResp->res.jsonValue["Resolved"] = resolved;
+ asyncResp->res.jsonValue["EntryType"] = "Event";
+ asyncResp->res.jsonValue["Severity"] =
+ translateSeverityDbusToRedfish(*severity);
+ asyncResp->res.jsonValue["Created"] =
+ crow::utility::getDateTime(timestamp);
+ asyncResp->res.jsonValue["Modified"] =
+ crow::utility::getDateTime(updateTimestamp);
+ if (filePath != nullptr)
+ {
+ asyncResp->res.jsonValue["AdditionalDataURI"] =
+ "/redfish/v1/Systems/system/LogServices/"
+ "EventLog/"
+ "attachment/" +
+ std::to_string(*id);
+ }
+ },
+ "xyz.openbmc_project.Logging",
+ "/xyz/openbmc_project/logging/entry/" + entryID,
+ "org.freedesktop.DBus.Properties", "GetAll", "");
+ });
+
+ BMCWEB_ROUTE(
+ app, "/redfish/v1/Systems/system/LogServices/EventLog/Entries/<str>/")
+ .privileges({"ConfigureManager"})
+ .methods(boost::beast::http::verb::patch)(
+ [](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& entryId) {
+ std::optional<bool> resolved;
+
+ if (!json_util::readJson(req, asyncResp->res, "Resolved",
+ resolved))
{
- messages::internalError(asyncResp->res);
return;
}
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogEntry.v1_8_0.LogEntry";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Systems/system/LogServices/EventLog/Entries/" +
- std::to_string(*id);
- asyncResp->res.jsonValue["Name"] = "System Event Log Entry";
- asyncResp->res.jsonValue["Id"] = std::to_string(*id);
- asyncResp->res.jsonValue["Message"] = *message;
- asyncResp->res.jsonValue["Resolved"] = resolved;
- asyncResp->res.jsonValue["EntryType"] = "Event";
- asyncResp->res.jsonValue["Severity"] =
- translateSeverityDbusToRedfish(*severity);
- asyncResp->res.jsonValue["Created"] =
- crow::utility::getDateTime(timestamp);
- asyncResp->res.jsonValue["Modified"] =
- crow::utility::getDateTime(updateTimestamp);
- if (filePath != nullptr)
- {
- asyncResp->res.jsonValue["AdditionalDataURI"] =
- "/redfish/v1/Systems/system/LogServices/EventLog/"
- "Entries/" +
- std::to_string(*id) + "/attachment";
- }
- },
- "xyz.openbmc_project.Logging",
- "/xyz/openbmc_project/logging/entry/" + entryID,
- "org.freedesktop.DBus.Properties", "GetAll", "");
- }
-
- void doPatch(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>& params) override
- {
+ BMCWEB_LOG_DEBUG << "Set Resolved";
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- std::string entryId = params[0];
+ crow::connections::systemBus->async_method_call(
+ [asyncResp, resolved,
+ entryId](const boost::system::error_code ec) {
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ },
+ "xyz.openbmc_project.Logging",
+ "/xyz/openbmc_project/logging/entry/" + entryId,
+ "org.freedesktop.DBus.Properties", "Set",
+ "xyz.openbmc_project.Logging.Entry", "Resolved",
+ std::variant<bool>(*resolved));
+ });
+
+ BMCWEB_ROUTE(
+ app, "/redfish/v1/Systems/system/LogServices/EventLog/Entries/<str>/")
+ .privileges({"ConfigureManager"})
+ .methods(boost::beast::http::verb::delete_)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& param)
- std::optional<bool> resolved;
+ {
+ BMCWEB_LOG_DEBUG << "Do delete single event entries.";
- if (!json_util::readJson(req, asyncResp->res, "Resolved", resolved))
- {
- return;
- }
+ std::string entryID = param;
- if (resolved)
- {
- BMCWEB_LOG_DEBUG << "Set Resolved";
+ dbus::utility::escapePathForDbus(entryID);
- crow::connections::systemBus->async_method_call(
- [asyncResp, resolved,
- entryId](const boost::system::error_code ec) {
+ // Process response from Logging service.
+ auto respHandler = [asyncResp, entryID](
+ const boost::system::error_code ec) {
+ BMCWEB_LOG_DEBUG
+ << "EventLogEntry (DBus) doDelete callback: Done";
if (ec)
{
- BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
- messages::internalError(asyncResp->res);
+ if (ec.value() == EBADR)
+ {
+ messages::resourceNotFound(asyncResp->res,
+ "LogEntry", entryID);
+ return;
+ }
+ // TODO Handle for specific error code
+ BMCWEB_LOG_ERROR << "EventLogEntry (DBus) doDelete "
+ "respHandler got error "
+ << ec;
+ asyncResp->res.result(
+ boost::beast::http::status::internal_server_error);
return;
}
- },
- "xyz.openbmc_project.Logging",
- "/xyz/openbmc_project/logging/entry/" + entryId,
- "org.freedesktop.DBus.Properties", "Set",
- "xyz.openbmc_project.Logging.Entry", "Resolved",
- std::variant<bool>(*resolved));
- }
- }
-
- void doDelete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&,
- const std::vector<std::string>& params) override
- {
-
- BMCWEB_LOG_DEBUG << "Do delete single event entries.";
-
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- std::string entryID = params[0];
- dbus::utility::escapePathForDbus(entryID);
+ asyncResp->res.result(boost::beast::http::status::ok);
+ };
- // Process response from Logging service.
- auto respHandler = [asyncResp,
- entryID](const boost::system::error_code ec) {
- BMCWEB_LOG_DEBUG << "EventLogEntry (DBus) doDelete callback: Done";
- if (ec)
- {
- if (ec.value() == EBADR)
- {
- messages::resourceNotFound(asyncResp->res, "LogEntry",
- entryID);
- return;
- }
- // TODO Handle for specific error code
- BMCWEB_LOG_ERROR
- << "EventLogEntry (DBus) doDelete respHandler got error "
- << ec;
- asyncResp->res.result(
- boost::beast::http::status::internal_server_error);
- return;
- }
-
- asyncResp->res.result(boost::beast::http::status::ok);
- };
-
- // Make call to Logging service to request Delete Log
- crow::connections::systemBus->async_method_call(
- respHandler, "xyz.openbmc_project.Logging",
- "/xyz/openbmc_project/logging/entry/" + entryID,
- "xyz.openbmc_project.Object.Delete", "Delete");
- }
-};
+ // Make call to Logging service to request Delete Log
+ crow::connections::systemBus->async_method_call(
+ respHandler, "xyz.openbmc_project.Logging",
+ "/xyz/openbmc_project/logging/entry/" + entryID,
+ "xyz.openbmc_project.Object.Delete", "Delete");
+ });
+}
-class DBusEventLogEntryDownload : public Node
+inline void requestRoutesDBusEventLogEntryDownload(App& app)
{
- public:
- DBusEventLogEntryDownload(App& app) :
- Node(app,
- "/redfish/v1/Systems/system/LogServices/EventLog/Entries/<str>/"
- "attachment",
- std::string())
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>& params) override
- {
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/LogServices/EventLog/Entries/"
+ "<str>/attachment")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& param)
- std::string_view acceptHeader = req.getHeaderValue("Accept");
- // The iterators in boost/http/rfc7230.hpp end the string if '/' is
- // found, so replace it with arbitrary character '|' which is not part
- // of the Accept header syntax.
- std::string acceptStr =
- boost::replace_all_copy(std::string(acceptHeader), "/", "|");
- boost::beast::http::ext_list acceptTypes{acceptStr};
- bool supported = false;
- for (const auto& type : acceptTypes)
- {
- if ((type.first == "*|*") ||
- (type.first == "application|octet-stream"))
{
- supported = true;
- break;
- }
- }
- if (!supported)
- {
- asyncResp->res.result(boost::beast::http::status::bad_request);
- return;
- }
-
- std::string entryID = params[0];
- dbus::utility::escapePathForDbus(entryID);
-
- crow::connections::systemBus->async_method_call(
- [asyncResp, entryID](const boost::system::error_code ec,
- const sdbusplus::message::unix_fd& unixfd) {
- if (ec.value() == EBADR)
+ std::string_view acceptHeader = req.getHeaderValue("Accept");
+ // The iterators in boost/http/rfc7230.hpp end the string if '/'
+ // is found, so replace it with arbitrary character '|' which is
+ // not part of the Accept header syntax.
+ std::string acceptStr = boost::replace_all_copy(
+ std::string(acceptHeader), "/", "|");
+ boost::beast::http::ext_list acceptTypes{acceptStr};
+ bool supported = false;
+ for (const auto& type : acceptTypes)
{
- messages::resourceNotFound(asyncResp->res,
- "EventLogAttachment", entryID);
- return;
+ if ((type.first == "*|*") ||
+ (type.first == "application|octet-stream"))
+ {
+ supported = true;
+ break;
+ }
}
- if (ec)
+ if (!supported)
{
- BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
- messages::internalError(asyncResp->res);
+ asyncResp->res.result(
+ boost::beast::http::status::bad_request);
return;
}
- int fd = -1;
- fd = dup(unixfd);
- if (fd == -1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
+ std::string entryID = param;
+ dbus::utility::escapePathForDbus(entryID);
- long long int size = lseek(fd, 0, SEEK_END);
- if (size == -1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
+ crow::connections::systemBus->async_method_call(
+ [asyncResp,
+ entryID](const boost::system::error_code ec,
+ const sdbusplus::message::unix_fd& unixfd) {
+ if (ec.value() == EBADR)
+ {
+ messages::resourceNotFound(
+ asyncResp->res, "EventLogAttachment", entryID);
+ return;
+ }
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
+ messages::internalError(asyncResp->res);
+ return;
+ }
- // Arbitrary max size of 64kb
- constexpr int maxFileSize = 65536;
- if (size > maxFileSize)
- {
- BMCWEB_LOG_ERROR
- << "File size exceeds maximum allowed size of "
- << maxFileSize;
- messages::internalError(asyncResp->res);
- return;
- }
- std::vector<char> data(static_cast<size_t>(size));
- long long int rc = lseek(fd, 0, SEEK_SET);
- if (rc == -1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- rc = read(fd, data.data(), data.size());
- if ((rc == -1) || (rc != size))
- {
- messages::internalError(asyncResp->res);
- return;
- }
- close(fd);
-
- std::string_view strData(data.data(), data.size());
- std::string output = crow::utility::base64encode(strData);
-
- asyncResp->res.addHeader("Content-Type",
- "application/octet-stream");
- asyncResp->res.addHeader("Content-Transfer-Encoding", "Base64");
- asyncResp->res.body() = std::move(output);
- },
- "xyz.openbmc_project.Logging",
- "/xyz/openbmc_project/logging/entry/" + entryID,
- "xyz.openbmc_project.Logging.Entry", "GetEntry");
- }
-};
+ int fd = -1;
+ fd = dup(unixfd);
+ if (fd == -1)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
-class BMCLogServiceCollection : public Node
-{
- public:
- BMCLogServiceCollection(App& app) :
- Node(app, "/redfish/v1/Managers/bmc/LogServices/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
+ long long int size = lseek(fd, 0, SEEK_END);
+ if (size == -1)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
- private:
- /**
- * Functions triggers appropriate requests on DBus
- */
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
+ // Arbitrary max size of 64kb
+ constexpr int maxFileSize = 65536;
+ if (size > maxFileSize)
+ {
+ BMCWEB_LOG_ERROR
+ << "File size exceeds maximum allowed size of "
+ << maxFileSize;
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ std::vector<char> data(static_cast<size_t>(size));
+ long long int rc = lseek(fd, 0, SEEK_SET);
+ if (rc == -1)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ rc = read(fd, data.data(), data.size());
+ if ((rc == -1) || (rc != size))
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ close(fd);
+
+ std::string_view strData(data.data(), data.size());
+ std::string output =
+ crow::utility::base64encode(strData);
+
+ asyncResp->res.addHeader("Content-Type",
+ "application/octet-stream");
+ asyncResp->res.addHeader("Content-Transfer-Encoding",
+ "Base64");
+ asyncResp->res.body() = std::move(output);
+ },
+ "xyz.openbmc_project.Logging",
+ "/xyz/openbmc_project/logging/entry/" + entryID,
+ "xyz.openbmc_project.Logging.Entry", "GetEntry");
+ });
+}
- // Collections don't include the static data added by SubRoute because
- // it has a duplicate entry for members
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogServiceCollection.LogServiceCollection";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Managers/bmc/LogServices";
- asyncResp->res.jsonValue["Name"] = "Open BMC Log Services Collection";
- asyncResp->res.jsonValue["Description"] =
- "Collection of LogServices for this Manager";
- nlohmann::json& logServiceArray = asyncResp->res.jsonValue["Members"];
- logServiceArray = nlohmann::json::array();
+inline void requestRoutesBMCLogServiceCollection(App& app)
+{
+ BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/LogServices/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ // Collections don't include the static data added by SubRoute
+ // because it has a duplicate entry for members
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogServiceCollection.LogServiceCollection";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Managers/bmc/LogServices";
+ asyncResp->res.jsonValue["Name"] =
+ "Open BMC Log Services Collection";
+ asyncResp->res.jsonValue["Description"] =
+ "Collection of LogServices for this Manager";
+ nlohmann::json& logServiceArray =
+ asyncResp->res.jsonValue["Members"];
+ logServiceArray = nlohmann::json::array();
#ifdef BMCWEB_ENABLE_REDFISH_DUMP_LOG
- logServiceArray.push_back(
- {{"@odata.id", "/redfish/v1/Managers/bmc/LogServices/Dump"}});
+ logServiceArray.push_back(
+ {{"@odata.id",
+ "/redfish/v1/Managers/bmc/LogServices/Dump"}});
#endif
#ifdef BMCWEB_ENABLE_REDFISH_BMC_JOURNAL
- logServiceArray.push_back(
- {{"@odata.id", "/redfish/v1/Managers/bmc/LogServices/Journal"}});
+ logServiceArray.push_back(
+ {{"@odata.id",
+ "/redfish/v1/Managers/bmc/LogServices/Journal"}});
#endif
- asyncResp->res.jsonValue["Members@odata.count"] =
- logServiceArray.size();
- }
-};
+ asyncResp->res.jsonValue["Members@odata.count"] =
+ logServiceArray.size();
+ });
+}
-class BMCJournalLogService : public Node
+inline void requestRoutesBMCJournalLogService(App& app)
{
- public:
- BMCJournalLogService(App& app) :
- Node(app, "/redfish/v1/Managers/bmc/LogServices/Journal/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
+ BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/LogServices/Journal/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogService.v1_1_0.LogService";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Managers/bmc/LogServices/Journal";
- asyncResp->res.jsonValue["Name"] = "Open BMC Journal Log Service";
- asyncResp->res.jsonValue["Description"] = "BMC Journal Log Service";
- asyncResp->res.jsonValue["Id"] = "BMC Journal";
- asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull";
- asyncResp->res.jsonValue["Entries"] = {
- {"@odata.id",
- "/redfish/v1/Managers/bmc/LogServices/Journal/Entries"}};
- }
-};
+ {
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogService.v1_1_0.LogService";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Managers/bmc/LogServices/Journal";
+ asyncResp->res.jsonValue["Name"] =
+ "Open BMC Journal Log Service";
+ asyncResp->res.jsonValue["Description"] =
+ "BMC Journal Log Service";
+ asyncResp->res.jsonValue["Id"] = "BMC Journal";
+ asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull";
+ asyncResp->res.jsonValue["Entries"] = {
+ {"@odata.id",
+ "/redfish/v1/Managers/bmc/LogServices/Journal/Entries"}};
+ });
+}
static int fillBMCJournalLogEntryJson(const std::string& bmcJournalLogEntryID,
sd_journal* journal,
@@ -2020,619 +1912,432 @@ static int fillBMCJournalLogEntryJson(const std::string& bmcJournalLogEntryID,
return 0;
}
-class BMCJournalLogEntryCollection : public Node
+inline void requestRoutesBMCJournalLogEntryCollection(App& app)
{
- public:
- BMCJournalLogEntryCollection(App& app) :
- Node(app, "/redfish/v1/Managers/bmc/LogServices/Journal/Entries/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>&) override
- {
+ BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/LogServices/Journal/Entries/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ static constexpr const long maxEntriesPerPage = 1000;
+ uint64_t skip = 0;
+ uint64_t top = maxEntriesPerPage; // Show max entries by default
+ if (!getSkipParam(asyncResp, req, skip))
+ {
+ return;
+ }
+ if (!getTopParam(asyncResp, req, top))
+ {
+ return;
+ }
+ // Collections don't include the static data added by SubRoute
+ // because it has a duplicate entry for members
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogEntryCollection.LogEntryCollection";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Managers/bmc/LogServices/Journal/Entries";
+ asyncResp->res.jsonValue["Name"] = "Open BMC Journal Entries";
+ asyncResp->res.jsonValue["Description"] =
+ "Collection of BMC Journal Entries";
+ nlohmann::json& logEntryArray =
+ asyncResp->res.jsonValue["Members"];
+ logEntryArray = nlohmann::json::array();
- static constexpr const long maxEntriesPerPage = 1000;
- uint64_t skip = 0;
- uint64_t top = maxEntriesPerPage; // Show max entries by default
- if (!getSkipParam(asyncResp, req, skip))
- {
- return;
- }
- if (!getTopParam(asyncResp, req, top))
- {
- return;
- }
- // Collections don't include the static data added by SubRoute because
- // it has a duplicate entry for members
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogEntryCollection.LogEntryCollection";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Managers/bmc/LogServices/Journal/Entries";
- asyncResp->res.jsonValue["Name"] = "Open BMC Journal Entries";
- asyncResp->res.jsonValue["Description"] =
- "Collection of BMC Journal Entries";
- nlohmann::json& logEntryArray = asyncResp->res.jsonValue["Members"];
- logEntryArray = nlohmann::json::array();
-
- // Go through the journal and use the timestamp to create a unique ID
- // for each entry
- sd_journal* journalTmp = nullptr;
- int ret = sd_journal_open(&journalTmp, SD_JOURNAL_LOCAL_ONLY);
- if (ret < 0)
- {
- BMCWEB_LOG_ERROR << "failed to open journal: " << strerror(-ret);
- messages::internalError(asyncResp->res);
- return;
- }
- std::unique_ptr<sd_journal, decltype(&sd_journal_close)> journal(
- journalTmp, sd_journal_close);
- journalTmp = nullptr;
- uint64_t entryCount = 0;
- // Reset the unique ID on the first entry
- bool firstEntry = true;
- SD_JOURNAL_FOREACH(journal.get())
- {
- entryCount++;
- // Handle paging using skip (number of entries to skip from the
- // start) and top (number of entries to display)
- if (entryCount <= skip || entryCount > skip + top)
- {
- continue;
- }
+ // Go through the journal and use the timestamp to create a
+ // unique ID for each entry
+ sd_journal* journalTmp = nullptr;
+ int ret = sd_journal_open(&journalTmp, SD_JOURNAL_LOCAL_ONLY);
+ if (ret < 0)
+ {
+ BMCWEB_LOG_ERROR << "failed to open journal: "
+ << strerror(-ret);
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ std::unique_ptr<sd_journal, decltype(&sd_journal_close)>
+ journal(journalTmp, sd_journal_close);
+ journalTmp = nullptr;
+ uint64_t entryCount = 0;
+ // Reset the unique ID on the first entry
+ bool firstEntry = true;
+ SD_JOURNAL_FOREACH(journal.get())
+ {
+ entryCount++;
+ // Handle paging using skip (number of entries to skip from
+ // the start) and top (number of entries to display)
+ if (entryCount <= skip || entryCount > skip + top)
+ {
+ continue;
+ }
- std::string idStr;
- if (!getUniqueEntryID(journal.get(), idStr, firstEntry))
- {
- continue;
- }
+ std::string idStr;
+ if (!getUniqueEntryID(journal.get(), idStr, firstEntry))
+ {
+ continue;
+ }
- if (firstEntry)
- {
- firstEntry = false;
- }
+ if (firstEntry)
+ {
+ firstEntry = false;
+ }
- logEntryArray.push_back({});
- nlohmann::json& bmcJournalLogEntry = logEntryArray.back();
- if (fillBMCJournalLogEntryJson(idStr, journal.get(),
- bmcJournalLogEntry) != 0)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- }
- asyncResp->res.jsonValue["Members@odata.count"] = entryCount;
- if (skip + top < entryCount)
- {
- asyncResp->res.jsonValue["Members@odata.nextLink"] =
- "/redfish/v1/Managers/bmc/LogServices/Journal/Entries?$skip=" +
- std::to_string(skip + top);
- }
- }
-};
+ logEntryArray.push_back({});
+ nlohmann::json& bmcJournalLogEntry = logEntryArray.back();
+ if (fillBMCJournalLogEntryJson(idStr, journal.get(),
+ bmcJournalLogEntry) != 0)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ }
+ asyncResp->res.jsonValue["Members@odata.count"] = entryCount;
+ if (skip + top < entryCount)
+ {
+ asyncResp->res.jsonValue["Members@odata.nextLink"] =
+ "/redfish/v1/Managers/bmc/LogServices/Journal/"
+ "Entries?$skip=" +
+ std::to_string(skip + top);
+ }
+ });
+}
-class BMCJournalLogEntry : public Node
+inline void requestRoutesBMCJournalLogEntry(App& app)
{
- public:
- BMCJournalLogEntry(App& app) :
- Node(app, "/redfish/v1/Managers/bmc/LogServices/Journal/Entries/<str>/",
- std::string())
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&,
- const std::vector<std::string>& params) override
- {
-
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- const std::string& entryID = params[0];
- // Convert the unique ID back to a timestamp to find the entry
- uint64_t ts = 0;
- uint64_t index = 0;
- if (!getTimestampFromID(asyncResp, entryID, ts, index))
- {
- return;
- }
+ BMCWEB_ROUTE(app,
+ "/redfish/v1/Managers/bmc/LogServices/Journal/Entries/<str>/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& entryID) {
+ // Convert the unique ID back to a timestamp to find the entry
+ uint64_t ts = 0;
+ uint64_t index = 0;
+ if (!getTimestampFromID(asyncResp, entryID, ts, index))
+ {
+ return;
+ }
- sd_journal* journalTmp = nullptr;
- int ret = sd_journal_open(&journalTmp, SD_JOURNAL_LOCAL_ONLY);
- if (ret < 0)
- {
- BMCWEB_LOG_ERROR << "failed to open journal: " << strerror(-ret);
- messages::internalError(asyncResp->res);
- return;
- }
- std::unique_ptr<sd_journal, decltype(&sd_journal_close)> journal(
- journalTmp, sd_journal_close);
- journalTmp = nullptr;
- // Go to the timestamp in the log and move to the entry at the index
- // tracking the unique ID
- std::string idStr;
- bool firstEntry = true;
- ret = sd_journal_seek_realtime_usec(journal.get(), ts);
- if (ret < 0)
- {
- BMCWEB_LOG_ERROR << "failed to seek to an entry in journal"
- << strerror(-ret);
- messages::internalError(asyncResp->res);
- return;
- }
- for (uint64_t i = 0; i <= index; i++)
- {
- sd_journal_next(journal.get());
- if (!getUniqueEntryID(journal.get(), idStr, firstEntry))
- {
- messages::internalError(asyncResp->res);
- return;
- }
- if (firstEntry)
- {
- firstEntry = false;
- }
- }
- // Confirm that the entry ID matches what was requested
- if (idStr != entryID)
- {
- messages::resourceMissingAtURI(asyncResp->res, entryID);
- return;
- }
+ sd_journal* journalTmp = nullptr;
+ int ret = sd_journal_open(&journalTmp, SD_JOURNAL_LOCAL_ONLY);
+ if (ret < 0)
+ {
+ BMCWEB_LOG_ERROR << "failed to open journal: "
+ << strerror(-ret);
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ std::unique_ptr<sd_journal, decltype(&sd_journal_close)>
+ journal(journalTmp, sd_journal_close);
+ journalTmp = nullptr;
+ // Go to the timestamp in the log and move to the entry at the
+ // index tracking the unique ID
+ std::string idStr;
+ bool firstEntry = true;
+ ret = sd_journal_seek_realtime_usec(journal.get(), ts);
+ if (ret < 0)
+ {
+ BMCWEB_LOG_ERROR << "failed to seek to an entry in journal"
+ << strerror(-ret);
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ for (uint64_t i = 0; i <= index; i++)
+ {
+ sd_journal_next(journal.get());
+ if (!getUniqueEntryID(journal.get(), idStr, firstEntry))
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ if (firstEntry)
+ {
+ firstEntry = false;
+ }
+ }
+ // Confirm that the entry ID matches what was requested
+ if (idStr != entryID)
+ {
+ messages::resourceMissingAtURI(asyncResp->res, entryID);
+ return;
+ }
- if (fillBMCJournalLogEntryJson(entryID, journal.get(),
- asyncResp->res.jsonValue) != 0)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- }
-};
+ if (fillBMCJournalLogEntryJson(entryID, journal.get(),
+ asyncResp->res.jsonValue) != 0)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ });
+}
-class BMCDumpService : public Node
+inline void requestRoutesBMCDumpService(App& app)
{
- public:
- BMCDumpService(App& app) :
- Node(app, "/redfish/v1/Managers/bmc/LogServices/Dump/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
-
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Managers/bmc/LogServices/Dump";
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogService.v1_2_0.LogService";
- asyncResp->res.jsonValue["Name"] = "Dump LogService";
- asyncResp->res.jsonValue["Description"] = "BMC Dump LogService";
- asyncResp->res.jsonValue["Id"] = "Dump";
- asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull";
- asyncResp->res.jsonValue["Entries"] = {
- {"@odata.id", "/redfish/v1/Managers/bmc/LogServices/Dump/Entries"}};
- asyncResp->res.jsonValue["Actions"] = {
- {"#LogService.ClearLog",
- {{"target", "/redfish/v1/Managers/bmc/LogServices/Dump/"
- "Actions/LogService.ClearLog"}}},
- {"#LogService.CollectDiagnosticData",
- {{"target", "/redfish/v1/Managers/bmc/LogServices/Dump/"
- "Actions/LogService.CollectDiagnosticData"}}}};
- }
-};
+ BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/LogServices/Dump/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Managers/bmc/LogServices/Dump";
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogService.v1_2_0.LogService";
+ asyncResp->res.jsonValue["Name"] = "Dump LogService";
+ asyncResp->res.jsonValue["Description"] = "BMC Dump LogService";
+ asyncResp->res.jsonValue["Id"] = "Dump";
+ asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull";
+ asyncResp->res.jsonValue["Entries"] = {
+ {"@odata.id",
+ "/redfish/v1/Managers/bmc/LogServices/Dump/Entries"}};
+ asyncResp->res.jsonValue["Actions"] = {
+ {"#LogService.ClearLog",
+ {{"target", "/redfish/v1/Managers/bmc/LogServices/Dump/"
+ "Actions/LogService.ClearLog"}}},
+ {"#LogService.CollectDiagnosticData",
+ {{"target", "/redfish/v1/Managers/bmc/LogServices/Dump/"
+ "Actions/LogService.CollectDiagnosticData"}}}};
+ });
+}
-class BMCDumpEntryCollection : public Node
+inline void requestRoutesBMCDumpEntryCollection(App& app)
{
- public:
- BMCDumpEntryCollection(App& app) :
- Node(app, "/redfish/v1/Managers/bmc/LogServices/Dump/Entries/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
- private:
/**
* Functions triggers appropriate requests on DBus
*/
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
-
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogEntryCollection.LogEntryCollection";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Managers/bmc/LogServices/Dump/Entries";
- asyncResp->res.jsonValue["Name"] = "BMC Dump Entries";
- asyncResp->res.jsonValue["Description"] =
- "Collection of BMC Dump Entries";
+ BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/LogServices/Dump/Entries/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogEntryCollection.LogEntryCollection";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Managers/bmc/LogServices/Dump/Entries";
+ asyncResp->res.jsonValue["Name"] = "BMC Dump Entries";
+ asyncResp->res.jsonValue["Description"] =
+ "Collection of BMC Dump Entries";
- getDumpEntryCollection(asyncResp, "BMC");
- }
-};
+ getDumpEntryCollection(asyncResp, "BMC");
+ });
+}
-class BMCDumpEntry : public Node
+inline void requestRoutesBMCDumpEntry(App& app)
{
- public:
- BMCDumpEntry(App& app) :
- Node(app, "/redfish/v1/Managers/bmc/LogServices/Dump/Entries/<str>/",
- std::string())
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&,
- const std::vector<std::string>& params) override
- {
-
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- getDumpEntryById(asyncResp, params[0], "BMC");
- }
-
- void doDelete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&,
- const std::vector<std::string>& params) override
- {
-
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- deleteDumpEntry(asyncResp, params[0], "bmc");
- }
-};
+ BMCWEB_ROUTE(app,
+ "/redfish/v1/Managers/bmc/LogServices/Dump/Entries/<str>/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& param) {
+ getDumpEntryById(asyncResp, param, "BMC");
+ });
+ BMCWEB_ROUTE(app,
+ "/redfish/v1/Managers/bmc/LogServices/Dump/Entries/<str>/")
+ .privileges({"ConfigureManager"})
+ .methods(boost::beast::http::verb::delete_)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& param) {
+ deleteDumpEntry(asyncResp, param, "bmc");
+ });
+}
-class BMCDumpCreate : public Node
+inline void requestRoutesBMCDumpCreate(App& app)
{
- public:
- BMCDumpCreate(App& app) :
- Node(app, "/redfish/v1/Managers/bmc/LogServices/Dump/"
- "Actions/"
- "LogService.CollectDiagnosticData/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
- private:
- void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>&) override
- {
- createDump(asyncResp, req, "BMC");
- }
-};
+ BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/LogServices/Dump/"
+ "Actions/"
+ "LogService.CollectDiagnosticData/")
+ .privileges({"ConfigureManager"})
+ .methods(boost::beast::http::verb::post)(
+ [](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ createDump(asyncResp, req, "BMC");
+ });
+}
-class BMCDumpClear : public Node
+inline void requestRoutesBMCDumpClear(App& app)
{
- public:
- BMCDumpClear(App& app) :
- Node(app, "/redfish/v1/Managers/bmc/LogServices/Dump/"
- "Actions/"
- "LogService.ClearLog/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
- clearDump(asyncResp, "BMC");
- }
-};
+ BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/LogServices/Dump/"
+ "Actions/"
+ "LogService.ClearLog/")
+ .privileges({"ConfigureManager"})
+ .methods(boost::beast::http::verb::post)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ clearDump(asyncResp, "BMC");
+ });
+}
-class SystemDumpService : public Node
+inline void requestRoutesSystemDumpService(App& app)
{
- public:
- SystemDumpService(App& app) :
- Node(app, "/redfish/v1/Systems/system/LogServices/Dump/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/LogServices/Dump/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
-
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Systems/system/LogServices/Dump";
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogService.v1_2_0.LogService";
- asyncResp->res.jsonValue["Name"] = "Dump LogService";
- asyncResp->res.jsonValue["Description"] = "System Dump LogService";
- asyncResp->res.jsonValue["Id"] = "Dump";
- asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull";
- asyncResp->res.jsonValue["Entries"] = {
- {"@odata.id",
- "/redfish/v1/Systems/system/LogServices/Dump/Entries"}};
- asyncResp->res.jsonValue["Actions"] = {
- {"#LogService.ClearLog",
- {{"target", "/redfish/v1/Systems/system/LogServices/Dump/Actions/"
- "LogService.ClearLog"}}},
- {"#LogService.CollectDiagnosticData",
- {{"target", "/redfish/v1/Systems/system/LogServices/Dump/Actions/"
- "LogService.CollectDiagnosticData"}}}};
- }
-};
+ {
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Systems/system/LogServices/Dump";
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogService.v1_2_0.LogService";
+ asyncResp->res.jsonValue["Name"] = "Dump LogService";
+ asyncResp->res.jsonValue["Description"] =
+ "System Dump LogService";
+ asyncResp->res.jsonValue["Id"] = "Dump";
+ asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull";
+ asyncResp->res.jsonValue["Entries"] = {
+ {"@odata.id",
+ "/redfish/v1/Systems/system/LogServices/Dump/Entries"}};
+ asyncResp->res.jsonValue["Actions"] = {
+ {"#LogService.ClearLog",
+ {{"target",
+ "/redfish/v1/Systems/system/LogServices/Dump/Actions/"
+ "LogService.ClearLog"}}},
+ {"#LogService.CollectDiagnosticData",
+ {{"target",
+ "/redfish/v1/Systems/system/LogServices/Dump/Actions/"
+ "LogService.CollectDiagnosticData"}}}};
+ });
+}
-class SystemDumpEntryCollection : public Node
+inline void requestRoutesSystemDumpEntryCollection(App& app)
{
- public:
- SystemDumpEntryCollection(App& app) :
- Node(app, "/redfish/v1/Systems/system/LogServices/Dump/Entries/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
- private:
/**
* Functions triggers appropriate requests on DBus
*/
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
-
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogEntryCollection.LogEntryCollection";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Systems/system/LogServices/Dump/Entries";
- asyncResp->res.jsonValue["Name"] = "System Dump Entries";
- asyncResp->res.jsonValue["Description"] =
- "Collection of System Dump Entries";
+ BMCWEB_ROUTE(app,
+ "/redfish/v1/Managers/bmc/LogServices/Dump/Entries/<str>/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string&) {
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogEntryCollection.LogEntryCollection";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Systems/system/LogServices/Dump/Entries";
+ asyncResp->res.jsonValue["Name"] = "System Dump Entries";
+ asyncResp->res.jsonValue["Description"] =
+ "Collection of System Dump Entries";
- getDumpEntryCollection(asyncResp, "System");
- }
-};
+ getDumpEntryCollection(asyncResp, "System");
+ });
+}
-class SystemDumpEntry : public Node
+inline void requestRoutesSystemDumpEntry(App& app)
{
- public:
- SystemDumpEntry(App& app) :
- Node(app, "/redfish/v1/Systems/system/LogServices/Dump/Entries/<str>/",
- std::string())
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&,
- const std::vector<std::string>& params) override
- {
-
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- getDumpEntryById(asyncResp, params[0], "System");
- }
-
- void doDelete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&,
- const std::vector<std::string>& params) override
- {
-
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- deleteDumpEntry(asyncResp, params[0], "system");
- }
-};
+ BMCWEB_ROUTE(app,
+ "redfish/v1/Systems/system/LogServices/Dump/Entries/<str>/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& param) {
+ getDumpEntryById(asyncResp, param, "System");
+ });
+
+ BMCWEB_ROUTE(app,
+ "redfish/v1/Systems/system/LogServices/Dump/Entries/<str>/")
+ .privileges({"ConfigureManager"})
+ .methods(boost::beast::http::verb::delete_)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& param) {
+ deleteDumpEntry(asyncResp, param, "system");
+ });
+}
-class SystemDumpCreate : public Node
+inline void requestRoutesSystemDumpCreate(App& app)
{
- public:
- SystemDumpCreate(App& app) :
- Node(app, "/redfish/v1/Systems/system/LogServices/Dump/"
- "Actions/"
- "LogService.CollectDiagnosticData/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>&) override
- {
- createDump(asyncResp, req, "System");
- }
-};
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/LogServices/Dump/"
+ "Actions/"
+ "LogService.CollectDiagnosticData/")
+ .privileges({"ConfigureManager"})
+ .methods(boost::beast::http::verb::post)(
+ [](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+
+ { createDump(asyncResp, req, "System"); });
+}
-class SystemDumpClear : public Node
+inline void requestRoutesSystemDumpClear(App& app)
{
- public:
- SystemDumpClear(App& app) :
- Node(app, "/redfish/v1/Systems/system/LogServices/Dump/"
- "Actions/"
- "LogService.ClearLog/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
- clearDump(asyncResp, "System");
- }
-};
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/LogServices/Dump/"
+ "Actions/"
+ "LogService.ClearLog/")
+ .privileges({"ConfigureManager"})
+ .methods(boost::beast::http::verb::post)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+
+ { clearDump(asyncResp, "System"); });
+}
-class CrashdumpService : public Node
+inline void requestRoutesCrashdumpService(App& app)
{
- public:
- CrashdumpService(App& app) :
- Node(app, "/redfish/v1/Systems/system/LogServices/Crashdump/")
- {
- // Note: Deviated from redfish privilege registry for GET & HEAD
- // method for security reasons.
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::head, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
+ // Note: Deviated from redfish privilege registry for GET & HEAD
+ // method for security reasons.
/**
* Functions triggers appropriate requests on DBus
*/
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
-
- // Copy over the static data to include the entries added by SubRoute
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Systems/system/LogServices/Crashdump";
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogService.v1_2_0.LogService";
- asyncResp->res.jsonValue["Name"] = "Open BMC Oem Crashdump Service";
- asyncResp->res.jsonValue["Description"] = "Oem Crashdump Service";
- asyncResp->res.jsonValue["Id"] = "Oem Crashdump";
- asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull";
- asyncResp->res.jsonValue["MaxNumberOfRecords"] = 3;
- asyncResp->res.jsonValue["Entries"] = {
- {"@odata.id",
- "/redfish/v1/Systems/system/LogServices/Crashdump/Entries"}};
- asyncResp->res.jsonValue["Actions"] = {
- {"#LogService.ClearLog",
- {{"target", "/redfish/v1/Systems/system/LogServices/Crashdump/"
- "Actions/LogService.ClearLog"}}},
- {"#LogService.CollectDiagnosticData",
- {{"target", "/redfish/v1/Systems/system/LogServices/Crashdump/"
- "Actions/LogService.CollectDiagnosticData"}}}};
- }
-};
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/LogServices/Crashdump/")
+ .privileges({"ConfigureManager"})
+ .methods(
+ boost::beast::http::verb::
+ get)([](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ // Copy over the static data to include the entries added by
+ // SubRoute
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Systems/system/LogServices/Crashdump";
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogService.v1_2_0.LogService";
+ asyncResp->res.jsonValue["Name"] = "Open BMC Oem Crashdump Service";
+ asyncResp->res.jsonValue["Description"] = "Oem Crashdump Service";
+ asyncResp->res.jsonValue["Id"] = "Oem Crashdump";
+ asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull";
+ asyncResp->res.jsonValue["MaxNumberOfRecords"] = 3;
+ asyncResp->res.jsonValue["Entries"] = {
+ {"@odata.id",
+ "/redfish/v1/Systems/system/LogServices/Crashdump/Entries"}};
+ asyncResp->res.jsonValue["Actions"] = {
+ {"#LogService.ClearLog",
+ {{"target", "/redfish/v1/Systems/system/LogServices/Crashdump/"
+ "Actions/LogService.ClearLog"}}},
+ {"#LogService.CollectDiagnosticData",
+ {{"target", "/redfish/v1/Systems/system/LogServices/Crashdump/"
+ "Actions/LogService.CollectDiagnosticData"}}}};
+ });
+}
-class CrashdumpClear : public Node
+void inline requestRoutesCrashdumpClear(App& app)
{
- public:
- CrashdumpClear(App& app) :
- Node(app, "/redfish/v1/Systems/system/LogServices/Crashdump/Actions/"
- "LogService.ClearLog/")
- {
- // Note: Deviated from redfish privilege registry for GET & HEAD
- // method for security reasons.
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::head, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
-
- private:
- void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
-
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code ec,
- const std::string&) {
- if (ec)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- messages::success(asyncResp->res);
- },
- crashdumpObject, crashdumpPath, deleteAllInterface, "DeleteAll");
- }
-};
+ BMCWEB_ROUTE(app,
+ "/redfish/v1/Systems/system/LogServices/Crashdump/Actions/"
+ "LogService.ClearLog/")
+ .privileges({"ConfigureComponents"})
+ .methods(boost::beast::http::verb::post)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code ec,
+ const std::string&) {
+ if (ec)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ messages::success(asyncResp->res);
+ },
+ crashdumpObject, crashdumpPath, deleteAllInterface,
+ "DeleteAll");
+ });
+}
static void
logCrashdumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
@@ -2690,474 +2395,396 @@ static void
"org.freedesktop.DBus.Properties", "GetAll", crashdumpInterface);
}
-class CrashdumpEntryCollection : public Node
+inline void requestRoutesCrashdumpEntryCollection(App& app)
{
- public:
- CrashdumpEntryCollection(App& app) :
- Node(app, "/redfish/v1/Systems/system/LogServices/Crashdump/Entries/")
- {
- // Note: Deviated from redfish privilege registry for GET & HEAD
- // method for security reasons.
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::head, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
+ // Note: Deviated from redfish privilege registry for GET & HEAD
+ // method for security reasons.
/**
* Functions triggers appropriate requests on DBus
*/
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
-
- // Collections don't include the static data added by SubRoute because
- // it has a duplicate entry for members
- auto getLogEntriesCallback = [asyncResp](
- const boost::system::error_code ec,
- const std::vector<std::string>& resp) {
- if (ec)
- {
- if (ec.value() !=
- boost::system::errc::no_such_file_or_directory)
+ BMCWEB_ROUTE(app,
+ "/redfish/v1/Systems/system/LogServices/Crashdump/Entries/")
+ .privileges({"ConfigureComponents"})
+ .methods(
+ boost::beast::http::verb::
+ get)([](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ // Collections don't include the static data added by SubRoute
+ // because it has a duplicate entry for members
+ auto getLogEntriesCallback = [asyncResp](
+ const boost::system::error_code ec,
+ const std::vector<std::string>&
+ resp) {
+ if (ec)
{
- BMCWEB_LOG_DEBUG << "failed to get entries ec: "
- << ec.message();
- messages::internalError(asyncResp->res);
- return;
+ if (ec.value() !=
+ boost::system::errc::no_such_file_or_directory)
+ {
+ BMCWEB_LOG_DEBUG << "failed to get entries ec: "
+ << ec.message();
+ messages::internalError(asyncResp->res);
+ return;
+ }
}
- }
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogEntryCollection.LogEntryCollection";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Systems/system/LogServices/Crashdump/Entries";
- asyncResp->res.jsonValue["Name"] = "Open BMC Crashdump Entries";
- asyncResp->res.jsonValue["Description"] =
- "Collection of Crashdump Entries";
- nlohmann::json& logEntryArray = asyncResp->res.jsonValue["Members"];
- logEntryArray = nlohmann::json::array();
- std::vector<std::string> logIDs;
- // Get the list of log entries and build up an empty array big
- // enough to hold them
- for (const std::string& objpath : resp)
- {
- // Get the log ID
- std::size_t lastPos = objpath.rfind('/');
- if (lastPos == std::string::npos)
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogEntryCollection.LogEntryCollection";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Systems/system/LogServices/Crashdump/Entries";
+ asyncResp->res.jsonValue["Name"] = "Open BMC Crashdump Entries";
+ asyncResp->res.jsonValue["Description"] =
+ "Collection of Crashdump Entries";
+ nlohmann::json& logEntryArray =
+ asyncResp->res.jsonValue["Members"];
+ logEntryArray = nlohmann::json::array();
+ std::vector<std::string> logIDs;
+ // Get the list of log entries and build up an empty array big
+ // enough to hold them
+ for (const std::string& objpath : resp)
{
- continue;
- }
- logIDs.emplace_back(objpath.substr(lastPos + 1));
+ // Get the log ID
+ std::size_t lastPos = objpath.rfind('/');
+ if (lastPos == std::string::npos)
+ {
+ continue;
+ }
+ logIDs.emplace_back(objpath.substr(lastPos + 1));
- // Add a space for the log entry to the array
- logEntryArray.push_back({});
- }
- // Now go through and set up async calls to fill in the entries
- size_t index = 0;
- for (const std::string& logID : logIDs)
- {
- // Add the log entry to the array
- logCrashdumpEntry(asyncResp, logID, logEntryArray[index++]);
- }
- asyncResp->res.jsonValue["Members@odata.count"] =
- logEntryArray.size();
- };
- crow::connections::systemBus->async_method_call(
- std::move(getLogEntriesCallback),
- "xyz.openbmc_project.ObjectMapper",
- "/xyz/openbmc_project/object_mapper",
- "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "", 0,
- std::array<const char*, 1>{crashdumpInterface});
- }
-};
+ // Add a space for the log entry to the array
+ logEntryArray.push_back({});
+ }
+ // Now go through and set up async calls to fill in the entries
+ size_t index = 0;
+ for (const std::string& logID : logIDs)
+ {
+ // Add the log entry to the array
+ logCrashdumpEntry(asyncResp, logID, logEntryArray[index++]);
+ }
+ asyncResp->res.jsonValue["Members@odata.count"] =
+ logEntryArray.size();
+ };
+ crow::connections::systemBus->async_method_call(
+ std::move(getLogEntriesCallback),
+ "xyz.openbmc_project.ObjectMapper",
+ "/xyz/openbmc_project/object_mapper",
+ "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "", 0,
+ std::array<const char*, 1>{crashdumpInterface});
+ });
+}
-class CrashdumpEntry : public Node
+inline void requestRoutesCrashdumpEntry(App& app)
{
- public:
- CrashdumpEntry(App& app) :
- Node(app,
- "/redfish/v1/Systems/system/LogServices/Crashdump/Entries/<str>/",
- std::string())
- {
- // Note: Deviated from redfish privilege registry for GET & HEAD
- // method for security reasons.
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::head, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&,
- const std::vector<std::string>& params) override
- {
-
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- const std::string& logID = params[0];
- logCrashdumpEntry(asyncResp, logID, asyncResp->res.jsonValue);
- }
-};
+ // Note: Deviated from redfish privilege registry for GET & HEAD
+ // method for security reasons.
+
+ BMCWEB_ROUTE(
+ app, "/redfish/v1/Systems/system/LogServices/Crashdump/Entries/<str>/")
+ .privileges({"ConfigureComponents"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& param) {
+ const std::string& logID = param;
+ logCrashdumpEntry(asyncResp, logID, asyncResp->res.jsonValue);
+ });
+}
-class CrashdumpFile : public Node
+inline void requestRoutesCrashdumpFile(App& app)
{
- public:
- CrashdumpFile(App& app) :
- Node(app,
- "/redfish/v1/Systems/system/LogServices/Crashdump/Entries/<str>/"
- "<str>/",
- std::string(), std::string())
- {
- // Note: Deviated from redfish privilege registry for GET & HEAD
- // method for security reasons.
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::head, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
+ // Note: Deviated from redfish privilege registry for GET & HEAD
+ // method for security reasons.
+ BMCWEB_ROUTE(
+ app,
+ "/redfish/v1/Systems/system/LogServices/Crashdump/Entries/<str>/<str>/")
+ .privileges({"ConfigureComponents"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& logID, const std::string& fileName) {
+ auto getStoredLogCallback =
+ [asyncResp, logID, fileName](
+ const boost::system::error_code ec,
+ const std::vector<std::pair<std::string, VariantType>>&
+ resp) {
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG << "failed to get log ec: "
+ << ec.message();
+ messages::internalError(asyncResp->res);
+ return;
+ }
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&,
- const std::vector<std::string>& params) override
- {
+ std::string dbusFilename{};
+ std::string dbusTimestamp{};
+ std::string dbusFilepath{};
- if (params.size() != 2)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- const std::string& logID = params[0];
- const std::string& fileName = params[1];
+ parseCrashdumpParameters(resp, dbusFilename,
+ dbusTimestamp, dbusFilepath);
- auto getStoredLogCallback =
- [asyncResp, logID, fileName](
- const boost::system::error_code ec,
- const std::vector<std::pair<std::string, VariantType>>& resp) {
- if (ec)
- {
- BMCWEB_LOG_DEBUG << "failed to get log ec: "
- << ec.message();
- messages::internalError(asyncResp->res);
- return;
- }
+ if (dbusFilename.empty() || dbusTimestamp.empty() ||
+ dbusFilepath.empty())
+ {
+ messages::resourceMissingAtURI(asyncResp->res,
+ fileName);
+ return;
+ }
- std::string dbusFilename{};
- std::string dbusTimestamp{};
- std::string dbusFilepath{};
+ // Verify the file name parameter is correct
+ if (fileName != dbusFilename)
+ {
+ messages::resourceMissingAtURI(asyncResp->res,
+ fileName);
+ return;
+ }
- parseCrashdumpParameters(resp, dbusFilename, dbusTimestamp,
- dbusFilepath);
+ if (!std::filesystem::exists(dbusFilepath))
+ {
+ messages::resourceMissingAtURI(asyncResp->res,
+ fileName);
+ return;
+ }
+ std::ifstream ifs(dbusFilepath, std::ios::in |
+ std::ios::binary |
+ std::ios::ate);
+ std::ifstream::pos_type fileSize = ifs.tellg();
+ if (fileSize < 0)
+ {
+ messages::generalError(asyncResp->res);
+ return;
+ }
+ ifs.seekg(0, std::ios::beg);
+
+ auto crashData = std::make_unique<char[]>(
+ static_cast<unsigned int>(fileSize));
+
+ ifs.read(crashData.get(), static_cast<int>(fileSize));
+
+ // The cast to std::string is intentional in order to
+ // use the assign() that applies move mechanics
+ asyncResp->res.body().assign(
+ static_cast<std::string>(crashData.get()));
+
+ // Configure this to be a file download when accessed
+ // from a browser
+ asyncResp->res.addHeader("Content-Disposition",
+ "attachment");
+ };
+ crow::connections::systemBus->async_method_call(
+ std::move(getStoredLogCallback), crashdumpObject,
+ crashdumpPath + std::string("/") + logID,
+ "org.freedesktop.DBus.Properties", "GetAll",
+ crashdumpInterface);
+ });
+}
- if (dbusFilename.empty() || dbusTimestamp.empty() ||
- dbusFilepath.empty())
- {
- messages::resourceMissingAtURI(asyncResp->res, fileName);
- return;
- }
+inline void requestRoutesCrashdumpCollect(App& app)
+{
+ // Note: Deviated from redfish privilege registry for GET & HEAD
+ // method for security reasons.
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/LogServices/Crashdump/"
+ "Actions/LogService.CollectDiagnosticData/")
+ .privileges({"ConfigureComponents"})
+ .methods(
+ boost::beast::http::verb::
+ post)([](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ std::string diagnosticDataType;
+ std::string oemDiagnosticDataType;
+ if (!redfish::json_util::readJson(
+ req, asyncResp->res, "DiagnosticDataType",
+ diagnosticDataType, "OEMDiagnosticDataType",
+ oemDiagnosticDataType))
+ {
+ return;
+ }
- // Verify the file name parameter is correct
- if (fileName != dbusFilename)
- {
- messages::resourceMissingAtURI(asyncResp->res, fileName);
- return;
- }
+ if (diagnosticDataType != "OEM")
+ {
+ BMCWEB_LOG_ERROR
+ << "Only OEM DiagnosticDataType supported for Crashdump";
+ messages::actionParameterValueFormatError(
+ asyncResp->res, diagnosticDataType, "DiagnosticDataType",
+ "CollectDiagnosticData");
+ return;
+ }
- if (!std::filesystem::exists(dbusFilepath))
- {
- messages::resourceMissingAtURI(asyncResp->res, fileName);
- return;
- }
- std::ifstream ifs(dbusFilepath, std::ios::in |
- std::ios::binary |
- std::ios::ate);
- std::ifstream::pos_type fileSize = ifs.tellg();
- if (fileSize < 0)
+ auto collectCrashdumpCallback = [asyncResp, req](
+ const boost::system::error_code
+ ec,
+ const std::string&) {
+ if (ec)
{
- messages::generalError(asyncResp->res);
+ if (ec.value() ==
+ boost::system::errc::operation_not_supported)
+ {
+ messages::resourceInStandby(asyncResp->res);
+ }
+ else if (ec.value() ==
+ boost::system::errc::device_or_resource_busy)
+ {
+ messages::serviceTemporarilyUnavailable(asyncResp->res,
+ "60");
+ }
+ else
+ {
+ messages::internalError(asyncResp->res);
+ }
return;
}
- ifs.seekg(0, std::ios::beg);
-
- auto crashData = std::make_unique<char[]>(
- static_cast<unsigned int>(fileSize));
-
- ifs.read(crashData.get(), static_cast<int>(fileSize));
-
- // The cast to std::string is intentional in order to use the
- // assign() that applies move mechanics
- asyncResp->res.body().assign(
- static_cast<std::string>(crashData.get()));
-
- // Configure this to be a file download when accessed from
- // a browser
- asyncResp->res.addHeader("Content-Disposition", "attachment");
+ std::shared_ptr<task::TaskData> task =
+ task::TaskData::createTask(
+ [](boost::system::error_code err,
+ sdbusplus::message::message&,
+ const std::shared_ptr<task::TaskData>& taskData) {
+ if (!err)
+ {
+ taskData->messages.emplace_back(
+ messages::taskCompletedOK(
+ std::to_string(taskData->index)));
+ taskData->state = "Completed";
+ }
+ return task::completed;
+ },
+ "type='signal',interface='org.freedesktop.DBus."
+ "Properties',"
+ "member='PropertiesChanged',arg0namespace='com.intel."
+ "crashdump'");
+ task->startTimer(std::chrono::minutes(5));
+ task->populateResp(asyncResp->res);
+ task->payload.emplace(req);
};
- crow::connections::systemBus->async_method_call(
- std::move(getStoredLogCallback), crashdumpObject,
- crashdumpPath + std::string("/") + logID,
- "org.freedesktop.DBus.Properties", "GetAll", crashdumpInterface);
- }
-};
-
-class CrashdumpCollect : public Node
-{
- public:
- CrashdumpCollect(App& app) :
- Node(app, "/redfish/v1/Systems/system/LogServices/Crashdump/Actions/"
- "LogService.CollectDiagnosticData/")
- {
- // Note: Deviated from redfish privilege registry for GET & HEAD
- // method for security reasons.
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::head, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
-
- private:
- void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>&) override
- {
-
- std::string diagnosticDataType;
- std::string oemDiagnosticDataType;
- if (!redfish::json_util::readJson(
- req, asyncResp->res, "DiagnosticDataType", diagnosticDataType,
- "OEMDiagnosticDataType", oemDiagnosticDataType))
- {
- return;
- }
- if (diagnosticDataType != "OEM")
- {
- BMCWEB_LOG_ERROR
- << "Only OEM DiagnosticDataType supported for Crashdump";
- messages::actionParameterValueFormatError(
- asyncResp->res, diagnosticDataType, "DiagnosticDataType",
- "CollectDiagnosticData");
- return;
- }
-
- auto collectCrashdumpCallback = [asyncResp, req](
- const boost::system::error_code ec,
- const std::string&) {
- if (ec)
+ if (oemDiagnosticDataType == "OnDemand")
{
- if (ec.value() == boost::system::errc::operation_not_supported)
- {
- messages::resourceInStandby(asyncResp->res);
- }
- else if (ec.value() ==
- boost::system::errc::device_or_resource_busy)
- {
- messages::serviceTemporarilyUnavailable(asyncResp->res,
- "60");
- }
- else
- {
- messages::internalError(asyncResp->res);
- }
+ crow::connections::systemBus->async_method_call(
+ std::move(collectCrashdumpCallback), crashdumpObject,
+ crashdumpPath, crashdumpOnDemandInterface,
+ "GenerateOnDemandLog");
+ }
+ else if (oemDiagnosticDataType == "Telemetry")
+ {
+ crow::connections::systemBus->async_method_call(
+ std::move(collectCrashdumpCallback), crashdumpObject,
+ crashdumpPath, crashdumpTelemetryInterface,
+ "GenerateTelemetryLog");
+ }
+ else
+ {
+ BMCWEB_LOG_ERROR << "Unsupported OEMDiagnosticDataType: "
+ << oemDiagnosticDataType;
+ messages::actionParameterValueFormatError(
+ asyncResp->res, oemDiagnosticDataType,
+ "OEMDiagnosticDataType", "CollectDiagnosticData");
return;
}
- std::shared_ptr<task::TaskData> task = task::TaskData::createTask(
- [](boost::system::error_code err, sdbusplus::message::message&,
- const std::shared_ptr<task::TaskData>& taskData) {
- if (!err)
- {
- taskData->messages.emplace_back(
- messages::taskCompletedOK(
- std::to_string(taskData->index)));
- taskData->state = "Completed";
- }
- return task::completed;
- },
- "type='signal',interface='org.freedesktop.DBus.Properties',"
- "member='PropertiesChanged',arg0namespace='com.intel."
- "crashdump'");
- task->startTimer(std::chrono::minutes(5));
- task->populateResp(asyncResp->res);
- task->payload.emplace(req);
- };
-
- if (oemDiagnosticDataType == "OnDemand")
- {
- crow::connections::systemBus->async_method_call(
- std::move(collectCrashdumpCallback), crashdumpObject,
- crashdumpPath, crashdumpOnDemandInterface,
- "GenerateOnDemandLog");
- }
- else if (oemDiagnosticDataType == "Telemetry")
- {
- crow::connections::systemBus->async_method_call(
- std::move(collectCrashdumpCallback), crashdumpObject,
- crashdumpPath, crashdumpTelemetryInterface,
- "GenerateTelemetryLog");
- }
- else
- {
- BMCWEB_LOG_ERROR << "Unsupported OEMDiagnosticDataType: "
- << oemDiagnosticDataType;
- messages::actionParameterValueFormatError(
- asyncResp->res, oemDiagnosticDataType, "OEMDiagnosticDataType",
- "CollectDiagnosticData");
- return;
- }
- }
-};
+ });
+}
/**
* DBusLogServiceActionsClear class supports POST method for ClearLog action.
*/
-class DBusLogServiceActionsClear : public Node
+inline void requestRoutesDBusLogServiceActionsClear(App& app)
{
- public:
- DBusLogServiceActionsClear(App& app) :
- Node(app, "/redfish/v1/Systems/system/LogServices/EventLog/Actions/"
- "LogService.ClearLog/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
/**
* Function handles POST method request.
* The Clear Log actions does not require any parameter.The action deletes
* all entries found in the Entries collection for this Log Service.
*/
- void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
- BMCWEB_LOG_DEBUG << "Do delete all entries.";
-
- // Process response from Logging service.
- auto respHandler = [asyncResp](const boost::system::error_code ec) {
- BMCWEB_LOG_DEBUG << "doClearLog resp_handler callback: Done";
- if (ec)
- {
- // TODO Handle for specific error code
- BMCWEB_LOG_ERROR << "doClearLog resp_handler got error " << ec;
- asyncResp->res.result(
- boost::beast::http::status::internal_server_error);
- return;
- }
- asyncResp->res.result(boost::beast::http::status::no_content);
- };
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/LogServices/EventLog/Actions/"
+ "LogService.ClearLog/")
+ .privileges({"ConfigureManager"})
+ .methods(boost::beast::http::verb::post)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ BMCWEB_LOG_DEBUG << "Do delete all entries.";
+
+ // Process response from Logging service.
+ auto respHandler = [asyncResp](
+ const boost::system::error_code ec) {
+ BMCWEB_LOG_DEBUG
+ << "doClearLog resp_handler callback: Done";
+ if (ec)
+ {
+ // TODO Handle for specific error code
+ BMCWEB_LOG_ERROR << "doClearLog resp_handler got error "
+ << ec;
+ asyncResp->res.result(
+ boost::beast::http::status::internal_server_error);
+ return;
+ }
- // Make call to Logging service to request Clear Log
- crow::connections::systemBus->async_method_call(
- respHandler, "xyz.openbmc_project.Logging",
- "/xyz/openbmc_project/logging",
- "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
- }
-};
+ asyncResp->res.result(
+ boost::beast::http::status::no_content);
+ };
+
+ // Make call to Logging service to request Clear Log
+ crow::connections::systemBus->async_method_call(
+ respHandler, "xyz.openbmc_project.Logging",
+ "/xyz/openbmc_project/logging",
+ "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
+ });
+}
/****************************************************
* Redfish PostCode interfaces
* using DBUS interface: getPostCodesTS
******************************************************/
-class PostCodesLogService : public Node
+inline void requestRoutesPostCodesLogService(App& app)
{
- public:
- PostCodesLogService(App& app) :
- Node(app, "/redfish/v1/Systems/system/LogServices/PostCodes/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
-
- asyncResp->res.jsonValue = {
- {"@odata.id", "/redfish/v1/Systems/system/LogServices/PostCodes"},
- {"@odata.type", "#LogService.v1_1_0.LogService"},
- {"Name", "POST Code Log Service"},
- {"Description", "POST Code Log Service"},
- {"Id", "BIOS POST Code Log"},
- {"OverWritePolicy", "WrapsWhenFull"},
- {"Entries",
- {{"@odata.id",
- "/redfish/v1/Systems/system/LogServices/PostCodes/Entries"}}}};
- asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"] = {
- {"target", "/redfish/v1/Systems/system/LogServices/PostCodes/"
- "Actions/LogService.ClearLog"}};
- }
-};
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/LogServices/PostCodes/")
+ .privileges({"Login"})
+ .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/PostCodes"},
+ {"@odata.type", "#LogService.v1_1_0.LogService"},
+ {"Name", "POST Code Log Service"},
+ {"Description", "POST Code Log Service"},
+ {"Id", "BIOS POST Code Log"},
+ {"OverWritePolicy", "WrapsWhenFull"},
+ {"Entries",
+ {{"@odata.id", "/redfish/v1/Systems/system/LogServices/"
+ "PostCodes/Entries"}}}};
+ asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"] = {
+ {"target",
+ "/redfish/v1/Systems/system/LogServices/PostCodes/"
+ "Actions/LogService.ClearLog"}};
+ });
+}
-class PostCodesClear : public Node
+inline void requestRoutesPostCodesClear(App& app)
{
- public:
- PostCodesClear(App& app) :
- Node(app, "/redfish/v1/Systems/system/LogServices/PostCodes/Actions/"
- "LogService.ClearLog/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
-
- private:
- void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
- BMCWEB_LOG_DEBUG << "Do delete all postcodes entries.";
-
- // Make call to post-code service to request clear all
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code ec) {
- if (ec)
- {
- // TODO Handle for specific error code
- BMCWEB_LOG_ERROR
- << "doClearPostCodes resp_handler got error " << ec;
- asyncResp->res.result(
- boost::beast::http::status::internal_server_error);
- messages::internalError(asyncResp->res);
- return;
- }
- },
- "xyz.openbmc_project.State.Boot.PostCode0",
- "/xyz/openbmc_project/State/Boot/PostCode0",
- "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
- }
-};
+ BMCWEB_ROUTE(app,
+ "/redfish/v1/Systems/system/LogServices/PostCodes/Actions/"
+ "LogService.ClearLog/")
+ .privileges({"ConfigureComponents"})
+ .methods(boost::beast::http::verb::post)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ BMCWEB_LOG_DEBUG << "Do delete all postcodes entries.";
+
+ // Make call to post-code service to request clear all
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code ec) {
+ if (ec)
+ {
+ // TODO Handle for specific error code
+ BMCWEB_LOG_ERROR
+ << "doClearPostCodes resp_handler got error "
+ << ec;
+ asyncResp->res.result(boost::beast::http::status::
+ internal_server_error);
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ },
+ "xyz.openbmc_project.State.Boot.PostCode0",
+ "/xyz/openbmc_project/State/Boot/PostCode0",
+ "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
+ });
+}
static void fillPostCodeEntry(
const std::shared_ptr<bmcweb::AsyncResp>& aResp,
@@ -3400,124 +3027,91 @@ static void
"xyz.openbmc_project.State.Boot.PostCode", "CurrentBootCycleCount");
}
-class PostCodesEntryCollection : public Node
+inline void requestRoutesPostCodesEntryCollection(App& app)
{
- public:
- PostCodesEntryCollection(App& app) :
- Node(app, "/redfish/v1/Systems/system/LogServices/PostCodes/Entries/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>&) override
- {
-
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogEntryCollection.LogEntryCollection";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Systems/system/LogServices/PostCodes/Entries";
- asyncResp->res.jsonValue["Name"] = "BIOS POST Code Log Entries";
- asyncResp->res.jsonValue["Description"] =
- "Collection of POST Code Log Entries";
- asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
- asyncResp->res.jsonValue["Members@odata.count"] = 0;
-
- uint64_t skip = 0;
- uint64_t top = maxEntriesPerPage; // Show max entries by default
- if (!getSkipParam(asyncResp, req, skip))
- {
- return;
- }
- if (!getTopParam(asyncResp, req, top))
- {
- return;
- }
- getCurrentBootNumber(asyncResp, skip, top);
- }
-};
+ BMCWEB_ROUTE(app,
+ "/redfish/v1/Systems/system/LogServices/PostCodes/Entries/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogEntryCollection.LogEntryCollection";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Systems/system/LogServices/PostCodes/Entries";
+ asyncResp->res.jsonValue["Name"] = "BIOS POST Code Log Entries";
+ asyncResp->res.jsonValue["Description"] =
+ "Collection of POST Code Log Entries";
+ asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
+ asyncResp->res.jsonValue["Members@odata.count"] = 0;
+
+ uint64_t skip = 0;
+ uint64_t top = maxEntriesPerPage; // Show max entries by default
+ if (!getSkipParam(asyncResp, req, skip))
+ {
+ return;
+ }
+ if (!getTopParam(asyncResp, req, top))
+ {
+ return;
+ }
+ getCurrentBootNumber(asyncResp, skip, top);
+ });
+}
-class PostCodesEntry : public Node
+inline void requestRoutesPostCodesEntry(App& app)
{
- public:
- PostCodesEntry(App& app) :
- Node(app,
- "/redfish/v1/Systems/system/LogServices/PostCodes/Entries/<str>/",
- std::string())
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&,
- const std::vector<std::string>& params) override
- {
-
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
-
- const std::string& targetID = params[0];
-
- size_t bootPos = targetID.find('B');
- if (bootPos == std::string::npos)
- {
- // Requested ID was not found
- messages::resourceMissingAtURI(asyncResp->res, targetID);
- return;
- }
- std::string_view bootIndexStr(targetID);
- bootIndexStr.remove_prefix(bootPos + 1);
- uint16_t bootIndex = 0;
- uint64_t codeIndex = 0;
- size_t dashPos = bootIndexStr.find('-');
+ BMCWEB_ROUTE(
+ app, "/redfish/v1/Systems/system/LogServices/PostCodes/Entries/<str>/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& targetID) {
+ size_t bootPos = targetID.find('B');
+ if (bootPos == std::string::npos)
+ {
+ // Requested ID was not found
+ messages::resourceMissingAtURI(asyncResp->res, targetID);
+ return;
+ }
+ std::string_view bootIndexStr(targetID);
+ bootIndexStr.remove_prefix(bootPos + 1);
+ uint16_t bootIndex = 0;
+ uint64_t codeIndex = 0;
+ size_t dashPos = bootIndexStr.find('-');
- if (dashPos == std::string::npos)
- {
- return;
- }
- std::string_view codeIndexStr(bootIndexStr);
- bootIndexStr.remove_suffix(dashPos);
- codeIndexStr.remove_prefix(dashPos + 1);
-
- bootIndex = static_cast<uint16_t>(
- strtoul(std::string(bootIndexStr).c_str(), nullptr, 0));
- codeIndex = strtoul(std::string(codeIndexStr).c_str(), nullptr, 0);
- if (bootIndex == 0 || codeIndex == 0)
- {
- BMCWEB_LOG_DEBUG << "Get Post Code invalid entry string "
- << params[0];
- }
+ if (dashPos == std::string::npos)
+ {
+ return;
+ }
+ std::string_view codeIndexStr(bootIndexStr);
+ bootIndexStr.remove_suffix(dashPos);
+ codeIndexStr.remove_prefix(dashPos + 1);
+
+ bootIndex = static_cast<uint16_t>(
+ strtoul(std::string(bootIndexStr).c_str(), nullptr, 0));
+ codeIndex =
+ strtoul(std::string(codeIndexStr).c_str(), nullptr, 0);
+ if (bootIndex == 0 || codeIndex == 0)
+ {
+ BMCWEB_LOG_DEBUG << "Get Post Code invalid entry string "
+ << targetID;
+ }
- asyncResp->res.jsonValue["@odata.type"] = "#LogEntry.v1_4_0.LogEntry";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Systems/system/LogServices/PostCodes/"
- "Entries";
- asyncResp->res.jsonValue["Name"] = "BIOS POST Code Log Entries";
- asyncResp->res.jsonValue["Description"] =
- "Collection of POST Code Log Entries";
- asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
- asyncResp->res.jsonValue["Members@odata.count"] = 0;
-
- getPostCodeForEntry(asyncResp, bootIndex, codeIndex);
- }
-};
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogEntry.v1_4_0.LogEntry";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Systems/system/LogServices/PostCodes/"
+ "Entries";
+ asyncResp->res.jsonValue["Name"] = "BIOS POST Code Log Entries";
+ asyncResp->res.jsonValue["Description"] =
+ "Collection of POST Code Log Entries";
+ asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
+ asyncResp->res.jsonValue["Members@odata.count"] = 0;
+
+ getPostCodeForEntry(asyncResp, bootIndex, codeIndex);
+ });
+}
} // namespace redfish