diff options
Diffstat (limited to 'redfish-core/lib/log_services.hpp')
-rw-r--r-- | redfish-core/lib/log_services.hpp | 214 |
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, |