Redfish: Creation of a BMC dump
This commit supports creation of a BMC dump entry.
After initiation of the dump creation, a task is
created that listens to "InterfaceAdded" signal over
"/xyz/openbmc_project/dump" path. Once the task is
completed, it returns the created BMC dump entry ID,
as a part of the task's message args as well as in
the task's http header.
Tested-By:
* curl -k -H "X-Auth-Token: $bmc_token" -X POST
https://${bmc}/redfish/v1/Managers/bmc/LogServices/
Dump/Actions/Oem/OemLogService.CollectDiagnosticData
-d '{"DiagnosticDataType" : "Managers",
"OEMDiagnosticDataType": ""}'
* curl -k -H "X-Auth-Token: $bmc_token" -X POST
https://${bmc}/redfish/v1/Systems/system/LogServices/
Dump/Actions/Oem/OemLogService.CollectDiagnosticData
-d '{"DiagnosticDataType" : "OEM", "OEMDiagnosticDataType":
"System"}'
<Returns a Task>
* curl -k -H "X-Auth-Token: $bmc_token" -X GET
https://${bmc}/redfish/v1/TaskService/Tasks/<task-id>
<Returns Dump ID on completion>
Signed-off-by: Asmitha Karunanithi <asmitk01@in.ibm.com>
Change-Id: Ide44b6abda797d738851123f06696558bab05ce0
diff --git a/redfish-core/include/redfish.hpp b/redfish-core/include/redfish.hpp
index 5dee66b..bf7b38b 100644
--- a/redfish-core/include/redfish.hpp
+++ b/redfish-core/include/redfish.hpp
@@ -108,13 +108,14 @@
nodes.emplace_back(std::make_unique<SystemDumpService>(app));
nodes.emplace_back(std::make_unique<SystemDumpEntryCollection>(app));
nodes.emplace_back(std::make_unique<SystemDumpEntry>(app));
+ nodes.emplace_back(std::make_unique<SystemDumpCreate>(app));
nodes.emplace_back(std::make_unique<SystemDumpEntryDownload>(app));
nodes.emplace_back(std::make_unique<SystemDumpClear>(app));
nodes.emplace_back(std::make_unique<BMCDumpService>(app));
nodes.emplace_back(std::make_unique<BMCDumpEntryCollection>(app));
nodes.emplace_back(std::make_unique<BMCDumpEntry>(app));
-
+ nodes.emplace_back(std::make_unique<BMCDumpCreate>(app));
#endif
#ifndef BMCWEB_ENABLE_REDFISH_DBUS_LOG_ENTRIES
diff --git a/redfish-core/lib/log_services.hpp b/redfish-core/lib/log_services.hpp
index 22c3ad7..1643c3a 100644
--- a/redfish-core/lib/log_services.hpp
+++ b/redfish-core/lib/log_services.hpp
@@ -739,6 +739,143 @@
"xyz.openbmc_project.Object.Delete", "Delete");
}
+inline void createDumpTaskCallback(const crow::Request& req,
+ std::shared_ptr<AsyncResp> asyncResp,
+ const uint32_t& dumpId,
+ const std::string& dumpPath,
+ const std::string& dumpType)
+{
+ std::shared_ptr<task::TaskData> task = task::TaskData::createTask(
+ [dumpId, dumpPath, dumpType](
+ boost::system::error_code err, sdbusplus::message::message& m,
+ const std::shared_ptr<task::TaskData>& taskData) {
+ std::vector<std::pair<
+ std::string,
+ std::vector<std::pair<std::string, std::variant<std::string>>>>>
+ interfacesList;
+
+ sdbusplus::message::object_path objPath;
+
+ m.read(objPath, interfacesList);
+
+ for (auto& interface : interfacesList)
+ {
+ if (interface.first ==
+ ("xyz.openbmc_project.Dump.Entry." + dumpType))
+ {
+ nlohmann::json retMessage = messages::success();
+ taskData->messages.emplace_back(retMessage);
+
+ std::string headerLoc =
+ "Location: " + dumpPath + std::to_string(dumpId);
+ taskData->payload->httpHeaders.emplace_back(
+ std::move(headerLoc));
+
+ taskData->state = "Completed";
+ return task::completed;
+ }
+ }
+ return !task::completed;
+ },
+ "type='signal',interface='org.freedesktop.DBus."
+ "ObjectManager',"
+ "member='InterfacesAdded', "
+ "path='/xyz/openbmc_project/dump'");
+
+ task->startTimer(std::chrono::minutes(3));
+ task->populateResp(asyncResp->res);
+ task->payload.emplace(req);
+}
+
+inline void createDump(crow::Response& res, const crow::Request& req,
+ const std::string& dumpType)
+{
+ std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
+
+ std::string dumpPath;
+ if (dumpType == "BMC")
+ {
+ dumpPath = "/redfish/v1/Managers/bmc/LogServices/Dump/Entries/";
+ }
+ else if (dumpType == "System")
+ {
+ dumpPath = "/redfish/v1/Systems/system/LogServices/Dump/Entries/";
+ }
+ else
+ {
+ BMCWEB_LOG_ERROR << "Invalid dump type: " << dumpType;
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ std::optional<std::string> diagnosticDataType;
+ std::optional<std::string> oemDiagnosticDataType;
+
+ if (!redfish::json_util::readJson(
+ req, asyncResp->res, "DiagnosticDataType", diagnosticDataType,
+ "OEMDiagnosticDataType", oemDiagnosticDataType))
+ {
+ return;
+ }
+
+ if (dumpType == "System")
+ {
+ if (!oemDiagnosticDataType || !diagnosticDataType)
+ {
+ BMCWEB_LOG_ERROR << "CreateDump action parameter "
+ "'DiagnosticDataType'/"
+ "'OEMDiagnosticDataType' value not found!";
+ messages::actionParameterMissing(
+ asyncResp->res, "CollectDiagnosticData",
+ "DiagnosticDataType & OEMDiagnosticDataType");
+ return;
+ }
+ else if ((*oemDiagnosticDataType != "System") ||
+ (*diagnosticDataType != "OEM"))
+ {
+ BMCWEB_LOG_ERROR << "Wrong parameter values passed";
+ messages::invalidObject(asyncResp->res,
+ "System Dump creation parameters");
+ return;
+ }
+ }
+ else if (dumpType == "BMC")
+ {
+ if (!diagnosticDataType)
+ {
+ BMCWEB_LOG_ERROR << "CreateDump action parameter "
+ "'DiagnosticDataType' not found!";
+ messages::actionParameterMissing(
+ asyncResp->res, "CollectDiagnosticData", "DiagnosticDataType");
+ return;
+ }
+ else if (*diagnosticDataType != "Manager")
+ {
+ BMCWEB_LOG_ERROR
+ << "Wrong parameter value passed for 'DiagnosticDataType'";
+ messages::invalidObject(asyncResp->res,
+ "BMC Dump creation parameters");
+ return;
+ }
+ }
+
+ crow::connections::systemBus->async_method_call(
+ [asyncResp, req, dumpPath, dumpType](const boost::system::error_code ec,
+ const uint32_t& dumpId) {
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR << "CreateDump resp_handler got error " << ec;
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ BMCWEB_LOG_DEBUG << "Dump Created. Id: " << dumpId;
+
+ createDumpTaskCallback(req, asyncResp, dumpId, dumpPath, dumpType);
+ },
+ "xyz.openbmc_project.Dump.Manager", "/xyz/openbmc_project/dump",
+ "xyz.openbmc_project.Dump.Create", "CreateDump");
+}
+
static void ParseCrashdumpParameters(
const std::vector<std::pair<std::string, VariantType>>& params,
std::string& filename, std::string& timestamp, std::string& logfile)
@@ -1971,6 +2108,31 @@
}
};
+class BMCDumpCreate : public Node
+{
+ public:
+ BMCDumpCreate(CrowApp& app) :
+ Node(app, "/redfish/v1/Managers/bmc/LogServices/Dump/"
+ "Actions/Oem/"
+ "OemLogService.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(crow::Response& res, const crow::Request& req,
+ const std::vector<std::string>& params) override
+ {
+ createDump(res, req, "BMC");
+ }
+};
+
class SystemDumpService : public Node
{
public:
@@ -2095,6 +2257,31 @@
}
};
+class SystemDumpCreate : public Node
+{
+ public:
+ SystemDumpCreate(CrowApp& app) :
+ Node(app, "/redfish/v1/Systems/system/LogServices/Dump/"
+ "Actions/Oem/"
+ "OemLogService.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(crow::Response& res, const crow::Request& req,
+ const std::vector<std::string>& params) override
+ {
+ createDump(res, req, "System");
+ }
+};
+
class SystemDumpEntryDownload : public Node
{
public: