1*40e9b92eSEd Tanous // SPDX-License-Identifier: Apache-2.0 2*40e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright OpenBMC Authors 3*40e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright 2018 Intel Corporation 41da66f75SEd Tanous #pragma once 51da66f75SEd Tanous 63ccb3adbSEd Tanous #include "app.hpp" 77a1dbc48SGeorge Liu #include "dbus_utility.hpp" 83ccb3adbSEd Tanous #include "error_messages.hpp" 968dd075aSAsmitha Karunanithi #include "generated/enums/log_entry.hpp" 10539d8c6bSEd Tanous #include "generated/enums/log_service.hpp" 11b7028ebfSSpencer Ku #include "gzfile.hpp" 12647b3cdcSGeorge Liu #include "http_utility.hpp" 13b7028ebfSSpencer Ku #include "human_sort.hpp" 143ccb3adbSEd Tanous #include "query.hpp" 154851d45dSJason M. Bills #include "registries.hpp" 164851d45dSJason M. Bills #include "registries/base_message_registry.hpp" 174851d45dSJason M. Bills #include "registries/openbmc_message_registry.hpp" 183ccb3adbSEd Tanous #include "registries/privilege_registry.hpp" 1946229577SJames Feist #include "task.hpp" 205b90429aSEd Tanous #include "task_messages.hpp" 21262dcc1cSAlexander Hansen #include "utils/dbus_event_log_entry.hpp" 223ccb3adbSEd Tanous #include "utils/dbus_utils.hpp" 235b90429aSEd Tanous #include "utils/json_utils.hpp" 243ccb3adbSEd Tanous #include "utils/time_utils.hpp" 251da66f75SEd Tanous 2675e8e218SMyung Bae #include <systemd/sd-id128.h> 278e31778eSAsmitha Karunanithi #include <tinyxml2.h> 28400fd1fbSAdriana Kobylak #include <unistd.h> 29e1f26343SJason M. Bills 3007c8c20dSEd Tanous #include <boost/beast/http/verb.hpp> 311da66f75SEd Tanous #include <boost/container/flat_map.hpp> 321ddcf01aSJason M. Bills #include <boost/system/linux_error.hpp> 33ef4c65b7SEd Tanous #include <boost/url/format.hpp> 34d1bde9e5SKrzysztof Grobelny #include <sdbusplus/asio/property.hpp> 35d1bde9e5SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp> 361214b7e7SGunnar Mills 377a1dbc48SGeorge Liu #include <array> 38647b3cdcSGeorge Liu #include <charconv> 39b5f288d2SAbhilash Raju #include <cstddef> 404418c7f0SJames Feist #include <filesystem> 4118f8f608SEd Tanous #include <iterator> 4275710de2SXiaochao Ma #include <optional> 433544d2a7SEd Tanous #include <ranges> 4426702d01SEd Tanous #include <span> 4518f8f608SEd Tanous #include <string> 46cd225da8SJason M. Bills #include <string_view> 47abf2add6SEd Tanous #include <variant> 481da66f75SEd Tanous 491da66f75SEd Tanous namespace redfish 501da66f75SEd Tanous { 511da66f75SEd Tanous 5289492a15SPatrick Williams constexpr const char* crashdumpObject = "com.intel.crashdump"; 5389492a15SPatrick Williams constexpr const char* crashdumpPath = "/com/intel/crashdump"; 5489492a15SPatrick Williams constexpr const char* crashdumpInterface = "com.intel.crashdump"; 5589492a15SPatrick Williams constexpr const char* deleteAllInterface = 565b61b5e8SJason M. Bills "xyz.openbmc_project.Collection.DeleteAll"; 5789492a15SPatrick Williams constexpr const char* crashdumpOnDemandInterface = 58424c4176SJason M. Bills "com.intel.crashdump.OnDemand"; 5989492a15SPatrick Williams constexpr const char* crashdumpTelemetryInterface = 606eda7685SKenny L. Ku "com.intel.crashdump.Telemetry"; 611da66f75SEd Tanous 628e31778eSAsmitha Karunanithi enum class DumpCreationProgress 638e31778eSAsmitha Karunanithi { 648e31778eSAsmitha Karunanithi DUMP_CREATE_SUCCESS, 658e31778eSAsmitha Karunanithi DUMP_CREATE_FAILED, 668e31778eSAsmitha Karunanithi DUMP_CREATE_INPROGRESS 678e31778eSAsmitha Karunanithi }; 688e31778eSAsmitha Karunanithi 69f6150403SJames Feist namespace fs = std::filesystem; 701da66f75SEd Tanous 71cb92c03bSAndrew Geissler inline std::string translateSeverityDbusToRedfish(const std::string& s) 72cb92c03bSAndrew Geissler { 73d4d25793SEd Tanous if ((s == "xyz.openbmc_project.Logging.Entry.Level.Alert") || 74d4d25793SEd Tanous (s == "xyz.openbmc_project.Logging.Entry.Level.Critical") || 75d4d25793SEd Tanous (s == "xyz.openbmc_project.Logging.Entry.Level.Emergency") || 76d4d25793SEd Tanous (s == "xyz.openbmc_project.Logging.Entry.Level.Error")) 77cb92c03bSAndrew Geissler { 78cb92c03bSAndrew Geissler return "Critical"; 79cb92c03bSAndrew Geissler } 803174e4dfSEd Tanous if ((s == "xyz.openbmc_project.Logging.Entry.Level.Debug") || 81d4d25793SEd Tanous (s == "xyz.openbmc_project.Logging.Entry.Level.Informational") || 82d4d25793SEd Tanous (s == "xyz.openbmc_project.Logging.Entry.Level.Notice")) 83cb92c03bSAndrew Geissler { 84cb92c03bSAndrew Geissler return "OK"; 85cb92c03bSAndrew Geissler } 863174e4dfSEd Tanous if (s == "xyz.openbmc_project.Logging.Entry.Level.Warning") 87cb92c03bSAndrew Geissler { 88cb92c03bSAndrew Geissler return "Warning"; 89cb92c03bSAndrew Geissler } 90cb92c03bSAndrew Geissler return ""; 91cb92c03bSAndrew Geissler } 92cb92c03bSAndrew Geissler 939017faf2SAbhishek Patel inline std::optional<bool> getProviderNotifyAction(const std::string& notify) 949017faf2SAbhishek Patel { 959017faf2SAbhishek Patel std::optional<bool> notifyAction; 969017faf2SAbhishek Patel if (notify == "xyz.openbmc_project.Logging.Entry.Notify.Notify") 979017faf2SAbhishek Patel { 989017faf2SAbhishek Patel notifyAction = true; 999017faf2SAbhishek Patel } 1009017faf2SAbhishek Patel else if (notify == "xyz.openbmc_project.Logging.Entry.Notify.Inhibit") 1019017faf2SAbhishek Patel { 1029017faf2SAbhishek Patel notifyAction = false; 1039017faf2SAbhishek Patel } 1049017faf2SAbhishek Patel 1059017faf2SAbhishek Patel return notifyAction; 1069017faf2SAbhishek Patel } 1079017faf2SAbhishek Patel 10818f8f608SEd Tanous inline std::string getDumpPath(std::string_view dumpType) 10918f8f608SEd Tanous { 11018f8f608SEd Tanous std::string dbusDumpPath = "/xyz/openbmc_project/dump/"; 11118f8f608SEd Tanous std::ranges::transform(dumpType, std::back_inserter(dbusDumpPath), 11218f8f608SEd Tanous bmcweb::asciiToLower); 11318f8f608SEd Tanous 11418f8f608SEd Tanous return dbusDumpPath; 11518f8f608SEd Tanous } 11618f8f608SEd Tanous 117055713e4SEd Tanous inline bool getUniqueEntryID(const std::string& logEntry, std::string& entryID, 118e85d6b16SJason M. Bills const bool firstEntry = true) 11995820184SJason M. Bills { 120271584abSEd Tanous static time_t prevTs = 0; 12195820184SJason M. Bills static int index = 0; 122e85d6b16SJason M. Bills if (firstEntry) 123e85d6b16SJason M. Bills { 124e85d6b16SJason M. Bills prevTs = 0; 125e85d6b16SJason M. Bills } 126e85d6b16SJason M. Bills 12795820184SJason M. Bills // Get the entry timestamp 128271584abSEd Tanous std::time_t curTs = 0; 12995820184SJason M. Bills std::tm timeStruct = {}; 13095820184SJason M. Bills std::istringstream entryStream(logEntry); 13195820184SJason M. Bills if (entryStream >> std::get_time(&timeStruct, "%Y-%m-%dT%H:%M:%S")) 13295820184SJason M. Bills { 13395820184SJason M. Bills curTs = std::mktime(&timeStruct); 13495820184SJason M. Bills } 13595820184SJason M. Bills // If the timestamp isn't unique, increment the index 13695820184SJason M. Bills if (curTs == prevTs) 13795820184SJason M. Bills { 13895820184SJason M. Bills index++; 13995820184SJason M. Bills } 14095820184SJason M. Bills else 14195820184SJason M. Bills { 14295820184SJason M. Bills // Otherwise, reset it 14395820184SJason M. Bills index = 0; 14495820184SJason M. Bills } 14595820184SJason M. Bills // Save the timestamp 14695820184SJason M. Bills prevTs = curTs; 14795820184SJason M. Bills 14895820184SJason M. Bills entryID = std::to_string(curTs); 14995820184SJason M. Bills if (index > 0) 15095820184SJason M. Bills { 15195820184SJason M. Bills entryID += "_" + std::to_string(index); 15295820184SJason M. Bills } 15395820184SJason M. Bills return true; 15495820184SJason M. Bills } 15595820184SJason M. Bills 1564ff0f1f4SEd Tanous inline bool 15795820184SJason M. Bills getRedfishLogFiles(std::vector<std::filesystem::path>& redfishLogFiles) 15895820184SJason M. Bills { 15995820184SJason M. Bills static const std::filesystem::path redfishLogDir = "/var/log"; 16095820184SJason M. Bills static const std::string redfishLogFilename = "redfish"; 16195820184SJason M. Bills 16295820184SJason M. Bills // Loop through the directory looking for redfish log files 16395820184SJason M. Bills for (const std::filesystem::directory_entry& dirEnt : 16495820184SJason M. Bills std::filesystem::directory_iterator(redfishLogDir)) 16595820184SJason M. Bills { 16695820184SJason M. Bills // If we find a redfish log file, save the path 16795820184SJason M. Bills std::string filename = dirEnt.path().filename(); 16811ba3979SEd Tanous if (filename.starts_with(redfishLogFilename)) 16995820184SJason M. Bills { 17095820184SJason M. Bills redfishLogFiles.emplace_back(redfishLogDir / filename); 17195820184SJason M. Bills } 17295820184SJason M. Bills } 17395820184SJason M. Bills // As the log files rotate, they are appended with a ".#" that is higher for 17495820184SJason M. Bills // the older logs. Since we don't expect more than 10 log files, we 17595820184SJason M. Bills // can just sort the list to get them in order from newest to oldest 1763544d2a7SEd Tanous std::ranges::sort(redfishLogFiles); 17795820184SJason M. Bills 17895820184SJason M. Bills return !redfishLogFiles.empty(); 17995820184SJason M. Bills } 18095820184SJason M. Bills 18168dd075aSAsmitha Karunanithi inline log_entry::OriginatorTypes 18268dd075aSAsmitha Karunanithi mapDbusOriginatorTypeToRedfish(const std::string& originatorType) 18368dd075aSAsmitha Karunanithi { 18468dd075aSAsmitha Karunanithi if (originatorType == 18568dd075aSAsmitha Karunanithi "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Client") 18668dd075aSAsmitha Karunanithi { 18768dd075aSAsmitha Karunanithi return log_entry::OriginatorTypes::Client; 18868dd075aSAsmitha Karunanithi } 18968dd075aSAsmitha Karunanithi if (originatorType == 19068dd075aSAsmitha Karunanithi "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Internal") 19168dd075aSAsmitha Karunanithi { 19268dd075aSAsmitha Karunanithi return log_entry::OriginatorTypes::Internal; 19368dd075aSAsmitha Karunanithi } 19468dd075aSAsmitha Karunanithi if (originatorType == 19568dd075aSAsmitha Karunanithi "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.SupportingService") 19668dd075aSAsmitha Karunanithi { 19768dd075aSAsmitha Karunanithi return log_entry::OriginatorTypes::SupportingService; 19868dd075aSAsmitha Karunanithi } 19968dd075aSAsmitha Karunanithi return log_entry::OriginatorTypes::Invalid; 20068dd075aSAsmitha Karunanithi } 20168dd075aSAsmitha Karunanithi 202aefe3786SClaire Weinan inline void parseDumpEntryFromDbusObject( 2032d613eb6SJiaqing Zhao const dbus::utility::ManagedObjectType::value_type& object, 204c6fecdabSClaire Weinan std::string& dumpStatus, uint64_t& size, uint64_t& timestampUs, 20568dd075aSAsmitha Karunanithi std::string& originatorId, log_entry::OriginatorTypes& originatorType, 206aefe3786SClaire Weinan const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 207aefe3786SClaire Weinan { 208aefe3786SClaire Weinan for (const auto& interfaceMap : object.second) 209aefe3786SClaire Weinan { 210aefe3786SClaire Weinan if (interfaceMap.first == "xyz.openbmc_project.Common.Progress") 211aefe3786SClaire Weinan { 212aefe3786SClaire Weinan for (const auto& propertyMap : interfaceMap.second) 213aefe3786SClaire Weinan { 214aefe3786SClaire Weinan if (propertyMap.first == "Status") 215aefe3786SClaire Weinan { 216aefe3786SClaire Weinan const auto* status = 217aefe3786SClaire Weinan std::get_if<std::string>(&propertyMap.second); 218aefe3786SClaire Weinan if (status == nullptr) 219aefe3786SClaire Weinan { 220aefe3786SClaire Weinan messages::internalError(asyncResp->res); 221aefe3786SClaire Weinan break; 222aefe3786SClaire Weinan } 223aefe3786SClaire Weinan dumpStatus = *status; 224aefe3786SClaire Weinan } 225aefe3786SClaire Weinan } 226aefe3786SClaire Weinan } 227aefe3786SClaire Weinan else if (interfaceMap.first == "xyz.openbmc_project.Dump.Entry") 228aefe3786SClaire Weinan { 229aefe3786SClaire Weinan for (const auto& propertyMap : interfaceMap.second) 230aefe3786SClaire Weinan { 231aefe3786SClaire Weinan if (propertyMap.first == "Size") 232aefe3786SClaire Weinan { 233aefe3786SClaire Weinan const auto* sizePtr = 234aefe3786SClaire Weinan std::get_if<uint64_t>(&propertyMap.second); 235aefe3786SClaire Weinan if (sizePtr == nullptr) 236aefe3786SClaire Weinan { 237aefe3786SClaire Weinan messages::internalError(asyncResp->res); 238aefe3786SClaire Weinan break; 239aefe3786SClaire Weinan } 240aefe3786SClaire Weinan size = *sizePtr; 241aefe3786SClaire Weinan break; 242aefe3786SClaire Weinan } 243aefe3786SClaire Weinan } 244aefe3786SClaire Weinan } 245aefe3786SClaire Weinan else if (interfaceMap.first == "xyz.openbmc_project.Time.EpochTime") 246aefe3786SClaire Weinan { 247aefe3786SClaire Weinan for (const auto& propertyMap : interfaceMap.second) 248aefe3786SClaire Weinan { 249aefe3786SClaire Weinan if (propertyMap.first == "Elapsed") 250aefe3786SClaire Weinan { 251aefe3786SClaire Weinan const uint64_t* usecsTimeStamp = 252aefe3786SClaire Weinan std::get_if<uint64_t>(&propertyMap.second); 253aefe3786SClaire Weinan if (usecsTimeStamp == nullptr) 254aefe3786SClaire Weinan { 255aefe3786SClaire Weinan messages::internalError(asyncResp->res); 256aefe3786SClaire Weinan break; 257aefe3786SClaire Weinan } 258c6fecdabSClaire Weinan timestampUs = *usecsTimeStamp; 259aefe3786SClaire Weinan break; 260aefe3786SClaire Weinan } 261aefe3786SClaire Weinan } 262aefe3786SClaire Weinan } 26368dd075aSAsmitha Karunanithi else if (interfaceMap.first == 26468dd075aSAsmitha Karunanithi "xyz.openbmc_project.Common.OriginatedBy") 26568dd075aSAsmitha Karunanithi { 26668dd075aSAsmitha Karunanithi for (const auto& propertyMap : interfaceMap.second) 26768dd075aSAsmitha Karunanithi { 26868dd075aSAsmitha Karunanithi if (propertyMap.first == "OriginatorId") 26968dd075aSAsmitha Karunanithi { 27068dd075aSAsmitha Karunanithi const std::string* id = 27168dd075aSAsmitha Karunanithi std::get_if<std::string>(&propertyMap.second); 27268dd075aSAsmitha Karunanithi if (id == nullptr) 27368dd075aSAsmitha Karunanithi { 27468dd075aSAsmitha Karunanithi messages::internalError(asyncResp->res); 27568dd075aSAsmitha Karunanithi break; 27668dd075aSAsmitha Karunanithi } 27768dd075aSAsmitha Karunanithi originatorId = *id; 27868dd075aSAsmitha Karunanithi } 27968dd075aSAsmitha Karunanithi 28068dd075aSAsmitha Karunanithi if (propertyMap.first == "OriginatorType") 28168dd075aSAsmitha Karunanithi { 28268dd075aSAsmitha Karunanithi const std::string* type = 28368dd075aSAsmitha Karunanithi std::get_if<std::string>(&propertyMap.second); 28468dd075aSAsmitha Karunanithi if (type == nullptr) 28568dd075aSAsmitha Karunanithi { 28668dd075aSAsmitha Karunanithi messages::internalError(asyncResp->res); 28768dd075aSAsmitha Karunanithi break; 28868dd075aSAsmitha Karunanithi } 28968dd075aSAsmitha Karunanithi 29068dd075aSAsmitha Karunanithi originatorType = mapDbusOriginatorTypeToRedfish(*type); 29168dd075aSAsmitha Karunanithi if (originatorType == log_entry::OriginatorTypes::Invalid) 29268dd075aSAsmitha Karunanithi { 29368dd075aSAsmitha Karunanithi messages::internalError(asyncResp->res); 29468dd075aSAsmitha Karunanithi break; 29568dd075aSAsmitha Karunanithi } 29668dd075aSAsmitha Karunanithi } 29768dd075aSAsmitha Karunanithi } 29868dd075aSAsmitha Karunanithi } 299aefe3786SClaire Weinan } 300aefe3786SClaire Weinan } 301aefe3786SClaire Weinan 30221ab404cSNan Zhou static std::string getDumpEntriesPath(const std::string& dumpType) 303fdd26906SClaire Weinan { 304fdd26906SClaire Weinan std::string entriesPath; 305fdd26906SClaire Weinan 306fdd26906SClaire Weinan if (dumpType == "BMC") 307fdd26906SClaire Weinan { 308253f11b8SEd Tanous entriesPath = 309253f11b8SEd Tanous std::format("/redfish/v1/Managers/{}/LogServices/Dump/Entries/", 310253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 311fdd26906SClaire Weinan } 312fdd26906SClaire Weinan else if (dumpType == "FaultLog") 313fdd26906SClaire Weinan { 314253f11b8SEd Tanous entriesPath = 315253f11b8SEd Tanous std::format("/redfish/v1/Managers/{}/LogServices/FaultLog/Entries/", 316253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 317fdd26906SClaire Weinan } 318fdd26906SClaire Weinan else if (dumpType == "System") 319fdd26906SClaire Weinan { 320253f11b8SEd Tanous entriesPath = 321253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/Dump/Entries/", 322253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 323fdd26906SClaire Weinan } 324fdd26906SClaire Weinan else 325fdd26906SClaire Weinan { 32662598e31SEd Tanous BMCWEB_LOG_ERROR("getDumpEntriesPath() invalid dump type: {}", 32762598e31SEd Tanous dumpType); 328fdd26906SClaire Weinan } 329fdd26906SClaire Weinan 330fdd26906SClaire Weinan // Returns empty string on error 331fdd26906SClaire Weinan return entriesPath; 332fdd26906SClaire Weinan } 333fdd26906SClaire Weinan 3348d1b46d7Szhanghch05 inline void 3358d1b46d7Szhanghch05 getDumpEntryCollection(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 3365cb1dd27SAsmitha Karunanithi const std::string& dumpType) 3375cb1dd27SAsmitha Karunanithi { 338fdd26906SClaire Weinan std::string entriesPath = getDumpEntriesPath(dumpType); 339fdd26906SClaire Weinan if (entriesPath.empty()) 3405cb1dd27SAsmitha Karunanithi { 3415cb1dd27SAsmitha Karunanithi messages::internalError(asyncResp->res); 3425cb1dd27SAsmitha Karunanithi return; 3435cb1dd27SAsmitha Karunanithi } 3445cb1dd27SAsmitha Karunanithi 3455eb468daSGeorge Liu sdbusplus::message::object_path path("/xyz/openbmc_project/dump"); 3465eb468daSGeorge Liu dbus::utility::getManagedObjects( 3475eb468daSGeorge Liu "xyz.openbmc_project.Dump.Manager", path, 348fdd26906SClaire Weinan [asyncResp, entriesPath, 3495e7e2dc5SEd Tanous dumpType](const boost::system::error_code& ec, 3505eb468daSGeorge Liu const dbus::utility::ManagedObjectType& objects) { 3515cb1dd27SAsmitha Karunanithi if (ec) 3525cb1dd27SAsmitha Karunanithi { 35362598e31SEd Tanous BMCWEB_LOG_ERROR("DumpEntry resp_handler got error {}", ec); 3545cb1dd27SAsmitha Karunanithi messages::internalError(asyncResp->res); 3555cb1dd27SAsmitha Karunanithi return; 3565cb1dd27SAsmitha Karunanithi } 3575cb1dd27SAsmitha Karunanithi 358fdd26906SClaire Weinan // Remove ending slash 359fdd26906SClaire Weinan std::string odataIdStr = entriesPath; 360fdd26906SClaire Weinan if (!odataIdStr.empty()) 361fdd26906SClaire Weinan { 362fdd26906SClaire Weinan odataIdStr.pop_back(); 363fdd26906SClaire Weinan } 364fdd26906SClaire Weinan 365fdd26906SClaire Weinan asyncResp->res.jsonValue["@odata.type"] = 366fdd26906SClaire Weinan "#LogEntryCollection.LogEntryCollection"; 367fdd26906SClaire Weinan asyncResp->res.jsonValue["@odata.id"] = std::move(odataIdStr); 368fdd26906SClaire Weinan asyncResp->res.jsonValue["Name"] = dumpType + " Dump Entries"; 369bd79bce8SPatrick Williams asyncResp->res.jsonValue["Description"] = 370bd79bce8SPatrick Williams "Collection of " + dumpType + " Dump Entries"; 371fdd26906SClaire Weinan 3723544d2a7SEd Tanous nlohmann::json::array_t entriesArray; 37318f8f608SEd Tanous std::string dumpEntryPath = getDumpPath(dumpType) + "/entry/"; 3745cb1dd27SAsmitha Karunanithi 3755eb468daSGeorge Liu dbus::utility::ManagedObjectType resp(objects); 3763544d2a7SEd Tanous std::ranges::sort(resp, [](const auto& l, const auto& r) { 377002d39b4SEd Tanous return AlphanumLess<std::string>()(l.first.filename(), 378002d39b4SEd Tanous r.first.filename()); 379565dfb6fSClaire Weinan }); 380565dfb6fSClaire Weinan 3815cb1dd27SAsmitha Karunanithi for (auto& object : resp) 3825cb1dd27SAsmitha Karunanithi { 383b47452b2SAsmitha Karunanithi if (object.first.str.find(dumpEntryPath) == std::string::npos) 3845cb1dd27SAsmitha Karunanithi { 3855cb1dd27SAsmitha Karunanithi continue; 3865cb1dd27SAsmitha Karunanithi } 387c6fecdabSClaire Weinan uint64_t timestampUs = 0; 3885cb1dd27SAsmitha Karunanithi uint64_t size = 0; 38935440d18SAsmitha Karunanithi std::string dumpStatus; 39068dd075aSAsmitha Karunanithi std::string originatorId; 39168dd075aSAsmitha Karunanithi log_entry::OriginatorTypes originatorType = 39268dd075aSAsmitha Karunanithi log_entry::OriginatorTypes::Internal; 393433b68b4SJason M. Bills nlohmann::json::object_t thisEntry; 3942dfd18efSEd Tanous 3952dfd18efSEd Tanous std::string entryID = object.first.filename(); 3962dfd18efSEd Tanous if (entryID.empty()) 3975cb1dd27SAsmitha Karunanithi { 3985cb1dd27SAsmitha Karunanithi continue; 3995cb1dd27SAsmitha Karunanithi } 4005cb1dd27SAsmitha Karunanithi 401bd79bce8SPatrick Williams parseDumpEntryFromDbusObject(object, dumpStatus, size, 402bd79bce8SPatrick Williams timestampUs, originatorId, 403bd79bce8SPatrick Williams originatorType, asyncResp); 4045cb1dd27SAsmitha Karunanithi 4050fda0f12SGeorge Liu if (dumpStatus != 4060fda0f12SGeorge Liu "xyz.openbmc_project.Common.Progress.OperationStatus.Completed" && 40735440d18SAsmitha Karunanithi !dumpStatus.empty()) 40835440d18SAsmitha Karunanithi { 40935440d18SAsmitha Karunanithi // Dump status is not Complete, no need to enumerate 41035440d18SAsmitha Karunanithi continue; 41135440d18SAsmitha Karunanithi } 41235440d18SAsmitha Karunanithi 41368dd075aSAsmitha Karunanithi thisEntry["@odata.type"] = "#LogEntry.v1_11_0.LogEntry"; 414fdd26906SClaire Weinan thisEntry["@odata.id"] = entriesPath + entryID; 4155cb1dd27SAsmitha Karunanithi thisEntry["Id"] = entryID; 4165cb1dd27SAsmitha Karunanithi thisEntry["EntryType"] = "Event"; 4175cb1dd27SAsmitha Karunanithi thisEntry["Name"] = dumpType + " Dump Entry"; 418bbd80db8SClaire Weinan thisEntry["Created"] = 419bbd80db8SClaire Weinan redfish::time_utils::getDateTimeUintUs(timestampUs); 4205cb1dd27SAsmitha Karunanithi 42168dd075aSAsmitha Karunanithi if (!originatorId.empty()) 42268dd075aSAsmitha Karunanithi { 42368dd075aSAsmitha Karunanithi thisEntry["Originator"] = originatorId; 42468dd075aSAsmitha Karunanithi thisEntry["OriginatorType"] = originatorType; 42568dd075aSAsmitha Karunanithi } 42668dd075aSAsmitha Karunanithi 4275cb1dd27SAsmitha Karunanithi if (dumpType == "BMC") 4285cb1dd27SAsmitha Karunanithi { 429d337bb72SAsmitha Karunanithi thisEntry["DiagnosticDataType"] = "Manager"; 430bd79bce8SPatrick Williams thisEntry["AdditionalDataURI"] = 431bd79bce8SPatrick Williams entriesPath + entryID + "/attachment"; 432fdd26906SClaire Weinan thisEntry["AdditionalDataSizeBytes"] = size; 4335cb1dd27SAsmitha Karunanithi } 4345cb1dd27SAsmitha Karunanithi else if (dumpType == "System") 4355cb1dd27SAsmitha Karunanithi { 436d337bb72SAsmitha Karunanithi thisEntry["DiagnosticDataType"] = "OEM"; 437d337bb72SAsmitha Karunanithi thisEntry["OEMDiagnosticDataType"] = "System"; 438bd79bce8SPatrick Williams thisEntry["AdditionalDataURI"] = 439bd79bce8SPatrick Williams entriesPath + entryID + "/attachment"; 440fdd26906SClaire Weinan thisEntry["AdditionalDataSizeBytes"] = size; 4415cb1dd27SAsmitha Karunanithi } 442b2ba3072SPatrick Williams entriesArray.emplace_back(std::move(thisEntry)); 4435cb1dd27SAsmitha Karunanithi } 444bd79bce8SPatrick Williams asyncResp->res.jsonValue["Members@odata.count"] = 445bd79bce8SPatrick Williams entriesArray.size(); 4463544d2a7SEd Tanous asyncResp->res.jsonValue["Members"] = std::move(entriesArray); 4475eb468daSGeorge Liu }); 4485cb1dd27SAsmitha Karunanithi } 4495cb1dd27SAsmitha Karunanithi 4508d1b46d7Szhanghch05 inline void 451c7a6d660SClaire Weinan getDumpEntryById(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 4528d1b46d7Szhanghch05 const std::string& entryID, const std::string& dumpType) 4535cb1dd27SAsmitha Karunanithi { 454fdd26906SClaire Weinan std::string entriesPath = getDumpEntriesPath(dumpType); 455fdd26906SClaire Weinan if (entriesPath.empty()) 4565cb1dd27SAsmitha Karunanithi { 4575cb1dd27SAsmitha Karunanithi messages::internalError(asyncResp->res); 4585cb1dd27SAsmitha Karunanithi return; 4595cb1dd27SAsmitha Karunanithi } 4605cb1dd27SAsmitha Karunanithi 4615eb468daSGeorge Liu sdbusplus::message::object_path path("/xyz/openbmc_project/dump"); 4625eb468daSGeorge Liu dbus::utility::getManagedObjects( 4635eb468daSGeorge Liu "xyz.openbmc_project.Dump.Manager", path, 464fdd26906SClaire Weinan [asyncResp, entryID, dumpType, 4655e7e2dc5SEd Tanous entriesPath](const boost::system::error_code& ec, 46602cad96eSEd Tanous const dbus::utility::ManagedObjectType& resp) { 4675cb1dd27SAsmitha Karunanithi if (ec) 4685cb1dd27SAsmitha Karunanithi { 46962598e31SEd Tanous BMCWEB_LOG_ERROR("DumpEntry resp_handler got error {}", ec); 4705cb1dd27SAsmitha Karunanithi messages::internalError(asyncResp->res); 4715cb1dd27SAsmitha Karunanithi return; 4725cb1dd27SAsmitha Karunanithi } 4735cb1dd27SAsmitha Karunanithi 474b47452b2SAsmitha Karunanithi bool foundDumpEntry = false; 47518f8f608SEd Tanous std::string dumpEntryPath = getDumpPath(dumpType) + "/entry/"; 476b47452b2SAsmitha Karunanithi 4779eb808c1SEd Tanous for (const auto& objectPath : resp) 4785cb1dd27SAsmitha Karunanithi { 479b47452b2SAsmitha Karunanithi if (objectPath.first.str != dumpEntryPath + entryID) 4805cb1dd27SAsmitha Karunanithi { 4815cb1dd27SAsmitha Karunanithi continue; 4825cb1dd27SAsmitha Karunanithi } 4835cb1dd27SAsmitha Karunanithi 4845cb1dd27SAsmitha Karunanithi foundDumpEntry = true; 485c6fecdabSClaire Weinan uint64_t timestampUs = 0; 4865cb1dd27SAsmitha Karunanithi uint64_t size = 0; 48735440d18SAsmitha Karunanithi std::string dumpStatus; 48868dd075aSAsmitha Karunanithi std::string originatorId; 48968dd075aSAsmitha Karunanithi log_entry::OriginatorTypes originatorType = 49068dd075aSAsmitha Karunanithi log_entry::OriginatorTypes::Internal; 4915cb1dd27SAsmitha Karunanithi 492aefe3786SClaire Weinan parseDumpEntryFromDbusObject(objectPath, dumpStatus, size, 49368dd075aSAsmitha Karunanithi timestampUs, originatorId, 49468dd075aSAsmitha Karunanithi originatorType, asyncResp); 4955cb1dd27SAsmitha Karunanithi 4960fda0f12SGeorge Liu if (dumpStatus != 4970fda0f12SGeorge Liu "xyz.openbmc_project.Common.Progress.OperationStatus.Completed" && 49835440d18SAsmitha Karunanithi !dumpStatus.empty()) 49935440d18SAsmitha Karunanithi { 50035440d18SAsmitha Karunanithi // Dump status is not Complete 50135440d18SAsmitha Karunanithi // return not found until status is changed to Completed 502bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, 503bd79bce8SPatrick Williams dumpType + " dump", entryID); 50435440d18SAsmitha Karunanithi return; 50535440d18SAsmitha Karunanithi } 50635440d18SAsmitha Karunanithi 5075cb1dd27SAsmitha Karunanithi asyncResp->res.jsonValue["@odata.type"] = 50868dd075aSAsmitha Karunanithi "#LogEntry.v1_11_0.LogEntry"; 509fdd26906SClaire Weinan asyncResp->res.jsonValue["@odata.id"] = entriesPath + entryID; 5105cb1dd27SAsmitha Karunanithi asyncResp->res.jsonValue["Id"] = entryID; 5115cb1dd27SAsmitha Karunanithi asyncResp->res.jsonValue["EntryType"] = "Event"; 5125cb1dd27SAsmitha Karunanithi asyncResp->res.jsonValue["Name"] = dumpType + " Dump Entry"; 513bbd80db8SClaire Weinan asyncResp->res.jsonValue["Created"] = 514bbd80db8SClaire Weinan redfish::time_utils::getDateTimeUintUs(timestampUs); 5155cb1dd27SAsmitha Karunanithi 51668dd075aSAsmitha Karunanithi if (!originatorId.empty()) 51768dd075aSAsmitha Karunanithi { 51868dd075aSAsmitha Karunanithi asyncResp->res.jsonValue["Originator"] = originatorId; 51968dd075aSAsmitha Karunanithi asyncResp->res.jsonValue["OriginatorType"] = originatorType; 52068dd075aSAsmitha Karunanithi } 52168dd075aSAsmitha Karunanithi 5225cb1dd27SAsmitha Karunanithi if (dumpType == "BMC") 5235cb1dd27SAsmitha Karunanithi { 524d337bb72SAsmitha Karunanithi asyncResp->res.jsonValue["DiagnosticDataType"] = "Manager"; 525d337bb72SAsmitha Karunanithi asyncResp->res.jsonValue["AdditionalDataURI"] = 526fdd26906SClaire Weinan entriesPath + entryID + "/attachment"; 527fdd26906SClaire Weinan asyncResp->res.jsonValue["AdditionalDataSizeBytes"] = size; 5285cb1dd27SAsmitha Karunanithi } 5295cb1dd27SAsmitha Karunanithi else if (dumpType == "System") 5305cb1dd27SAsmitha Karunanithi { 531d337bb72SAsmitha Karunanithi asyncResp->res.jsonValue["DiagnosticDataType"] = "OEM"; 532bd79bce8SPatrick Williams asyncResp->res.jsonValue["OEMDiagnosticDataType"] = 533bd79bce8SPatrick Williams "System"; 534d337bb72SAsmitha Karunanithi asyncResp->res.jsonValue["AdditionalDataURI"] = 535fdd26906SClaire Weinan entriesPath + entryID + "/attachment"; 536fdd26906SClaire Weinan asyncResp->res.jsonValue["AdditionalDataSizeBytes"] = size; 5375cb1dd27SAsmitha Karunanithi } 5385cb1dd27SAsmitha Karunanithi } 539e05aec50SEd Tanous if (!foundDumpEntry) 540b47452b2SAsmitha Karunanithi { 54162598e31SEd Tanous BMCWEB_LOG_WARNING("Can't find Dump Entry {}", entryID); 542b90d14f2SMyung Bae messages::resourceNotFound(asyncResp->res, dumpType + " dump", 543b90d14f2SMyung Bae entryID); 544b47452b2SAsmitha Karunanithi return; 545b47452b2SAsmitha Karunanithi } 5465eb468daSGeorge Liu }); 5475cb1dd27SAsmitha Karunanithi } 5485cb1dd27SAsmitha Karunanithi 5498d1b46d7Szhanghch05 inline void deleteDumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 5509878256fSStanley Chu const std::string& entryID, 551b47452b2SAsmitha Karunanithi const std::string& dumpType) 5525cb1dd27SAsmitha Karunanithi { 5535a39f77aSPatrick Williams auto respHandler = [asyncResp, 5545a39f77aSPatrick Williams entryID](const boost::system::error_code& ec) { 55562598e31SEd Tanous BMCWEB_LOG_DEBUG("Dump Entry doDelete callback: Done"); 5565cb1dd27SAsmitha Karunanithi if (ec) 5575cb1dd27SAsmitha Karunanithi { 5583de8d8baSGeorge Liu if (ec.value() == EBADR) 5593de8d8baSGeorge Liu { 5603de8d8baSGeorge Liu messages::resourceNotFound(asyncResp->res, "LogEntry", entryID); 5613de8d8baSGeorge Liu return; 5623de8d8baSGeorge Liu } 56362598e31SEd Tanous BMCWEB_LOG_ERROR( 56462598e31SEd Tanous "Dump (DBus) doDelete respHandler got error {} entryID={}", ec, 56562598e31SEd Tanous entryID); 5665cb1dd27SAsmitha Karunanithi messages::internalError(asyncResp->res); 5675cb1dd27SAsmitha Karunanithi return; 5685cb1dd27SAsmitha Karunanithi } 5695cb1dd27SAsmitha Karunanithi }; 57018f8f608SEd Tanous 5715cb1dd27SAsmitha Karunanithi crow::connections::systemBus->async_method_call( 5725cb1dd27SAsmitha Karunanithi respHandler, "xyz.openbmc_project.Dump.Manager", 57318f8f608SEd Tanous std::format("{}/entry/{}", getDumpPath(dumpType), entryID), 5745cb1dd27SAsmitha Karunanithi "xyz.openbmc_project.Object.Delete", "Delete"); 5755cb1dd27SAsmitha Karunanithi } 576b5f288d2SAbhilash Raju inline bool checkSizeLimit(int fd, crow::Response& res) 577b5f288d2SAbhilash Raju { 578b5f288d2SAbhilash Raju long long int size = lseek(fd, 0, SEEK_END); 579b5f288d2SAbhilash Raju if (size <= 0) 580b5f288d2SAbhilash Raju { 581b5f288d2SAbhilash Raju BMCWEB_LOG_ERROR("Failed to get size of file, lseek() returned {}", 582b5f288d2SAbhilash Raju size); 583b5f288d2SAbhilash Raju messages::internalError(res); 584b5f288d2SAbhilash Raju return false; 585b5f288d2SAbhilash Raju } 5865cb1dd27SAsmitha Karunanithi 587b5f288d2SAbhilash Raju // Arbitrary max size of 20MB to accommodate BMC dumps 588b5f288d2SAbhilash Raju constexpr long long int maxFileSize = 20LL * 1024LL * 1024LL; 589b5f288d2SAbhilash Raju if (size > maxFileSize) 590b5f288d2SAbhilash Raju { 591b5f288d2SAbhilash Raju BMCWEB_LOG_ERROR("File size {} exceeds maximum allowed size of {}", 592b5f288d2SAbhilash Raju size, maxFileSize); 593b5f288d2SAbhilash Raju messages::internalError(res); 594b5f288d2SAbhilash Raju return false; 595b5f288d2SAbhilash Raju } 596b5f288d2SAbhilash Raju off_t rc = lseek(fd, 0, SEEK_SET); 597b5f288d2SAbhilash Raju if (rc < 0) 598b5f288d2SAbhilash Raju { 599b5f288d2SAbhilash Raju BMCWEB_LOG_ERROR("Failed to reset file offset to 0"); 600b5f288d2SAbhilash Raju messages::internalError(res); 601b5f288d2SAbhilash Raju return false; 602b5f288d2SAbhilash Raju } 603b5f288d2SAbhilash Raju return true; 604b5f288d2SAbhilash Raju } 605bd79bce8SPatrick Williams inline void downloadEntryCallback( 606bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 607bd79bce8SPatrick Williams const std::string& entryID, const std::string& downloadEntryType, 608168d1b1aSCarson Labrado const boost::system::error_code& ec, 609168d1b1aSCarson Labrado const sdbusplus::message::unix_fd& unixfd) 610168d1b1aSCarson Labrado { 611168d1b1aSCarson Labrado if (ec.value() == EBADR) 612168d1b1aSCarson Labrado { 613168d1b1aSCarson Labrado messages::resourceNotFound(asyncResp->res, "EntryAttachment", entryID); 614168d1b1aSCarson Labrado return; 615168d1b1aSCarson Labrado } 616168d1b1aSCarson Labrado if (ec) 617168d1b1aSCarson Labrado { 618168d1b1aSCarson Labrado BMCWEB_LOG_ERROR("DBUS response error: {}", ec); 619168d1b1aSCarson Labrado messages::internalError(asyncResp->res); 620168d1b1aSCarson Labrado return; 621168d1b1aSCarson Labrado } 622168d1b1aSCarson Labrado 623168d1b1aSCarson Labrado // Make sure we know how to process the retrieved entry attachment 624168d1b1aSCarson Labrado if ((downloadEntryType != "BMC") && (downloadEntryType != "System")) 625168d1b1aSCarson Labrado { 626168d1b1aSCarson Labrado BMCWEB_LOG_ERROR("downloadEntryCallback() invalid entry type: {}", 627168d1b1aSCarson Labrado downloadEntryType); 628168d1b1aSCarson Labrado messages::internalError(asyncResp->res); 629168d1b1aSCarson Labrado } 630168d1b1aSCarson Labrado 631168d1b1aSCarson Labrado int fd = -1; 632168d1b1aSCarson Labrado fd = dup(unixfd); 633168d1b1aSCarson Labrado if (fd < 0) 634168d1b1aSCarson Labrado { 635168d1b1aSCarson Labrado BMCWEB_LOG_ERROR("Failed to open file"); 636168d1b1aSCarson Labrado messages::internalError(asyncResp->res); 637168d1b1aSCarson Labrado return; 638168d1b1aSCarson Labrado } 639b5f288d2SAbhilash Raju if (!checkSizeLimit(fd, asyncResp->res)) 640168d1b1aSCarson Labrado { 641168d1b1aSCarson Labrado close(fd); 642168d1b1aSCarson Labrado return; 643168d1b1aSCarson Labrado } 644168d1b1aSCarson Labrado if (downloadEntryType == "System") 645168d1b1aSCarson Labrado { 646b5f288d2SAbhilash Raju if (!asyncResp->res.openFd(fd, bmcweb::EncodingType::Base64)) 647b5f288d2SAbhilash Raju { 648b5f288d2SAbhilash Raju messages::internalError(asyncResp->res); 649b5f288d2SAbhilash Raju close(fd); 650b5f288d2SAbhilash Raju return; 651b5f288d2SAbhilash Raju } 652168d1b1aSCarson Labrado asyncResp->res.addHeader( 653168d1b1aSCarson Labrado boost::beast::http::field::content_transfer_encoding, "Base64"); 654b5f288d2SAbhilash Raju return; 655168d1b1aSCarson Labrado } 656b5f288d2SAbhilash Raju if (!asyncResp->res.openFd(fd)) 65727b0cf90SEd Tanous { 658b5f288d2SAbhilash Raju messages::internalError(asyncResp->res); 659b5f288d2SAbhilash Raju close(fd); 660b5f288d2SAbhilash Raju return; 66127b0cf90SEd Tanous } 662168d1b1aSCarson Labrado asyncResp->res.addHeader(boost::beast::http::field::content_type, 663168d1b1aSCarson Labrado "application/octet-stream"); 664168d1b1aSCarson Labrado } 665168d1b1aSCarson Labrado 666168d1b1aSCarson Labrado inline void 667168d1b1aSCarson Labrado downloadDumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 668168d1b1aSCarson Labrado const std::string& entryID, const std::string& dumpType) 669168d1b1aSCarson Labrado { 670168d1b1aSCarson Labrado if (dumpType != "BMC") 671168d1b1aSCarson Labrado { 672168d1b1aSCarson Labrado BMCWEB_LOG_WARNING("Can't find Dump Entry {}", entryID); 673168d1b1aSCarson Labrado messages::resourceNotFound(asyncResp->res, dumpType + " dump", entryID); 674168d1b1aSCarson Labrado return; 675168d1b1aSCarson Labrado } 676168d1b1aSCarson Labrado 677bd79bce8SPatrick Williams std::string dumpEntryPath = 678bd79bce8SPatrick Williams std::format("{}/entry/{}", getDumpPath(dumpType), entryID); 679168d1b1aSCarson Labrado 680168d1b1aSCarson Labrado auto downloadDumpEntryHandler = 681168d1b1aSCarson Labrado [asyncResp, entryID, 682168d1b1aSCarson Labrado dumpType](const boost::system::error_code& ec, 683168d1b1aSCarson Labrado const sdbusplus::message::unix_fd& unixfd) { 684168d1b1aSCarson Labrado downloadEntryCallback(asyncResp, entryID, dumpType, ec, unixfd); 685168d1b1aSCarson Labrado }; 686168d1b1aSCarson Labrado 687168d1b1aSCarson Labrado crow::connections::systemBus->async_method_call( 688168d1b1aSCarson Labrado std::move(downloadDumpEntryHandler), "xyz.openbmc_project.Dump.Manager", 689168d1b1aSCarson Labrado dumpEntryPath, "xyz.openbmc_project.Dump.Entry", "GetFileHandle"); 690168d1b1aSCarson Labrado } 691168d1b1aSCarson Labrado 692bd79bce8SPatrick Williams inline void downloadEventLogEntry( 693bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 694bd79bce8SPatrick Williams const std::string& systemName, const std::string& entryID, 695168d1b1aSCarson Labrado const std::string& dumpType) 696168d1b1aSCarson Labrado { 69725b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 698168d1b1aSCarson Labrado { 699168d1b1aSCarson Labrado // Option currently returns no systems. TBD 700168d1b1aSCarson Labrado messages::resourceNotFound(asyncResp->res, "ComputerSystem", 701168d1b1aSCarson Labrado systemName); 702168d1b1aSCarson Labrado return; 703168d1b1aSCarson Labrado } 704253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 705168d1b1aSCarson Labrado { 706168d1b1aSCarson Labrado messages::resourceNotFound(asyncResp->res, "ComputerSystem", 707168d1b1aSCarson Labrado systemName); 708168d1b1aSCarson Labrado return; 709168d1b1aSCarson Labrado } 710168d1b1aSCarson Labrado 711168d1b1aSCarson Labrado std::string entryPath = 712168d1b1aSCarson Labrado sdbusplus::message::object_path("/xyz/openbmc_project/logging/entry") / 713168d1b1aSCarson Labrado entryID; 714168d1b1aSCarson Labrado 715168d1b1aSCarson Labrado auto downloadEventLogEntryHandler = 716168d1b1aSCarson Labrado [asyncResp, entryID, 717168d1b1aSCarson Labrado dumpType](const boost::system::error_code& ec, 718168d1b1aSCarson Labrado const sdbusplus::message::unix_fd& unixfd) { 719168d1b1aSCarson Labrado downloadEntryCallback(asyncResp, entryID, dumpType, ec, unixfd); 720168d1b1aSCarson Labrado }; 721168d1b1aSCarson Labrado 722168d1b1aSCarson Labrado crow::connections::systemBus->async_method_call( 723168d1b1aSCarson Labrado std::move(downloadEventLogEntryHandler), "xyz.openbmc_project.Logging", 724168d1b1aSCarson Labrado entryPath, "xyz.openbmc_project.Logging.Entry", "GetEntry"); 725168d1b1aSCarson Labrado } 726168d1b1aSCarson Labrado 7278e31778eSAsmitha Karunanithi inline DumpCreationProgress 7288e31778eSAsmitha Karunanithi mapDbusStatusToDumpProgress(const std::string& status) 729a43be80fSAsmitha Karunanithi { 7308e31778eSAsmitha Karunanithi if (status == 7318e31778eSAsmitha Karunanithi "xyz.openbmc_project.Common.Progress.OperationStatus.Failed" || 7328e31778eSAsmitha Karunanithi status == "xyz.openbmc_project.Common.Progress.OperationStatus.Aborted") 7338e31778eSAsmitha Karunanithi { 7348e31778eSAsmitha Karunanithi return DumpCreationProgress::DUMP_CREATE_FAILED; 7358e31778eSAsmitha Karunanithi } 7368e31778eSAsmitha Karunanithi if (status == 7378e31778eSAsmitha Karunanithi "xyz.openbmc_project.Common.Progress.OperationStatus.Completed") 7388e31778eSAsmitha Karunanithi { 7398e31778eSAsmitha Karunanithi return DumpCreationProgress::DUMP_CREATE_SUCCESS; 7408e31778eSAsmitha Karunanithi } 7418e31778eSAsmitha Karunanithi return DumpCreationProgress::DUMP_CREATE_INPROGRESS; 7428e31778eSAsmitha Karunanithi } 7438e31778eSAsmitha Karunanithi 7448e31778eSAsmitha Karunanithi inline DumpCreationProgress 7458e31778eSAsmitha Karunanithi getDumpCompletionStatus(const dbus::utility::DBusPropertiesMap& values) 7468e31778eSAsmitha Karunanithi { 7478e31778eSAsmitha Karunanithi for (const auto& [key, val] : values) 7488e31778eSAsmitha Karunanithi { 7498e31778eSAsmitha Karunanithi if (key == "Status") 7508e31778eSAsmitha Karunanithi { 7518e31778eSAsmitha Karunanithi const std::string* value = std::get_if<std::string>(&val); 7528e31778eSAsmitha Karunanithi if (value == nullptr) 7538e31778eSAsmitha Karunanithi { 75462598e31SEd Tanous BMCWEB_LOG_ERROR("Status property value is null"); 7558e31778eSAsmitha Karunanithi return DumpCreationProgress::DUMP_CREATE_FAILED; 7568e31778eSAsmitha Karunanithi } 7578e31778eSAsmitha Karunanithi return mapDbusStatusToDumpProgress(*value); 7588e31778eSAsmitha Karunanithi } 7598e31778eSAsmitha Karunanithi } 7608e31778eSAsmitha Karunanithi return DumpCreationProgress::DUMP_CREATE_INPROGRESS; 7618e31778eSAsmitha Karunanithi } 7628e31778eSAsmitha Karunanithi 7638e31778eSAsmitha Karunanithi inline std::string getDumpEntryPath(const std::string& dumpPath) 7648e31778eSAsmitha Karunanithi { 7658e31778eSAsmitha Karunanithi if (dumpPath == "/xyz/openbmc_project/dump/bmc/entry") 7668e31778eSAsmitha Karunanithi { 767253f11b8SEd Tanous return std::format("/redfish/v1/Managers/{}/LogServices/Dump/Entries/", 7689f565090SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 7698e31778eSAsmitha Karunanithi } 7708e31778eSAsmitha Karunanithi if (dumpPath == "/xyz/openbmc_project/dump/system/entry") 7718e31778eSAsmitha Karunanithi { 772253f11b8SEd Tanous return std::format("/redfish/v1/Systems/{}/LogServices/Dump/Entries/", 773253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 7748e31778eSAsmitha Karunanithi } 7758e31778eSAsmitha Karunanithi return ""; 7768e31778eSAsmitha Karunanithi } 7778e31778eSAsmitha Karunanithi 7788e31778eSAsmitha Karunanithi inline void createDumpTaskCallback( 7798e31778eSAsmitha Karunanithi task::Payload&& payload, 7808e31778eSAsmitha Karunanithi const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 7818e31778eSAsmitha Karunanithi const sdbusplus::message::object_path& createdObjPath) 7828e31778eSAsmitha Karunanithi { 7838e31778eSAsmitha Karunanithi const std::string dumpPath = createdObjPath.parent_path().str; 7848e31778eSAsmitha Karunanithi const std::string dumpId = createdObjPath.filename(); 7858e31778eSAsmitha Karunanithi 7868e31778eSAsmitha Karunanithi std::string dumpEntryPath = getDumpEntryPath(dumpPath); 7878e31778eSAsmitha Karunanithi 7888e31778eSAsmitha Karunanithi if (dumpEntryPath.empty()) 7898e31778eSAsmitha Karunanithi { 79062598e31SEd Tanous BMCWEB_LOG_ERROR("Invalid dump type received"); 7918e31778eSAsmitha Karunanithi messages::internalError(asyncResp->res); 7928e31778eSAsmitha Karunanithi return; 7938e31778eSAsmitha Karunanithi } 7948e31778eSAsmitha Karunanithi 7958e31778eSAsmitha Karunanithi crow::connections::systemBus->async_method_call( 7968cb2c024SEd Tanous [asyncResp, payload = std::move(payload), createdObjPath, 7978e31778eSAsmitha Karunanithi dumpEntryPath{std::move(dumpEntryPath)}, 7985e7e2dc5SEd Tanous dumpId](const boost::system::error_code& ec, 7998e31778eSAsmitha Karunanithi const std::string& introspectXml) { 8008e31778eSAsmitha Karunanithi if (ec) 8018e31778eSAsmitha Karunanithi { 80262598e31SEd Tanous BMCWEB_LOG_ERROR("Introspect call failed with error: {}", 80362598e31SEd Tanous ec.message()); 8048e31778eSAsmitha Karunanithi messages::internalError(asyncResp->res); 8058e31778eSAsmitha Karunanithi return; 8068e31778eSAsmitha Karunanithi } 8078e31778eSAsmitha Karunanithi 8088e31778eSAsmitha Karunanithi // Check if the created dump object has implemented Progress 8098e31778eSAsmitha Karunanithi // interface to track dump completion. If yes, fetch the "Status" 8108e31778eSAsmitha Karunanithi // property of the interface, modify the task state accordingly. 8118e31778eSAsmitha Karunanithi // Else, return task completed. 8128e31778eSAsmitha Karunanithi tinyxml2::XMLDocument doc; 8138e31778eSAsmitha Karunanithi 8148e31778eSAsmitha Karunanithi doc.Parse(introspectXml.data(), introspectXml.size()); 8158e31778eSAsmitha Karunanithi tinyxml2::XMLNode* pRoot = doc.FirstChildElement("node"); 8168e31778eSAsmitha Karunanithi if (pRoot == nullptr) 8178e31778eSAsmitha Karunanithi { 81862598e31SEd Tanous BMCWEB_LOG_ERROR("XML document failed to parse"); 8198e31778eSAsmitha Karunanithi messages::internalError(asyncResp->res); 8208e31778eSAsmitha Karunanithi return; 8218e31778eSAsmitha Karunanithi } 8228e31778eSAsmitha Karunanithi tinyxml2::XMLElement* interfaceNode = 8238e31778eSAsmitha Karunanithi pRoot->FirstChildElement("interface"); 8248e31778eSAsmitha Karunanithi 8258e31778eSAsmitha Karunanithi bool isProgressIntfPresent = false; 8268e31778eSAsmitha Karunanithi while (interfaceNode != nullptr) 8278e31778eSAsmitha Karunanithi { 828bd79bce8SPatrick Williams const char* thisInterfaceName = 829bd79bce8SPatrick Williams interfaceNode->Attribute("name"); 8308e31778eSAsmitha Karunanithi if (thisInterfaceName != nullptr) 8318e31778eSAsmitha Karunanithi { 8328e31778eSAsmitha Karunanithi if (thisInterfaceName == 8338e31778eSAsmitha Karunanithi std::string_view("xyz.openbmc_project.Common.Progress")) 8348e31778eSAsmitha Karunanithi { 8358e31778eSAsmitha Karunanithi interfaceNode = 8368e31778eSAsmitha Karunanithi interfaceNode->NextSiblingElement("interface"); 8378e31778eSAsmitha Karunanithi continue; 8388e31778eSAsmitha Karunanithi } 8398e31778eSAsmitha Karunanithi isProgressIntfPresent = true; 8408e31778eSAsmitha Karunanithi break; 8418e31778eSAsmitha Karunanithi } 8428e31778eSAsmitha Karunanithi interfaceNode = interfaceNode->NextSiblingElement("interface"); 8438e31778eSAsmitha Karunanithi } 8448e31778eSAsmitha Karunanithi 845a43be80fSAsmitha Karunanithi std::shared_ptr<task::TaskData> task = task::TaskData::createTask( 8468e31778eSAsmitha Karunanithi [createdObjPath, dumpEntryPath, dumpId, isProgressIntfPresent]( 847bd79bce8SPatrick Williams const boost::system::error_code& ec2, 848bd79bce8SPatrick Williams sdbusplus::message_t& msg, 849a43be80fSAsmitha Karunanithi const std::shared_ptr<task::TaskData>& taskData) { 8508b24275dSEd Tanous if (ec2) 851cb13a392SEd Tanous { 85262598e31SEd Tanous BMCWEB_LOG_ERROR("{}: Error in creating dump", 85362598e31SEd Tanous createdObjPath.str); 854bd79bce8SPatrick Williams taskData->messages.emplace_back( 855bd79bce8SPatrick Williams messages::internalError()); 8566145ed6fSAsmitha Karunanithi taskData->state = "Cancelled"; 8576145ed6fSAsmitha Karunanithi return task::completed; 858cb13a392SEd Tanous } 859b9d36b47SEd Tanous 8608e31778eSAsmitha Karunanithi if (isProgressIntfPresent) 861a43be80fSAsmitha Karunanithi { 8628e31778eSAsmitha Karunanithi dbus::utility::DBusPropertiesMap values; 8638e31778eSAsmitha Karunanithi std::string prop; 8648e31778eSAsmitha Karunanithi msg.read(prop, values); 8658e31778eSAsmitha Karunanithi 8668e31778eSAsmitha Karunanithi DumpCreationProgress dumpStatus = 8678e31778eSAsmitha Karunanithi getDumpCompletionStatus(values); 868bd79bce8SPatrick Williams if (dumpStatus == 869bd79bce8SPatrick Williams DumpCreationProgress::DUMP_CREATE_FAILED) 8708e31778eSAsmitha Karunanithi { 87162598e31SEd Tanous BMCWEB_LOG_ERROR("{}: Error in creating dump", 87262598e31SEd Tanous createdObjPath.str); 8738e31778eSAsmitha Karunanithi taskData->state = "Cancelled"; 8748e31778eSAsmitha Karunanithi return task::completed; 8758e31778eSAsmitha Karunanithi } 8768e31778eSAsmitha Karunanithi 877bd79bce8SPatrick Williams if (dumpStatus == 878bd79bce8SPatrick Williams DumpCreationProgress::DUMP_CREATE_INPROGRESS) 8798e31778eSAsmitha Karunanithi { 880bd79bce8SPatrick Williams BMCWEB_LOG_DEBUG( 881bd79bce8SPatrick Williams "{}: Dump creation task is in progress", 88262598e31SEd Tanous createdObjPath.str); 8838e31778eSAsmitha Karunanithi return !task::completed; 8848e31778eSAsmitha Karunanithi } 8858e31778eSAsmitha Karunanithi } 8868e31778eSAsmitha Karunanithi 887a43be80fSAsmitha Karunanithi nlohmann::json retMessage = messages::success(); 888a43be80fSAsmitha Karunanithi taskData->messages.emplace_back(retMessage); 889a43be80fSAsmitha Karunanithi 890c51a58eeSEd Tanous boost::urls::url url = boost::urls::format( 891253f11b8SEd Tanous "/redfish/v1/Managers/{}/LogServices/Dump/Entries/{}", 892253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME, dumpId); 893c51a58eeSEd Tanous 894c51a58eeSEd Tanous std::string headerLoc = "Location: "; 895c51a58eeSEd Tanous headerLoc += url.buffer(); 896c51a58eeSEd Tanous 897bd79bce8SPatrick Williams taskData->payload->httpHeaders.emplace_back( 898bd79bce8SPatrick Williams std::move(headerLoc)); 899a43be80fSAsmitha Karunanithi 90062598e31SEd Tanous BMCWEB_LOG_DEBUG("{}: Dump creation task completed", 90162598e31SEd Tanous createdObjPath.str); 902a43be80fSAsmitha Karunanithi taskData->state = "Completed"; 903b47452b2SAsmitha Karunanithi return task::completed; 904a43be80fSAsmitha Karunanithi }, 9058e31778eSAsmitha Karunanithi "type='signal',interface='org.freedesktop.DBus.Properties'," 9068e31778eSAsmitha Karunanithi "member='PropertiesChanged',path='" + 9078e31778eSAsmitha Karunanithi createdObjPath.str + "'"); 908a43be80fSAsmitha Karunanithi 9098e31778eSAsmitha Karunanithi // The task timer is set to max time limit within which the 9108e31778eSAsmitha Karunanithi // requested dump will be collected. 9118e31778eSAsmitha Karunanithi task->startTimer(std::chrono::minutes(6)); 912a43be80fSAsmitha Karunanithi task->populateResp(asyncResp->res); 9138e31778eSAsmitha Karunanithi task->payload.emplace(payload); 9148e31778eSAsmitha Karunanithi }, 9158e31778eSAsmitha Karunanithi "xyz.openbmc_project.Dump.Manager", createdObjPath, 9168e31778eSAsmitha Karunanithi "org.freedesktop.DBus.Introspectable", "Introspect"); 917a43be80fSAsmitha Karunanithi } 918a43be80fSAsmitha Karunanithi 9198d1b46d7Szhanghch05 inline void createDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 9208d1b46d7Szhanghch05 const crow::Request& req, const std::string& dumpType) 921a43be80fSAsmitha Karunanithi { 922fdd26906SClaire Weinan std::string dumpPath = getDumpEntriesPath(dumpType); 923fdd26906SClaire Weinan if (dumpPath.empty()) 924a43be80fSAsmitha Karunanithi { 925a43be80fSAsmitha Karunanithi messages::internalError(asyncResp->res); 926a43be80fSAsmitha Karunanithi return; 927a43be80fSAsmitha Karunanithi } 928a43be80fSAsmitha Karunanithi 929a43be80fSAsmitha Karunanithi std::optional<std::string> diagnosticDataType; 930a43be80fSAsmitha Karunanithi std::optional<std::string> oemDiagnosticDataType; 931a43be80fSAsmitha Karunanithi 932afc474aeSMyung Bae if (!redfish::json_util::readJsonAction( // 933afc474aeSMyung Bae req, asyncResp->res, // 934afc474aeSMyung Bae "DiagnosticDataType", diagnosticDataType, // 935afc474aeSMyung Bae "OEMDiagnosticDataType", oemDiagnosticDataType // 936afc474aeSMyung Bae )) 937a43be80fSAsmitha Karunanithi { 938a43be80fSAsmitha Karunanithi return; 939a43be80fSAsmitha Karunanithi } 940a43be80fSAsmitha Karunanithi 941a43be80fSAsmitha Karunanithi if (dumpType == "System") 942a43be80fSAsmitha Karunanithi { 943a43be80fSAsmitha Karunanithi if (!oemDiagnosticDataType || !diagnosticDataType) 944a43be80fSAsmitha Karunanithi { 94562598e31SEd Tanous BMCWEB_LOG_ERROR( 94662598e31SEd Tanous "CreateDump action parameter 'DiagnosticDataType'/'OEMDiagnosticDataType' value not found!"); 947a43be80fSAsmitha Karunanithi messages::actionParameterMissing( 948a43be80fSAsmitha Karunanithi asyncResp->res, "CollectDiagnosticData", 949a43be80fSAsmitha Karunanithi "DiagnosticDataType & OEMDiagnosticDataType"); 950a43be80fSAsmitha Karunanithi return; 951a43be80fSAsmitha Karunanithi } 9523174e4dfSEd Tanous if ((*oemDiagnosticDataType != "System") || 953a43be80fSAsmitha Karunanithi (*diagnosticDataType != "OEM")) 954a43be80fSAsmitha Karunanithi { 95562598e31SEd Tanous BMCWEB_LOG_ERROR("Wrong parameter values passed"); 956ace85d60SEd Tanous messages::internalError(asyncResp->res); 957a43be80fSAsmitha Karunanithi return; 958a43be80fSAsmitha Karunanithi } 959253f11b8SEd Tanous dumpPath = std::format("/redfish/v1/Systems/{}/LogServices/Dump/", 960253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 961a43be80fSAsmitha Karunanithi } 962a43be80fSAsmitha Karunanithi else if (dumpType == "BMC") 963a43be80fSAsmitha Karunanithi { 964a43be80fSAsmitha Karunanithi if (!diagnosticDataType) 965a43be80fSAsmitha Karunanithi { 96662598e31SEd Tanous BMCWEB_LOG_ERROR( 96762598e31SEd Tanous "CreateDump action parameter 'DiagnosticDataType' not found!"); 968a43be80fSAsmitha Karunanithi messages::actionParameterMissing( 969a43be80fSAsmitha Karunanithi asyncResp->res, "CollectDiagnosticData", "DiagnosticDataType"); 970a43be80fSAsmitha Karunanithi return; 971a43be80fSAsmitha Karunanithi } 9723174e4dfSEd Tanous if (*diagnosticDataType != "Manager") 973a43be80fSAsmitha Karunanithi { 97462598e31SEd Tanous BMCWEB_LOG_ERROR( 97562598e31SEd Tanous "Wrong parameter value passed for 'DiagnosticDataType'"); 976ace85d60SEd Tanous messages::internalError(asyncResp->res); 977a43be80fSAsmitha Karunanithi return; 978a43be80fSAsmitha Karunanithi } 979253f11b8SEd Tanous dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/Dump/", 980253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 9815907571dSAsmitha Karunanithi } 9825907571dSAsmitha Karunanithi else 9835907571dSAsmitha Karunanithi { 98462598e31SEd Tanous BMCWEB_LOG_ERROR("CreateDump failed. Unknown dump type"); 9855907571dSAsmitha Karunanithi messages::internalError(asyncResp->res); 9865907571dSAsmitha Karunanithi return; 987a43be80fSAsmitha Karunanithi } 988a43be80fSAsmitha Karunanithi 9898e31778eSAsmitha Karunanithi std::vector<std::pair<std::string, std::variant<std::string, uint64_t>>> 9908e31778eSAsmitha Karunanithi createDumpParamVec; 9918e31778eSAsmitha Karunanithi 992f574a8e1SCarson Labrado if (req.session != nullptr) 993f574a8e1SCarson Labrado { 99468dd075aSAsmitha Karunanithi createDumpParamVec.emplace_back( 99568dd075aSAsmitha Karunanithi "xyz.openbmc_project.Dump.Create.CreateParameters.OriginatorId", 99668dd075aSAsmitha Karunanithi req.session->clientIp); 99768dd075aSAsmitha Karunanithi createDumpParamVec.emplace_back( 99868dd075aSAsmitha Karunanithi "xyz.openbmc_project.Dump.Create.CreateParameters.OriginatorType", 99968dd075aSAsmitha Karunanithi "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Client"); 1000f574a8e1SCarson Labrado } 100168dd075aSAsmitha Karunanithi 1002a43be80fSAsmitha Karunanithi crow::connections::systemBus->async_method_call( 10035e7e2dc5SEd Tanous [asyncResp, payload(task::Payload(req)), 10045e7e2dc5SEd Tanous dumpPath](const boost::system::error_code& ec, 10055e7e2dc5SEd Tanous const sdbusplus::message_t& msg, 10068e31778eSAsmitha Karunanithi const sdbusplus::message::object_path& objPath) mutable { 1007a43be80fSAsmitha Karunanithi if (ec) 1008a43be80fSAsmitha Karunanithi { 100962598e31SEd Tanous BMCWEB_LOG_ERROR("CreateDump resp_handler got error {}", ec); 10105907571dSAsmitha Karunanithi const sd_bus_error* dbusError = msg.get_error(); 10115907571dSAsmitha Karunanithi if (dbusError == nullptr) 10125907571dSAsmitha Karunanithi { 10135907571dSAsmitha Karunanithi messages::internalError(asyncResp->res); 10145907571dSAsmitha Karunanithi return; 10155907571dSAsmitha Karunanithi } 10165907571dSAsmitha Karunanithi 101762598e31SEd Tanous BMCWEB_LOG_ERROR("CreateDump DBus error: {} and error msg: {}", 101862598e31SEd Tanous dbusError->name, dbusError->message); 10195907571dSAsmitha Karunanithi if (std::string_view( 10205907571dSAsmitha Karunanithi "xyz.openbmc_project.Common.Error.NotAllowed") == 10215907571dSAsmitha Karunanithi dbusError->name) 10225907571dSAsmitha Karunanithi { 10235907571dSAsmitha Karunanithi messages::resourceInStandby(asyncResp->res); 10245907571dSAsmitha Karunanithi return; 10255907571dSAsmitha Karunanithi } 10265907571dSAsmitha Karunanithi if (std::string_view( 10275907571dSAsmitha Karunanithi "xyz.openbmc_project.Dump.Create.Error.Disabled") == 10285907571dSAsmitha Karunanithi dbusError->name) 10295907571dSAsmitha Karunanithi { 10305907571dSAsmitha Karunanithi messages::serviceDisabled(asyncResp->res, dumpPath); 10315907571dSAsmitha Karunanithi return; 10325907571dSAsmitha Karunanithi } 10335907571dSAsmitha Karunanithi if (std::string_view( 10345907571dSAsmitha Karunanithi "xyz.openbmc_project.Common.Error.Unavailable") == 10355907571dSAsmitha Karunanithi dbusError->name) 10365907571dSAsmitha Karunanithi { 10375907571dSAsmitha Karunanithi messages::resourceInUse(asyncResp->res); 10385907571dSAsmitha Karunanithi return; 10395907571dSAsmitha Karunanithi } 10405907571dSAsmitha Karunanithi // Other Dbus errors such as: 10415907571dSAsmitha Karunanithi // xyz.openbmc_project.Common.Error.InvalidArgument & 10425907571dSAsmitha Karunanithi // org.freedesktop.DBus.Error.InvalidArgs are all related to 10435907571dSAsmitha Karunanithi // the dbus call that is made here in the bmcweb 10445907571dSAsmitha Karunanithi // implementation and has nothing to do with the client's 10455907571dSAsmitha Karunanithi // input in the request. Hence, returning internal error 10465907571dSAsmitha Karunanithi // back to the client. 1047a43be80fSAsmitha Karunanithi messages::internalError(asyncResp->res); 1048a43be80fSAsmitha Karunanithi return; 1049a43be80fSAsmitha Karunanithi } 105062598e31SEd Tanous BMCWEB_LOG_DEBUG("Dump Created. Path: {}", objPath.str); 10518e31778eSAsmitha Karunanithi createDumpTaskCallback(std::move(payload), asyncResp, objPath); 1052a43be80fSAsmitha Karunanithi }, 105318f8f608SEd Tanous "xyz.openbmc_project.Dump.Manager", getDumpPath(dumpType), 10548e31778eSAsmitha Karunanithi "xyz.openbmc_project.Dump.Create", "CreateDump", createDumpParamVec); 1055a43be80fSAsmitha Karunanithi } 1056a43be80fSAsmitha Karunanithi 10578d1b46d7Szhanghch05 inline void clearDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 10588d1b46d7Szhanghch05 const std::string& dumpType) 105980319af1SAsmitha Karunanithi { 10600d946211SClaire Weinan crow::connections::systemBus->async_method_call( 10610d946211SClaire Weinan [asyncResp](const boost::system::error_code& ec) { 106280319af1SAsmitha Karunanithi if (ec) 106380319af1SAsmitha Karunanithi { 106462598e31SEd Tanous BMCWEB_LOG_ERROR("clearDump resp_handler got error {}", ec); 106580319af1SAsmitha Karunanithi messages::internalError(asyncResp->res); 106680319af1SAsmitha Karunanithi return; 106780319af1SAsmitha Karunanithi } 10680d946211SClaire Weinan }, 106918f8f608SEd Tanous "xyz.openbmc_project.Dump.Manager", getDumpPath(dumpType), 10700d946211SClaire Weinan "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll"); 107180319af1SAsmitha Karunanithi } 107280319af1SAsmitha Karunanithi 1073bd79bce8SPatrick Williams inline void parseCrashdumpParameters( 1074bd79bce8SPatrick Williams const dbus::utility::DBusPropertiesMap& params, std::string& filename, 1075bd79bce8SPatrick Williams std::string& timestamp, std::string& logfile) 1076043a0536SJohnathan Mantey { 1077d1bde9e5SKrzysztof Grobelny const std::string* filenamePtr = nullptr; 1078d1bde9e5SKrzysztof Grobelny const std::string* timestampPtr = nullptr; 1079d1bde9e5SKrzysztof Grobelny const std::string* logfilePtr = nullptr; 1080d1bde9e5SKrzysztof Grobelny 1081d1bde9e5SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 1082d1bde9e5SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), params, "Timestamp", timestampPtr, 1083d1bde9e5SKrzysztof Grobelny "Filename", filenamePtr, "Log", logfilePtr); 1084d1bde9e5SKrzysztof Grobelny 1085d1bde9e5SKrzysztof Grobelny if (!success) 1086043a0536SJohnathan Mantey { 1087d1bde9e5SKrzysztof Grobelny return; 1088043a0536SJohnathan Mantey } 1089d1bde9e5SKrzysztof Grobelny 1090d1bde9e5SKrzysztof Grobelny if (filenamePtr != nullptr) 1091043a0536SJohnathan Mantey { 1092d1bde9e5SKrzysztof Grobelny filename = *filenamePtr; 1093d1bde9e5SKrzysztof Grobelny } 1094d1bde9e5SKrzysztof Grobelny 1095d1bde9e5SKrzysztof Grobelny if (timestampPtr != nullptr) 1096043a0536SJohnathan Mantey { 1097d1bde9e5SKrzysztof Grobelny timestamp = *timestampPtr; 1098043a0536SJohnathan Mantey } 1099d1bde9e5SKrzysztof Grobelny 1100d1bde9e5SKrzysztof Grobelny if (logfilePtr != nullptr) 1101043a0536SJohnathan Mantey { 1102d1bde9e5SKrzysztof Grobelny logfile = *logfilePtr; 1103043a0536SJohnathan Mantey } 1104043a0536SJohnathan Mantey } 1105043a0536SJohnathan Mantey 11067e860f15SJohn Edward Broadbent inline void requestRoutesSystemLogServiceCollection(App& app) 11071da66f75SEd Tanous { 1108c4bf6374SJason M. Bills /** 1109c4bf6374SJason M. Bills * Functions triggers appropriate requests on DBus 1110c4bf6374SJason M. Bills */ 111122d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/") 1112ed398213SEd Tanous .privileges(redfish::privileges::getLogServiceCollection) 1113bd79bce8SPatrick Williams .methods( 1114bd79bce8SPatrick Williams boost::beast::http::verb:: 1115bd79bce8SPatrick Williams get)([&app](const crow::Request& req, 111622d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 111722d268cbSEd Tanous const std::string& systemName) { 11183ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 1119c4bf6374SJason M. Bills { 112045ca1b86SEd Tanous return; 112145ca1b86SEd Tanous } 112225b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 11237f3e84a1SEd Tanous { 11247f3e84a1SEd Tanous // Option currently returns no systems. TBD 11257f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 11267f3e84a1SEd Tanous systemName); 11277f3e84a1SEd Tanous return; 11287f3e84a1SEd Tanous } 1129253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 113022d268cbSEd Tanous { 113122d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 113222d268cbSEd Tanous systemName); 113322d268cbSEd Tanous return; 113422d268cbSEd Tanous } 113522d268cbSEd Tanous 11367e860f15SJohn Edward Broadbent // Collections don't include the static data added by SubRoute 11377e860f15SJohn Edward Broadbent // because it has a duplicate entry for members 1138c4bf6374SJason M. Bills asyncResp->res.jsonValue["@odata.type"] = 1139c4bf6374SJason M. Bills "#LogServiceCollection.LogServiceCollection"; 1140c4bf6374SJason M. Bills asyncResp->res.jsonValue["@odata.id"] = 1141253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices", 1142253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 114345ca1b86SEd Tanous asyncResp->res.jsonValue["Name"] = "System Log Services Collection"; 1144c4bf6374SJason M. Bills asyncResp->res.jsonValue["Description"] = 1145c4bf6374SJason M. Bills "Collection of LogServices for this Computer System"; 1146bd79bce8SPatrick Williams nlohmann::json& logServiceArray = 1147bd79bce8SPatrick Williams asyncResp->res.jsonValue["Members"]; 1148c4bf6374SJason M. Bills logServiceArray = nlohmann::json::array(); 11491476687dSEd Tanous nlohmann::json::object_t eventLog; 11501476687dSEd Tanous eventLog["@odata.id"] = 1151253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/EventLog", 1152253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1153b2ba3072SPatrick Williams logServiceArray.emplace_back(std::move(eventLog)); 115425b54dbaSEd Tanous if constexpr (BMCWEB_REDFISH_DUMP_LOG) 115525b54dbaSEd Tanous { 11561476687dSEd Tanous nlohmann::json::object_t dumpLog; 115725b54dbaSEd Tanous dumpLog["@odata.id"] = 1158253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/Dump", 1159253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1160b2ba3072SPatrick Williams logServiceArray.emplace_back(std::move(dumpLog)); 116125b54dbaSEd Tanous } 1162c9bb6861Sraviteja-b 11635ffd11f2SGunnar Mills if constexpr (BMCWEB_REDFISH_CPU_LOG) 116425b54dbaSEd Tanous { 11651476687dSEd Tanous nlohmann::json::object_t crashdump; 11661476687dSEd Tanous crashdump["@odata.id"] = 1167253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/Crashdump", 1168253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1169b2ba3072SPatrick Williams logServiceArray.emplace_back(std::move(crashdump)); 117025b54dbaSEd Tanous } 1171b7028ebfSSpencer Ku 117225b54dbaSEd Tanous if constexpr (BMCWEB_REDFISH_HOST_LOGGER) 117325b54dbaSEd Tanous { 11741476687dSEd Tanous nlohmann::json::object_t hostlogger; 11751476687dSEd Tanous hostlogger["@odata.id"] = 1176253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/HostLogger", 1177253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1178b2ba3072SPatrick Williams logServiceArray.emplace_back(std::move(hostlogger)); 117925b54dbaSEd Tanous } 1180c4bf6374SJason M. Bills asyncResp->res.jsonValue["Members@odata.count"] = 1181c4bf6374SJason M. Bills logServiceArray.size(); 1182a3316fc6SZhikuiRen 11837a1dbc48SGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 11847a1dbc48SGeorge Liu "xyz.openbmc_project.State.Boot.PostCode"}; 11857a1dbc48SGeorge Liu dbus::utility::getSubTreePaths( 11867a1dbc48SGeorge Liu "/", 0, interfaces, 11877a1dbc48SGeorge Liu [asyncResp](const boost::system::error_code& ec, 1188b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreePathsResponse& 1189b9d36b47SEd Tanous subtreePath) { 1190a3316fc6SZhikuiRen if (ec) 1191a3316fc6SZhikuiRen { 119262598e31SEd Tanous BMCWEB_LOG_ERROR("{}", ec); 1193a3316fc6SZhikuiRen return; 1194a3316fc6SZhikuiRen } 1195a3316fc6SZhikuiRen 119655f79e6fSEd Tanous for (const auto& pathStr : subtreePath) 1197a3316fc6SZhikuiRen { 1198a3316fc6SZhikuiRen if (pathStr.find("PostCode") != std::string::npos) 1199a3316fc6SZhikuiRen { 120023a21a1cSEd Tanous nlohmann::json& logServiceArrayLocal = 1201a3316fc6SZhikuiRen asyncResp->res.jsonValue["Members"]; 1202613dabeaSEd Tanous nlohmann::json::object_t member; 1203253f11b8SEd Tanous member["@odata.id"] = std::format( 1204253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/PostCodes", 1205253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1206613dabeaSEd Tanous 1207bd79bce8SPatrick Williams logServiceArrayLocal.emplace_back( 1208bd79bce8SPatrick Williams std::move(member)); 1209613dabeaSEd Tanous 121045ca1b86SEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = 121123a21a1cSEd Tanous logServiceArrayLocal.size(); 1212a3316fc6SZhikuiRen return; 1213a3316fc6SZhikuiRen } 1214a3316fc6SZhikuiRen } 12157a1dbc48SGeorge Liu }); 12167e860f15SJohn Edward Broadbent }); 1217c4bf6374SJason M. Bills } 1218c4bf6374SJason M. Bills 12197e860f15SJohn Edward Broadbent inline void requestRoutesEventLogService(App& app) 1220c4bf6374SJason M. Bills { 122122d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/") 1222ed398213SEd Tanous .privileges(redfish::privileges::getLogService) 1223bd79bce8SPatrick Williams .methods( 1224bd79bce8SPatrick Williams boost::beast::http::verb:: 1225bd79bce8SPatrick Williams get)([&app](const crow::Request& req, 122622d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 122722d268cbSEd Tanous const std::string& systemName) { 12283ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 122945ca1b86SEd Tanous { 123045ca1b86SEd Tanous return; 123145ca1b86SEd Tanous } 1232253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 123322d268cbSEd Tanous { 123422d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 123522d268cbSEd Tanous systemName); 123622d268cbSEd Tanous return; 123722d268cbSEd Tanous } 1238c4bf6374SJason M. Bills asyncResp->res.jsonValue["@odata.id"] = 1239253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/EventLog", 1240253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1241c4bf6374SJason M. Bills asyncResp->res.jsonValue["@odata.type"] = 1242b25644a1SJanet Adkins "#LogService.v1_2_0.LogService"; 1243c4bf6374SJason M. Bills asyncResp->res.jsonValue["Name"] = "Event Log Service"; 1244bd79bce8SPatrick Williams asyncResp->res.jsonValue["Description"] = 1245bd79bce8SPatrick Williams "System Event Log Service"; 1246c4bf6374SJason M. Bills asyncResp->res.jsonValue["Id"] = "EventLog"; 1247539d8c6bSEd Tanous asyncResp->res.jsonValue["OverWritePolicy"] = 1248539d8c6bSEd Tanous log_service::OverWritePolicy::WrapsWhenFull; 12497c8c4058STejas Patil 12507c8c4058STejas Patil std::pair<std::string, std::string> redfishDateTimeOffset = 12512b82937eSEd Tanous redfish::time_utils::getDateTimeOffsetNow(); 12527c8c4058STejas Patil 12537c8c4058STejas Patil asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first; 12547c8c4058STejas Patil asyncResp->res.jsonValue["DateTimeLocalOffset"] = 12557c8c4058STejas Patil redfishDateTimeOffset.second; 12567c8c4058STejas Patil 1257bd79bce8SPatrick Williams asyncResp->res.jsonValue["Entries"]["@odata.id"] = std::format( 1258bd79bce8SPatrick Williams "/redfish/v1/Systems/{}/LogServices/EventLog/Entries", 1259253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1260bd79bce8SPatrick Williams asyncResp->res 1261bd79bce8SPatrick Williams .jsonValue["Actions"]["#LogService.ClearLog"]["target"] 1262e7d6c8b2SGunnar Mills 126320fa6a2cSEd Tanous = std::format( 1264253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/EventLog/Actions/LogService.ClearLog", 126520fa6a2cSEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 12667e860f15SJohn Edward Broadbent }); 1267489640c6SJason M. Bills } 1268489640c6SJason M. Bills 1269599b9af3SAlexander Hansen inline void handleSystemsLogServicesEventLogActionsClearPost( 1270599b9af3SAlexander Hansen App& app, const crow::Request& req, 127122d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1272599b9af3SAlexander Hansen const std::string& systemName) 1273599b9af3SAlexander Hansen { 12743ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 127545ca1b86SEd Tanous { 127645ca1b86SEd Tanous return; 127745ca1b86SEd Tanous } 1278253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 127922d268cbSEd Tanous { 128022d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 128122d268cbSEd Tanous systemName); 128222d268cbSEd Tanous return; 128322d268cbSEd Tanous } 1284599b9af3SAlexander Hansen 1285489640c6SJason M. Bills // Clear the EventLog by deleting the log files 1286489640c6SJason M. Bills std::vector<std::filesystem::path> redfishLogFiles; 1287489640c6SJason M. Bills if (getRedfishLogFiles(redfishLogFiles)) 1288489640c6SJason M. Bills { 1289489640c6SJason M. Bills for (const std::filesystem::path& file : redfishLogFiles) 1290489640c6SJason M. Bills { 1291489640c6SJason M. Bills std::error_code ec; 1292489640c6SJason M. Bills std::filesystem::remove(file, ec); 1293489640c6SJason M. Bills } 1294489640c6SJason M. Bills } 1295489640c6SJason M. Bills 1296489640c6SJason M. Bills // Reload rsyslog so it knows to start new log files 1297489640c6SJason M. Bills crow::connections::systemBus->async_method_call( 12985e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 1299489640c6SJason M. Bills if (ec) 1300489640c6SJason M. Bills { 130162598e31SEd Tanous BMCWEB_LOG_ERROR("Failed to reload rsyslog: {}", ec); 1302489640c6SJason M. Bills messages::internalError(asyncResp->res); 1303489640c6SJason M. Bills return; 1304489640c6SJason M. Bills } 1305489640c6SJason M. Bills 1306489640c6SJason M. Bills messages::success(asyncResp->res); 1307489640c6SJason M. Bills }, 1308489640c6SJason M. Bills "org.freedesktop.systemd1", "/org/freedesktop/systemd1", 1309002d39b4SEd Tanous "org.freedesktop.systemd1.Manager", "ReloadUnit", "rsyslog.service", 1310002d39b4SEd Tanous "replace"); 1311599b9af3SAlexander Hansen } 1312599b9af3SAlexander Hansen 1313599b9af3SAlexander Hansen inline void requestRoutesJournalEventLogClear(App& app) 1314599b9af3SAlexander Hansen { 1315599b9af3SAlexander Hansen BMCWEB_ROUTE( 1316599b9af3SAlexander Hansen app, 1317599b9af3SAlexander Hansen "/redfish/v1/Systems/<str>/LogServices/EventLog/Actions/LogService.ClearLog/") 1318599b9af3SAlexander Hansen .privileges({{"ConfigureComponents"}}) 1319599b9af3SAlexander Hansen .methods(boost::beast::http::verb::post)(std::bind_front( 1320599b9af3SAlexander Hansen handleSystemsLogServicesEventLogActionsClearPost, std::ref(app))); 1321c4bf6374SJason M. Bills } 1322c4bf6374SJason M. Bills 1323ac992cdeSJason M. Bills enum class LogParseError 1324ac992cdeSJason M. Bills { 1325ac992cdeSJason M. Bills success, 1326ac992cdeSJason M. Bills parseFailed, 1327ac992cdeSJason M. Bills messageIdNotInRegistry, 1328ac992cdeSJason M. Bills }; 1329ac992cdeSJason M. Bills 1330bd79bce8SPatrick Williams static LogParseError fillEventLogEntryJson( 1331bd79bce8SPatrick Williams const std::string& logEntryID, const std::string& logEntry, 1332de703c5dSJason M. Bills nlohmann::json::object_t& logEntryJson) 1333c4bf6374SJason M. Bills { 133495820184SJason M. Bills // The redfish log format is "<Timestamp> <MessageId>,<MessageArgs>" 1335cd225da8SJason M. Bills // First get the Timestamp 1336f23b7296SEd Tanous size_t space = logEntry.find_first_of(' '); 1337cd225da8SJason M. Bills if (space == std::string::npos) 133895820184SJason M. Bills { 1339ac992cdeSJason M. Bills return LogParseError::parseFailed; 134095820184SJason M. Bills } 1341cd225da8SJason M. Bills std::string timestamp = logEntry.substr(0, space); 1342cd225da8SJason M. Bills // Then get the log contents 1343f23b7296SEd Tanous size_t entryStart = logEntry.find_first_not_of(' ', space); 1344cd225da8SJason M. Bills if (entryStart == std::string::npos) 1345cd225da8SJason M. Bills { 1346ac992cdeSJason M. Bills return LogParseError::parseFailed; 1347cd225da8SJason M. Bills } 1348cd225da8SJason M. Bills std::string_view entry(logEntry); 1349cd225da8SJason M. Bills entry.remove_prefix(entryStart); 1350cd225da8SJason M. Bills // Use split to separate the entry into its fields 1351cd225da8SJason M. Bills std::vector<std::string> logEntryFields; 135250ebd4afSEd Tanous bmcweb::split(logEntryFields, entry, ','); 1353cd225da8SJason M. Bills // We need at least a MessageId to be valid 13541e6deaf6SEd Tanous auto logEntryIter = logEntryFields.begin(); 13551e6deaf6SEd Tanous if (logEntryIter == logEntryFields.end()) 1356cd225da8SJason M. Bills { 1357ac992cdeSJason M. Bills return LogParseError::parseFailed; 1358cd225da8SJason M. Bills } 13591e6deaf6SEd Tanous std::string& messageID = *logEntryIter; 13604851d45dSJason M. Bills // Get the Message from the MessageRegistry 1361fffb8c1fSEd Tanous const registries::Message* message = registries::getMessage(messageID); 1362c4bf6374SJason M. Bills 13631e6deaf6SEd Tanous logEntryIter++; 136454417b02SSui Chen if (message == nullptr) 1365c4bf6374SJason M. Bills { 136662598e31SEd Tanous BMCWEB_LOG_WARNING("Log entry not found in registry: {}", logEntry); 1367ac992cdeSJason M. Bills return LogParseError::messageIdNotInRegistry; 1368c4bf6374SJason M. Bills } 1369c4bf6374SJason M. Bills 13701e6deaf6SEd Tanous std::vector<std::string_view> messageArgs(logEntryIter, 13711e6deaf6SEd Tanous logEntryFields.end()); 1372c05bba45SEd Tanous messageArgs.resize(message->numberOfArgs); 1373c05bba45SEd Tanous 1374bd79bce8SPatrick Williams std::string msg = 1375bd79bce8SPatrick Williams redfish::registries::fillMessageArgs(messageArgs, message->message); 13761e6deaf6SEd Tanous if (msg.empty()) 137715a86ff6SJason M. Bills { 13781e6deaf6SEd Tanous return LogParseError::parseFailed; 137915a86ff6SJason M. Bills } 13804851d45dSJason M. Bills 138195820184SJason M. Bills // Get the Created time from the timestamp. The log timestamp is in RFC3339 138295820184SJason M. Bills // format which matches the Redfish format except for the fractional seconds 138395820184SJason M. Bills // between the '.' and the '+', so just remove them. 1384f23b7296SEd Tanous std::size_t dot = timestamp.find_first_of('.'); 1385f23b7296SEd Tanous std::size_t plus = timestamp.find_first_of('+'); 138695820184SJason M. Bills if (dot != std::string::npos && plus != std::string::npos) 1387c4bf6374SJason M. Bills { 138895820184SJason M. Bills timestamp.erase(dot, plus - dot); 1389c4bf6374SJason M. Bills } 1390c4bf6374SJason M. Bills 1391c4bf6374SJason M. Bills // Fill in the log entry with the gathered data 13929c11a172SVijay Lobo logEntryJson["@odata.type"] = "#LogEntry.v1_9_0.LogEntry"; 1393ef4c65b7SEd Tanous logEntryJson["@odata.id"] = boost::urls::format( 1394253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}", 1395253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, logEntryID); 139684afc48bSJason M. Bills logEntryJson["Name"] = "System Event Log Entry"; 139784afc48bSJason M. Bills logEntryJson["Id"] = logEntryID; 139884afc48bSJason M. Bills logEntryJson["Message"] = std::move(msg); 139984afc48bSJason M. Bills logEntryJson["MessageId"] = std::move(messageID); 140084afc48bSJason M. Bills logEntryJson["MessageArgs"] = messageArgs; 140184afc48bSJason M. Bills logEntryJson["EntryType"] = "Event"; 140284afc48bSJason M. Bills logEntryJson["Severity"] = message->messageSeverity; 140384afc48bSJason M. Bills logEntryJson["Created"] = std::move(timestamp); 1404ac992cdeSJason M. Bills return LogParseError::success; 1405c4bf6374SJason M. Bills } 1406c4bf6374SJason M. Bills 1407898f2aa2SEd Tanous inline void fillEventLogLogEntryFromPropertyMap( 1408898f2aa2SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1409898f2aa2SEd Tanous const dbus::utility::DBusPropertiesMap& resp, 1410898f2aa2SEd Tanous nlohmann::json& objectToFillOut) 1411898f2aa2SEd Tanous { 1412262dcc1cSAlexander Hansen std::optional<DbusEventLogEntry> optEntry = 1413262dcc1cSAlexander Hansen fillDbusEventLogEntryFromPropertyMap(resp); 1414898f2aa2SEd Tanous 1415262dcc1cSAlexander Hansen if (!optEntry.has_value()) 1416898f2aa2SEd Tanous { 1417898f2aa2SEd Tanous messages::internalError(asyncResp->res); 1418898f2aa2SEd Tanous return; 1419898f2aa2SEd Tanous } 1420262dcc1cSAlexander Hansen DbusEventLogEntry entry = optEntry.value(); 1421898f2aa2SEd Tanous 1422898f2aa2SEd Tanous objectToFillOut["@odata.type"] = "#LogEntry.v1_9_0.LogEntry"; 1423898f2aa2SEd Tanous objectToFillOut["@odata.id"] = boost::urls::format( 1424898f2aa2SEd Tanous "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}", 1425262dcc1cSAlexander Hansen BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(entry.Id)); 1426898f2aa2SEd Tanous objectToFillOut["Name"] = "System Event Log Entry"; 1427262dcc1cSAlexander Hansen objectToFillOut["Id"] = std::to_string(entry.Id); 1428262dcc1cSAlexander Hansen objectToFillOut["Message"] = entry.Message; 1429262dcc1cSAlexander Hansen objectToFillOut["Resolved"] = entry.Resolved; 1430262dcc1cSAlexander Hansen std::optional<bool> notifyAction = 1431262dcc1cSAlexander Hansen getProviderNotifyAction(entry.ServiceProviderNotify); 1432898f2aa2SEd Tanous if (notifyAction) 1433898f2aa2SEd Tanous { 1434898f2aa2SEd Tanous objectToFillOut["ServiceProviderNotified"] = *notifyAction; 1435898f2aa2SEd Tanous } 1436262dcc1cSAlexander Hansen if ((entry.Resolution != nullptr) && !entry.Resolution->empty()) 1437898f2aa2SEd Tanous { 1438262dcc1cSAlexander Hansen objectToFillOut["Resolution"] = *entry.Resolution; 1439898f2aa2SEd Tanous } 1440898f2aa2SEd Tanous objectToFillOut["EntryType"] = "Event"; 1441262dcc1cSAlexander Hansen objectToFillOut["Severity"] = 1442262dcc1cSAlexander Hansen translateSeverityDbusToRedfish(entry.Severity); 1443898f2aa2SEd Tanous objectToFillOut["Created"] = 1444262dcc1cSAlexander Hansen redfish::time_utils::getDateTimeUintMs(entry.Timestamp); 1445898f2aa2SEd Tanous objectToFillOut["Modified"] = 1446262dcc1cSAlexander Hansen redfish::time_utils::getDateTimeUintMs(entry.UpdateTimestamp); 1447262dcc1cSAlexander Hansen if (entry.Path != nullptr) 1448898f2aa2SEd Tanous { 1449898f2aa2SEd Tanous objectToFillOut["AdditionalDataURI"] = boost::urls::format( 1450898f2aa2SEd Tanous "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}/attachment", 1451262dcc1cSAlexander Hansen BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(entry.Id)); 1452898f2aa2SEd Tanous } 1453898f2aa2SEd Tanous } 1454898f2aa2SEd Tanous 1455b729096dSEd Tanous inline void afterLogEntriesGetManagedObjects( 1456b729096dSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1457b729096dSEd Tanous const boost::system::error_code& ec, 1458b729096dSEd Tanous const dbus::utility::ManagedObjectType& resp) 1459b729096dSEd Tanous { 1460b729096dSEd Tanous if (ec) 1461b729096dSEd Tanous { 1462b729096dSEd Tanous // TODO Handle for specific error code 1463b729096dSEd Tanous BMCWEB_LOG_ERROR("getLogEntriesIfaceData resp_handler got error {}", 1464b729096dSEd Tanous ec); 1465b729096dSEd Tanous messages::internalError(asyncResp->res); 1466b729096dSEd Tanous return; 1467b729096dSEd Tanous } 1468b729096dSEd Tanous nlohmann::json::array_t entriesArray; 1469b729096dSEd Tanous for (const auto& objectPath : resp) 1470b729096dSEd Tanous { 1471898f2aa2SEd Tanous dbus::utility::DBusPropertiesMap propsFlattened; 1472bd79bce8SPatrick Williams auto isEntry = 1473bd79bce8SPatrick Williams std::ranges::find_if(objectPath.second, [](const auto& object) { 1474898f2aa2SEd Tanous return object.first == "xyz.openbmc_project.Logging.Entry"; 1475898f2aa2SEd Tanous }); 1476898f2aa2SEd Tanous if (isEntry == objectPath.second.end()) 1477b729096dSEd Tanous { 1478b729096dSEd Tanous continue; 1479b729096dSEd Tanous } 1480898f2aa2SEd Tanous for (const auto& interfaceMap : objectPath.second) 1481b729096dSEd Tanous { 1482898f2aa2SEd Tanous for (const auto& propertyMap : interfaceMap.second) 1483b729096dSEd Tanous { 1484898f2aa2SEd Tanous propsFlattened.emplace_back(propertyMap.first, 1485898f2aa2SEd Tanous propertyMap.second); 1486b729096dSEd Tanous } 1487b729096dSEd Tanous } 1488898f2aa2SEd Tanous fillEventLogLogEntryFromPropertyMap(asyncResp, propsFlattened, 1489898f2aa2SEd Tanous entriesArray.emplace_back()); 1490b729096dSEd Tanous } 1491898f2aa2SEd Tanous 1492b729096dSEd Tanous std::ranges::sort(entriesArray, [](const nlohmann::json& left, 1493b729096dSEd Tanous const nlohmann::json& right) { 1494b729096dSEd Tanous return (left["Id"] <= right["Id"]); 1495b729096dSEd Tanous }); 1496b729096dSEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = entriesArray.size(); 1497b729096dSEd Tanous asyncResp->res.jsonValue["Members"] = std::move(entriesArray); 1498b729096dSEd Tanous } 1499b729096dSEd Tanous 1500599b9af3SAlexander Hansen inline void handleSystemsLogServiceEventLogLogEntryCollection( 1501599b9af3SAlexander Hansen App& app, const crow::Request& req, 150222d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1503599b9af3SAlexander Hansen const std::string& systemName) 1504599b9af3SAlexander Hansen { 1505c937d2bfSEd Tanous query_param::QueryCapabilities capabilities = { 1506c937d2bfSEd Tanous .canDelegateTop = true, 1507c937d2bfSEd Tanous .canDelegateSkip = true, 1508c937d2bfSEd Tanous }; 1509c937d2bfSEd Tanous query_param::Query delegatedQuery; 1510599b9af3SAlexander Hansen if (!redfish::setUpRedfishRouteWithDelegation(app, req, asyncResp, 1511599b9af3SAlexander Hansen delegatedQuery, capabilities)) 1512c4bf6374SJason M. Bills { 1513c4bf6374SJason M. Bills return; 1514c4bf6374SJason M. Bills } 151525b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 15167f3e84a1SEd Tanous { 15177f3e84a1SEd Tanous // Option currently returns no systems. TBD 15187f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 15197f3e84a1SEd Tanous systemName); 15207f3e84a1SEd Tanous return; 15217f3e84a1SEd Tanous } 1522253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 152322d268cbSEd Tanous { 152422d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 152522d268cbSEd Tanous systemName); 152622d268cbSEd Tanous return; 152722d268cbSEd Tanous } 152822d268cbSEd Tanous 15295143f7a5SJiaqing Zhao size_t top = delegatedQuery.top.value_or(query_param::Query::maxTop); 15303648c8beSEd Tanous size_t skip = delegatedQuery.skip.value_or(0); 15313648c8beSEd Tanous 15327e860f15SJohn Edward Broadbent // Collections don't include the static data added by SubRoute 15337e860f15SJohn Edward Broadbent // because it has a duplicate entry for members 1534c4bf6374SJason M. Bills asyncResp->res.jsonValue["@odata.type"] = 1535c4bf6374SJason M. Bills "#LogEntryCollection.LogEntryCollection"; 1536c4bf6374SJason M. Bills asyncResp->res.jsonValue["@odata.id"] = 1537253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries", 1538253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1539c4bf6374SJason M. Bills asyncResp->res.jsonValue["Name"] = "System Event Log Entries"; 1540c4bf6374SJason M. Bills asyncResp->res.jsonValue["Description"] = 1541c4bf6374SJason M. Bills "Collection of System Event Log Entries"; 1542cb92c03bSAndrew Geissler 15434978b63fSJason M. Bills nlohmann::json& logEntryArray = asyncResp->res.jsonValue["Members"]; 1544c4bf6374SJason M. Bills logEntryArray = nlohmann::json::array(); 15457e860f15SJohn Edward Broadbent // Go through the log files and create a unique ID for each 15467e860f15SJohn Edward Broadbent // entry 154795820184SJason M. Bills std::vector<std::filesystem::path> redfishLogFiles; 154895820184SJason M. Bills getRedfishLogFiles(redfishLogFiles); 1549b01bf299SEd Tanous uint64_t entryCount = 0; 1550cd225da8SJason M. Bills std::string logEntry; 155195820184SJason M. Bills 15527e860f15SJohn Edward Broadbent // Oldest logs are in the last file, so start there and loop 15537e860f15SJohn Edward Broadbent // backwards 1554599b9af3SAlexander Hansen for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend(); it++) 1555c4bf6374SJason M. Bills { 1556cd225da8SJason M. Bills std::ifstream logStream(*it); 155795820184SJason M. Bills if (!logStream.is_open()) 1558c4bf6374SJason M. Bills { 1559c4bf6374SJason M. Bills continue; 1560c4bf6374SJason M. Bills } 1561c4bf6374SJason M. Bills 1562e85d6b16SJason M. Bills // Reset the unique ID on the first entry 1563e85d6b16SJason M. Bills bool firstEntry = true; 156495820184SJason M. Bills while (std::getline(logStream, logEntry)) 156595820184SJason M. Bills { 1566c4bf6374SJason M. Bills std::string idStr; 1567e85d6b16SJason M. Bills if (!getUniqueEntryID(logEntry, idStr, firstEntry)) 1568c4bf6374SJason M. Bills { 1569c4bf6374SJason M. Bills continue; 1570c4bf6374SJason M. Bills } 1571e85d6b16SJason M. Bills firstEntry = false; 1572e85d6b16SJason M. Bills 1573de703c5dSJason M. Bills nlohmann::json::object_t bmcLogEntry; 1574bd79bce8SPatrick Williams LogParseError status = 1575bd79bce8SPatrick Williams fillEventLogEntryJson(idStr, logEntry, bmcLogEntry); 1576ac992cdeSJason M. Bills if (status == LogParseError::messageIdNotInRegistry) 1577ac992cdeSJason M. Bills { 1578ac992cdeSJason M. Bills continue; 1579ac992cdeSJason M. Bills } 1580ac992cdeSJason M. Bills if (status != LogParseError::success) 1581c4bf6374SJason M. Bills { 1582c4bf6374SJason M. Bills messages::internalError(asyncResp->res); 1583c4bf6374SJason M. Bills return; 1584c4bf6374SJason M. Bills } 1585de703c5dSJason M. Bills 1586de703c5dSJason M. Bills entryCount++; 1587de703c5dSJason M. Bills // Handle paging using skip (number of entries to skip from the 1588de703c5dSJason M. Bills // start) and top (number of entries to display) 15893648c8beSEd Tanous if (entryCount <= skip || entryCount > skip + top) 1590de703c5dSJason M. Bills { 1591de703c5dSJason M. Bills continue; 1592de703c5dSJason M. Bills } 1593de703c5dSJason M. Bills 1594b2ba3072SPatrick Williams logEntryArray.emplace_back(std::move(bmcLogEntry)); 1595c4bf6374SJason M. Bills } 159695820184SJason M. Bills } 1597c4bf6374SJason M. Bills asyncResp->res.jsonValue["Members@odata.count"] = entryCount; 15983648c8beSEd Tanous if (skip + top < entryCount) 1599c4bf6374SJason M. Bills { 1600599b9af3SAlexander Hansen asyncResp->res.jsonValue["Members@odata.nextLink"] = 1601599b9af3SAlexander Hansen boost::urls::format( 1602253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/EventLog/Entries?$skip={}", 1603253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(skip + top)); 1604c4bf6374SJason M. Bills } 1605897967deSJason M. Bills } 1606897967deSJason M. Bills 1607599b9af3SAlexander Hansen inline void requestRoutesJournalEventLogEntryCollection(App& app) 1608897967deSJason M. Bills { 1609599b9af3SAlexander Hansen BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/") 1610599b9af3SAlexander Hansen .privileges(redfish::privileges::getLogEntryCollection) 1611599b9af3SAlexander Hansen .methods(boost::beast::http::verb::get)(std::bind_front( 1612599b9af3SAlexander Hansen handleSystemsLogServiceEventLogLogEntryCollection, std::ref(app))); 1613599b9af3SAlexander Hansen } 1614599b9af3SAlexander Hansen 1615599b9af3SAlexander Hansen inline void handleSystemsLogServiceEventLogEntriesGet( 1616599b9af3SAlexander Hansen App& app, const crow::Request& req, 16177e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1618599b9af3SAlexander Hansen const std::string& systemName, const std::string& param) 1619599b9af3SAlexander Hansen { 16203ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 162145ca1b86SEd Tanous { 162245ca1b86SEd Tanous return; 162345ca1b86SEd Tanous } 162425b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 16257f3e84a1SEd Tanous { 16267f3e84a1SEd Tanous // Option currently returns no systems. TBD 16277f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 16287f3e84a1SEd Tanous systemName); 16297f3e84a1SEd Tanous return; 16307f3e84a1SEd Tanous } 163122d268cbSEd Tanous 1632253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 163322d268cbSEd Tanous { 163422d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 163522d268cbSEd Tanous systemName); 163622d268cbSEd Tanous return; 163722d268cbSEd Tanous } 163822d268cbSEd Tanous 16397e860f15SJohn Edward Broadbent const std::string& targetID = param; 16408d1b46d7Szhanghch05 16417e860f15SJohn Edward Broadbent // Go through the log files and check the unique ID for each 16427e860f15SJohn Edward Broadbent // entry to find the target entry 1643897967deSJason M. Bills std::vector<std::filesystem::path> redfishLogFiles; 1644897967deSJason M. Bills getRedfishLogFiles(redfishLogFiles); 1645897967deSJason M. Bills std::string logEntry; 1646897967deSJason M. Bills 16477e860f15SJohn Edward Broadbent // Oldest logs are in the last file, so start there and loop 16487e860f15SJohn Edward Broadbent // backwards 1649599b9af3SAlexander Hansen for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend(); it++) 1650897967deSJason M. Bills { 1651897967deSJason M. Bills std::ifstream logStream(*it); 1652897967deSJason M. Bills if (!logStream.is_open()) 1653897967deSJason M. Bills { 1654897967deSJason M. Bills continue; 1655897967deSJason M. Bills } 1656897967deSJason M. Bills 1657897967deSJason M. Bills // Reset the unique ID on the first entry 1658897967deSJason M. Bills bool firstEntry = true; 1659897967deSJason M. Bills while (std::getline(logStream, logEntry)) 1660897967deSJason M. Bills { 1661897967deSJason M. Bills std::string idStr; 1662897967deSJason M. Bills if (!getUniqueEntryID(logEntry, idStr, firstEntry)) 1663897967deSJason M. Bills { 1664897967deSJason M. Bills continue; 1665897967deSJason M. Bills } 1666897967deSJason M. Bills firstEntry = false; 1667897967deSJason M. Bills 1668897967deSJason M. Bills if (idStr == targetID) 1669897967deSJason M. Bills { 1670de703c5dSJason M. Bills nlohmann::json::object_t bmcLogEntry; 1671bd79bce8SPatrick Williams LogParseError status = 1672bd79bce8SPatrick Williams fillEventLogEntryJson(idStr, logEntry, bmcLogEntry); 1673ac992cdeSJason M. Bills if (status != LogParseError::success) 1674897967deSJason M. Bills { 1675897967deSJason M. Bills messages::internalError(asyncResp->res); 1676897967deSJason M. Bills return; 1677897967deSJason M. Bills } 1678d405bb51SJason M. Bills asyncResp->res.jsonValue.update(bmcLogEntry); 1679897967deSJason M. Bills return; 1680897967deSJason M. Bills } 1681897967deSJason M. Bills } 1682897967deSJason M. Bills } 1683897967deSJason M. Bills // Requested ID was not found 16849db4ba25SJiaqing Zhao messages::resourceNotFound(asyncResp->res, "LogEntry", targetID); 1685599b9af3SAlexander Hansen } 1686599b9af3SAlexander Hansen 1687599b9af3SAlexander Hansen inline void requestRoutesJournalEventLogEntry(App& app) 1688599b9af3SAlexander Hansen { 1689599b9af3SAlexander Hansen BMCWEB_ROUTE( 1690599b9af3SAlexander Hansen app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/") 1691599b9af3SAlexander Hansen .privileges(redfish::privileges::getLogEntry) 1692599b9af3SAlexander Hansen .methods(boost::beast::http::verb::get)(std::bind_front( 1693599b9af3SAlexander Hansen handleSystemsLogServiceEventLogEntriesGet, std::ref(app))); 1694599b9af3SAlexander Hansen } 1695599b9af3SAlexander Hansen 1696599b9af3SAlexander Hansen inline void dBusEventLogEntryCollection( 1697599b9af3SAlexander Hansen const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1698599b9af3SAlexander Hansen { 1699599b9af3SAlexander Hansen // Collections don't include the static data added by SubRoute 1700599b9af3SAlexander Hansen // because it has a duplicate entry for members 1701599b9af3SAlexander Hansen asyncResp->res.jsonValue["@odata.type"] = 1702599b9af3SAlexander Hansen "#LogEntryCollection.LogEntryCollection"; 1703599b9af3SAlexander Hansen asyncResp->res.jsonValue["@odata.id"] = 1704599b9af3SAlexander Hansen std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries", 1705599b9af3SAlexander Hansen BMCWEB_REDFISH_SYSTEM_URI_NAME); 1706599b9af3SAlexander Hansen asyncResp->res.jsonValue["Name"] = "System Event Log Entries"; 1707599b9af3SAlexander Hansen asyncResp->res.jsonValue["Description"] = 1708599b9af3SAlexander Hansen "Collection of System Event Log Entries"; 1709599b9af3SAlexander Hansen 1710599b9af3SAlexander Hansen // DBus implementation of EventLog/Entries 1711599b9af3SAlexander Hansen // Make call to Logging Service to find all log entry objects 1712599b9af3SAlexander Hansen sdbusplus::message::object_path path("/xyz/openbmc_project/logging"); 1713599b9af3SAlexander Hansen dbus::utility::getManagedObjects( 1714599b9af3SAlexander Hansen "xyz.openbmc_project.Logging", path, 1715599b9af3SAlexander Hansen [asyncResp](const boost::system::error_code& ec, 1716599b9af3SAlexander Hansen const dbus::utility::ManagedObjectType& resp) { 1717b729096dSEd Tanous afterLogEntriesGetManagedObjects(asyncResp, ec, resp); 17187e860f15SJohn Edward Broadbent }); 171908a4e4b5SAnthony Wilson } 172008a4e4b5SAnthony Wilson 17217e860f15SJohn Edward Broadbent inline void requestRoutesDBusEventLogEntryCollection(App& app) 172208a4e4b5SAnthony Wilson { 172322d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/") 1724ed398213SEd Tanous .privileges(redfish::privileges::getLogEntryCollection) 1725002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 1726002d39b4SEd Tanous [&app](const crow::Request& req, 172722d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 172822d268cbSEd Tanous const std::string& systemName) { 17293ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 173045ca1b86SEd Tanous { 173145ca1b86SEd Tanous return; 173245ca1b86SEd Tanous } 173325b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 17347f3e84a1SEd Tanous { 17357f3e84a1SEd Tanous // Option currently returns no systems. TBD 17367f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 17377f3e84a1SEd Tanous systemName); 17387f3e84a1SEd Tanous return; 17397f3e84a1SEd Tanous } 1740253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 174122d268cbSEd Tanous { 174222d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 174322d268cbSEd Tanous systemName); 174422d268cbSEd Tanous return; 174522d268cbSEd Tanous } 1746599b9af3SAlexander Hansen dBusEventLogEntryCollection(asyncResp); 1747599b9af3SAlexander Hansen }); 1748599b9af3SAlexander Hansen } 174922d268cbSEd Tanous 1750bd79bce8SPatrick Williams inline void dBusEventLogEntryGet( 1751bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID) 1752599b9af3SAlexander Hansen { 1753599b9af3SAlexander Hansen dbus::utility::escapePathForDbus(entryID); 175408a4e4b5SAnthony Wilson 1755cb92c03bSAndrew Geissler // DBus implementation of EventLog/Entries 1756cb92c03bSAndrew Geissler // Make call to Logging Service to find all log entry objects 1757deae6a78SEd Tanous dbus::utility::getAllProperties( 1758deae6a78SEd Tanous "xyz.openbmc_project.Logging", 1759599b9af3SAlexander Hansen "/xyz/openbmc_project/logging/entry/" + entryID, "", 1760599b9af3SAlexander Hansen [asyncResp, entryID](const boost::system::error_code& ec, 1761599b9af3SAlexander Hansen const dbus::utility::DBusPropertiesMap& resp) { 1762599b9af3SAlexander Hansen if (ec.value() == EBADR) 1763599b9af3SAlexander Hansen { 1764599b9af3SAlexander Hansen messages::resourceNotFound(asyncResp->res, "EventLogEntry", 1765599b9af3SAlexander Hansen entryID); 1766599b9af3SAlexander Hansen return; 1767599b9af3SAlexander Hansen } 1768cb92c03bSAndrew Geissler if (ec) 1769cb92c03bSAndrew Geissler { 1770bd79bce8SPatrick Williams BMCWEB_LOG_ERROR( 1771bd79bce8SPatrick Williams "EventLogEntry (DBus) resp_handler got error {}", ec); 1772cb92c03bSAndrew Geissler messages::internalError(asyncResp->res); 1773cb92c03bSAndrew Geissler return; 1774cb92c03bSAndrew Geissler } 17759017faf2SAbhishek Patel 1776898f2aa2SEd Tanous fillEventLogLogEntryFromPropertyMap(asyncResp, resp, 1777898f2aa2SEd Tanous asyncResp->res.jsonValue); 1778599b9af3SAlexander Hansen }); 17797e860f15SJohn Edward Broadbent } 1780599b9af3SAlexander Hansen 1781599b9af3SAlexander Hansen inline void 1782599b9af3SAlexander Hansen dBusEventLogEntryPatch(const crow::Request& req, 1783599b9af3SAlexander Hansen const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1784599b9af3SAlexander Hansen const std::string& entryId) 1785599b9af3SAlexander Hansen { 1786599b9af3SAlexander Hansen std::optional<bool> resolved; 1787599b9af3SAlexander Hansen 1788599b9af3SAlexander Hansen if (!json_util::readJsonPatch(req, asyncResp->res, "Resolved", resolved)) 1789599b9af3SAlexander Hansen { 1790599b9af3SAlexander Hansen return; 1791599b9af3SAlexander Hansen } 1792599b9af3SAlexander Hansen BMCWEB_LOG_DEBUG("Set Resolved"); 1793599b9af3SAlexander Hansen 1794599b9af3SAlexander Hansen setDbusProperty(asyncResp, "Resolved", "xyz.openbmc_project.Logging", 1795599b9af3SAlexander Hansen "/xyz/openbmc_project/logging/entry/" + entryId, 1796599b9af3SAlexander Hansen "xyz.openbmc_project.Logging.Entry", "Resolved", 1797599b9af3SAlexander Hansen resolved.value_or(false)); 1798599b9af3SAlexander Hansen } 1799599b9af3SAlexander Hansen 1800bd79bce8SPatrick Williams inline void dBusEventLogEntryDelete( 1801bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID) 1802599b9af3SAlexander Hansen { 1803599b9af3SAlexander Hansen BMCWEB_LOG_DEBUG("Do delete single event entries."); 1804599b9af3SAlexander Hansen 1805599b9af3SAlexander Hansen dbus::utility::escapePathForDbus(entryID); 1806599b9af3SAlexander Hansen 1807599b9af3SAlexander Hansen // Process response from Logging service. 1808599b9af3SAlexander Hansen auto respHandler = [asyncResp, 1809599b9af3SAlexander Hansen entryID](const boost::system::error_code& ec) { 1810599b9af3SAlexander Hansen BMCWEB_LOG_DEBUG("EventLogEntry (DBus) doDelete callback: Done"); 1811599b9af3SAlexander Hansen if (ec) 1812599b9af3SAlexander Hansen { 1813599b9af3SAlexander Hansen if (ec.value() == EBADR) 1814599b9af3SAlexander Hansen { 1815599b9af3SAlexander Hansen messages::resourceNotFound(asyncResp->res, "LogEntry", entryID); 1816599b9af3SAlexander Hansen return; 1817599b9af3SAlexander Hansen } 1818599b9af3SAlexander Hansen // TODO Handle for specific error code 1819599b9af3SAlexander Hansen BMCWEB_LOG_ERROR( 1820599b9af3SAlexander Hansen "EventLogEntry (DBus) doDelete respHandler got error {}", ec); 1821599b9af3SAlexander Hansen asyncResp->res.result( 1822599b9af3SAlexander Hansen boost::beast::http::status::internal_server_error); 1823599b9af3SAlexander Hansen return; 1824599b9af3SAlexander Hansen } 1825599b9af3SAlexander Hansen 1826599b9af3SAlexander Hansen asyncResp->res.result(boost::beast::http::status::ok); 1827599b9af3SAlexander Hansen }; 1828599b9af3SAlexander Hansen 1829599b9af3SAlexander Hansen // Make call to Logging service to request Delete Log 1830599b9af3SAlexander Hansen crow::connections::systemBus->async_method_call( 1831599b9af3SAlexander Hansen respHandler, "xyz.openbmc_project.Logging", 1832599b9af3SAlexander Hansen "/xyz/openbmc_project/logging/entry/" + entryID, 1833599b9af3SAlexander Hansen "xyz.openbmc_project.Object.Delete", "Delete"); 18347e860f15SJohn Edward Broadbent } 18357e860f15SJohn Edward Broadbent 18367e860f15SJohn Edward Broadbent inline void requestRoutesDBusEventLogEntry(App& app) 18377e860f15SJohn Edward Broadbent { 18387e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 183922d268cbSEd Tanous app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/") 1840ed398213SEd Tanous .privileges(redfish::privileges::getLogEntry) 1841002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 1842002d39b4SEd Tanous [&app](const crow::Request& req, 18437e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1844898f2aa2SEd Tanous const std::string& systemName, const std::string& entryId) { 18453ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 18467e860f15SJohn Edward Broadbent { 184745ca1b86SEd Tanous return; 184845ca1b86SEd Tanous } 184925b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 18507f3e84a1SEd Tanous { 18517f3e84a1SEd Tanous // Option currently returns no systems. TBD 18527f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 18537f3e84a1SEd Tanous systemName); 18547f3e84a1SEd Tanous return; 18557f3e84a1SEd Tanous } 1856253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 185722d268cbSEd Tanous { 185822d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 185922d268cbSEd Tanous systemName); 186022d268cbSEd Tanous return; 186122d268cbSEd Tanous } 186222d268cbSEd Tanous 1863898f2aa2SEd Tanous dBusEventLogEntryGet(asyncResp, entryId); 18647e860f15SJohn Edward Broadbent }); 1865336e96c6SChicago Duan 18667e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 186722d268cbSEd Tanous app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/") 1868ed398213SEd Tanous .privileges(redfish::privileges::patchLogEntry) 18697e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::patch)( 187045ca1b86SEd Tanous [&app](const crow::Request& req, 18717e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 187222d268cbSEd Tanous const std::string& systemName, const std::string& entryId) { 18733ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 187445ca1b86SEd Tanous { 187545ca1b86SEd Tanous return; 187645ca1b86SEd Tanous } 187725b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 18787f3e84a1SEd Tanous { 18797f3e84a1SEd Tanous // Option currently returns no systems. TBD 18807f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 18817f3e84a1SEd Tanous systemName); 18827f3e84a1SEd Tanous return; 18837f3e84a1SEd Tanous } 1884253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 188522d268cbSEd Tanous { 188622d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 188722d268cbSEd Tanous systemName); 188822d268cbSEd Tanous return; 188922d268cbSEd Tanous } 189075710de2SXiaochao Ma 1891599b9af3SAlexander Hansen dBusEventLogEntryPatch(req, asyncResp, entryId); 18927e860f15SJohn Edward Broadbent }); 189375710de2SXiaochao Ma 18947e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 189522d268cbSEd Tanous app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/") 1896ed398213SEd Tanous .privileges(redfish::privileges::deleteLogEntry) 1897ed398213SEd Tanous 1898002d39b4SEd Tanous .methods(boost::beast::http::verb::delete_)( 1899002d39b4SEd Tanous [&app](const crow::Request& req, 1900002d39b4SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 190122d268cbSEd Tanous const std::string& systemName, const std::string& param) { 19023ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 1903336e96c6SChicago Duan { 190445ca1b86SEd Tanous return; 190545ca1b86SEd Tanous } 190625b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 19077f3e84a1SEd Tanous { 19087f3e84a1SEd Tanous // Option currently returns no systems. TBD 19097f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 19107f3e84a1SEd Tanous systemName); 19117f3e84a1SEd Tanous return; 19127f3e84a1SEd Tanous } 1913253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 191422d268cbSEd Tanous { 191522d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 191622d268cbSEd Tanous systemName); 191722d268cbSEd Tanous return; 191822d268cbSEd Tanous } 1919599b9af3SAlexander Hansen dBusEventLogEntryDelete(asyncResp, param); 19207e860f15SJohn Edward Broadbent }); 1921400fd1fbSAdriana Kobylak } 1922400fd1fbSAdriana Kobylak 1923b7028ebfSSpencer Ku constexpr const char* hostLoggerFolderPath = "/var/log/console"; 1924b7028ebfSSpencer Ku 1925b7028ebfSSpencer Ku inline bool 1926b7028ebfSSpencer Ku getHostLoggerFiles(const std::string& hostLoggerFilePath, 1927b7028ebfSSpencer Ku std::vector<std::filesystem::path>& hostLoggerFiles) 1928b7028ebfSSpencer Ku { 1929b7028ebfSSpencer Ku std::error_code ec; 1930b7028ebfSSpencer Ku std::filesystem::directory_iterator logPath(hostLoggerFilePath, ec); 1931b7028ebfSSpencer Ku if (ec) 1932b7028ebfSSpencer Ku { 1933bf2ddedeSCarson Labrado BMCWEB_LOG_WARNING("{}", ec.message()); 1934b7028ebfSSpencer Ku return false; 1935b7028ebfSSpencer Ku } 1936b7028ebfSSpencer Ku for (const std::filesystem::directory_entry& it : logPath) 1937b7028ebfSSpencer Ku { 1938b7028ebfSSpencer Ku std::string filename = it.path().filename(); 1939b7028ebfSSpencer Ku // Prefix of each log files is "log". Find the file and save the 1940b7028ebfSSpencer Ku // path 194111ba3979SEd Tanous if (filename.starts_with("log")) 1942b7028ebfSSpencer Ku { 1943b7028ebfSSpencer Ku hostLoggerFiles.emplace_back(it.path()); 1944b7028ebfSSpencer Ku } 1945b7028ebfSSpencer Ku } 1946b7028ebfSSpencer Ku // As the log files rotate, they are appended with a ".#" that is higher for 1947b7028ebfSSpencer Ku // the older logs. Since we start from oldest logs, sort the name in 1948b7028ebfSSpencer Ku // descending order. 1949b7028ebfSSpencer Ku std::sort(hostLoggerFiles.rbegin(), hostLoggerFiles.rend(), 1950b7028ebfSSpencer Ku AlphanumLess<std::string>()); 1951b7028ebfSSpencer Ku 1952b7028ebfSSpencer Ku return true; 1953b7028ebfSSpencer Ku } 1954b7028ebfSSpencer Ku 195502cad96eSEd Tanous inline bool getHostLoggerEntries( 195602cad96eSEd Tanous const std::vector<std::filesystem::path>& hostLoggerFiles, uint64_t skip, 195702cad96eSEd Tanous uint64_t top, std::vector<std::string>& logEntries, size_t& logCount) 1958b7028ebfSSpencer Ku { 1959b7028ebfSSpencer Ku GzFileReader logFile; 1960b7028ebfSSpencer Ku 1961b7028ebfSSpencer Ku // Go though all log files and expose host logs. 1962b7028ebfSSpencer Ku for (const std::filesystem::path& it : hostLoggerFiles) 1963b7028ebfSSpencer Ku { 1964b7028ebfSSpencer Ku if (!logFile.gzGetLines(it.string(), skip, top, logEntries, logCount)) 1965b7028ebfSSpencer Ku { 196662598e31SEd Tanous BMCWEB_LOG_ERROR("fail to expose host logs"); 1967b7028ebfSSpencer Ku return false; 1968b7028ebfSSpencer Ku } 1969b7028ebfSSpencer Ku } 1970b7028ebfSSpencer Ku // Get lastMessage from constructor by getter 1971b7028ebfSSpencer Ku std::string lastMessage = logFile.getLastMessage(); 1972b7028ebfSSpencer Ku if (!lastMessage.empty()) 1973b7028ebfSSpencer Ku { 1974b7028ebfSSpencer Ku logCount++; 1975b7028ebfSSpencer Ku if (logCount > skip && logCount <= (skip + top)) 1976b7028ebfSSpencer Ku { 1977b7028ebfSSpencer Ku logEntries.push_back(lastMessage); 1978b7028ebfSSpencer Ku } 1979b7028ebfSSpencer Ku } 1980b7028ebfSSpencer Ku return true; 1981b7028ebfSSpencer Ku } 1982b7028ebfSSpencer Ku 1983dd72e87bSClaire Weinan inline void handleBMCLogServicesCollectionGet( 1984fdd26906SClaire Weinan crow::App& app, const crow::Request& req, 1985253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1986253f11b8SEd Tanous const std::string& managerId) 19871da66f75SEd Tanous { 19883ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 198945ca1b86SEd Tanous { 199045ca1b86SEd Tanous return; 199145ca1b86SEd Tanous } 1992253f11b8SEd Tanous 1993253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 1994253f11b8SEd Tanous { 1995253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 1996253f11b8SEd Tanous return; 1997253f11b8SEd Tanous } 1998253f11b8SEd Tanous 19997e860f15SJohn Edward Broadbent // Collections don't include the static data added by SubRoute 20007e860f15SJohn Edward Broadbent // because it has a duplicate entry for members 2001e1f26343SJason M. Bills asyncResp->res.jsonValue["@odata.type"] = 20021da66f75SEd Tanous "#LogServiceCollection.LogServiceCollection"; 2003253f11b8SEd Tanous asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 2004253f11b8SEd Tanous "/redfish/v1/Managers/{}/LogServices", BMCWEB_REDFISH_MANAGER_URI_NAME); 2005002d39b4SEd Tanous asyncResp->res.jsonValue["Name"] = "Open BMC Log Services Collection"; 2006e1f26343SJason M. Bills asyncResp->res.jsonValue["Description"] = 20071da66f75SEd Tanous "Collection of LogServices for this Manager"; 2008002d39b4SEd Tanous nlohmann::json& logServiceArray = asyncResp->res.jsonValue["Members"]; 2009c4bf6374SJason M. Bills logServiceArray = nlohmann::json::array(); 2010fdd26906SClaire Weinan 201125b54dbaSEd Tanous if constexpr (BMCWEB_REDFISH_BMC_JOURNAL) 201225b54dbaSEd Tanous { 2013613dabeaSEd Tanous nlohmann::json::object_t journal; 2014253f11b8SEd Tanous journal["@odata.id"] = 2015253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}/LogServices/Journal", 2016253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 2017b2ba3072SPatrick Williams logServiceArray.emplace_back(std::move(journal)); 201825b54dbaSEd Tanous } 2019fdd26906SClaire Weinan 2020fdd26906SClaire Weinan asyncResp->res.jsonValue["Members@odata.count"] = logServiceArray.size(); 2021fdd26906SClaire Weinan 202225b54dbaSEd Tanous if constexpr (BMCWEB_REDFISH_DUMP_LOG) 202325b54dbaSEd Tanous { 202415912159SGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 20257a1dbc48SGeorge Liu "xyz.openbmc_project.Collection.DeleteAll"}; 20267a1dbc48SGeorge Liu dbus::utility::getSubTreePaths( 20277a1dbc48SGeorge Liu "/xyz/openbmc_project/dump", 0, interfaces, 202825b54dbaSEd Tanous [asyncResp](const boost::system::error_code& ec, 202925b54dbaSEd Tanous const dbus::utility::MapperGetSubTreePathsResponse& 203025b54dbaSEd Tanous subTreePaths) { 2031fdd26906SClaire Weinan if (ec) 2032fdd26906SClaire Weinan { 203362598e31SEd Tanous BMCWEB_LOG_ERROR( 203462598e31SEd Tanous "handleBMCLogServicesCollectionGet respHandler got error {}", 203562598e31SEd Tanous ec); 2036bd79bce8SPatrick Williams // Assume that getting an error simply means there are no 2037bd79bce8SPatrick Williams // dump LogServices. Return without adding any error 2038bd79bce8SPatrick Williams // response. 2039fdd26906SClaire Weinan return; 2040fdd26906SClaire Weinan } 2041fdd26906SClaire Weinan 2042fdd26906SClaire Weinan nlohmann::json& logServiceArrayLocal = 2043fdd26906SClaire Weinan asyncResp->res.jsonValue["Members"]; 2044fdd26906SClaire Weinan 2045fdd26906SClaire Weinan for (const std::string& path : subTreePaths) 2046fdd26906SClaire Weinan { 2047fdd26906SClaire Weinan if (path == "/xyz/openbmc_project/dump/bmc") 2048fdd26906SClaire Weinan { 2049613dabeaSEd Tanous nlohmann::json::object_t member; 2050253f11b8SEd Tanous member["@odata.id"] = boost::urls::format( 2051253f11b8SEd Tanous "/redfish/v1/Managers/{}/LogServices/Dump", 2052253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 2053b2ba3072SPatrick Williams logServiceArrayLocal.emplace_back(std::move(member)); 2054fdd26906SClaire Weinan } 2055fdd26906SClaire Weinan else if (path == "/xyz/openbmc_project/dump/faultlog") 2056fdd26906SClaire Weinan { 2057613dabeaSEd Tanous nlohmann::json::object_t member; 2058253f11b8SEd Tanous member["@odata.id"] = boost::urls::format( 2059253f11b8SEd Tanous "/redfish/v1/Managers/{}/LogServices/FaultLog", 2060253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 2061b2ba3072SPatrick Williams logServiceArrayLocal.emplace_back(std::move(member)); 2062fdd26906SClaire Weinan } 2063fdd26906SClaire Weinan } 2064fdd26906SClaire Weinan 2065e1f26343SJason M. Bills asyncResp->res.jsonValue["Members@odata.count"] = 2066fdd26906SClaire Weinan logServiceArrayLocal.size(); 20677a1dbc48SGeorge Liu }); 206825b54dbaSEd Tanous } 2069fdd26906SClaire Weinan } 2070fdd26906SClaire Weinan 2071fdd26906SClaire Weinan inline void requestRoutesBMCLogServiceCollection(App& app) 2072fdd26906SClaire Weinan { 2073253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/") 2074fdd26906SClaire Weinan .privileges(redfish::privileges::getLogServiceCollection) 2075fdd26906SClaire Weinan .methods(boost::beast::http::verb::get)( 2076dd72e87bSClaire Weinan std::bind_front(handleBMCLogServicesCollectionGet, std::ref(app))); 2077e1f26343SJason M. Bills } 2078e1f26343SJason M. Bills 2079fdd26906SClaire Weinan inline void 2080fdd26906SClaire Weinan getDumpServiceInfo(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2081fdd26906SClaire Weinan const std::string& dumpType) 2082c9bb6861Sraviteja-b { 2083fdd26906SClaire Weinan std::string dumpPath; 2084539d8c6bSEd Tanous log_service::OverWritePolicy overWritePolicy = 2085539d8c6bSEd Tanous log_service::OverWritePolicy::Invalid; 2086fdd26906SClaire Weinan bool collectDiagnosticDataSupported = false; 2087fdd26906SClaire Weinan 2088fdd26906SClaire Weinan if (dumpType == "BMC") 208945ca1b86SEd Tanous { 2090253f11b8SEd Tanous dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/Dump", 2091253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 2092539d8c6bSEd Tanous overWritePolicy = log_service::OverWritePolicy::WrapsWhenFull; 2093fdd26906SClaire Weinan collectDiagnosticDataSupported = true; 2094fdd26906SClaire Weinan } 2095fdd26906SClaire Weinan else if (dumpType == "FaultLog") 2096fdd26906SClaire Weinan { 2097253f11b8SEd Tanous dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/FaultLog", 2098253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 2099539d8c6bSEd Tanous overWritePolicy = log_service::OverWritePolicy::Unknown; 2100fdd26906SClaire Weinan collectDiagnosticDataSupported = false; 2101fdd26906SClaire Weinan } 2102fdd26906SClaire Weinan else if (dumpType == "System") 2103fdd26906SClaire Weinan { 2104253f11b8SEd Tanous dumpPath = std::format("/redfish/v1/Systems/{}/LogServices/Dump", 2105253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 2106539d8c6bSEd Tanous overWritePolicy = log_service::OverWritePolicy::WrapsWhenFull; 2107fdd26906SClaire Weinan collectDiagnosticDataSupported = true; 2108fdd26906SClaire Weinan } 2109fdd26906SClaire Weinan else 2110fdd26906SClaire Weinan { 211162598e31SEd Tanous BMCWEB_LOG_ERROR("getDumpServiceInfo() invalid dump type: {}", 211262598e31SEd Tanous dumpType); 2113fdd26906SClaire Weinan messages::internalError(asyncResp->res); 211445ca1b86SEd Tanous return; 211545ca1b86SEd Tanous } 2116fdd26906SClaire Weinan 2117fdd26906SClaire Weinan asyncResp->res.jsonValue["@odata.id"] = dumpPath; 2118fdd26906SClaire Weinan asyncResp->res.jsonValue["@odata.type"] = "#LogService.v1_2_0.LogService"; 2119c9bb6861Sraviteja-b asyncResp->res.jsonValue["Name"] = "Dump LogService"; 2120fdd26906SClaire Weinan asyncResp->res.jsonValue["Description"] = dumpType + " Dump LogService"; 2121fdd26906SClaire Weinan asyncResp->res.jsonValue["Id"] = std::filesystem::path(dumpPath).filename(); 2122539d8c6bSEd Tanous asyncResp->res.jsonValue["OverWritePolicy"] = overWritePolicy; 21237c8c4058STejas Patil 21247c8c4058STejas Patil std::pair<std::string, std::string> redfishDateTimeOffset = 21252b82937eSEd Tanous redfish::time_utils::getDateTimeOffsetNow(); 21260fda0f12SGeorge Liu asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first; 21277c8c4058STejas Patil asyncResp->res.jsonValue["DateTimeLocalOffset"] = 21287c8c4058STejas Patil redfishDateTimeOffset.second; 21297c8c4058STejas Patil 2130fdd26906SClaire Weinan asyncResp->res.jsonValue["Entries"]["@odata.id"] = dumpPath + "/Entries"; 2131fdd26906SClaire Weinan 2132fdd26906SClaire Weinan if (collectDiagnosticDataSupported) 2133fdd26906SClaire Weinan { 2134002d39b4SEd Tanous asyncResp->res.jsonValue["Actions"]["#LogService.CollectDiagnosticData"] 21351476687dSEd Tanous ["target"] = 2136fdd26906SClaire Weinan dumpPath + "/Actions/LogService.CollectDiagnosticData"; 2137fdd26906SClaire Weinan } 21380d946211SClaire Weinan 21390d946211SClaire Weinan constexpr std::array<std::string_view, 1> interfaces = {deleteAllInterface}; 21400d946211SClaire Weinan dbus::utility::getSubTreePaths( 21410d946211SClaire Weinan "/xyz/openbmc_project/dump", 0, interfaces, 21420d946211SClaire Weinan [asyncResp, dumpType, dumpPath]( 21430d946211SClaire Weinan const boost::system::error_code& ec, 21440d946211SClaire Weinan const dbus::utility::MapperGetSubTreePathsResponse& subTreePaths) { 21450d946211SClaire Weinan if (ec) 21460d946211SClaire Weinan { 2147bd79bce8SPatrick Williams BMCWEB_LOG_ERROR("getDumpServiceInfo respHandler got error {}", 2148bd79bce8SPatrick Williams ec); 21490d946211SClaire Weinan // Assume that getting an error simply means there are no dump 21500d946211SClaire Weinan // LogServices. Return without adding any error response. 21510d946211SClaire Weinan return; 21520d946211SClaire Weinan } 215318f8f608SEd Tanous std::string dbusDumpPath = getDumpPath(dumpType); 21540d946211SClaire Weinan for (const std::string& path : subTreePaths) 21550d946211SClaire Weinan { 21560d946211SClaire Weinan if (path == dbusDumpPath) 21570d946211SClaire Weinan { 2158bd79bce8SPatrick Williams asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"] 2159bd79bce8SPatrick Williams ["target"] = 21600d946211SClaire Weinan dumpPath + "/Actions/LogService.ClearLog"; 21610d946211SClaire Weinan break; 21620d946211SClaire Weinan } 21630d946211SClaire Weinan } 21640d946211SClaire Weinan }); 2165c9bb6861Sraviteja-b } 2166c9bb6861Sraviteja-b 2167fdd26906SClaire Weinan inline void handleLogServicesDumpServiceGet( 2168fdd26906SClaire Weinan crow::App& app, const std::string& dumpType, const crow::Request& req, 2169253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2170253f11b8SEd Tanous const std::string& managerId) 21717e860f15SJohn Edward Broadbent { 21723ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 217345ca1b86SEd Tanous { 217445ca1b86SEd Tanous return; 217545ca1b86SEd Tanous } 2176253f11b8SEd Tanous 2177253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2178253f11b8SEd Tanous { 2179253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2180253f11b8SEd Tanous return; 2181253f11b8SEd Tanous } 2182253f11b8SEd Tanous 2183fdd26906SClaire Weinan getDumpServiceInfo(asyncResp, dumpType); 2184fdd26906SClaire Weinan } 2185c9bb6861Sraviteja-b 218622d268cbSEd Tanous inline void handleLogServicesDumpServiceComputerSystemGet( 218722d268cbSEd Tanous crow::App& app, const crow::Request& req, 218822d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 218922d268cbSEd Tanous const std::string& chassisId) 219022d268cbSEd Tanous { 219122d268cbSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 219222d268cbSEd Tanous { 219322d268cbSEd Tanous return; 219422d268cbSEd Tanous } 2195253f11b8SEd Tanous if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME) 219622d268cbSEd Tanous { 219722d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId); 219822d268cbSEd Tanous return; 219922d268cbSEd Tanous } 220022d268cbSEd Tanous getDumpServiceInfo(asyncResp, "System"); 220122d268cbSEd Tanous } 220222d268cbSEd Tanous 2203fdd26906SClaire Weinan inline void handleLogServicesDumpEntriesCollectionGet( 2204fdd26906SClaire Weinan crow::App& app, const std::string& dumpType, const crow::Request& req, 2205253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2206253f11b8SEd Tanous const std::string& managerId) 2207fdd26906SClaire Weinan { 2208fdd26906SClaire Weinan if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2209fdd26906SClaire Weinan { 2210fdd26906SClaire Weinan return; 2211fdd26906SClaire Weinan } 2212253f11b8SEd Tanous 2213253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2214253f11b8SEd Tanous { 2215253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2216253f11b8SEd Tanous return; 2217253f11b8SEd Tanous } 2218fdd26906SClaire Weinan getDumpEntryCollection(asyncResp, dumpType); 2219fdd26906SClaire Weinan } 2220fdd26906SClaire Weinan 222122d268cbSEd Tanous inline void handleLogServicesDumpEntriesCollectionComputerSystemGet( 222222d268cbSEd Tanous crow::App& app, const crow::Request& req, 222322d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 222422d268cbSEd Tanous const std::string& chassisId) 222522d268cbSEd Tanous { 222622d268cbSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 222722d268cbSEd Tanous { 222822d268cbSEd Tanous return; 222922d268cbSEd Tanous } 2230253f11b8SEd Tanous if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME) 223122d268cbSEd Tanous { 223222d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId); 223322d268cbSEd Tanous return; 223422d268cbSEd Tanous } 223522d268cbSEd Tanous getDumpEntryCollection(asyncResp, "System"); 223622d268cbSEd Tanous } 223722d268cbSEd Tanous 2238fdd26906SClaire Weinan inline void handleLogServicesDumpEntryGet( 2239fdd26906SClaire Weinan crow::App& app, const std::string& dumpType, const crow::Request& req, 2240fdd26906SClaire Weinan const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2241253f11b8SEd Tanous const std::string& managerId, const std::string& dumpId) 2242fdd26906SClaire Weinan { 2243fdd26906SClaire Weinan if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2244fdd26906SClaire Weinan { 2245fdd26906SClaire Weinan return; 2246fdd26906SClaire Weinan } 2247253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2248253f11b8SEd Tanous { 2249253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2250253f11b8SEd Tanous return; 2251253f11b8SEd Tanous } 2252fdd26906SClaire Weinan getDumpEntryById(asyncResp, dumpId, dumpType); 2253fdd26906SClaire Weinan } 2254168d1b1aSCarson Labrado 225522d268cbSEd Tanous inline void handleLogServicesDumpEntryComputerSystemGet( 225622d268cbSEd Tanous crow::App& app, const crow::Request& req, 225722d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 225822d268cbSEd Tanous const std::string& chassisId, const std::string& dumpId) 225922d268cbSEd Tanous { 226022d268cbSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 226122d268cbSEd Tanous { 226222d268cbSEd Tanous return; 226322d268cbSEd Tanous } 2264253f11b8SEd Tanous if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME) 226522d268cbSEd Tanous { 226622d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId); 226722d268cbSEd Tanous return; 226822d268cbSEd Tanous } 226922d268cbSEd Tanous getDumpEntryById(asyncResp, dumpId, "System"); 227022d268cbSEd Tanous } 2271fdd26906SClaire Weinan 2272fdd26906SClaire Weinan inline void handleLogServicesDumpEntryDelete( 2273fdd26906SClaire Weinan crow::App& app, const std::string& dumpType, const crow::Request& req, 2274fdd26906SClaire Weinan const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2275253f11b8SEd Tanous const std::string& managerId, const std::string& dumpId) 2276fdd26906SClaire Weinan { 2277fdd26906SClaire Weinan if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2278fdd26906SClaire Weinan { 2279fdd26906SClaire Weinan return; 2280fdd26906SClaire Weinan } 2281253f11b8SEd Tanous 2282253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2283253f11b8SEd Tanous { 2284253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2285253f11b8SEd Tanous return; 2286253f11b8SEd Tanous } 2287fdd26906SClaire Weinan deleteDumpEntry(asyncResp, dumpId, dumpType); 2288fdd26906SClaire Weinan } 2289fdd26906SClaire Weinan 229022d268cbSEd Tanous inline void handleLogServicesDumpEntryComputerSystemDelete( 229122d268cbSEd Tanous crow::App& app, const crow::Request& req, 229222d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 229322d268cbSEd Tanous const std::string& chassisId, const std::string& dumpId) 229422d268cbSEd Tanous { 229522d268cbSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 229622d268cbSEd Tanous { 229722d268cbSEd Tanous return; 229822d268cbSEd Tanous } 2299253f11b8SEd Tanous if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME) 230022d268cbSEd Tanous { 230122d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId); 230222d268cbSEd Tanous return; 230322d268cbSEd Tanous } 230422d268cbSEd Tanous deleteDumpEntry(asyncResp, dumpId, "System"); 230522d268cbSEd Tanous } 230622d268cbSEd Tanous 2307168d1b1aSCarson Labrado inline void handleLogServicesDumpEntryDownloadGet( 2308168d1b1aSCarson Labrado crow::App& app, const std::string& dumpType, const crow::Request& req, 2309168d1b1aSCarson Labrado const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2310253f11b8SEd Tanous const std::string& managerId, const std::string& dumpId) 2311168d1b1aSCarson Labrado { 2312168d1b1aSCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2313168d1b1aSCarson Labrado { 2314168d1b1aSCarson Labrado return; 2315168d1b1aSCarson Labrado } 2316253f11b8SEd Tanous 2317253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2318253f11b8SEd Tanous { 2319253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2320253f11b8SEd Tanous return; 2321253f11b8SEd Tanous } 2322168d1b1aSCarson Labrado downloadDumpEntry(asyncResp, dumpId, dumpType); 2323168d1b1aSCarson Labrado } 2324168d1b1aSCarson Labrado 2325168d1b1aSCarson Labrado inline void handleDBusEventLogEntryDownloadGet( 2326168d1b1aSCarson Labrado crow::App& app, const std::string& dumpType, const crow::Request& req, 2327168d1b1aSCarson Labrado const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2328168d1b1aSCarson Labrado const std::string& systemName, const std::string& entryID) 2329168d1b1aSCarson Labrado { 2330168d1b1aSCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2331168d1b1aSCarson Labrado { 2332168d1b1aSCarson Labrado return; 2333168d1b1aSCarson Labrado } 2334168d1b1aSCarson Labrado if (!http_helpers::isContentTypeAllowed( 2335168d1b1aSCarson Labrado req.getHeaderValue("Accept"), 2336168d1b1aSCarson Labrado http_helpers::ContentType::OctetStream, true)) 2337168d1b1aSCarson Labrado { 2338168d1b1aSCarson Labrado asyncResp->res.result(boost::beast::http::status::bad_request); 2339168d1b1aSCarson Labrado return; 2340168d1b1aSCarson Labrado } 2341168d1b1aSCarson Labrado downloadEventLogEntry(asyncResp, systemName, entryID, dumpType); 2342168d1b1aSCarson Labrado } 2343168d1b1aSCarson Labrado 2344fdd26906SClaire Weinan inline void handleLogServicesDumpCollectDiagnosticDataPost( 2345fdd26906SClaire Weinan crow::App& app, const std::string& dumpType, const crow::Request& req, 2346253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2347253f11b8SEd Tanous const std::string& managerId) 2348fdd26906SClaire Weinan { 2349fdd26906SClaire Weinan if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2350fdd26906SClaire Weinan { 2351fdd26906SClaire Weinan return; 2352fdd26906SClaire Weinan } 2353253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2354253f11b8SEd Tanous { 2355253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2356253f11b8SEd Tanous return; 2357253f11b8SEd Tanous } 2358253f11b8SEd Tanous 2359fdd26906SClaire Weinan createDump(asyncResp, req, dumpType); 2360fdd26906SClaire Weinan } 2361fdd26906SClaire Weinan 236222d268cbSEd Tanous inline void handleLogServicesDumpCollectDiagnosticDataComputerSystemPost( 236322d268cbSEd Tanous crow::App& app, const crow::Request& req, 236422d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 23657f3e84a1SEd Tanous const std::string& systemName) 236622d268cbSEd Tanous { 236722d268cbSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 236822d268cbSEd Tanous { 236922d268cbSEd Tanous return; 237022d268cbSEd Tanous } 23717f3e84a1SEd Tanous 237225b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 237322d268cbSEd Tanous { 23747f3e84a1SEd Tanous // Option currently returns no systems. TBD 23757f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 23767f3e84a1SEd Tanous systemName); 23777f3e84a1SEd Tanous return; 23787f3e84a1SEd Tanous } 2379253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 23807f3e84a1SEd Tanous { 23817f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 23827f3e84a1SEd Tanous systemName); 238322d268cbSEd Tanous return; 238422d268cbSEd Tanous } 238522d268cbSEd Tanous createDump(asyncResp, req, "System"); 238622d268cbSEd Tanous } 238722d268cbSEd Tanous 2388fdd26906SClaire Weinan inline void handleLogServicesDumpClearLogPost( 2389fdd26906SClaire Weinan crow::App& app, const std::string& dumpType, const crow::Request& req, 2390253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2391253f11b8SEd Tanous const std::string& managerId) 2392fdd26906SClaire Weinan { 2393fdd26906SClaire Weinan if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2394fdd26906SClaire Weinan { 2395fdd26906SClaire Weinan return; 2396fdd26906SClaire Weinan } 2397253f11b8SEd Tanous 2398253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2399253f11b8SEd Tanous { 2400253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2401253f11b8SEd Tanous return; 2402253f11b8SEd Tanous } 2403fdd26906SClaire Weinan clearDump(asyncResp, dumpType); 2404fdd26906SClaire Weinan } 2405fdd26906SClaire Weinan 240622d268cbSEd Tanous inline void handleLogServicesDumpClearLogComputerSystemPost( 240722d268cbSEd Tanous crow::App& app, const crow::Request& req, 240822d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 24097f3e84a1SEd Tanous const std::string& systemName) 241022d268cbSEd Tanous { 241122d268cbSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 241222d268cbSEd Tanous { 241322d268cbSEd Tanous return; 241422d268cbSEd Tanous } 241525b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 241622d268cbSEd Tanous { 24177f3e84a1SEd Tanous // Option currently returns no systems. TBD 24187f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 24197f3e84a1SEd Tanous systemName); 24207f3e84a1SEd Tanous return; 24217f3e84a1SEd Tanous } 2422253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 24237f3e84a1SEd Tanous { 24247f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 24257f3e84a1SEd Tanous systemName); 242622d268cbSEd Tanous return; 242722d268cbSEd Tanous } 242822d268cbSEd Tanous clearDump(asyncResp, "System"); 242922d268cbSEd Tanous } 243022d268cbSEd Tanous 2431fdd26906SClaire Weinan inline void requestRoutesBMCDumpService(App& app) 2432fdd26906SClaire Weinan { 2433253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/Dump/") 2434fdd26906SClaire Weinan .privileges(redfish::privileges::getLogService) 2435fdd26906SClaire Weinan .methods(boost::beast::http::verb::get)(std::bind_front( 2436fdd26906SClaire Weinan handleLogServicesDumpServiceGet, std::ref(app), "BMC")); 2437fdd26906SClaire Weinan } 2438fdd26906SClaire Weinan 2439fdd26906SClaire Weinan inline void requestRoutesBMCDumpEntryCollection(App& app) 2440fdd26906SClaire Weinan { 2441253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/") 2442fdd26906SClaire Weinan .privileges(redfish::privileges::getLogEntryCollection) 2443fdd26906SClaire Weinan .methods(boost::beast::http::verb::get)(std::bind_front( 2444fdd26906SClaire Weinan handleLogServicesDumpEntriesCollectionGet, std::ref(app), "BMC")); 2445c9bb6861Sraviteja-b } 2446c9bb6861Sraviteja-b 24477e860f15SJohn Edward Broadbent inline void requestRoutesBMCDumpEntry(App& app) 2448c9bb6861Sraviteja-b { 24497e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 2450253f11b8SEd Tanous "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/") 2451ed398213SEd Tanous .privileges(redfish::privileges::getLogEntry) 2452fdd26906SClaire Weinan .methods(boost::beast::http::verb::get)(std::bind_front( 2453fdd26906SClaire Weinan handleLogServicesDumpEntryGet, std::ref(app), "BMC")); 2454fdd26906SClaire Weinan 24557e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 2456253f11b8SEd Tanous "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/") 2457ed398213SEd Tanous .privileges(redfish::privileges::deleteLogEntry) 2458fdd26906SClaire Weinan .methods(boost::beast::http::verb::delete_)(std::bind_front( 2459fdd26906SClaire Weinan handleLogServicesDumpEntryDelete, std::ref(app), "BMC")); 2460c9bb6861Sraviteja-b } 2461c9bb6861Sraviteja-b 2462168d1b1aSCarson Labrado inline void requestRoutesBMCDumpEntryDownload(App& app) 2463168d1b1aSCarson Labrado { 2464168d1b1aSCarson Labrado BMCWEB_ROUTE( 2465168d1b1aSCarson Labrado app, 2466253f11b8SEd Tanous "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/attachment/") 2467168d1b1aSCarson Labrado .privileges(redfish::privileges::getLogEntry) 2468168d1b1aSCarson Labrado .methods(boost::beast::http::verb::get)(std::bind_front( 2469168d1b1aSCarson Labrado handleLogServicesDumpEntryDownloadGet, std::ref(app), "BMC")); 2470168d1b1aSCarson Labrado } 2471168d1b1aSCarson Labrado 24727e860f15SJohn Edward Broadbent inline void requestRoutesBMCDumpCreate(App& app) 2473c9bb6861Sraviteja-b { 24740fda0f12SGeorge Liu BMCWEB_ROUTE( 24750fda0f12SGeorge Liu app, 2476253f11b8SEd Tanous "/redfish/v1/Managers/<str>/LogServices/Dump/Actions/LogService.CollectDiagnosticData/") 2477ed398213SEd Tanous .privileges(redfish::privileges::postLogService) 24787e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 2479fdd26906SClaire Weinan std::bind_front(handleLogServicesDumpCollectDiagnosticDataPost, 2480fdd26906SClaire Weinan std::ref(app), "BMC")); 2481a43be80fSAsmitha Karunanithi } 2482a43be80fSAsmitha Karunanithi 24837e860f15SJohn Edward Broadbent inline void requestRoutesBMCDumpClear(App& app) 248480319af1SAsmitha Karunanithi { 24850fda0f12SGeorge Liu BMCWEB_ROUTE( 24860fda0f12SGeorge Liu app, 2487253f11b8SEd Tanous "/redfish/v1/Managers/<str>/LogServices/Dump/Actions/LogService.ClearLog/") 2488ed398213SEd Tanous .privileges(redfish::privileges::postLogService) 2489fdd26906SClaire Weinan .methods(boost::beast::http::verb::post)(std::bind_front( 2490fdd26906SClaire Weinan handleLogServicesDumpClearLogPost, std::ref(app), "BMC")); 249145ca1b86SEd Tanous } 2492fdd26906SClaire Weinan 2493168d1b1aSCarson Labrado inline void requestRoutesDBusEventLogEntryDownload(App& app) 2494168d1b1aSCarson Labrado { 2495168d1b1aSCarson Labrado BMCWEB_ROUTE( 2496168d1b1aSCarson Labrado app, 24979e9d99daSRavi Teja "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/attachment/") 2498168d1b1aSCarson Labrado .privileges(redfish::privileges::getLogEntry) 2499168d1b1aSCarson Labrado .methods(boost::beast::http::verb::get)(std::bind_front( 2500168d1b1aSCarson Labrado handleDBusEventLogEntryDownloadGet, std::ref(app), "System")); 2501168d1b1aSCarson Labrado } 2502168d1b1aSCarson Labrado 2503fdd26906SClaire Weinan inline void requestRoutesFaultLogDumpService(App& app) 2504fdd26906SClaire Weinan { 2505253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/") 2506fdd26906SClaire Weinan .privileges(redfish::privileges::getLogService) 2507fdd26906SClaire Weinan .methods(boost::beast::http::verb::get)(std::bind_front( 2508fdd26906SClaire Weinan handleLogServicesDumpServiceGet, std::ref(app), "FaultLog")); 2509fdd26906SClaire Weinan } 2510fdd26906SClaire Weinan 2511fdd26906SClaire Weinan inline void requestRoutesFaultLogDumpEntryCollection(App& app) 2512fdd26906SClaire Weinan { 2513253f11b8SEd Tanous BMCWEB_ROUTE(app, 2514253f11b8SEd Tanous "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/") 2515fdd26906SClaire Weinan .privileges(redfish::privileges::getLogEntryCollection) 2516fdd26906SClaire Weinan .methods(boost::beast::http::verb::get)( 2517fdd26906SClaire Weinan std::bind_front(handleLogServicesDumpEntriesCollectionGet, 2518fdd26906SClaire Weinan std::ref(app), "FaultLog")); 2519fdd26906SClaire Weinan } 2520fdd26906SClaire Weinan 2521fdd26906SClaire Weinan inline void requestRoutesFaultLogDumpEntry(App& app) 2522fdd26906SClaire Weinan { 2523253f11b8SEd Tanous BMCWEB_ROUTE( 2524253f11b8SEd Tanous app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/<str>/") 2525fdd26906SClaire Weinan .privileges(redfish::privileges::getLogEntry) 2526fdd26906SClaire Weinan .methods(boost::beast::http::verb::get)(std::bind_front( 2527fdd26906SClaire Weinan handleLogServicesDumpEntryGet, std::ref(app), "FaultLog")); 2528fdd26906SClaire Weinan 2529253f11b8SEd Tanous BMCWEB_ROUTE( 2530253f11b8SEd Tanous app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/<str>/") 2531fdd26906SClaire Weinan .privileges(redfish::privileges::deleteLogEntry) 2532fdd26906SClaire Weinan .methods(boost::beast::http::verb::delete_)(std::bind_front( 2533fdd26906SClaire Weinan handleLogServicesDumpEntryDelete, std::ref(app), "FaultLog")); 2534fdd26906SClaire Weinan } 2535fdd26906SClaire Weinan 2536fdd26906SClaire Weinan inline void requestRoutesFaultLogDumpClear(App& app) 2537fdd26906SClaire Weinan { 2538fdd26906SClaire Weinan BMCWEB_ROUTE( 2539fdd26906SClaire Weinan app, 2540253f11b8SEd Tanous "/redfish/v1/Managers/<str>/LogServices/FaultLog/Actions/LogService.ClearLog/") 2541fdd26906SClaire Weinan .privileges(redfish::privileges::postLogService) 2542fdd26906SClaire Weinan .methods(boost::beast::http::verb::post)(std::bind_front( 2543fdd26906SClaire Weinan handleLogServicesDumpClearLogPost, std::ref(app), "FaultLog")); 25445cb1dd27SAsmitha Karunanithi } 25455cb1dd27SAsmitha Karunanithi 25467e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpService(App& app) 25475cb1dd27SAsmitha Karunanithi { 254822d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Dump/") 2549ed398213SEd Tanous .privileges(redfish::privileges::getLogService) 25506ab9ad54SClaire Weinan .methods(boost::beast::http::verb::get)(std::bind_front( 255122d268cbSEd Tanous handleLogServicesDumpServiceComputerSystemGet, std::ref(app))); 25525cb1dd27SAsmitha Karunanithi } 25535cb1dd27SAsmitha Karunanithi 25547e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpEntryCollection(App& app) 25557e860f15SJohn Edward Broadbent { 255622d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/") 2557ed398213SEd Tanous .privileges(redfish::privileges::getLogEntryCollection) 255822d268cbSEd Tanous .methods(boost::beast::http::verb::get)(std::bind_front( 255922d268cbSEd Tanous handleLogServicesDumpEntriesCollectionComputerSystemGet, 256022d268cbSEd Tanous std::ref(app))); 25615cb1dd27SAsmitha Karunanithi } 25625cb1dd27SAsmitha Karunanithi 25637e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpEntry(App& app) 25645cb1dd27SAsmitha Karunanithi { 25657e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 256622d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/<str>/") 2567ed398213SEd Tanous .privileges(redfish::privileges::getLogEntry) 25686ab9ad54SClaire Weinan .methods(boost::beast::http::verb::get)(std::bind_front( 256922d268cbSEd Tanous handleLogServicesDumpEntryComputerSystemGet, std::ref(app))); 25708d1b46d7Szhanghch05 25717e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 257222d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/<str>/") 2573ed398213SEd Tanous .privileges(redfish::privileges::deleteLogEntry) 25746ab9ad54SClaire Weinan .methods(boost::beast::http::verb::delete_)(std::bind_front( 257522d268cbSEd Tanous handleLogServicesDumpEntryComputerSystemDelete, std::ref(app))); 25765cb1dd27SAsmitha Karunanithi } 2577c9bb6861Sraviteja-b 25787e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpCreate(App& app) 2579c9bb6861Sraviteja-b { 25800fda0f12SGeorge Liu BMCWEB_ROUTE( 25810fda0f12SGeorge Liu app, 258222d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Dump/Actions/LogService.CollectDiagnosticData/") 2583ed398213SEd Tanous .privileges(redfish::privileges::postLogService) 258422d268cbSEd Tanous .methods(boost::beast::http::verb::post)(std::bind_front( 258522d268cbSEd Tanous handleLogServicesDumpCollectDiagnosticDataComputerSystemPost, 258622d268cbSEd Tanous std::ref(app))); 2587a43be80fSAsmitha Karunanithi } 2588a43be80fSAsmitha Karunanithi 25897e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpClear(App& app) 2590a43be80fSAsmitha Karunanithi { 25910fda0f12SGeorge Liu BMCWEB_ROUTE( 25920fda0f12SGeorge Liu app, 259322d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Dump/Actions/LogService.ClearLog/") 2594ed398213SEd Tanous .privileges(redfish::privileges::postLogService) 25956ab9ad54SClaire Weinan .methods(boost::beast::http::verb::post)(std::bind_front( 259622d268cbSEd Tanous handleLogServicesDumpClearLogComputerSystemPost, std::ref(app))); 2597013487e5Sraviteja-b } 2598013487e5Sraviteja-b 25997e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpService(App& app) 26001da66f75SEd Tanous { 26013946028dSAppaRao Puli // Note: Deviated from redfish privilege registry for GET & HEAD 26023946028dSAppaRao Puli // method for security reasons. 26031da66f75SEd Tanous /** 26041da66f75SEd Tanous * Functions triggers appropriate requests on DBus 26051da66f75SEd Tanous */ 260622d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Crashdump/") 2607ed398213SEd Tanous // This is incorrect, should be: 2608ed398213SEd Tanous //.privileges(redfish::privileges::getLogService) 2609432a890cSEd Tanous .privileges({{"ConfigureManager"}}) 2610bd79bce8SPatrick Williams .methods( 2611bd79bce8SPatrick Williams boost::beast::http::verb:: 2612bd79bce8SPatrick Williams get)([&app](const crow::Request& req, 261322d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 261422d268cbSEd Tanous const std::string& systemName) { 26153ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 261645ca1b86SEd Tanous { 261745ca1b86SEd Tanous return; 261845ca1b86SEd Tanous } 261925b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 26207f3e84a1SEd Tanous { 26217f3e84a1SEd Tanous // Option currently returns no systems. TBD 26227f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 26237f3e84a1SEd Tanous systemName); 26247f3e84a1SEd Tanous return; 26257f3e84a1SEd Tanous } 2626253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 262722d268cbSEd Tanous { 262822d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 262922d268cbSEd Tanous systemName); 263022d268cbSEd Tanous return; 263122d268cbSEd Tanous } 263222d268cbSEd Tanous 26337e860f15SJohn Edward Broadbent // Copy over the static data to include the entries added by 26347e860f15SJohn Edward Broadbent // SubRoute 26350f74e643SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 2636253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/Crashdump", 2637253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 2638e1f26343SJason M. Bills asyncResp->res.jsonValue["@odata.type"] = 26398e6c099aSJason M. Bills "#LogService.v1_2_0.LogService"; 26404f50ae4bSGunnar Mills asyncResp->res.jsonValue["Name"] = "Open BMC Oem Crashdump Service"; 26414f50ae4bSGunnar Mills asyncResp->res.jsonValue["Description"] = "Oem Crashdump Service"; 264215b89725SV-Sanjana asyncResp->res.jsonValue["Id"] = "Crashdump"; 2643539d8c6bSEd Tanous asyncResp->res.jsonValue["OverWritePolicy"] = 2644539d8c6bSEd Tanous log_service::OverWritePolicy::WrapsWhenFull; 2645e1f26343SJason M. Bills asyncResp->res.jsonValue["MaxNumberOfRecords"] = 3; 26467c8c4058STejas Patil 26477c8c4058STejas Patil std::pair<std::string, std::string> redfishDateTimeOffset = 26482b82937eSEd Tanous redfish::time_utils::getDateTimeOffsetNow(); 26497c8c4058STejas Patil asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first; 26507c8c4058STejas Patil asyncResp->res.jsonValue["DateTimeLocalOffset"] = 26517c8c4058STejas Patil redfishDateTimeOffset.second; 26527c8c4058STejas Patil 2653bd79bce8SPatrick Williams asyncResp->res.jsonValue["Entries"]["@odata.id"] = std::format( 2654bd79bce8SPatrick Williams "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries", 2655253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 2656253f11b8SEd Tanous asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"] 2657253f11b8SEd Tanous ["target"] = std::format( 2658253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/Crashdump/Actions/LogService.ClearLog", 2659253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 2660bd79bce8SPatrick Williams asyncResp->res 2661bd79bce8SPatrick Williams .jsonValue["Actions"]["#LogService.CollectDiagnosticData"] 2662253f11b8SEd Tanous ["target"] = std::format( 2663253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/Crashdump/Actions/LogService.CollectDiagnosticData", 2664253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 26657e860f15SJohn Edward Broadbent }); 26661da66f75SEd Tanous } 26671da66f75SEd Tanous 26687e860f15SJohn Edward Broadbent void inline requestRoutesCrashdumpClear(App& app) 26695b61b5e8SJason M. Bills { 26700fda0f12SGeorge Liu BMCWEB_ROUTE( 26710fda0f12SGeorge Liu app, 267222d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Crashdump/Actions/LogService.ClearLog/") 2673ed398213SEd Tanous // This is incorrect, should be: 2674ed398213SEd Tanous //.privileges(redfish::privileges::postLogService) 2675432a890cSEd Tanous .privileges({{"ConfigureComponents"}}) 26767e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 267745ca1b86SEd Tanous [&app](const crow::Request& req, 267822d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 267922d268cbSEd Tanous const std::string& systemName) { 26803ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 268145ca1b86SEd Tanous { 268245ca1b86SEd Tanous return; 268345ca1b86SEd Tanous } 268425b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 26857f3e84a1SEd Tanous { 26867f3e84a1SEd Tanous // Option currently returns no systems. TBD 26877f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 26887f3e84a1SEd Tanous systemName); 26897f3e84a1SEd Tanous return; 26907f3e84a1SEd Tanous } 2691253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 269222d268cbSEd Tanous { 269322d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 269422d268cbSEd Tanous systemName); 269522d268cbSEd Tanous return; 269622d268cbSEd Tanous } 26975b61b5e8SJason M. Bills crow::connections::systemBus->async_method_call( 26985e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec, 2699cb13a392SEd Tanous const std::string&) { 27005b61b5e8SJason M. Bills if (ec) 27015b61b5e8SJason M. Bills { 27025b61b5e8SJason M. Bills messages::internalError(asyncResp->res); 27035b61b5e8SJason M. Bills return; 27045b61b5e8SJason M. Bills } 27055b61b5e8SJason M. Bills messages::success(asyncResp->res); 27065b61b5e8SJason M. Bills }, 2707bd79bce8SPatrick Williams crashdumpObject, crashdumpPath, deleteAllInterface, 2708bd79bce8SPatrick Williams "DeleteAll"); 27097e860f15SJohn Edward Broadbent }); 27105b61b5e8SJason M. Bills } 27115b61b5e8SJason M. Bills 27124ff0f1f4SEd Tanous inline void 27138d1b46d7Szhanghch05 logCrashdumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 27148d1b46d7Szhanghch05 const std::string& logID, nlohmann::json& logEntryJson) 2715e855dd28SJason M. Bills { 2716043a0536SJohnathan Mantey auto getStoredLogCallback = 2717b9d36b47SEd Tanous [asyncResp, logID, 27185e7e2dc5SEd Tanous &logEntryJson](const boost::system::error_code& ec, 2719b9d36b47SEd Tanous const dbus::utility::DBusPropertiesMap& params) { 2720e855dd28SJason M. Bills if (ec) 2721e855dd28SJason M. Bills { 272262598e31SEd Tanous BMCWEB_LOG_DEBUG("failed to get log ec: {}", ec.message()); 27231ddcf01aSJason M. Bills if (ec.value() == 27241ddcf01aSJason M. Bills boost::system::linux_error::bad_request_descriptor) 27251ddcf01aSJason M. Bills { 2726bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "LogEntry", 2727bd79bce8SPatrick Williams logID); 27281ddcf01aSJason M. Bills } 27291ddcf01aSJason M. Bills else 27301ddcf01aSJason M. Bills { 2731e855dd28SJason M. Bills messages::internalError(asyncResp->res); 27321ddcf01aSJason M. Bills } 2733e855dd28SJason M. Bills return; 2734e855dd28SJason M. Bills } 2735043a0536SJohnathan Mantey 2736043a0536SJohnathan Mantey std::string timestamp{}; 2737043a0536SJohnathan Mantey std::string filename{}; 2738043a0536SJohnathan Mantey std::string logfile{}; 27392c70f800SEd Tanous parseCrashdumpParameters(params, filename, timestamp, logfile); 2740043a0536SJohnathan Mantey 2741043a0536SJohnathan Mantey if (filename.empty() || timestamp.empty()) 2742e855dd28SJason M. Bills { 27439db4ba25SJiaqing Zhao messages::resourceNotFound(asyncResp->res, "LogEntry", logID); 2744e855dd28SJason M. Bills return; 2745e855dd28SJason M. Bills } 2746e855dd28SJason M. Bills 2747043a0536SJohnathan Mantey std::string crashdumpURI = 2748bd79bce8SPatrick Williams std::format( 2749bd79bce8SPatrick Williams "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries/", 2750253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME) + 2751043a0536SJohnathan Mantey logID + "/" + filename; 275284afc48bSJason M. Bills nlohmann::json::object_t logEntry; 27539c11a172SVijay Lobo logEntry["@odata.type"] = "#LogEntry.v1_9_0.LogEntry"; 2754ef4c65b7SEd Tanous logEntry["@odata.id"] = boost::urls::format( 2755253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries/{}", 2756253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, logID); 275784afc48bSJason M. Bills logEntry["Name"] = "CPU Crashdump"; 275884afc48bSJason M. Bills logEntry["Id"] = logID; 2759539d8c6bSEd Tanous logEntry["EntryType"] = log_entry::LogEntryType::Oem; 276084afc48bSJason M. Bills logEntry["AdditionalDataURI"] = std::move(crashdumpURI); 276184afc48bSJason M. Bills logEntry["DiagnosticDataType"] = "OEM"; 276284afc48bSJason M. Bills logEntry["OEMDiagnosticDataType"] = "PECICrashdump"; 276384afc48bSJason M. Bills logEntry["Created"] = std::move(timestamp); 27642b20ef6eSJason M. Bills 27652b20ef6eSJason M. Bills // If logEntryJson references an array of LogEntry resources 27662b20ef6eSJason M. Bills // ('Members' list), then push this as a new entry, otherwise set it 27672b20ef6eSJason M. Bills // directly 27682b20ef6eSJason M. Bills if (logEntryJson.is_array()) 27692b20ef6eSJason M. Bills { 27702b20ef6eSJason M. Bills logEntryJson.push_back(logEntry); 27712b20ef6eSJason M. Bills asyncResp->res.jsonValue["Members@odata.count"] = 27722b20ef6eSJason M. Bills logEntryJson.size(); 27732b20ef6eSJason M. Bills } 27742b20ef6eSJason M. Bills else 27752b20ef6eSJason M. Bills { 2776d405bb51SJason M. Bills logEntryJson.update(logEntry); 27772b20ef6eSJason M. Bills } 2778e855dd28SJason M. Bills }; 2779deae6a78SEd Tanous dbus::utility::getAllProperties( 2780deae6a78SEd Tanous crashdumpObject, crashdumpPath + std::string("/") + logID, 2781deae6a78SEd Tanous crashdumpInterface, std::move(getStoredLogCallback)); 2782e855dd28SJason M. Bills } 2783e855dd28SJason M. Bills 27847e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpEntryCollection(App& app) 27851da66f75SEd Tanous { 27863946028dSAppaRao Puli // Note: Deviated from redfish privilege registry for GET & HEAD 27873946028dSAppaRao Puli // method for security reasons. 27881da66f75SEd Tanous /** 27891da66f75SEd Tanous * Functions triggers appropriate requests on DBus 27901da66f75SEd Tanous */ 27917e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 279222d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/") 2793ed398213SEd Tanous // This is incorrect, should be. 2794ed398213SEd Tanous //.privileges(redfish::privileges::postLogEntryCollection) 2795432a890cSEd Tanous .privileges({{"ConfigureComponents"}}) 2796bd79bce8SPatrick Williams .methods( 2797bd79bce8SPatrick Williams boost::beast::http::verb:: 2798bd79bce8SPatrick Williams get)([&app](const crow::Request& req, 279922d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 280022d268cbSEd Tanous const std::string& systemName) { 28013ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 280245ca1b86SEd Tanous { 280345ca1b86SEd Tanous return; 280445ca1b86SEd Tanous } 280525b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 28067f3e84a1SEd Tanous { 28077f3e84a1SEd Tanous // Option currently returns no systems. TBD 28087f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 28097f3e84a1SEd Tanous systemName); 28107f3e84a1SEd Tanous return; 28117f3e84a1SEd Tanous } 2812253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 281322d268cbSEd Tanous { 281422d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 281522d268cbSEd Tanous systemName); 281622d268cbSEd Tanous return; 281722d268cbSEd Tanous } 281822d268cbSEd Tanous 28197a1dbc48SGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 28207a1dbc48SGeorge Liu crashdumpInterface}; 28217a1dbc48SGeorge Liu dbus::utility::getSubTreePaths( 28227a1dbc48SGeorge Liu "/", 0, interfaces, 28237a1dbc48SGeorge Liu [asyncResp](const boost::system::error_code& ec, 28242b20ef6eSJason M. Bills const std::vector<std::string>& resp) { 28251da66f75SEd Tanous if (ec) 28261da66f75SEd Tanous { 28271da66f75SEd Tanous if (ec.value() != 28281da66f75SEd Tanous boost::system::errc::no_such_file_or_directory) 28291da66f75SEd Tanous { 283062598e31SEd Tanous BMCWEB_LOG_DEBUG("failed to get entries ec: {}", 283162598e31SEd Tanous ec.message()); 2832f12894f8SJason M. Bills messages::internalError(asyncResp->res); 28331da66f75SEd Tanous return; 28341da66f75SEd Tanous } 28351da66f75SEd Tanous } 2836e1f26343SJason M. Bills asyncResp->res.jsonValue["@odata.type"] = 28371da66f75SEd Tanous "#LogEntryCollection.LogEntryCollection"; 2838253f11b8SEd Tanous asyncResp->res.jsonValue["@odata.id"] = std::format( 2839253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries", 2840253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 2841bd79bce8SPatrick Williams asyncResp->res.jsonValue["Name"] = 2842bd79bce8SPatrick Williams "Open BMC Crashdump Entries"; 2843e1f26343SJason M. Bills asyncResp->res.jsonValue["Description"] = 2844424c4176SJason M. Bills "Collection of Crashdump Entries"; 2845bd79bce8SPatrick Williams asyncResp->res.jsonValue["Members"] = 2846bd79bce8SPatrick Williams nlohmann::json::array(); 2847a2dd60a6SBrandon Kim asyncResp->res.jsonValue["Members@odata.count"] = 0; 28482b20ef6eSJason M. Bills 28492b20ef6eSJason M. Bills for (const std::string& path : resp) 28501da66f75SEd Tanous { 28512b20ef6eSJason M. Bills const sdbusplus::message::object_path objPath(path); 2852e855dd28SJason M. Bills // Get the log ID 28532b20ef6eSJason M. Bills std::string logID = objPath.filename(); 28542b20ef6eSJason M. Bills if (logID.empty()) 28551da66f75SEd Tanous { 2856e855dd28SJason M. Bills continue; 28571da66f75SEd Tanous } 2858e855dd28SJason M. Bills // Add the log entry to the array 28592b20ef6eSJason M. Bills logCrashdumpEntry(asyncResp, logID, 28602b20ef6eSJason M. Bills asyncResp->res.jsonValue["Members"]); 28611da66f75SEd Tanous } 28627a1dbc48SGeorge Liu }); 28637e860f15SJohn Edward Broadbent }); 28641da66f75SEd Tanous } 28651da66f75SEd Tanous 28667e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpEntry(App& app) 28671da66f75SEd Tanous { 28683946028dSAppaRao Puli // Note: Deviated from redfish privilege registry for GET & HEAD 28693946028dSAppaRao Puli // method for security reasons. 28701da66f75SEd Tanous 28717e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 287222d268cbSEd Tanous app, "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/<str>/") 2873ed398213SEd Tanous // this is incorrect, should be 2874ed398213SEd Tanous // .privileges(redfish::privileges::getLogEntry) 2875432a890cSEd Tanous .privileges({{"ConfigureComponents"}}) 28767e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 287745ca1b86SEd Tanous [&app](const crow::Request& req, 28787e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 287922d268cbSEd Tanous const std::string& systemName, const std::string& param) { 28803ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 288145ca1b86SEd Tanous { 288245ca1b86SEd Tanous return; 288345ca1b86SEd Tanous } 288425b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 28857f3e84a1SEd Tanous { 28867f3e84a1SEd Tanous // Option currently returns no systems. TBD 28877f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 28887f3e84a1SEd Tanous systemName); 28897f3e84a1SEd Tanous return; 28907f3e84a1SEd Tanous } 2891253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 289222d268cbSEd Tanous { 289322d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 289422d268cbSEd Tanous systemName); 289522d268cbSEd Tanous return; 289622d268cbSEd Tanous } 28977e860f15SJohn Edward Broadbent const std::string& logID = param; 2898e855dd28SJason M. Bills logCrashdumpEntry(asyncResp, logID, asyncResp->res.jsonValue); 28997e860f15SJohn Edward Broadbent }); 2900e855dd28SJason M. Bills } 2901e855dd28SJason M. Bills 29027e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpFile(App& app) 2903e855dd28SJason M. Bills { 29043946028dSAppaRao Puli // Note: Deviated from redfish privilege registry for GET & HEAD 29053946028dSAppaRao Puli // method for security reasons. 29067e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 29077e860f15SJohn Edward Broadbent app, 290822d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/<str>/<str>/") 2909ed398213SEd Tanous .privileges(redfish::privileges::getLogEntry) 29107e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 2911a4ce114aSNan Zhou [](const crow::Request& req, 29127e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 291322d268cbSEd Tanous const std::string& systemName, const std::string& logID, 291422d268cbSEd Tanous const std::string& fileName) { 2915bd79bce8SPatrick Williams // Do not call getRedfishRoute here since the crashdump file is 2916bd79bce8SPatrick Williams // not a Redfish resource. 291722d268cbSEd Tanous 291825b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 29197f3e84a1SEd Tanous { 29207f3e84a1SEd Tanous // Option currently returns no systems. TBD 29217f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 29227f3e84a1SEd Tanous systemName); 29237f3e84a1SEd Tanous return; 29247f3e84a1SEd Tanous } 2925253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 292622d268cbSEd Tanous { 292722d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 292822d268cbSEd Tanous systemName); 292922d268cbSEd Tanous return; 293022d268cbSEd Tanous } 293122d268cbSEd Tanous 2932043a0536SJohnathan Mantey auto getStoredLogCallback = 2933bd79bce8SPatrick Williams [asyncResp, logID, fileName, 2934bd79bce8SPatrick Williams url(boost::urls::url(req.url()))]( 29355e7e2dc5SEd Tanous const boost::system::error_code& ec, 2936bd79bce8SPatrick Williams const std::vector<std::pair< 2937bd79bce8SPatrick Williams std::string, dbus::utility::DbusVariantType>>& 29387e860f15SJohn Edward Broadbent resp) { 29391da66f75SEd Tanous if (ec) 29401da66f75SEd Tanous { 2941bd79bce8SPatrick Williams BMCWEB_LOG_DEBUG("failed to get log ec: {}", 2942bd79bce8SPatrick Williams ec.message()); 2943f12894f8SJason M. Bills messages::internalError(asyncResp->res); 29441da66f75SEd Tanous return; 29451da66f75SEd Tanous } 2946e855dd28SJason M. Bills 2947043a0536SJohnathan Mantey std::string dbusFilename{}; 2948043a0536SJohnathan Mantey std::string dbusTimestamp{}; 2949043a0536SJohnathan Mantey std::string dbusFilepath{}; 2950043a0536SJohnathan Mantey 2951bd79bce8SPatrick Williams parseCrashdumpParameters(resp, dbusFilename, 2952bd79bce8SPatrick Williams dbusTimestamp, dbusFilepath); 2953043a0536SJohnathan Mantey 2954043a0536SJohnathan Mantey if (dbusFilename.empty() || dbusTimestamp.empty() || 2955043a0536SJohnathan Mantey dbusFilepath.empty()) 29561da66f75SEd Tanous { 2957bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, 2958bd79bce8SPatrick Williams "LogEntry", logID); 29591da66f75SEd Tanous return; 29601da66f75SEd Tanous } 2961e855dd28SJason M. Bills 2962043a0536SJohnathan Mantey // Verify the file name parameter is correct 2963043a0536SJohnathan Mantey if (fileName != dbusFilename) 2964043a0536SJohnathan Mantey { 2965bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, 2966bd79bce8SPatrick Williams "LogEntry", logID); 2967043a0536SJohnathan Mantey return; 2968043a0536SJohnathan Mantey } 2969043a0536SJohnathan Mantey 2970d51c61b4SMyung Bae if (asyncResp->res.openFile(dbusFilepath) != 2971d51c61b4SMyung Bae crow::OpenCode::Success) 2972043a0536SJohnathan Mantey { 2973bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, 2974bd79bce8SPatrick Williams "LogEntry", logID); 2975043a0536SJohnathan Mantey return; 2976043a0536SJohnathan Mantey } 2977043a0536SJohnathan Mantey 29787e860f15SJohn Edward Broadbent // Configure this to be a file download when accessed 29797e860f15SJohn Edward Broadbent // from a browser 2980d9f6c621SEd Tanous asyncResp->res.addHeader( 2981bd79bce8SPatrick Williams boost::beast::http::field::content_disposition, 2982bd79bce8SPatrick Williams "attachment"); 29831da66f75SEd Tanous }; 2984deae6a78SEd Tanous dbus::utility::getAllProperties( 2985d1bde9e5SKrzysztof Grobelny *crow::connections::systemBus, crashdumpObject, 2986bd79bce8SPatrick Williams crashdumpPath + std::string("/") + logID, 2987bd79bce8SPatrick Williams crashdumpInterface, std::move(getStoredLogCallback)); 29887e860f15SJohn Edward Broadbent }); 29891da66f75SEd Tanous } 29901da66f75SEd Tanous 2991c5a4c82aSJason M. Bills enum class OEMDiagnosticType 2992c5a4c82aSJason M. Bills { 2993c5a4c82aSJason M. Bills onDemand, 2994c5a4c82aSJason M. Bills telemetry, 2995c5a4c82aSJason M. Bills invalid, 2996c5a4c82aSJason M. Bills }; 2997c5a4c82aSJason M. Bills 299826ccae32SEd Tanous inline OEMDiagnosticType getOEMDiagnosticType(std::string_view oemDiagStr) 2999c5a4c82aSJason M. Bills { 3000c5a4c82aSJason M. Bills if (oemDiagStr == "OnDemand") 3001c5a4c82aSJason M. Bills { 3002c5a4c82aSJason M. Bills return OEMDiagnosticType::onDemand; 3003c5a4c82aSJason M. Bills } 3004c5a4c82aSJason M. Bills if (oemDiagStr == "Telemetry") 3005c5a4c82aSJason M. Bills { 3006c5a4c82aSJason M. Bills return OEMDiagnosticType::telemetry; 3007c5a4c82aSJason M. Bills } 3008c5a4c82aSJason M. Bills 3009c5a4c82aSJason M. Bills return OEMDiagnosticType::invalid; 3010c5a4c82aSJason M. Bills } 3011c5a4c82aSJason M. Bills 30127e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpCollect(App& app) 30131da66f75SEd Tanous { 30143946028dSAppaRao Puli // Note: Deviated from redfish privilege registry for GET & HEAD 30153946028dSAppaRao Puli // method for security reasons. 30160fda0f12SGeorge Liu BMCWEB_ROUTE( 30170fda0f12SGeorge Liu app, 301822d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Crashdump/Actions/LogService.CollectDiagnosticData/") 3019ed398213SEd Tanous // The below is incorrect; Should be ConfigureManager 3020ed398213SEd Tanous //.privileges(redfish::privileges::postLogService) 3021432a890cSEd Tanous .privileges({{"ConfigureComponents"}}) 3022002d39b4SEd Tanous .methods(boost::beast::http::verb::post)( 3023002d39b4SEd Tanous [&app](const crow::Request& req, 302422d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 302522d268cbSEd Tanous const std::string& systemName) { 30263ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 302745ca1b86SEd Tanous { 302845ca1b86SEd Tanous return; 302945ca1b86SEd Tanous } 303022d268cbSEd Tanous 303125b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 30327f3e84a1SEd Tanous { 30337f3e84a1SEd Tanous // Option currently returns no systems. TBD 30347f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 30357f3e84a1SEd Tanous systemName); 30367f3e84a1SEd Tanous return; 30377f3e84a1SEd Tanous } 3038253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 303922d268cbSEd Tanous { 304022d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 304122d268cbSEd Tanous systemName); 304222d268cbSEd Tanous return; 304322d268cbSEd Tanous } 304422d268cbSEd Tanous 30458e6c099aSJason M. Bills std::string diagnosticDataType; 30468e6c099aSJason M. Bills std::string oemDiagnosticDataType; 3047afc474aeSMyung Bae if (!redfish::json_util::readJsonAction( // 3048afc474aeSMyung Bae req, asyncResp->res, // 3049afc474aeSMyung Bae "DiagnosticDataType", diagnosticDataType, // 3050afc474aeSMyung Bae "OEMDiagnosticDataType", oemDiagnosticDataType // 3051afc474aeSMyung Bae )) 30528e6c099aSJason M. Bills { 30538e6c099aSJason M. Bills return; 30548e6c099aSJason M. Bills } 30558e6c099aSJason M. Bills 30568e6c099aSJason M. Bills if (diagnosticDataType != "OEM") 30578e6c099aSJason M. Bills { 305862598e31SEd Tanous BMCWEB_LOG_ERROR( 305962598e31SEd Tanous "Only OEM DiagnosticDataType supported for Crashdump"); 30608e6c099aSJason M. Bills messages::actionParameterValueFormatError( 3061bd79bce8SPatrick Williams asyncResp->res, diagnosticDataType, 3062bd79bce8SPatrick Williams "DiagnosticDataType", "CollectDiagnosticData"); 30638e6c099aSJason M. Bills return; 30648e6c099aSJason M. Bills } 30658e6c099aSJason M. Bills 3066c5a4c82aSJason M. Bills OEMDiagnosticType oemDiagType = 3067c5a4c82aSJason M. Bills getOEMDiagnosticType(oemDiagnosticDataType); 3068c5a4c82aSJason M. Bills 3069c5a4c82aSJason M. Bills std::string iface; 3070c5a4c82aSJason M. Bills std::string method; 3071c5a4c82aSJason M. Bills std::string taskMatchStr; 3072c5a4c82aSJason M. Bills if (oemDiagType == OEMDiagnosticType::onDemand) 3073c5a4c82aSJason M. Bills { 3074c5a4c82aSJason M. Bills iface = crashdumpOnDemandInterface; 3075c5a4c82aSJason M. Bills method = "GenerateOnDemandLog"; 3076bd79bce8SPatrick Williams taskMatchStr = 3077bd79bce8SPatrick Williams "type='signal'," 3078c5a4c82aSJason M. Bills "interface='org.freedesktop.DBus.Properties'," 3079c5a4c82aSJason M. Bills "member='PropertiesChanged'," 3080c5a4c82aSJason M. Bills "arg0namespace='com.intel.crashdump'"; 3081c5a4c82aSJason M. Bills } 3082c5a4c82aSJason M. Bills else if (oemDiagType == OEMDiagnosticType::telemetry) 3083c5a4c82aSJason M. Bills { 3084c5a4c82aSJason M. Bills iface = crashdumpTelemetryInterface; 3085c5a4c82aSJason M. Bills method = "GenerateTelemetryLog"; 3086bd79bce8SPatrick Williams taskMatchStr = 3087bd79bce8SPatrick Williams "type='signal'," 3088c5a4c82aSJason M. Bills "interface='org.freedesktop.DBus.Properties'," 3089c5a4c82aSJason M. Bills "member='PropertiesChanged'," 3090c5a4c82aSJason M. Bills "arg0namespace='com.intel.crashdump'"; 3091c5a4c82aSJason M. Bills } 3092c5a4c82aSJason M. Bills else 3093c5a4c82aSJason M. Bills { 309462598e31SEd Tanous BMCWEB_LOG_ERROR("Unsupported OEMDiagnosticDataType: {}", 309562598e31SEd Tanous oemDiagnosticDataType); 3096c5a4c82aSJason M. Bills messages::actionParameterValueFormatError( 3097bd79bce8SPatrick Williams asyncResp->res, oemDiagnosticDataType, 3098bd79bce8SPatrick Williams "OEMDiagnosticDataType", "CollectDiagnosticData"); 3099c5a4c82aSJason M. Bills return; 3100c5a4c82aSJason M. Bills } 3101c5a4c82aSJason M. Bills 3102c5a4c82aSJason M. Bills auto collectCrashdumpCallback = 3103c5a4c82aSJason M. Bills [asyncResp, payload(task::Payload(req)), 31045e7e2dc5SEd Tanous taskMatchStr](const boost::system::error_code& ec, 310598be3e39SEd Tanous const std::string&) mutable { 31061da66f75SEd Tanous if (ec) 31071da66f75SEd Tanous { 3108bd79bce8SPatrick Williams if (ec.value() == 3109bd79bce8SPatrick Williams boost::system::errc::operation_not_supported) 31101da66f75SEd Tanous { 3111f12894f8SJason M. Bills messages::resourceInStandby(asyncResp->res); 31121da66f75SEd Tanous } 3113bd79bce8SPatrick Williams else if (ec.value() == boost::system::errc:: 3114bd79bce8SPatrick Williams device_or_resource_busy) 31154363d3b2SJason M. Bills { 3116bd79bce8SPatrick Williams messages::serviceTemporarilyUnavailable( 3117bd79bce8SPatrick Williams asyncResp->res, "60"); 31184363d3b2SJason M. Bills } 31191da66f75SEd Tanous else 31201da66f75SEd Tanous { 3121f12894f8SJason M. Bills messages::internalError(asyncResp->res); 31221da66f75SEd Tanous } 31231da66f75SEd Tanous return; 31241da66f75SEd Tanous } 3125bd79bce8SPatrick Williams std::shared_ptr<task::TaskData> task = 3126bd79bce8SPatrick Williams task::TaskData::createTask( 3127bd79bce8SPatrick Williams [](const boost::system::error_code& ec2, 3128bd79bce8SPatrick Williams sdbusplus::message_t&, 3129bd79bce8SPatrick Williams const std::shared_ptr<task::TaskData>& 3130bd79bce8SPatrick Williams taskData) { 31318b24275dSEd Tanous if (!ec2) 313266afe4faSJames Feist { 3133bd79bce8SPatrick Williams taskData->messages.emplace_back( 3134bd79bce8SPatrick Williams messages::taskCompletedOK( 3135bd79bce8SPatrick Williams std::to_string( 3136bd79bce8SPatrick Williams taskData->index))); 3137831d6b09SJames Feist taskData->state = "Completed"; 313866afe4faSJames Feist } 313932898ceaSJames Feist return task::completed; 314066afe4faSJames Feist }, 3141c5a4c82aSJason M. Bills taskMatchStr); 3142c5a4c82aSJason M. Bills 314346229577SJames Feist task->startTimer(std::chrono::minutes(5)); 314446229577SJames Feist task->populateResp(asyncResp->res); 314598be3e39SEd Tanous task->payload.emplace(std::move(payload)); 31461da66f75SEd Tanous }; 31478e6c099aSJason M. Bills 31481da66f75SEd Tanous crow::connections::systemBus->async_method_call( 3149bd79bce8SPatrick Williams std::move(collectCrashdumpCallback), crashdumpObject, 3150bd79bce8SPatrick Williams crashdumpPath, iface, method); 31517e860f15SJohn Edward Broadbent }); 31526eda7685SKenny L. Ku } 31536eda7685SKenny L. Ku 3154599b9af3SAlexander Hansen inline void dBusLogServiceActionsClear( 3155599b9af3SAlexander Hansen const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 3156599b9af3SAlexander Hansen { 3157599b9af3SAlexander Hansen BMCWEB_LOG_DEBUG("Do delete all entries."); 3158599b9af3SAlexander Hansen 3159599b9af3SAlexander Hansen // Process response from Logging service. 3160599b9af3SAlexander Hansen auto respHandler = [asyncResp](const boost::system::error_code& ec) { 3161599b9af3SAlexander Hansen BMCWEB_LOG_DEBUG("doClearLog resp_handler callback: Done"); 3162599b9af3SAlexander Hansen if (ec) 3163599b9af3SAlexander Hansen { 3164599b9af3SAlexander Hansen // TODO Handle for specific error code 3165599b9af3SAlexander Hansen BMCWEB_LOG_ERROR("doClearLog resp_handler got error {}", ec); 3166599b9af3SAlexander Hansen asyncResp->res.result( 3167599b9af3SAlexander Hansen boost::beast::http::status::internal_server_error); 3168599b9af3SAlexander Hansen return; 3169599b9af3SAlexander Hansen } 3170599b9af3SAlexander Hansen 3171599b9af3SAlexander Hansen asyncResp->res.result(boost::beast::http::status::no_content); 3172599b9af3SAlexander Hansen }; 3173599b9af3SAlexander Hansen 3174599b9af3SAlexander Hansen // Make call to Logging service to request Clear Log 3175599b9af3SAlexander Hansen crow::connections::systemBus->async_method_call( 3176599b9af3SAlexander Hansen respHandler, "xyz.openbmc_project.Logging", 3177599b9af3SAlexander Hansen "/xyz/openbmc_project/logging", 3178599b9af3SAlexander Hansen "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll"); 3179599b9af3SAlexander Hansen } 3180599b9af3SAlexander Hansen 3181cb92c03bSAndrew Geissler /** 3182cb92c03bSAndrew Geissler * DBusLogServiceActionsClear class supports POST method for ClearLog action. 3183cb92c03bSAndrew Geissler */ 31847e860f15SJohn Edward Broadbent inline void requestRoutesDBusLogServiceActionsClear(App& app) 3185cb92c03bSAndrew Geissler { 3186cb92c03bSAndrew Geissler /** 3187cb92c03bSAndrew Geissler * Function handles POST method request. 3188cb92c03bSAndrew Geissler * The Clear Log actions does not require any parameter.The action deletes 3189cb92c03bSAndrew Geissler * all entries found in the Entries collection for this Log Service. 3190cb92c03bSAndrew Geissler */ 31917e860f15SJohn Edward Broadbent 31920fda0f12SGeorge Liu BMCWEB_ROUTE( 31930fda0f12SGeorge Liu app, 319422d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/EventLog/Actions/LogService.ClearLog/") 3195ed398213SEd Tanous .privileges(redfish::privileges::postLogService) 31967e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 319745ca1b86SEd Tanous [&app](const crow::Request& req, 319822d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 319922d268cbSEd Tanous const std::string& systemName) { 32003ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 320145ca1b86SEd Tanous { 320245ca1b86SEd Tanous return; 320345ca1b86SEd Tanous } 320425b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 32057f3e84a1SEd Tanous { 32067f3e84a1SEd Tanous // Option currently returns no systems. TBD 32077f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 32087f3e84a1SEd Tanous systemName); 32097f3e84a1SEd Tanous return; 32107f3e84a1SEd Tanous } 3211253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 321222d268cbSEd Tanous { 321322d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 321422d268cbSEd Tanous systemName); 321522d268cbSEd Tanous return; 321622d268cbSEd Tanous } 3217599b9af3SAlexander Hansen dBusLogServiceActionsClear(asyncResp); 32187e860f15SJohn Edward Broadbent }); 3219cb92c03bSAndrew Geissler } 3220a3316fc6SZhikuiRen 32211da66f75SEd Tanous } // namespace redfish 3222