summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAsmitha Karunanithi <asmitk01@in.ibm.com>2020-12-10 12:35:05 +0300
committerAsmitha Karunanithi <asmitk01@in.ibm.com>2022-10-11 19:45:46 +0300
commit8e31778e76b90c9a36ef40fff898d6218c649df6 (patch)
tree662b7c91ca5ff59c7ed5cc5203eae5a6bcd43bbe
parent9db4ba251522a6499e55b9060a796f89390bbb3d (diff)
downloadbmcweb-8e31778e76b90c9a36ef40fff898d6218c649df6.tar.xz
CreateDump: Accept dump object path
This commit contains changes to accept the object path instead of the dumpId for user-initiated dumps. Earlier a task would be started to monitor the 'interfaces added' signal when a new dump object is created. Now, this change checks if the created dump object has implemented Progress interface, if yes, then the 'Status' property is used to track the dump creation progress. Else, task will be marked completed. With this change failed dumps will now be returning an internal error back to the user, as a part of the task message. The createDump dbus call has been changed in the backend to accept additional arguments with the below commits: [1] https://gerrit.openbmc-project.xyz/c/openbmc/phosphor-dbus-interfaces/+/36331 [2] https://gerrit.openbmc-project.xyz/c/openbmc/phosphor-debug-collector/+/37792 [3] https://gerrit.openbmc-project.xyz/c/openbmc/phosphor-dbus-interfaces/+/44380 This commit also bumps up the task timeout. During system boot, the BMC dump takes more than 3 minutes to complete and task expires with a timeout. This commit increases this timeout to be 6 minutes. Tested-By: * POST https://${bmc}/redfish/v1/Managers/bmc/LogServices/Dump/Actions/ LogService.CollectDiagnosticData -d '{"DiagnosticDataType":"Manager"}' => A task will be returned as the redfish response * GET https://${bmc}/redfish/v1/TaskService/Tasks/1 => Get on the task URI to verify the task status for success and failure scenarios Signed-off-by: Asmitha Karunanithi <asmitk01@in.ibm.com> Change-Id: I1686823a86eae836f770c19f33ffb21c98dd79ef
-rw-r--r--redfish-core/lib/log_services.hpp214
1 files changed, 176 insertions, 38 deletions
diff --git a/redfish-core/lib/log_services.hpp b/redfish-core/lib/log_services.hpp
index ec873b1ac7..5e732fb83f 100644
--- a/redfish-core/lib/log_services.hpp
+++ b/redfish-core/lib/log_services.hpp
@@ -24,6 +24,7 @@
#include "task.hpp"
#include <systemd/sd-journal.h>
+#include <tinyxml2.h>
#include <unistd.h>
#include <app.hpp>
@@ -63,6 +64,13 @@ constexpr char const* crashdumpOnDemandInterface =
constexpr char const* crashdumpTelemetryInterface =
"com.intel.crashdump.Telemetry";
+enum class DumpCreationProgress
+{
+ DUMP_CREATE_SUCCESS,
+ DUMP_CREATE_FAILED,
+ DUMP_CREATE_INPROGRESS
+};
+
namespace registries
{
static const Message*
@@ -658,53 +666,182 @@ inline void deleteDumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
"xyz.openbmc_project.Object.Delete", "Delete");
}
-inline void
- createDumpTaskCallback(task::Payload&& payload,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const uint32_t& dumpId, const std::string& dumpPath,
- const std::string& dumpType)
+inline DumpCreationProgress
+ mapDbusStatusToDumpProgress(const std::string& status)
{
- std::shared_ptr<task::TaskData> task = task::TaskData::createTask(
- [dumpId, dumpPath,
- dumpType](boost::system::error_code err, sdbusplus::message_t& m,
- const std::shared_ptr<task::TaskData>& taskData) {
- if (err)
+ if (status ==
+ "xyz.openbmc_project.Common.Progress.OperationStatus.Failed" ||
+ status == "xyz.openbmc_project.Common.Progress.OperationStatus.Aborted")
+ {
+ return DumpCreationProgress::DUMP_CREATE_FAILED;
+ }
+ if (status ==
+ "xyz.openbmc_project.Common.Progress.OperationStatus.Completed")
+ {
+ return DumpCreationProgress::DUMP_CREATE_SUCCESS;
+ }
+ return DumpCreationProgress::DUMP_CREATE_INPROGRESS;
+}
+
+inline DumpCreationProgress
+ getDumpCompletionStatus(const dbus::utility::DBusPropertiesMap& values)
+{
+ for (const auto& [key, val] : values)
+ {
+ if (key == "Status")
{
- BMCWEB_LOG_ERROR << "Error in creating a dump";
- taskData->state = "Cancelled";
- return task::completed;
+ const std::string* value = std::get_if<std::string>(&val);
+ if (value == nullptr)
+ {
+ BMCWEB_LOG_ERROR << "Status property value is null";
+ return DumpCreationProgress::DUMP_CREATE_FAILED;
+ }
+ return mapDbusStatusToDumpProgress(*value);
}
+ }
+ return DumpCreationProgress::DUMP_CREATE_INPROGRESS;
+}
- dbus::utility::DBusInteracesMap interfacesList;
+inline std::string getDumpEntryPath(const std::string& dumpPath)
+{
+ if (dumpPath == "/xyz/openbmc_project/dump/bmc/entry")
+ {
+ return "/redfish/v1/Managers/bmc/LogServices/Dump/Entries/";
+ }
+ if (dumpPath == "/xyz/openbmc_project/dump/system/entry")
+ {
+ return "/redfish/v1/Systems/system/LogServices/Dump/Entries/";
+ }
+ return "";
+}
+
+inline void createDumpTaskCallback(
+ task::Payload&& payload,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const sdbusplus::message::object_path& createdObjPath)
+{
+ const std::string dumpPath = createdObjPath.parent_path().str;
+ const std::string dumpId = createdObjPath.filename();
- sdbusplus::message::object_path objPath;
+ std::string dumpEntryPath = getDumpEntryPath(dumpPath);
- m.read(objPath, interfacesList);
+ if (dumpEntryPath.empty())
+ {
+ BMCWEB_LOG_ERROR << "Invalid dump type received";
+ messages::internalError(asyncResp->res);
+ return;
+ }
- if (objPath.str ==
- "/xyz/openbmc_project/dump/" +
- std::string(boost::algorithm::to_lower_copy(dumpType)) +
- "/entry/" + std::to_string(dumpId))
+ crow::connections::systemBus->async_method_call(
+ [asyncResp, payload, createdObjPath,
+ dumpEntryPath{std::move(dumpEntryPath)},
+ dumpId](const boost::system::error_code ec,
+ const std::string& introspectXml) {
+ if (ec)
{
+ BMCWEB_LOG_ERROR << "Introspect call failed with error: "
+ << ec.message();
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ // Check if the created dump object has implemented Progress
+ // interface to track dump completion. If yes, fetch the "Status"
+ // property of the interface, modify the task state accordingly.
+ // Else, return task completed.
+ tinyxml2::XMLDocument doc;
+
+ doc.Parse(introspectXml.data(), introspectXml.size());
+ tinyxml2::XMLNode* pRoot = doc.FirstChildElement("node");
+ if (pRoot == nullptr)
+ {
+ BMCWEB_LOG_ERROR << "XML document failed to parse";
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ tinyxml2::XMLElement* interfaceNode =
+ pRoot->FirstChildElement("interface");
+
+ bool isProgressIntfPresent = false;
+ while (interfaceNode != nullptr)
+ {
+ const char* thisInterfaceName = interfaceNode->Attribute("name");
+ if (thisInterfaceName != nullptr)
+ {
+ if (thisInterfaceName ==
+ std::string_view("xyz.openbmc_project.Common.Progress"))
+ {
+ interfaceNode =
+ interfaceNode->NextSiblingElement("interface");
+ continue;
+ }
+ isProgressIntfPresent = true;
+ break;
+ }
+ interfaceNode = interfaceNode->NextSiblingElement("interface");
+ }
+
+ std::shared_ptr<task::TaskData> task = task::TaskData::createTask(
+ [createdObjPath, dumpEntryPath, dumpId, isProgressIntfPresent](
+ boost::system::error_code err, sdbusplus::message::message& msg,
+ const std::shared_ptr<task::TaskData>& taskData) {
+ if (err)
+ {
+ BMCWEB_LOG_ERROR << createdObjPath.str
+ << ": Error in creating dump";
+ taskData->messages.emplace_back(messages::internalError());
+ taskData->state = "Cancelled";
+ return task::completed;
+ }
+
+ if (isProgressIntfPresent)
+ {
+ dbus::utility::DBusPropertiesMap values;
+ std::string prop;
+ msg.read(prop, values);
+
+ DumpCreationProgress dumpStatus =
+ getDumpCompletionStatus(values);
+ if (dumpStatus == DumpCreationProgress::DUMP_CREATE_FAILED)
+ {
+ BMCWEB_LOG_ERROR << createdObjPath.str
+ << ": Error in creating dump";
+ taskData->state = "Cancelled";
+ return task::completed;
+ }
+
+ if (dumpStatus == DumpCreationProgress::DUMP_CREATE_INPROGRESS)
+ {
+ BMCWEB_LOG_DEBUG << createdObjPath.str
+ << ": Dump creation task is in progress";
+ return !task::completed;
+ }
+ }
+
nlohmann::json retMessage = messages::success();
taskData->messages.emplace_back(retMessage);
std::string headerLoc =
- "Location: " + dumpPath + std::to_string(dumpId);
+ "Location: " + dumpEntryPath + http_helpers::urlEncode(dumpId);
taskData->payload->httpHeaders.emplace_back(std::move(headerLoc));
+ BMCWEB_LOG_DEBUG << createdObjPath.str
+ << ": Dump creation task completed";
taskData->state = "Completed";
return task::completed;
- }
- return task::completed;
+ },
+ "type='signal',interface='org.freedesktop.DBus.Properties',"
+ "member='PropertiesChanged',path='" +
+ createdObjPath.str + "'");
+
+ // The task timer is set to max time limit within which the
+ // requested dump will be collected.
+ task->startTimer(std::chrono::minutes(6));
+ task->populateResp(asyncResp->res);
+ task->payload.emplace(payload);
},
- "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(std::move(payload));
+ "xyz.openbmc_project.Dump.Manager", createdObjPath,
+ "org.freedesktop.DBus.Introspectable", "Introspect");
}
inline void createDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
@@ -773,11 +910,14 @@ inline void createDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
return;
}
+ std::vector<std::pair<std::string, std::variant<std::string, uint64_t>>>
+ createDumpParamVec;
+
crow::connections::systemBus->async_method_call(
- [asyncResp, payload(task::Payload(req)), dumpPath,
- dumpType](const boost::system::error_code ec,
+ [asyncResp, payload(task::Payload(req)),
+ dumpPath](const boost::system::error_code ec,
const sdbusplus::message::message& msg,
- const uint32_t& dumpId) mutable {
+ const sdbusplus::message::object_path& objPath) mutable {
if (ec)
{
BMCWEB_LOG_ERROR << "CreateDump resp_handler got error " << ec;
@@ -821,15 +961,13 @@ inline void createDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
messages::internalError(asyncResp->res);
return;
}
- BMCWEB_LOG_DEBUG << "Dump Created. Id: " << dumpId;
-
- createDumpTaskCallback(std::move(payload), asyncResp, dumpId, dumpPath,
- dumpType);
+ BMCWEB_LOG_DEBUG << "Dump Created. Path: " << objPath.str;
+ createDumpTaskCallback(std::move(payload), asyncResp, objPath);
},
"xyz.openbmc_project.Dump.Manager",
"/xyz/openbmc_project/dump/" +
std::string(boost::algorithm::to_lower_copy(dumpType)),
- "xyz.openbmc_project.Dump.Create", "CreateDump");
+ "xyz.openbmc_project.Dump.Create", "CreateDump", createDumpParamVec);
}
inline void clearDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,