diff options
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0002-Match-BMCWeb-crashdump-to-the-D-Bus-interface-provid.patch')
-rw-r--r-- | meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0002-Match-BMCWeb-crashdump-to-the-D-Bus-interface-provid.patch | 331 |
1 files changed, 331 insertions, 0 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0002-Match-BMCWeb-crashdump-to-the-D-Bus-interface-provid.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0002-Match-BMCWeb-crashdump-to-the-D-Bus-interface-provid.patch new file mode 100644 index 000000000..995b62750 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0002-Match-BMCWeb-crashdump-to-the-D-Bus-interface-provid.patch @@ -0,0 +1,331 @@ +From 7c55dfb33e035f8a31f11fd3e047a4b674f392ac Mon Sep 17 00:00:00 2001 +From: Johnathan Mantey <johnathanx.mantey@intel.com> +Date: Tue, 10 Mar 2020 17:15:28 -0700 +Subject: [PATCH] Match BMCWeb crashdump to the D-Bus interface provided by + crashdump + +The crashdump service changed to eliminate hangs, and failures to +retrieve the crashdump data. The BMCWeb crashdump handling code has to +be aligned with the server. + +Tested: +Confirmed each of the primary functions operates as expected. +Getting the collection +Getting the entries +Forcing an on demand capture +Polling for the on demand capture to complete +Retrieving the creashdump data +Clearing all of the crashdump content + +Change-Id: Ie8fb48369a782d905b942c1f9bef11f387f6463e +Signed-off-by: Johnathan Mantey <johnathanx.mantey@intel.com> +--- + redfish-core/lib/log_services.hpp | 268 +++++++++++++++++------------- + 1 file changed, 150 insertions(+), 118 deletions(-) + +diff --git a/redfish-core/lib/log_services.hpp b/redfish-core/lib/log_services.hpp +index f864007..4b13897 100644 +--- a/redfish-core/lib/log_services.hpp ++++ b/redfish-core/lib/log_services.hpp +@@ -1575,109 +1575,80 @@ class CrashdumpClear : public Node + } + }; + +-std::string getLogCreatedTime(const std::string &crashdump) +-{ +- nlohmann::json crashdumpJson = +- nlohmann::json::parse(crashdump, nullptr, false); +- if (crashdumpJson.is_discarded()) +- { +- return std::string(); +- } +- +- nlohmann::json::const_iterator cdIt = crashdumpJson.find("crash_data"); +- if (cdIt == crashdumpJson.end()) +- { +- return std::string(); +- } +- +- nlohmann::json::const_iterator siIt = cdIt->find("METADATA"); +- if (siIt == cdIt->end()) +- { +- return std::string(); +- } +- +- nlohmann::json::const_iterator tsIt = siIt->find("timestamp"); +- if (tsIt == siIt->end()) +- { +- return std::string(); +- } +- +- const std::string *logTime = tsIt->get_ptr<const std::string *>(); +- if (logTime == nullptr) +- { +- return std::string(); +- } +- +- std::string redfishDateTime = *logTime; +- if (redfishDateTime.length() > 2) +- { +- redfishDateTime.insert(redfishDateTime.end() - 2, ':'); +- } +- +- return redfishDateTime; +-} +- +-std::string getLogFileName(const std::string &logTime) +-{ +- // Set the crashdump file name to "crashdump_<logTime>.json" using the +- // created time without the timezone info +- std::string fileTime = logTime; +- size_t plusPos = fileTime.rfind('+'); +- if (plusPos != std::string::npos) +- { +- fileTime.erase(plusPos); +- } +- return "crashdump_" + fileTime + ".json"; +-} +- + static void logCrashdumpEntry(std::shared_ptr<AsyncResp> asyncResp, + const std::string &logID, + nlohmann::json &logEntryJson) + { +- auto getStoredLogCallback = [asyncResp, logID, &logEntryJson]( +- const boost::system::error_code ec, +- const std::variant<std::string> &resp) { +- if (ec) +- { +- BMCWEB_LOG_DEBUG << "failed to get log ec: " << ec.message(); +- if (ec.value() == +- boost::system::linux_error::bad_request_descriptor) ++ auto getStoredLogCallback = ++ [asyncResp, logID, &logEntryJson]( ++ const boost::system::error_code ec, ++ const std::vector<std::pair<std::string, VariantType>> ¶ms) { ++ if (ec) + { +- messages::resourceNotFound(asyncResp->res, "LogEntry", logID); ++ BMCWEB_LOG_DEBUG << "failed to get log ec: " << ec.message(); ++ if (ec.value() == ++ boost::system::linux_error::bad_request_descriptor) ++ { ++ messages::resourceNotFound(asyncResp->res, "LogEntry", ++ logID); ++ } ++ else ++ { ++ messages::internalError(asyncResp->res); ++ } ++ return; + } +- else ++ ++ std::string timestamp{}; ++ std::string filename{}; ++ for (auto property : params) + { +- messages::internalError(asyncResp->res); ++ if (property.first == "Timestamp") ++ { ++ const std::string *value = ++ sdbusplus::message::variant_ns::get_if<std::string>( ++ &property.second); ++ if (value != nullptr) ++ { ++ timestamp = *value; ++ } ++ } ++ else if (property.first == "Filename") ++ { ++ const std::string *value = ++ sdbusplus::message::variant_ns::get_if<std::string>( ++ &property.second); ++ if (value != nullptr) ++ { ++ filename = *value; ++ } ++ } + } +- return; +- } +- const std::string *log = std::get_if<std::string>(&resp); +- if (log == nullptr) +- { +- messages::internalError(asyncResp->res); +- return; +- } +- std::string logTime = getLogCreatedTime(*log); +- std::string fileName = getLogFileName(logTime); + +- logEntryJson = { +- {"@odata.type", "#LogEntry.v1_4_0.LogEntry"}, +- {"@odata.id", +- "/redfish/v1/Systems/system/LogServices/Crashdump/Entries/" + +- logID}, +- {"Name", "CPU Crashdump"}, +- {"Id", logID}, +- {"EntryType", "Oem"}, +- {"OemRecordFormat", "Crashdump URI"}, +- {"Message", +- "/redfish/v1/Systems/system/LogServices/Crashdump/Entries/" + +- logID + "/" + fileName}, +- {"Created", std::move(logTime)}}; +- }; ++ if (filename.empty() || timestamp.empty()) ++ { ++ messages::resourceMissingAtURI(asyncResp->res, logID); ++ return; ++ } ++ ++ std::string crashdumpURI = ++ "/redfish/v1/Systems/system/LogServices/Crashdump/Entries/" + ++ logID + "/" + filename; ++ logEntryJson = {{"@odata.type", "#LogEntry.v1_4_0.LogEntry"}, ++ {"@odata.id", "/redfish/v1/Systems/system/" ++ "LogServices/Crashdump/Entries/" + ++ logID}, ++ {"Name", "CPU Crashdump"}, ++ {"Id", logID}, ++ {"EntryType", "Oem"}, ++ {"OemRecordFormat", "Crashdump URI"}, ++ {"Message", std::move(crashdumpURI)}, ++ {"Created", std::move(timestamp)}}; ++ }; + crow::connections::systemBus->async_method_call( + std::move(getStoredLogCallback), crashdumpObject, + crashdumpPath + std::string("/") + logID, +- "org.freedesktop.DBus.Properties", "Get", crashdumpInterface, "Log"); ++ "org.freedesktop.DBus.Properties", "GetAll", crashdumpInterface); + } + + class CrashdumpEntryCollection : public Node +@@ -1827,38 +1798,99 @@ class CrashdumpFile : public Node + const std::string &logID = params[0]; + const std::string &fileName = params[1]; + +- auto getStoredLogCallback = [asyncResp, logID, fileName]( +- const boost::system::error_code ec, +- const std::variant<std::string> &resp) { +- if (ec) +- { +- BMCWEB_LOG_DEBUG << "failed to get log ec: " << ec.message(); +- messages::internalError(asyncResp->res); +- return; +- } +- const std::string *log = std::get_if<std::string>(&resp); +- if (log == nullptr) +- { +- messages::internalError(asyncResp->res); +- return; +- } ++ 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; ++ } + +- // Verify the file name parameter is correct +- if (fileName != getLogFileName(getLogCreatedTime(*log))) +- { +- messages::resourceMissingAtURI(asyncResp->res, fileName); +- return; +- } ++ std::string dbusFilename{}; ++ std::string dbusTimestamp{}; ++ std::string dbusFilepath{}; + +- // Configure this to be a file download when accessed from a browser +- asyncResp->res.addHeader("Content-Disposition", "attachment"); +- asyncResp->res.body() = *log; +- }; ++ for (auto property : resp) ++ { ++ if (property.first == "Timestamp") ++ { ++ const std::string *value = ++ sdbusplus::message::variant_ns::get_if<std::string>( ++ &property.second); ++ if (value != nullptr) ++ { ++ dbusTimestamp = *value; ++ } ++ } ++ else if (property.first == "Filename") ++ { ++ const std::string *value = ++ sdbusplus::message::variant_ns::get_if<std::string>( ++ &property.second); ++ if (value != nullptr) ++ { ++ dbusFilename = *value; ++ } ++ } ++ else if (property.first == "Log") ++ { ++ const std::string *value = ++ sdbusplus::message::variant_ns::get_if<std::string>( ++ &property.second); ++ if (value != nullptr) ++ { ++ dbusFilepath = *value; ++ } ++ } ++ } ++ ++ if (dbusFilename.empty() || dbusTimestamp.empty() || ++ dbusFilepath.empty()) ++ { ++ messages::resourceMissingAtURI(asyncResp->res, fileName); ++ return; ++ } ++ ++ // Verify the file name parameter is correct ++ if (fileName != dbusFilename) ++ { ++ messages::resourceMissingAtURI(asyncResp->res, fileName); ++ 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) ++ { ++ messages::generalError(asyncResp->res); ++ return; ++ } ++ ifs.seekg(0, std::ios::beg); ++ ++ std::string dumpData; ++ dumpData.reserve(static_cast<unsigned int>(fileSize)); ++ ifs.read(dumpData.data(), static_cast<int>(fileSize)); ++ ++ // Configure this to be a file download when accessed from ++ // a browser ++ asyncResp->res.addHeader("Content-Disposition", "attachment"); ++ asyncResp->res.body() = dumpData.data(); ++ }; + crow::connections::systemBus->async_method_call( + std::move(getStoredLogCallback), crashdumpObject, + crashdumpPath + std::string("/") + logID, +- "org.freedesktop.DBus.Properties", "Get", crashdumpInterface, +- "Log"); ++ "org.freedesktop.DBus.Properties", "GetAll", crashdumpInterface); + } + }; + +-- +2.25.1 + |