summaryrefslogtreecommitdiff
path: root/redfish-core
diff options
context:
space:
mode:
authorraviteja-b <raviteja28031990@gmail.com>2020-02-03 20:53:32 +0300
committerRavi Teja <raviteja28031990@gmail.com>2020-05-08 11:38:31 +0300
commitc9bb6861cd1bac2e1849b09176564f01c185207c (patch)
treece0f1c59130d745294648b1a1c0b49c768d89c9f /redfish-core
parent8a3bb71ebcdf14dafd5967192f73bf2416e8bb6e (diff)
downloadbmcweb-c9bb6861cd1bac2e1849b09176564f01c185207c.tar.xz
Redfish: Log service implementation for system dump
Dump is the debug data collected at any point of time from the system and is stored in a file Currently, Redfish doesn't have schema for operations on debug data(dump). This commit implements logService for system dump. we have a DMTF proposal to extend existing LogService schema for this purpose but its still work in progress, so moved to oem schema. below commit has changes to move properties to OEM https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/30352 Tested By: GET https://${IP}/redfish/v1/Systems/system/LogServices/SystemDump DELETE https://${IP}/redfish/v1/Systems/system/LogServices/SystemDump/Entries/<id> Redfish validator passed. (above mentioned commit required to pass validator). Change-Id: I4a4a4083be4556bc46a4335d31ce56f834bd4f5a Signed-off-by: Ravi Teja <raviteja28031990@gmail.com>
Diffstat (limited to 'redfish-core')
-rw-r--r--redfish-core/include/redfish.hpp6
-rw-r--r--redfish-core/lib/log_services.hpp331
2 files changed, 337 insertions, 0 deletions
diff --git a/redfish-core/include/redfish.hpp b/redfish-core/include/redfish.hpp
index 1f97b18c2b..ce5e5fb649 100644
--- a/redfish-core/include/redfish.hpp
+++ b/redfish-core/include/redfish.hpp
@@ -100,6 +100,12 @@ class RedfishService
nodes.emplace_back(std::make_unique<PostCodesEntry>(app));
nodes.emplace_back(std::make_unique<PostCodesEntryCollection>(app));
+#ifdef BMCWEB_ENABLE_REDFISH_SYSTEMDUMP_LOG
+ nodes.emplace_back(std::make_unique<SystemDumpService>(app));
+ nodes.emplace_back(std::make_unique<SystemDumpEntryCollection>(app));
+ nodes.emplace_back(std::make_unique<SystemDumpEntry>(app));
+#endif
+
#ifndef BMCWEB_ENABLE_REDFISH_DBUS_LOG_ENTRIES
nodes.emplace_back(
std::make_unique<JournalEventLogEntryCollection>(app));
diff --git a/redfish-core/lib/log_services.hpp b/redfish-core/lib/log_services.hpp
index 73a7bb6f4b..767a7fcf14 100644
--- a/redfish-core/lib/log_services.hpp
+++ b/redfish-core/lib/log_services.hpp
@@ -141,6 +141,30 @@ inline std::string translateSeverityDbusToRedfish(const std::string &s)
return "";
}
+inline void deleteSystemDumpEntry(crow::Response &res,
+ const std::string &entryID)
+{
+ std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
+
+ auto respHandler = [asyncResp](const boost::system::error_code ec) {
+ BMCWEB_LOG_DEBUG << "System Dump Entry doDelete callback: Done";
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR
+ << "System Dump (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);
+ };
+ crow::connections::systemBus->async_method_call(
+ respHandler, "xyz.openbmc_project.Dump.Manager",
+ "/xyz/openbmc_project/dump/entry/" + entryID,
+ "xyz.openbmc_project.Object.Delete", "Delete");
+}
+
static int getJournalMetadata(sd_journal *journal,
const std::string_view &field,
std::string_view &contents)
@@ -503,6 +527,11 @@ class SystemLogServiceCollection : public Node
logServiceArray = nlohmann::json::array();
logServiceArray.push_back(
{{"@odata.id", "/redfish/v1/Systems/system/LogServices/EventLog"}});
+#ifdef BMCWEB_ENABLE_REDFISH_SYSTEMDUMP_LOG
+ logServiceArray.push_back(
+ {{"@odata.id", "/redfish/v1/Systems/system/LogServices/System"}});
+#endif
+
#ifdef BMCWEB_ENABLE_REDFISH_CPU_LOG
logServiceArray.push_back(
{{"@odata.id",
@@ -1523,6 +1552,308 @@ class BMCJournalLogEntry : public Node
}
};
+class SystemDumpService : public Node
+{
+ public:
+ template <typename CrowApp>
+ SystemDumpService(CrowApp &app) :
+ Node(app, "/redfish/v1/Systems/system/LogServices/System/")
+ {
+ 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(crow::Response &res, const crow::Request &req,
+ const std::vector<std::string> &params) override
+ {
+ std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
+
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Systems/system/LogServices/System";
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogService.v1_1_0.LogService";
+ asyncResp->res.jsonValue["Name"] = "Dump Log Service";
+ asyncResp->res.jsonValue["Description"] = "System Dump Log Service";
+ asyncResp->res.jsonValue["Id"] = "System";
+ asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull";
+ asyncResp->res.jsonValue["LogEntryTypes"] = "Dump";
+ asyncResp->res.jsonValue["Oem"]["DumpType"] = "System";
+
+ asyncResp->res.jsonValue["Entries"] = {
+ {"@odata.id",
+ "/redfish/v1/Systems/system/LogServices/System/Entries"}};
+ asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"] = {
+ {"target", "/redfish/v1/Systems/system/LogServices/System/"
+ "Actions/LogService.ClearLog"}};
+ asyncResp->res.jsonValue["Actions"]["#LogService.CreateLog"] = {
+ {"target", "/redfish/v1/Systems/system/LogServices/System/"
+ "Actions/LogService.CreateLog"}};
+ }
+};
+
+class SystemDumpEntryCollection : public Node
+{
+ public:
+ template <typename CrowApp>
+ SystemDumpEntryCollection(CrowApp &app) :
+ Node(app, "/redfish/v1/Systems/system/LogServices/System/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(crow::Response &res, const crow::Request &req,
+ const std::vector<std::string> &params) override
+ {
+ std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
+
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogEntryCollection.LogEntryCollection";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Systems/system/LogServices/System/Entries";
+ asyncResp->res.jsonValue["Name"] = "System Dump Entries";
+ asyncResp->res.jsonValue["Description"] =
+ "Collection of System Dump Entries";
+
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code ec,
+ const crow::openbmc_mapper::GetSubTreeType &resp) {
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR << " resp_handler got error " << ec;
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ nlohmann::json &logArray = asyncResp->res.jsonValue["Members"];
+ logArray = nlohmann::json::array();
+ for (auto &object : resp)
+ {
+ const std::string &path =
+ static_cast<const std::string &>(object.first);
+ std::size_t lastPos = path.rfind("/");
+ if (lastPos == std::string::npos)
+ {
+ continue;
+ }
+ std::string logID = path.substr(lastPos + 1);
+ logArray.push_back(
+ {{"@odata.id", "/redfish/v1/Systems/system/LogServices/"
+ "System/Entries/" +
+ logID}});
+ }
+ asyncResp->res.jsonValue["Members@odata.count"] =
+ logArray.size();
+ },
+ "xyz.openbmc_project.ObjectMapper",
+ "/xyz/openbmc_project/object_mapper",
+ "xyz.openbmc_project.ObjectMapper", "GetSubTree",
+ "/xyz/openbmc_project/dump", 0,
+ std::array<const char *, 1>{
+ "xyz.openbmc_project.Dump.Entry.System"});
+ }
+};
+
+class SystemDumpEntry : public Node
+{
+ public:
+ SystemDumpEntry(CrowApp &app) :
+ Node(app,
+ "/redfish/v1/Systems/system/LogServices/System/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(crow::Response &res, const crow::Request &req,
+ const std::vector<std::string> &params) override
+ {
+ std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
+ if (params.size() != 1)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ const std::string &entryID = params[0];
+ crow::connections::systemBus->async_method_call(
+ [asyncResp, entryID](const boost::system::error_code ec,
+ GetManagedObjectsType &resp) {
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR
+ << "SystemDumpEntry resp_handler got error " << ec;
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ for (auto &objectPath : resp)
+ {
+ if (objectPath.first.str.find(
+ "/xyz/openbmc_project/dump/entry/" + entryID) ==
+ std::string::npos)
+ {
+ continue;
+ }
+
+ bool foundSystemDumpEntry = false;
+ for (auto &interfaceMap : objectPath.second)
+ {
+ if (interfaceMap.first ==
+ "xyz.openbmc_project.Dump.Entry.System")
+ {
+ foundSystemDumpEntry = true;
+ break;
+ }
+ }
+ if (foundSystemDumpEntry == false)
+ {
+ BMCWEB_LOG_DEBUG << "Can't find System Dump Entry";
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ std::string timestamp{};
+ uint64_t size = 0;
+
+ for (auto &interfaceMap : objectPath.second)
+ {
+ if (interfaceMap.first ==
+ "xyz.openbmc_project.Dump.Entry")
+ {
+ for (auto &propertyMap : interfaceMap.second)
+ {
+ if (propertyMap.first == "Size")
+ {
+ auto sizePtr = std::get_if<uint64_t>(
+ &propertyMap.second);
+ if (sizePtr == nullptr)
+ {
+ messages::propertyMissing(
+ asyncResp->res, "Size");
+ break;
+ }
+ size = *sizePtr;
+ break;
+ }
+ }
+ }
+ else if (interfaceMap.first ==
+ "xyz.openbmc_project.Time.EpochTime")
+ {
+ for (auto &propertyMap : interfaceMap.second)
+ {
+ if (propertyMap.first == "Elapsed")
+ {
+ const uint64_t *usecsTimeStamp =
+ std::get_if<uint64_t>(
+ &propertyMap.second);
+ if (usecsTimeStamp == nullptr)
+ {
+ messages::propertyMissing(
+ asyncResp->res, "Elapsed");
+ break;
+ }
+ getTimestampStr(*usecsTimeStamp, timestamp);
+ break;
+ }
+ }
+ }
+ }
+ asyncResp->res.jsonValue = {
+ {"@odata.type", "#LogEntry.v1_4_0.LogEntry"},
+ {"@odata.id",
+ "/redfish/v1/Systems/system/LogServices/System/"
+ "Entries/" +
+ entryID},
+ {"Name", "System Dump Entry"},
+ {"Id", entryID},
+ {"SizeInB", size},
+ {"EntryType", "Dump"},
+ {"EntryCode", "User generated dump"},
+ {"Created", timestamp}};
+
+ asyncResp->res
+ .jsonValue["Actions"]["#LogEntry.DownloadLog"] = {
+ {"target",
+ "/redfish/v1/Systems/system/LogServices/System/"
+ "Entries/" +
+ entryID + "/Actions/LogEntry.DownloadLog"}};
+ }
+ },
+ "xyz.openbmc_project.Dump.Manager", "/xyz/openbmc_project/dump",
+ "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
+ }
+
+ void doDelete(crow::Response &res, const crow::Request &req,
+ const std::vector<std::string> &params) override
+ {
+ BMCWEB_LOG_DEBUG << "Do delete single dump entry";
+
+ auto asyncResp = std::make_shared<AsyncResp>(res);
+
+ if (params.size() != 1)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ std::string entryID = params[0];
+
+ crow::connections::systemBus->async_method_call(
+ [asyncResp,
+ entryID](const boost::system::error_code ec,
+ const crow::openbmc_mapper::GetSubTreeType &resp) {
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR << " resp_handler got error " << ec;
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ for (auto &object : resp)
+ {
+ const std::string &path =
+ static_cast<const std::string &>(object.first);
+
+ std::size_t pos = path.rfind(
+ "/xyz/openbmc_project/dump/entry/" + entryID);
+ if (pos != std::string::npos)
+ {
+ deleteSystemDumpEntry(asyncResp->res, entryID);
+ return;
+ }
+ }
+ },
+ "xyz.openbmc_project.ObjectMapper",
+ "/xyz/openbmc_project/object_mapper",
+ "xyz.openbmc_project.ObjectMapper", "GetSubTree",
+ "/xyz/openbmc_project/dump", 0,
+ std::array<const char *, 1>{
+ "xyz.openbmc_project.Dump.Entry.System"});
+ }
+};
+
class CrashdumpService : public Node
{
public: