140e9b92eSEd Tanous // SPDX-License-Identifier: Apache-2.0 240e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright OpenBMC Authors 340e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright 2018 Intel Corporation 41da66f75SEd Tanous #pragma once 51da66f75SEd Tanous 6d7857201SEd Tanous #include "bmcweb_config.h" 7d7857201SEd Tanous 83ccb3adbSEd Tanous #include "app.hpp" 9d7857201SEd Tanous #include "async_resp.hpp" 10d7857201SEd Tanous #include "dbus_singleton.hpp" 117a1dbc48SGeorge Liu #include "dbus_utility.hpp" 123ccb3adbSEd Tanous #include "error_messages.hpp" 1368dd075aSAsmitha Karunanithi #include "generated/enums/log_entry.hpp" 14539d8c6bSEd Tanous #include "generated/enums/log_service.hpp" 15d7857201SEd Tanous #include "http_body.hpp" 16d7857201SEd Tanous #include "http_request.hpp" 17d7857201SEd Tanous #include "http_response.hpp" 18647b3cdcSGeorge Liu #include "http_utility.hpp" 19b7028ebfSSpencer Ku #include "human_sort.hpp" 20d7857201SEd Tanous #include "logging.hpp" 213ccb3adbSEd Tanous #include "query.hpp" 224851d45dSJason M. Bills #include "registries.hpp" 233ccb3adbSEd Tanous #include "registries/privilege_registry.hpp" 24d7857201SEd Tanous #include "str_utility.hpp" 2546229577SJames Feist #include "task.hpp" 265b90429aSEd Tanous #include "task_messages.hpp" 27262dcc1cSAlexander Hansen #include "utils/dbus_event_log_entry.hpp" 283ccb3adbSEd Tanous #include "utils/dbus_utils.hpp" 295b90429aSEd Tanous #include "utils/json_utils.hpp" 30d7857201SEd Tanous #include "utils/query_param.hpp" 313ccb3adbSEd Tanous #include "utils/time_utils.hpp" 321da66f75SEd Tanous 33d7857201SEd Tanous #include <asm-generic/errno.h> 34d7857201SEd Tanous #include <systemd/sd-bus.h> 358e31778eSAsmitha Karunanithi #include <tinyxml2.h> 36400fd1fbSAdriana Kobylak #include <unistd.h> 37e1f26343SJason M. Bills 38d7857201SEd Tanous #include <boost/beast/http/field.hpp> 39d7857201SEd Tanous #include <boost/beast/http/status.hpp> 4007c8c20dSEd Tanous #include <boost/beast/http/verb.hpp> 411ddcf01aSJason M. Bills #include <boost/system/linux_error.hpp> 42ef4c65b7SEd Tanous #include <boost/url/format.hpp> 43d7857201SEd Tanous #include <boost/url/url.hpp> 44d7857201SEd Tanous #include <sdbusplus/message.hpp> 45d7857201SEd Tanous #include <sdbusplus/message/native_types.hpp> 46d1bde9e5SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp> 471214b7e7SGunnar Mills 48d7857201SEd Tanous #include <algorithm> 497a1dbc48SGeorge Liu #include <array> 50d7857201SEd Tanous #include <chrono> 51b5f288d2SAbhilash Raju #include <cstddef> 52d7857201SEd Tanous #include <cstdint> 53d7857201SEd Tanous #include <cstdio> 54d7857201SEd Tanous #include <ctime> 554418c7f0SJames Feist #include <filesystem> 56d7857201SEd Tanous #include <format> 57d7857201SEd Tanous #include <fstream> 58d7857201SEd Tanous #include <functional> 59d7857201SEd Tanous #include <iomanip> 6018f8f608SEd Tanous #include <iterator> 61d7857201SEd Tanous #include <memory> 6275710de2SXiaochao Ma #include <optional> 633544d2a7SEd Tanous #include <ranges> 6426702d01SEd Tanous #include <span> 65d7857201SEd Tanous #include <sstream> 6618f8f608SEd Tanous #include <string> 67cd225da8SJason M. Bills #include <string_view> 68d7857201SEd Tanous #include <system_error> 69d7857201SEd Tanous #include <utility> 70abf2add6SEd Tanous #include <variant> 71d7857201SEd Tanous #include <vector> 721da66f75SEd Tanous 731da66f75SEd Tanous namespace redfish 741da66f75SEd Tanous { 751da66f75SEd Tanous 7689492a15SPatrick Williams constexpr const char* crashdumpObject = "com.intel.crashdump"; 7789492a15SPatrick Williams constexpr const char* crashdumpPath = "/com/intel/crashdump"; 7889492a15SPatrick Williams constexpr const char* crashdumpInterface = "com.intel.crashdump"; 7989492a15SPatrick Williams constexpr const char* deleteAllInterface = 805b61b5e8SJason M. Bills "xyz.openbmc_project.Collection.DeleteAll"; 8189492a15SPatrick Williams constexpr const char* crashdumpOnDemandInterface = 82424c4176SJason M. Bills "com.intel.crashdump.OnDemand"; 8389492a15SPatrick Williams constexpr const char* crashdumpTelemetryInterface = 846eda7685SKenny L. Ku "com.intel.crashdump.Telemetry"; 851da66f75SEd Tanous 868e31778eSAsmitha Karunanithi enum class DumpCreationProgress 878e31778eSAsmitha Karunanithi { 888e31778eSAsmitha Karunanithi DUMP_CREATE_SUCCESS, 898e31778eSAsmitha Karunanithi DUMP_CREATE_FAILED, 908e31778eSAsmitha Karunanithi DUMP_CREATE_INPROGRESS 918e31778eSAsmitha Karunanithi }; 928e31778eSAsmitha Karunanithi 93cb92c03bSAndrew Geissler inline std::string translateSeverityDbusToRedfish(const std::string& s) 94cb92c03bSAndrew Geissler { 95d4d25793SEd Tanous if ((s == "xyz.openbmc_project.Logging.Entry.Level.Alert") || 96d4d25793SEd Tanous (s == "xyz.openbmc_project.Logging.Entry.Level.Critical") || 97d4d25793SEd Tanous (s == "xyz.openbmc_project.Logging.Entry.Level.Emergency") || 98d4d25793SEd Tanous (s == "xyz.openbmc_project.Logging.Entry.Level.Error")) 99cb92c03bSAndrew Geissler { 100cb92c03bSAndrew Geissler return "Critical"; 101cb92c03bSAndrew Geissler } 1023174e4dfSEd Tanous if ((s == "xyz.openbmc_project.Logging.Entry.Level.Debug") || 103d4d25793SEd Tanous (s == "xyz.openbmc_project.Logging.Entry.Level.Informational") || 104d4d25793SEd Tanous (s == "xyz.openbmc_project.Logging.Entry.Level.Notice")) 105cb92c03bSAndrew Geissler { 106cb92c03bSAndrew Geissler return "OK"; 107cb92c03bSAndrew Geissler } 1083174e4dfSEd Tanous if (s == "xyz.openbmc_project.Logging.Entry.Level.Warning") 109cb92c03bSAndrew Geissler { 110cb92c03bSAndrew Geissler return "Warning"; 111cb92c03bSAndrew Geissler } 112cb92c03bSAndrew Geissler return ""; 113cb92c03bSAndrew Geissler } 114cb92c03bSAndrew Geissler 1159017faf2SAbhishek Patel inline std::optional<bool> getProviderNotifyAction(const std::string& notify) 1169017faf2SAbhishek Patel { 1179017faf2SAbhishek Patel std::optional<bool> notifyAction; 1189017faf2SAbhishek Patel if (notify == "xyz.openbmc_project.Logging.Entry.Notify.Notify") 1199017faf2SAbhishek Patel { 1209017faf2SAbhishek Patel notifyAction = true; 1219017faf2SAbhishek Patel } 1229017faf2SAbhishek Patel else if (notify == "xyz.openbmc_project.Logging.Entry.Notify.Inhibit") 1239017faf2SAbhishek Patel { 1249017faf2SAbhishek Patel notifyAction = false; 1259017faf2SAbhishek Patel } 1269017faf2SAbhishek Patel 1279017faf2SAbhishek Patel return notifyAction; 1289017faf2SAbhishek Patel } 1299017faf2SAbhishek Patel 13018f8f608SEd Tanous inline std::string getDumpPath(std::string_view dumpType) 13118f8f608SEd Tanous { 13218f8f608SEd Tanous std::string dbusDumpPath = "/xyz/openbmc_project/dump/"; 13318f8f608SEd Tanous std::ranges::transform(dumpType, std::back_inserter(dbusDumpPath), 13418f8f608SEd Tanous bmcweb::asciiToLower); 13518f8f608SEd Tanous 13618f8f608SEd Tanous return dbusDumpPath; 13718f8f608SEd Tanous } 13818f8f608SEd Tanous 139055713e4SEd Tanous inline bool getUniqueEntryID(const std::string& logEntry, std::string& entryID, 140e85d6b16SJason M. Bills const bool firstEntry = true) 14195820184SJason M. Bills { 142271584abSEd Tanous static time_t prevTs = 0; 14395820184SJason M. Bills static int index = 0; 144e85d6b16SJason M. Bills if (firstEntry) 145e85d6b16SJason M. Bills { 146e85d6b16SJason M. Bills prevTs = 0; 147e85d6b16SJason M. Bills } 148e85d6b16SJason M. Bills 14995820184SJason M. Bills // Get the entry timestamp 150271584abSEd Tanous std::time_t curTs = 0; 15195820184SJason M. Bills std::tm timeStruct = {}; 15295820184SJason M. Bills std::istringstream entryStream(logEntry); 15395820184SJason M. Bills if (entryStream >> std::get_time(&timeStruct, "%Y-%m-%dT%H:%M:%S")) 15495820184SJason M. Bills { 15595820184SJason M. Bills curTs = std::mktime(&timeStruct); 15695820184SJason M. Bills } 15795820184SJason M. Bills // If the timestamp isn't unique, increment the index 15895820184SJason M. Bills if (curTs == prevTs) 15995820184SJason M. Bills { 16095820184SJason M. Bills index++; 16195820184SJason M. Bills } 16295820184SJason M. Bills else 16395820184SJason M. Bills { 16495820184SJason M. Bills // Otherwise, reset it 16595820184SJason M. Bills index = 0; 16695820184SJason M. Bills } 16795820184SJason M. Bills // Save the timestamp 16895820184SJason M. Bills prevTs = curTs; 16995820184SJason M. Bills 17095820184SJason M. Bills entryID = std::to_string(curTs); 17195820184SJason M. Bills if (index > 0) 17295820184SJason M. Bills { 17395820184SJason M. Bills entryID += "_" + std::to_string(index); 17495820184SJason M. Bills } 17595820184SJason M. Bills return true; 17695820184SJason M. Bills } 17795820184SJason M. Bills 178504af5a0SPatrick Williams inline bool getRedfishLogFiles( 179504af5a0SPatrick Williams std::vector<std::filesystem::path>& redfishLogFiles) 18095820184SJason M. Bills { 18195820184SJason M. Bills static const std::filesystem::path redfishLogDir = "/var/log"; 18295820184SJason M. Bills static const std::string redfishLogFilename = "redfish"; 18395820184SJason M. Bills 18495820184SJason M. Bills // Loop through the directory looking for redfish log files 18595820184SJason M. Bills for (const std::filesystem::directory_entry& dirEnt : 18695820184SJason M. Bills std::filesystem::directory_iterator(redfishLogDir)) 18795820184SJason M. Bills { 18895820184SJason M. Bills // If we find a redfish log file, save the path 18995820184SJason M. Bills std::string filename = dirEnt.path().filename(); 19011ba3979SEd Tanous if (filename.starts_with(redfishLogFilename)) 19195820184SJason M. Bills { 19295820184SJason M. Bills redfishLogFiles.emplace_back(redfishLogDir / filename); 19395820184SJason M. Bills } 19495820184SJason M. Bills } 19595820184SJason M. Bills // As the log files rotate, they are appended with a ".#" that is higher for 19695820184SJason M. Bills // the older logs. Since we don't expect more than 10 log files, we 19795820184SJason M. Bills // can just sort the list to get them in order from newest to oldest 1983544d2a7SEd Tanous std::ranges::sort(redfishLogFiles); 19995820184SJason M. Bills 20095820184SJason M. Bills return !redfishLogFiles.empty(); 20195820184SJason M. Bills } 20295820184SJason M. Bills 203504af5a0SPatrick Williams inline log_entry::OriginatorTypes mapDbusOriginatorTypeToRedfish( 204504af5a0SPatrick Williams const std::string& originatorType) 20568dd075aSAsmitha Karunanithi { 20668dd075aSAsmitha Karunanithi if (originatorType == 20768dd075aSAsmitha Karunanithi "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Client") 20868dd075aSAsmitha Karunanithi { 20968dd075aSAsmitha Karunanithi return log_entry::OriginatorTypes::Client; 21068dd075aSAsmitha Karunanithi } 21168dd075aSAsmitha Karunanithi if (originatorType == 21268dd075aSAsmitha Karunanithi "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Internal") 21368dd075aSAsmitha Karunanithi { 21468dd075aSAsmitha Karunanithi return log_entry::OriginatorTypes::Internal; 21568dd075aSAsmitha Karunanithi } 21668dd075aSAsmitha Karunanithi if (originatorType == 21768dd075aSAsmitha Karunanithi "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.SupportingService") 21868dd075aSAsmitha Karunanithi { 21968dd075aSAsmitha Karunanithi return log_entry::OriginatorTypes::SupportingService; 22068dd075aSAsmitha Karunanithi } 22168dd075aSAsmitha Karunanithi return log_entry::OriginatorTypes::Invalid; 22268dd075aSAsmitha Karunanithi } 22368dd075aSAsmitha Karunanithi 224aefe3786SClaire Weinan inline void parseDumpEntryFromDbusObject( 2252d613eb6SJiaqing Zhao const dbus::utility::ManagedObjectType::value_type& object, 226c6fecdabSClaire Weinan std::string& dumpStatus, uint64_t& size, uint64_t& timestampUs, 22768dd075aSAsmitha Karunanithi std::string& originatorId, log_entry::OriginatorTypes& originatorType, 228aefe3786SClaire Weinan const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 229aefe3786SClaire Weinan { 230aefe3786SClaire Weinan for (const auto& interfaceMap : object.second) 231aefe3786SClaire Weinan { 232aefe3786SClaire Weinan if (interfaceMap.first == "xyz.openbmc_project.Common.Progress") 233aefe3786SClaire Weinan { 234aefe3786SClaire Weinan for (const auto& propertyMap : interfaceMap.second) 235aefe3786SClaire Weinan { 236aefe3786SClaire Weinan if (propertyMap.first == "Status") 237aefe3786SClaire Weinan { 238aefe3786SClaire Weinan const auto* status = 239aefe3786SClaire Weinan std::get_if<std::string>(&propertyMap.second); 240aefe3786SClaire Weinan if (status == nullptr) 241aefe3786SClaire Weinan { 242aefe3786SClaire Weinan messages::internalError(asyncResp->res); 243aefe3786SClaire Weinan break; 244aefe3786SClaire Weinan } 245aefe3786SClaire Weinan dumpStatus = *status; 246aefe3786SClaire Weinan } 247aefe3786SClaire Weinan } 248aefe3786SClaire Weinan } 249aefe3786SClaire Weinan else if (interfaceMap.first == "xyz.openbmc_project.Dump.Entry") 250aefe3786SClaire Weinan { 251aefe3786SClaire Weinan for (const auto& propertyMap : interfaceMap.second) 252aefe3786SClaire Weinan { 253aefe3786SClaire Weinan if (propertyMap.first == "Size") 254aefe3786SClaire Weinan { 255aefe3786SClaire Weinan const auto* sizePtr = 256aefe3786SClaire Weinan std::get_if<uint64_t>(&propertyMap.second); 257aefe3786SClaire Weinan if (sizePtr == nullptr) 258aefe3786SClaire Weinan { 259aefe3786SClaire Weinan messages::internalError(asyncResp->res); 260aefe3786SClaire Weinan break; 261aefe3786SClaire Weinan } 262aefe3786SClaire Weinan size = *sizePtr; 263aefe3786SClaire Weinan break; 264aefe3786SClaire Weinan } 265aefe3786SClaire Weinan } 266aefe3786SClaire Weinan } 267aefe3786SClaire Weinan else if (interfaceMap.first == "xyz.openbmc_project.Time.EpochTime") 268aefe3786SClaire Weinan { 269aefe3786SClaire Weinan for (const auto& propertyMap : interfaceMap.second) 270aefe3786SClaire Weinan { 271aefe3786SClaire Weinan if (propertyMap.first == "Elapsed") 272aefe3786SClaire Weinan { 273aefe3786SClaire Weinan const uint64_t* usecsTimeStamp = 274aefe3786SClaire Weinan std::get_if<uint64_t>(&propertyMap.second); 275aefe3786SClaire Weinan if (usecsTimeStamp == nullptr) 276aefe3786SClaire Weinan { 277aefe3786SClaire Weinan messages::internalError(asyncResp->res); 278aefe3786SClaire Weinan break; 279aefe3786SClaire Weinan } 280c6fecdabSClaire Weinan timestampUs = *usecsTimeStamp; 281aefe3786SClaire Weinan break; 282aefe3786SClaire Weinan } 283aefe3786SClaire Weinan } 284aefe3786SClaire Weinan } 28568dd075aSAsmitha Karunanithi else if (interfaceMap.first == 28668dd075aSAsmitha Karunanithi "xyz.openbmc_project.Common.OriginatedBy") 28768dd075aSAsmitha Karunanithi { 28868dd075aSAsmitha Karunanithi for (const auto& propertyMap : interfaceMap.second) 28968dd075aSAsmitha Karunanithi { 29068dd075aSAsmitha Karunanithi if (propertyMap.first == "OriginatorId") 29168dd075aSAsmitha Karunanithi { 29268dd075aSAsmitha Karunanithi const std::string* id = 29368dd075aSAsmitha Karunanithi std::get_if<std::string>(&propertyMap.second); 29468dd075aSAsmitha Karunanithi if (id == nullptr) 29568dd075aSAsmitha Karunanithi { 29668dd075aSAsmitha Karunanithi messages::internalError(asyncResp->res); 29768dd075aSAsmitha Karunanithi break; 29868dd075aSAsmitha Karunanithi } 29968dd075aSAsmitha Karunanithi originatorId = *id; 30068dd075aSAsmitha Karunanithi } 30168dd075aSAsmitha Karunanithi 30268dd075aSAsmitha Karunanithi if (propertyMap.first == "OriginatorType") 30368dd075aSAsmitha Karunanithi { 30468dd075aSAsmitha Karunanithi const std::string* type = 30568dd075aSAsmitha Karunanithi std::get_if<std::string>(&propertyMap.second); 30668dd075aSAsmitha Karunanithi if (type == nullptr) 30768dd075aSAsmitha Karunanithi { 30868dd075aSAsmitha Karunanithi messages::internalError(asyncResp->res); 30968dd075aSAsmitha Karunanithi break; 31068dd075aSAsmitha Karunanithi } 31168dd075aSAsmitha Karunanithi 31268dd075aSAsmitha Karunanithi originatorType = mapDbusOriginatorTypeToRedfish(*type); 31368dd075aSAsmitha Karunanithi if (originatorType == log_entry::OriginatorTypes::Invalid) 31468dd075aSAsmitha Karunanithi { 31568dd075aSAsmitha Karunanithi messages::internalError(asyncResp->res); 31668dd075aSAsmitha Karunanithi break; 31768dd075aSAsmitha Karunanithi } 31868dd075aSAsmitha Karunanithi } 31968dd075aSAsmitha Karunanithi } 32068dd075aSAsmitha Karunanithi } 321aefe3786SClaire Weinan } 322aefe3786SClaire Weinan } 323aefe3786SClaire Weinan 32421ab404cSNan Zhou static std::string getDumpEntriesPath(const std::string& dumpType) 325fdd26906SClaire Weinan { 326fdd26906SClaire Weinan std::string entriesPath; 327fdd26906SClaire Weinan 328fdd26906SClaire Weinan if (dumpType == "BMC") 329fdd26906SClaire Weinan { 330253f11b8SEd Tanous entriesPath = 331253f11b8SEd Tanous std::format("/redfish/v1/Managers/{}/LogServices/Dump/Entries/", 332253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 333fdd26906SClaire Weinan } 334fdd26906SClaire Weinan else if (dumpType == "FaultLog") 335fdd26906SClaire Weinan { 336253f11b8SEd Tanous entriesPath = 337253f11b8SEd Tanous std::format("/redfish/v1/Managers/{}/LogServices/FaultLog/Entries/", 338253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 339fdd26906SClaire Weinan } 340fdd26906SClaire Weinan else if (dumpType == "System") 341fdd26906SClaire Weinan { 342253f11b8SEd Tanous entriesPath = 343253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/Dump/Entries/", 344253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 345fdd26906SClaire Weinan } 346fdd26906SClaire Weinan else 347fdd26906SClaire Weinan { 34862598e31SEd Tanous BMCWEB_LOG_ERROR("getDumpEntriesPath() invalid dump type: {}", 34962598e31SEd Tanous dumpType); 350fdd26906SClaire Weinan } 351fdd26906SClaire Weinan 352fdd26906SClaire Weinan // Returns empty string on error 353fdd26906SClaire Weinan return entriesPath; 354fdd26906SClaire Weinan } 355fdd26906SClaire Weinan 356504af5a0SPatrick Williams inline void getDumpEntryCollection( 357504af5a0SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 3585cb1dd27SAsmitha Karunanithi const std::string& dumpType) 3595cb1dd27SAsmitha Karunanithi { 360fdd26906SClaire Weinan std::string entriesPath = getDumpEntriesPath(dumpType); 361fdd26906SClaire Weinan if (entriesPath.empty()) 3625cb1dd27SAsmitha Karunanithi { 3635cb1dd27SAsmitha Karunanithi messages::internalError(asyncResp->res); 3645cb1dd27SAsmitha Karunanithi return; 3655cb1dd27SAsmitha Karunanithi } 3665cb1dd27SAsmitha Karunanithi 3675eb468daSGeorge Liu sdbusplus::message::object_path path("/xyz/openbmc_project/dump"); 3685eb468daSGeorge Liu dbus::utility::getManagedObjects( 3695eb468daSGeorge Liu "xyz.openbmc_project.Dump.Manager", path, 370fdd26906SClaire Weinan [asyncResp, entriesPath, 3715e7e2dc5SEd Tanous dumpType](const boost::system::error_code& ec, 3725eb468daSGeorge Liu const dbus::utility::ManagedObjectType& objects) { 3735cb1dd27SAsmitha Karunanithi if (ec) 3745cb1dd27SAsmitha Karunanithi { 37562598e31SEd Tanous BMCWEB_LOG_ERROR("DumpEntry resp_handler got error {}", ec); 3765cb1dd27SAsmitha Karunanithi messages::internalError(asyncResp->res); 3775cb1dd27SAsmitha Karunanithi return; 3785cb1dd27SAsmitha Karunanithi } 3795cb1dd27SAsmitha Karunanithi 380fdd26906SClaire Weinan // Remove ending slash 381fdd26906SClaire Weinan std::string odataIdStr = entriesPath; 382fdd26906SClaire Weinan if (!odataIdStr.empty()) 383fdd26906SClaire Weinan { 384fdd26906SClaire Weinan odataIdStr.pop_back(); 385fdd26906SClaire Weinan } 386fdd26906SClaire Weinan 387fdd26906SClaire Weinan asyncResp->res.jsonValue["@odata.type"] = 388fdd26906SClaire Weinan "#LogEntryCollection.LogEntryCollection"; 389fdd26906SClaire Weinan asyncResp->res.jsonValue["@odata.id"] = std::move(odataIdStr); 390fdd26906SClaire Weinan asyncResp->res.jsonValue["Name"] = dumpType + " Dump Entries"; 391bd79bce8SPatrick Williams asyncResp->res.jsonValue["Description"] = 392bd79bce8SPatrick Williams "Collection of " + dumpType + " Dump Entries"; 393fdd26906SClaire Weinan 3943544d2a7SEd Tanous nlohmann::json::array_t entriesArray; 39518f8f608SEd Tanous std::string dumpEntryPath = getDumpPath(dumpType) + "/entry/"; 3965cb1dd27SAsmitha Karunanithi 3975eb468daSGeorge Liu dbus::utility::ManagedObjectType resp(objects); 3983544d2a7SEd Tanous std::ranges::sort(resp, [](const auto& l, const auto& r) { 399002d39b4SEd Tanous return AlphanumLess<std::string>()(l.first.filename(), 400002d39b4SEd Tanous r.first.filename()); 401565dfb6fSClaire Weinan }); 402565dfb6fSClaire Weinan 4035cb1dd27SAsmitha Karunanithi for (auto& object : resp) 4045cb1dd27SAsmitha Karunanithi { 405b47452b2SAsmitha Karunanithi if (object.first.str.find(dumpEntryPath) == std::string::npos) 4065cb1dd27SAsmitha Karunanithi { 4075cb1dd27SAsmitha Karunanithi continue; 4085cb1dd27SAsmitha Karunanithi } 409c6fecdabSClaire Weinan uint64_t timestampUs = 0; 4105cb1dd27SAsmitha Karunanithi uint64_t size = 0; 41135440d18SAsmitha Karunanithi std::string dumpStatus; 41268dd075aSAsmitha Karunanithi std::string originatorId; 41368dd075aSAsmitha Karunanithi log_entry::OriginatorTypes originatorType = 41468dd075aSAsmitha Karunanithi log_entry::OriginatorTypes::Internal; 415433b68b4SJason M. Bills nlohmann::json::object_t thisEntry; 4162dfd18efSEd Tanous 4172dfd18efSEd Tanous std::string entryID = object.first.filename(); 4182dfd18efSEd Tanous if (entryID.empty()) 4195cb1dd27SAsmitha Karunanithi { 4205cb1dd27SAsmitha Karunanithi continue; 4215cb1dd27SAsmitha Karunanithi } 4225cb1dd27SAsmitha Karunanithi 423bd79bce8SPatrick Williams parseDumpEntryFromDbusObject(object, dumpStatus, size, 424bd79bce8SPatrick Williams timestampUs, originatorId, 425bd79bce8SPatrick Williams originatorType, asyncResp); 4265cb1dd27SAsmitha Karunanithi 4270fda0f12SGeorge Liu if (dumpStatus != 4280fda0f12SGeorge Liu "xyz.openbmc_project.Common.Progress.OperationStatus.Completed" && 42935440d18SAsmitha Karunanithi !dumpStatus.empty()) 43035440d18SAsmitha Karunanithi { 43135440d18SAsmitha Karunanithi // Dump status is not Complete, no need to enumerate 43235440d18SAsmitha Karunanithi continue; 43335440d18SAsmitha Karunanithi } 43435440d18SAsmitha Karunanithi 43568dd075aSAsmitha Karunanithi thisEntry["@odata.type"] = "#LogEntry.v1_11_0.LogEntry"; 436fdd26906SClaire Weinan thisEntry["@odata.id"] = entriesPath + entryID; 4375cb1dd27SAsmitha Karunanithi thisEntry["Id"] = entryID; 4385cb1dd27SAsmitha Karunanithi thisEntry["EntryType"] = "Event"; 4395cb1dd27SAsmitha Karunanithi thisEntry["Name"] = dumpType + " Dump Entry"; 440bbd80db8SClaire Weinan thisEntry["Created"] = 441bbd80db8SClaire Weinan redfish::time_utils::getDateTimeUintUs(timestampUs); 4425cb1dd27SAsmitha Karunanithi 44368dd075aSAsmitha Karunanithi if (!originatorId.empty()) 44468dd075aSAsmitha Karunanithi { 44568dd075aSAsmitha Karunanithi thisEntry["Originator"] = originatorId; 44668dd075aSAsmitha Karunanithi thisEntry["OriginatorType"] = originatorType; 44768dd075aSAsmitha Karunanithi } 44868dd075aSAsmitha Karunanithi 4495cb1dd27SAsmitha Karunanithi if (dumpType == "BMC") 4505cb1dd27SAsmitha Karunanithi { 451d337bb72SAsmitha Karunanithi thisEntry["DiagnosticDataType"] = "Manager"; 452bd79bce8SPatrick Williams thisEntry["AdditionalDataURI"] = 453bd79bce8SPatrick Williams entriesPath + entryID + "/attachment"; 454fdd26906SClaire Weinan thisEntry["AdditionalDataSizeBytes"] = size; 4555cb1dd27SAsmitha Karunanithi } 4565cb1dd27SAsmitha Karunanithi else if (dumpType == "System") 4575cb1dd27SAsmitha Karunanithi { 458d337bb72SAsmitha Karunanithi thisEntry["DiagnosticDataType"] = "OEM"; 459d337bb72SAsmitha Karunanithi thisEntry["OEMDiagnosticDataType"] = "System"; 460bd79bce8SPatrick Williams thisEntry["AdditionalDataURI"] = 461bd79bce8SPatrick Williams entriesPath + entryID + "/attachment"; 462fdd26906SClaire Weinan thisEntry["AdditionalDataSizeBytes"] = size; 4635cb1dd27SAsmitha Karunanithi } 464b2ba3072SPatrick Williams entriesArray.emplace_back(std::move(thisEntry)); 4655cb1dd27SAsmitha Karunanithi } 466bd79bce8SPatrick Williams asyncResp->res.jsonValue["Members@odata.count"] = 467bd79bce8SPatrick Williams entriesArray.size(); 4683544d2a7SEd Tanous asyncResp->res.jsonValue["Members"] = std::move(entriesArray); 4695eb468daSGeorge Liu }); 4705cb1dd27SAsmitha Karunanithi } 4715cb1dd27SAsmitha Karunanithi 472504af5a0SPatrick Williams inline void getDumpEntryById( 473504af5a0SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 4748d1b46d7Szhanghch05 const std::string& entryID, const std::string& dumpType) 4755cb1dd27SAsmitha Karunanithi { 476fdd26906SClaire Weinan std::string entriesPath = getDumpEntriesPath(dumpType); 477fdd26906SClaire Weinan if (entriesPath.empty()) 4785cb1dd27SAsmitha Karunanithi { 4795cb1dd27SAsmitha Karunanithi messages::internalError(asyncResp->res); 4805cb1dd27SAsmitha Karunanithi return; 4815cb1dd27SAsmitha Karunanithi } 4825cb1dd27SAsmitha Karunanithi 4835eb468daSGeorge Liu sdbusplus::message::object_path path("/xyz/openbmc_project/dump"); 4845eb468daSGeorge Liu dbus::utility::getManagedObjects( 4855eb468daSGeorge Liu "xyz.openbmc_project.Dump.Manager", path, 486fdd26906SClaire Weinan [asyncResp, entryID, dumpType, 4875e7e2dc5SEd Tanous entriesPath](const boost::system::error_code& ec, 48802cad96eSEd Tanous const dbus::utility::ManagedObjectType& resp) { 4895cb1dd27SAsmitha Karunanithi if (ec) 4905cb1dd27SAsmitha Karunanithi { 49162598e31SEd Tanous BMCWEB_LOG_ERROR("DumpEntry resp_handler got error {}", ec); 4925cb1dd27SAsmitha Karunanithi messages::internalError(asyncResp->res); 4935cb1dd27SAsmitha Karunanithi return; 4945cb1dd27SAsmitha Karunanithi } 4955cb1dd27SAsmitha Karunanithi 496b47452b2SAsmitha Karunanithi bool foundDumpEntry = false; 49718f8f608SEd Tanous std::string dumpEntryPath = getDumpPath(dumpType) + "/entry/"; 498b47452b2SAsmitha Karunanithi 4999eb808c1SEd Tanous for (const auto& objectPath : resp) 5005cb1dd27SAsmitha Karunanithi { 501b47452b2SAsmitha Karunanithi if (objectPath.first.str != dumpEntryPath + entryID) 5025cb1dd27SAsmitha Karunanithi { 5035cb1dd27SAsmitha Karunanithi continue; 5045cb1dd27SAsmitha Karunanithi } 5055cb1dd27SAsmitha Karunanithi 5065cb1dd27SAsmitha Karunanithi foundDumpEntry = true; 507c6fecdabSClaire Weinan uint64_t timestampUs = 0; 5085cb1dd27SAsmitha Karunanithi uint64_t size = 0; 50935440d18SAsmitha Karunanithi std::string dumpStatus; 51068dd075aSAsmitha Karunanithi std::string originatorId; 51168dd075aSAsmitha Karunanithi log_entry::OriginatorTypes originatorType = 51268dd075aSAsmitha Karunanithi log_entry::OriginatorTypes::Internal; 5135cb1dd27SAsmitha Karunanithi 514aefe3786SClaire Weinan parseDumpEntryFromDbusObject(objectPath, dumpStatus, size, 51568dd075aSAsmitha Karunanithi timestampUs, originatorId, 51668dd075aSAsmitha Karunanithi originatorType, asyncResp); 5175cb1dd27SAsmitha Karunanithi 5180fda0f12SGeorge Liu if (dumpStatus != 5190fda0f12SGeorge Liu "xyz.openbmc_project.Common.Progress.OperationStatus.Completed" && 52035440d18SAsmitha Karunanithi !dumpStatus.empty()) 52135440d18SAsmitha Karunanithi { 52235440d18SAsmitha Karunanithi // Dump status is not Complete 52335440d18SAsmitha Karunanithi // return not found until status is changed to Completed 524bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, 525bd79bce8SPatrick Williams dumpType + " dump", entryID); 52635440d18SAsmitha Karunanithi return; 52735440d18SAsmitha Karunanithi } 52835440d18SAsmitha Karunanithi 5295cb1dd27SAsmitha Karunanithi asyncResp->res.jsonValue["@odata.type"] = 53068dd075aSAsmitha Karunanithi "#LogEntry.v1_11_0.LogEntry"; 531fdd26906SClaire Weinan asyncResp->res.jsonValue["@odata.id"] = entriesPath + entryID; 5325cb1dd27SAsmitha Karunanithi asyncResp->res.jsonValue["Id"] = entryID; 5335cb1dd27SAsmitha Karunanithi asyncResp->res.jsonValue["EntryType"] = "Event"; 5345cb1dd27SAsmitha Karunanithi asyncResp->res.jsonValue["Name"] = dumpType + " Dump Entry"; 535bbd80db8SClaire Weinan asyncResp->res.jsonValue["Created"] = 536bbd80db8SClaire Weinan redfish::time_utils::getDateTimeUintUs(timestampUs); 5375cb1dd27SAsmitha Karunanithi 53868dd075aSAsmitha Karunanithi if (!originatorId.empty()) 53968dd075aSAsmitha Karunanithi { 54068dd075aSAsmitha Karunanithi asyncResp->res.jsonValue["Originator"] = originatorId; 54168dd075aSAsmitha Karunanithi asyncResp->res.jsonValue["OriginatorType"] = originatorType; 54268dd075aSAsmitha Karunanithi } 54368dd075aSAsmitha Karunanithi 5445cb1dd27SAsmitha Karunanithi if (dumpType == "BMC") 5455cb1dd27SAsmitha Karunanithi { 546d337bb72SAsmitha Karunanithi asyncResp->res.jsonValue["DiagnosticDataType"] = "Manager"; 547d337bb72SAsmitha Karunanithi asyncResp->res.jsonValue["AdditionalDataURI"] = 548fdd26906SClaire Weinan entriesPath + entryID + "/attachment"; 549fdd26906SClaire Weinan asyncResp->res.jsonValue["AdditionalDataSizeBytes"] = size; 5505cb1dd27SAsmitha Karunanithi } 5515cb1dd27SAsmitha Karunanithi else if (dumpType == "System") 5525cb1dd27SAsmitha Karunanithi { 553d337bb72SAsmitha Karunanithi asyncResp->res.jsonValue["DiagnosticDataType"] = "OEM"; 554bd79bce8SPatrick Williams asyncResp->res.jsonValue["OEMDiagnosticDataType"] = 555bd79bce8SPatrick Williams "System"; 556d337bb72SAsmitha Karunanithi asyncResp->res.jsonValue["AdditionalDataURI"] = 557fdd26906SClaire Weinan entriesPath + entryID + "/attachment"; 558fdd26906SClaire Weinan asyncResp->res.jsonValue["AdditionalDataSizeBytes"] = size; 5595cb1dd27SAsmitha Karunanithi } 5605cb1dd27SAsmitha Karunanithi } 561e05aec50SEd Tanous if (!foundDumpEntry) 562b47452b2SAsmitha Karunanithi { 56362598e31SEd Tanous BMCWEB_LOG_WARNING("Can't find Dump Entry {}", entryID); 564b90d14f2SMyung Bae messages::resourceNotFound(asyncResp->res, dumpType + " dump", 565b90d14f2SMyung Bae entryID); 566b47452b2SAsmitha Karunanithi return; 567b47452b2SAsmitha Karunanithi } 5685eb468daSGeorge Liu }); 5695cb1dd27SAsmitha Karunanithi } 5705cb1dd27SAsmitha Karunanithi 5718d1b46d7Szhanghch05 inline void deleteDumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 5729878256fSStanley Chu const std::string& entryID, 573b47452b2SAsmitha Karunanithi const std::string& dumpType) 5745cb1dd27SAsmitha Karunanithi { 5755a39f77aSPatrick Williams auto respHandler = [asyncResp, 5765a39f77aSPatrick Williams entryID](const boost::system::error_code& ec) { 57762598e31SEd Tanous BMCWEB_LOG_DEBUG("Dump Entry doDelete callback: Done"); 5785cb1dd27SAsmitha Karunanithi if (ec) 5795cb1dd27SAsmitha Karunanithi { 5803de8d8baSGeorge Liu if (ec.value() == EBADR) 5813de8d8baSGeorge Liu { 5823de8d8baSGeorge Liu messages::resourceNotFound(asyncResp->res, "LogEntry", entryID); 5833de8d8baSGeorge Liu return; 5843de8d8baSGeorge Liu } 58562598e31SEd Tanous BMCWEB_LOG_ERROR( 58662598e31SEd Tanous "Dump (DBus) doDelete respHandler got error {} entryID={}", ec, 58762598e31SEd Tanous entryID); 5885cb1dd27SAsmitha Karunanithi messages::internalError(asyncResp->res); 5895cb1dd27SAsmitha Karunanithi return; 5905cb1dd27SAsmitha Karunanithi } 5915cb1dd27SAsmitha Karunanithi }; 59218f8f608SEd Tanous 593177612aaSEd Tanous dbus::utility::async_method_call( 594177612aaSEd Tanous asyncResp, respHandler, "xyz.openbmc_project.Dump.Manager", 59518f8f608SEd Tanous std::format("{}/entry/{}", getDumpPath(dumpType), entryID), 5965cb1dd27SAsmitha Karunanithi "xyz.openbmc_project.Object.Delete", "Delete"); 5975cb1dd27SAsmitha Karunanithi } 598b5f288d2SAbhilash Raju inline bool checkSizeLimit(int fd, crow::Response& res) 599b5f288d2SAbhilash Raju { 600b5f288d2SAbhilash Raju long long int size = lseek(fd, 0, SEEK_END); 601b5f288d2SAbhilash Raju if (size <= 0) 602b5f288d2SAbhilash Raju { 603b5f288d2SAbhilash Raju BMCWEB_LOG_ERROR("Failed to get size of file, lseek() returned {}", 604b5f288d2SAbhilash Raju size); 605b5f288d2SAbhilash Raju messages::internalError(res); 606b5f288d2SAbhilash Raju return false; 607b5f288d2SAbhilash Raju } 6085cb1dd27SAsmitha Karunanithi 609b5f288d2SAbhilash Raju // Arbitrary max size of 20MB to accommodate BMC dumps 610b5f288d2SAbhilash Raju constexpr long long int maxFileSize = 20LL * 1024LL * 1024LL; 611b5f288d2SAbhilash Raju if (size > maxFileSize) 612b5f288d2SAbhilash Raju { 613b5f288d2SAbhilash Raju BMCWEB_LOG_ERROR("File size {} exceeds maximum allowed size of {}", 614b5f288d2SAbhilash Raju size, maxFileSize); 615b5f288d2SAbhilash Raju messages::internalError(res); 616b5f288d2SAbhilash Raju return false; 617b5f288d2SAbhilash Raju } 618b5f288d2SAbhilash Raju off_t rc = lseek(fd, 0, SEEK_SET); 619b5f288d2SAbhilash Raju if (rc < 0) 620b5f288d2SAbhilash Raju { 621b5f288d2SAbhilash Raju BMCWEB_LOG_ERROR("Failed to reset file offset to 0"); 622b5f288d2SAbhilash Raju messages::internalError(res); 623b5f288d2SAbhilash Raju return false; 624b5f288d2SAbhilash Raju } 625b5f288d2SAbhilash Raju return true; 626b5f288d2SAbhilash Raju } 627bd79bce8SPatrick Williams inline void downloadEntryCallback( 628bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 629bd79bce8SPatrick Williams const std::string& entryID, const std::string& downloadEntryType, 630168d1b1aSCarson Labrado const boost::system::error_code& ec, 631168d1b1aSCarson Labrado const sdbusplus::message::unix_fd& unixfd) 632168d1b1aSCarson Labrado { 633168d1b1aSCarson Labrado if (ec.value() == EBADR) 634168d1b1aSCarson Labrado { 635168d1b1aSCarson Labrado messages::resourceNotFound(asyncResp->res, "EntryAttachment", entryID); 636168d1b1aSCarson Labrado return; 637168d1b1aSCarson Labrado } 638168d1b1aSCarson Labrado if (ec) 639168d1b1aSCarson Labrado { 640168d1b1aSCarson Labrado BMCWEB_LOG_ERROR("DBUS response error: {}", ec); 641168d1b1aSCarson Labrado messages::internalError(asyncResp->res); 642168d1b1aSCarson Labrado return; 643168d1b1aSCarson Labrado } 644168d1b1aSCarson Labrado 645168d1b1aSCarson Labrado // Make sure we know how to process the retrieved entry attachment 646168d1b1aSCarson Labrado if ((downloadEntryType != "BMC") && (downloadEntryType != "System")) 647168d1b1aSCarson Labrado { 648168d1b1aSCarson Labrado BMCWEB_LOG_ERROR("downloadEntryCallback() invalid entry type: {}", 649168d1b1aSCarson Labrado downloadEntryType); 650168d1b1aSCarson Labrado messages::internalError(asyncResp->res); 651168d1b1aSCarson Labrado } 652168d1b1aSCarson Labrado 653168d1b1aSCarson Labrado int fd = -1; 654168d1b1aSCarson Labrado fd = dup(unixfd); 655168d1b1aSCarson Labrado if (fd < 0) 656168d1b1aSCarson Labrado { 657168d1b1aSCarson Labrado BMCWEB_LOG_ERROR("Failed to open file"); 658168d1b1aSCarson Labrado messages::internalError(asyncResp->res); 659168d1b1aSCarson Labrado return; 660168d1b1aSCarson Labrado } 661b5f288d2SAbhilash Raju if (!checkSizeLimit(fd, asyncResp->res)) 662168d1b1aSCarson Labrado { 663168d1b1aSCarson Labrado close(fd); 664168d1b1aSCarson Labrado return; 665168d1b1aSCarson Labrado } 666168d1b1aSCarson Labrado if (downloadEntryType == "System") 667168d1b1aSCarson Labrado { 668b5f288d2SAbhilash Raju if (!asyncResp->res.openFd(fd, bmcweb::EncodingType::Base64)) 669b5f288d2SAbhilash Raju { 670b5f288d2SAbhilash Raju messages::internalError(asyncResp->res); 671b5f288d2SAbhilash Raju close(fd); 672b5f288d2SAbhilash Raju return; 673b5f288d2SAbhilash Raju } 674168d1b1aSCarson Labrado asyncResp->res.addHeader( 675168d1b1aSCarson Labrado boost::beast::http::field::content_transfer_encoding, "Base64"); 676b5f288d2SAbhilash Raju return; 677168d1b1aSCarson Labrado } 678b5f288d2SAbhilash Raju if (!asyncResp->res.openFd(fd)) 67927b0cf90SEd Tanous { 680b5f288d2SAbhilash Raju messages::internalError(asyncResp->res); 681b5f288d2SAbhilash Raju close(fd); 682b5f288d2SAbhilash Raju return; 68327b0cf90SEd Tanous } 684168d1b1aSCarson Labrado asyncResp->res.addHeader(boost::beast::http::field::content_type, 685168d1b1aSCarson Labrado "application/octet-stream"); 686168d1b1aSCarson Labrado } 687168d1b1aSCarson Labrado 688504af5a0SPatrick Williams inline void downloadDumpEntry( 689504af5a0SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 690168d1b1aSCarson Labrado const std::string& entryID, const std::string& dumpType) 691168d1b1aSCarson Labrado { 692168d1b1aSCarson Labrado if (dumpType != "BMC") 693168d1b1aSCarson Labrado { 694168d1b1aSCarson Labrado BMCWEB_LOG_WARNING("Can't find Dump Entry {}", entryID); 695168d1b1aSCarson Labrado messages::resourceNotFound(asyncResp->res, dumpType + " dump", entryID); 696168d1b1aSCarson Labrado return; 697168d1b1aSCarson Labrado } 698168d1b1aSCarson Labrado 699bd79bce8SPatrick Williams std::string dumpEntryPath = 700bd79bce8SPatrick Williams std::format("{}/entry/{}", getDumpPath(dumpType), entryID); 701168d1b1aSCarson Labrado 702168d1b1aSCarson Labrado auto downloadDumpEntryHandler = 703168d1b1aSCarson Labrado [asyncResp, entryID, 704168d1b1aSCarson Labrado dumpType](const boost::system::error_code& ec, 705168d1b1aSCarson Labrado const sdbusplus::message::unix_fd& unixfd) { 706168d1b1aSCarson Labrado downloadEntryCallback(asyncResp, entryID, dumpType, ec, unixfd); 707168d1b1aSCarson Labrado }; 708168d1b1aSCarson Labrado 709177612aaSEd Tanous dbus::utility::async_method_call( 710177612aaSEd Tanous asyncResp, std::move(downloadDumpEntryHandler), 711177612aaSEd Tanous "xyz.openbmc_project.Dump.Manager", dumpEntryPath, 712177612aaSEd Tanous "xyz.openbmc_project.Dump.Entry", "GetFileHandle"); 713168d1b1aSCarson Labrado } 714168d1b1aSCarson Labrado 715bd79bce8SPatrick Williams inline void downloadEventLogEntry( 716bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 717bd79bce8SPatrick Williams const std::string& systemName, const std::string& entryID, 718168d1b1aSCarson Labrado const std::string& dumpType) 719168d1b1aSCarson Labrado { 72025b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 721168d1b1aSCarson Labrado { 722168d1b1aSCarson Labrado // Option currently returns no systems. TBD 723168d1b1aSCarson Labrado messages::resourceNotFound(asyncResp->res, "ComputerSystem", 724168d1b1aSCarson Labrado systemName); 725168d1b1aSCarson Labrado return; 726168d1b1aSCarson Labrado } 727253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 728168d1b1aSCarson Labrado { 729168d1b1aSCarson Labrado messages::resourceNotFound(asyncResp->res, "ComputerSystem", 730168d1b1aSCarson Labrado systemName); 731168d1b1aSCarson Labrado return; 732168d1b1aSCarson Labrado } 733168d1b1aSCarson Labrado 734168d1b1aSCarson Labrado std::string entryPath = 735168d1b1aSCarson Labrado sdbusplus::message::object_path("/xyz/openbmc_project/logging/entry") / 736168d1b1aSCarson Labrado entryID; 737168d1b1aSCarson Labrado 738168d1b1aSCarson Labrado auto downloadEventLogEntryHandler = 739168d1b1aSCarson Labrado [asyncResp, entryID, 740168d1b1aSCarson Labrado dumpType](const boost::system::error_code& ec, 741168d1b1aSCarson Labrado const sdbusplus::message::unix_fd& unixfd) { 742168d1b1aSCarson Labrado downloadEntryCallback(asyncResp, entryID, dumpType, ec, unixfd); 743168d1b1aSCarson Labrado }; 744168d1b1aSCarson Labrado 745177612aaSEd Tanous dbus::utility::async_method_call( 746177612aaSEd Tanous asyncResp, std::move(downloadEventLogEntryHandler), 747177612aaSEd Tanous "xyz.openbmc_project.Logging", entryPath, 748177612aaSEd Tanous "xyz.openbmc_project.Logging.Entry", "GetEntry"); 749168d1b1aSCarson Labrado } 750168d1b1aSCarson Labrado 751504af5a0SPatrick Williams inline DumpCreationProgress mapDbusStatusToDumpProgress( 752504af5a0SPatrick Williams const std::string& status) 753a43be80fSAsmitha Karunanithi { 7548e31778eSAsmitha Karunanithi if (status == 7558e31778eSAsmitha Karunanithi "xyz.openbmc_project.Common.Progress.OperationStatus.Failed" || 7568e31778eSAsmitha Karunanithi status == "xyz.openbmc_project.Common.Progress.OperationStatus.Aborted") 7578e31778eSAsmitha Karunanithi { 7588e31778eSAsmitha Karunanithi return DumpCreationProgress::DUMP_CREATE_FAILED; 7598e31778eSAsmitha Karunanithi } 7608e31778eSAsmitha Karunanithi if (status == 7618e31778eSAsmitha Karunanithi "xyz.openbmc_project.Common.Progress.OperationStatus.Completed") 7628e31778eSAsmitha Karunanithi { 7638e31778eSAsmitha Karunanithi return DumpCreationProgress::DUMP_CREATE_SUCCESS; 7648e31778eSAsmitha Karunanithi } 7658e31778eSAsmitha Karunanithi return DumpCreationProgress::DUMP_CREATE_INPROGRESS; 7668e31778eSAsmitha Karunanithi } 7678e31778eSAsmitha Karunanithi 768504af5a0SPatrick Williams inline DumpCreationProgress getDumpCompletionStatus( 769504af5a0SPatrick Williams const dbus::utility::DBusPropertiesMap& values) 7708e31778eSAsmitha Karunanithi { 7718e31778eSAsmitha Karunanithi for (const auto& [key, val] : values) 7728e31778eSAsmitha Karunanithi { 7738e31778eSAsmitha Karunanithi if (key == "Status") 7748e31778eSAsmitha Karunanithi { 7758e31778eSAsmitha Karunanithi const std::string* value = std::get_if<std::string>(&val); 7768e31778eSAsmitha Karunanithi if (value == nullptr) 7778e31778eSAsmitha Karunanithi { 77862598e31SEd Tanous BMCWEB_LOG_ERROR("Status property value is null"); 7798e31778eSAsmitha Karunanithi return DumpCreationProgress::DUMP_CREATE_FAILED; 7808e31778eSAsmitha Karunanithi } 7818e31778eSAsmitha Karunanithi return mapDbusStatusToDumpProgress(*value); 7828e31778eSAsmitha Karunanithi } 7838e31778eSAsmitha Karunanithi } 7848e31778eSAsmitha Karunanithi return DumpCreationProgress::DUMP_CREATE_INPROGRESS; 7858e31778eSAsmitha Karunanithi } 7868e31778eSAsmitha Karunanithi 7878e31778eSAsmitha Karunanithi inline std::string getDumpEntryPath(const std::string& dumpPath) 7888e31778eSAsmitha Karunanithi { 7898e31778eSAsmitha Karunanithi if (dumpPath == "/xyz/openbmc_project/dump/bmc/entry") 7908e31778eSAsmitha Karunanithi { 791253f11b8SEd Tanous return std::format("/redfish/v1/Managers/{}/LogServices/Dump/Entries/", 7929f565090SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 7938e31778eSAsmitha Karunanithi } 7948e31778eSAsmitha Karunanithi if (dumpPath == "/xyz/openbmc_project/dump/system/entry") 7958e31778eSAsmitha Karunanithi { 796253f11b8SEd Tanous return std::format("/redfish/v1/Systems/{}/LogServices/Dump/Entries/", 797253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 7988e31778eSAsmitha Karunanithi } 7998e31778eSAsmitha Karunanithi return ""; 8008e31778eSAsmitha Karunanithi } 8018e31778eSAsmitha Karunanithi 8028e31778eSAsmitha Karunanithi inline void createDumpTaskCallback( 8038e31778eSAsmitha Karunanithi task::Payload&& payload, 8048e31778eSAsmitha Karunanithi const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 8058e31778eSAsmitha Karunanithi const sdbusplus::message::object_path& createdObjPath) 8068e31778eSAsmitha Karunanithi { 8078e31778eSAsmitha Karunanithi const std::string dumpPath = createdObjPath.parent_path().str; 8088e31778eSAsmitha Karunanithi const std::string dumpId = createdObjPath.filename(); 8098e31778eSAsmitha Karunanithi 8108e31778eSAsmitha Karunanithi std::string dumpEntryPath = getDumpEntryPath(dumpPath); 8118e31778eSAsmitha Karunanithi 8128e31778eSAsmitha Karunanithi if (dumpEntryPath.empty()) 8138e31778eSAsmitha Karunanithi { 81462598e31SEd Tanous BMCWEB_LOG_ERROR("Invalid dump type received"); 8158e31778eSAsmitha Karunanithi messages::internalError(asyncResp->res); 8168e31778eSAsmitha Karunanithi return; 8178e31778eSAsmitha Karunanithi } 8188e31778eSAsmitha Karunanithi 819177612aaSEd Tanous dbus::utility::async_method_call( 820177612aaSEd Tanous asyncResp, 8218cb2c024SEd Tanous [asyncResp, payload = std::move(payload), createdObjPath, 8228e31778eSAsmitha Karunanithi dumpEntryPath{std::move(dumpEntryPath)}, 8235e7e2dc5SEd Tanous dumpId](const boost::system::error_code& ec, 8248e31778eSAsmitha Karunanithi const std::string& introspectXml) { 8258e31778eSAsmitha Karunanithi if (ec) 8268e31778eSAsmitha Karunanithi { 82762598e31SEd Tanous BMCWEB_LOG_ERROR("Introspect call failed with error: {}", 82862598e31SEd Tanous ec.message()); 8298e31778eSAsmitha Karunanithi messages::internalError(asyncResp->res); 8308e31778eSAsmitha Karunanithi return; 8318e31778eSAsmitha Karunanithi } 8328e31778eSAsmitha Karunanithi 8338e31778eSAsmitha Karunanithi // Check if the created dump object has implemented Progress 8348e31778eSAsmitha Karunanithi // interface to track dump completion. If yes, fetch the "Status" 8358e31778eSAsmitha Karunanithi // property of the interface, modify the task state accordingly. 8368e31778eSAsmitha Karunanithi // Else, return task completed. 8378e31778eSAsmitha Karunanithi tinyxml2::XMLDocument doc; 8388e31778eSAsmitha Karunanithi 8398e31778eSAsmitha Karunanithi doc.Parse(introspectXml.data(), introspectXml.size()); 8408e31778eSAsmitha Karunanithi tinyxml2::XMLNode* pRoot = doc.FirstChildElement("node"); 8418e31778eSAsmitha Karunanithi if (pRoot == nullptr) 8428e31778eSAsmitha Karunanithi { 84362598e31SEd Tanous BMCWEB_LOG_ERROR("XML document failed to parse"); 8448e31778eSAsmitha Karunanithi messages::internalError(asyncResp->res); 8458e31778eSAsmitha Karunanithi return; 8468e31778eSAsmitha Karunanithi } 8478e31778eSAsmitha Karunanithi tinyxml2::XMLElement* interfaceNode = 8488e31778eSAsmitha Karunanithi pRoot->FirstChildElement("interface"); 8498e31778eSAsmitha Karunanithi 8508e31778eSAsmitha Karunanithi bool isProgressIntfPresent = false; 8518e31778eSAsmitha Karunanithi while (interfaceNode != nullptr) 8528e31778eSAsmitha Karunanithi { 853bd79bce8SPatrick Williams const char* thisInterfaceName = 854bd79bce8SPatrick Williams interfaceNode->Attribute("name"); 8558e31778eSAsmitha Karunanithi if (thisInterfaceName != nullptr) 8568e31778eSAsmitha Karunanithi { 8578e31778eSAsmitha Karunanithi if (thisInterfaceName == 8588e31778eSAsmitha Karunanithi std::string_view("xyz.openbmc_project.Common.Progress")) 8598e31778eSAsmitha Karunanithi { 8608e31778eSAsmitha Karunanithi interfaceNode = 8618e31778eSAsmitha Karunanithi interfaceNode->NextSiblingElement("interface"); 8628e31778eSAsmitha Karunanithi continue; 8638e31778eSAsmitha Karunanithi } 8648e31778eSAsmitha Karunanithi isProgressIntfPresent = true; 8658e31778eSAsmitha Karunanithi break; 8668e31778eSAsmitha Karunanithi } 8678e31778eSAsmitha Karunanithi interfaceNode = interfaceNode->NextSiblingElement("interface"); 8688e31778eSAsmitha Karunanithi } 8698e31778eSAsmitha Karunanithi 870a43be80fSAsmitha Karunanithi std::shared_ptr<task::TaskData> task = task::TaskData::createTask( 8718e31778eSAsmitha Karunanithi [createdObjPath, dumpEntryPath, dumpId, isProgressIntfPresent]( 872bd79bce8SPatrick Williams const boost::system::error_code& ec2, 873bd79bce8SPatrick Williams sdbusplus::message_t& msg, 874a43be80fSAsmitha Karunanithi const std::shared_ptr<task::TaskData>& taskData) { 8758b24275dSEd Tanous if (ec2) 876cb13a392SEd Tanous { 87762598e31SEd Tanous BMCWEB_LOG_ERROR("{}: Error in creating dump", 87862598e31SEd Tanous createdObjPath.str); 879bd79bce8SPatrick Williams taskData->messages.emplace_back( 880bd79bce8SPatrick Williams messages::internalError()); 8816145ed6fSAsmitha Karunanithi taskData->state = "Cancelled"; 8826145ed6fSAsmitha Karunanithi return task::completed; 883cb13a392SEd Tanous } 884b9d36b47SEd Tanous 8858e31778eSAsmitha Karunanithi if (isProgressIntfPresent) 886a43be80fSAsmitha Karunanithi { 8878e31778eSAsmitha Karunanithi dbus::utility::DBusPropertiesMap values; 8888e31778eSAsmitha Karunanithi std::string prop; 8898e31778eSAsmitha Karunanithi msg.read(prop, values); 8908e31778eSAsmitha Karunanithi 8918e31778eSAsmitha Karunanithi DumpCreationProgress dumpStatus = 8928e31778eSAsmitha Karunanithi getDumpCompletionStatus(values); 893bd79bce8SPatrick Williams if (dumpStatus == 894bd79bce8SPatrick Williams DumpCreationProgress::DUMP_CREATE_FAILED) 8958e31778eSAsmitha Karunanithi { 89662598e31SEd Tanous BMCWEB_LOG_ERROR("{}: Error in creating dump", 89762598e31SEd Tanous createdObjPath.str); 8988e31778eSAsmitha Karunanithi taskData->state = "Cancelled"; 8998e31778eSAsmitha Karunanithi return task::completed; 9008e31778eSAsmitha Karunanithi } 9018e31778eSAsmitha Karunanithi 902bd79bce8SPatrick Williams if (dumpStatus == 903bd79bce8SPatrick Williams DumpCreationProgress::DUMP_CREATE_INPROGRESS) 9048e31778eSAsmitha Karunanithi { 905bd79bce8SPatrick Williams BMCWEB_LOG_DEBUG( 906bd79bce8SPatrick Williams "{}: Dump creation task is in progress", 90762598e31SEd Tanous createdObjPath.str); 9088e31778eSAsmitha Karunanithi return !task::completed; 9098e31778eSAsmitha Karunanithi } 9108e31778eSAsmitha Karunanithi } 9118e31778eSAsmitha Karunanithi 912a43be80fSAsmitha Karunanithi nlohmann::json retMessage = messages::success(); 913a43be80fSAsmitha Karunanithi taskData->messages.emplace_back(retMessage); 914a43be80fSAsmitha Karunanithi 915c51a58eeSEd Tanous boost::urls::url url = boost::urls::format( 916253f11b8SEd Tanous "/redfish/v1/Managers/{}/LogServices/Dump/Entries/{}", 917253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME, dumpId); 918c51a58eeSEd Tanous 919c51a58eeSEd Tanous std::string headerLoc = "Location: "; 920c51a58eeSEd Tanous headerLoc += url.buffer(); 921c51a58eeSEd Tanous 922bd79bce8SPatrick Williams taskData->payload->httpHeaders.emplace_back( 923bd79bce8SPatrick Williams std::move(headerLoc)); 924a43be80fSAsmitha Karunanithi 92562598e31SEd Tanous BMCWEB_LOG_DEBUG("{}: Dump creation task completed", 92662598e31SEd Tanous createdObjPath.str); 927a43be80fSAsmitha Karunanithi taskData->state = "Completed"; 928b47452b2SAsmitha Karunanithi return task::completed; 929a43be80fSAsmitha Karunanithi }, 9308e31778eSAsmitha Karunanithi "type='signal',interface='org.freedesktop.DBus.Properties'," 9318e31778eSAsmitha Karunanithi "member='PropertiesChanged',path='" + 9328e31778eSAsmitha Karunanithi createdObjPath.str + "'"); 933a43be80fSAsmitha Karunanithi 9348e31778eSAsmitha Karunanithi // The task timer is set to max time limit within which the 9358e31778eSAsmitha Karunanithi // requested dump will be collected. 9368e31778eSAsmitha Karunanithi task->startTimer(std::chrono::minutes(6)); 9378e31778eSAsmitha Karunanithi task->payload.emplace(payload); 938*29e2bdd7SChinmay Shripad Hegde task->populateResp(asyncResp->res); 9398e31778eSAsmitha Karunanithi }, 9408e31778eSAsmitha Karunanithi "xyz.openbmc_project.Dump.Manager", createdObjPath, 9418e31778eSAsmitha Karunanithi "org.freedesktop.DBus.Introspectable", "Introspect"); 942a43be80fSAsmitha Karunanithi } 943a43be80fSAsmitha Karunanithi 9448d1b46d7Szhanghch05 inline void createDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 9458d1b46d7Szhanghch05 const crow::Request& req, const std::string& dumpType) 946a43be80fSAsmitha Karunanithi { 947fdd26906SClaire Weinan std::string dumpPath = getDumpEntriesPath(dumpType); 948fdd26906SClaire Weinan if (dumpPath.empty()) 949a43be80fSAsmitha Karunanithi { 950a43be80fSAsmitha Karunanithi messages::internalError(asyncResp->res); 951a43be80fSAsmitha Karunanithi return; 952a43be80fSAsmitha Karunanithi } 953a43be80fSAsmitha Karunanithi 954a43be80fSAsmitha Karunanithi std::optional<std::string> diagnosticDataType; 955a43be80fSAsmitha Karunanithi std::optional<std::string> oemDiagnosticDataType; 956a43be80fSAsmitha Karunanithi 957afc474aeSMyung Bae if (!redfish::json_util::readJsonAction( // 958afc474aeSMyung Bae req, asyncResp->res, // 959afc474aeSMyung Bae "DiagnosticDataType", diagnosticDataType, // 960afc474aeSMyung Bae "OEMDiagnosticDataType", oemDiagnosticDataType // 961afc474aeSMyung Bae )) 962a43be80fSAsmitha Karunanithi { 963a43be80fSAsmitha Karunanithi return; 964a43be80fSAsmitha Karunanithi } 965a43be80fSAsmitha Karunanithi 966a43be80fSAsmitha Karunanithi if (dumpType == "System") 967a43be80fSAsmitha Karunanithi { 968a43be80fSAsmitha Karunanithi if (!oemDiagnosticDataType || !diagnosticDataType) 969a43be80fSAsmitha Karunanithi { 97062598e31SEd Tanous BMCWEB_LOG_ERROR( 97162598e31SEd Tanous "CreateDump action parameter 'DiagnosticDataType'/'OEMDiagnosticDataType' value not found!"); 972a43be80fSAsmitha Karunanithi messages::actionParameterMissing( 973a43be80fSAsmitha Karunanithi asyncResp->res, "CollectDiagnosticData", 974a43be80fSAsmitha Karunanithi "DiagnosticDataType & OEMDiagnosticDataType"); 975a43be80fSAsmitha Karunanithi return; 976a43be80fSAsmitha Karunanithi } 9773174e4dfSEd Tanous if ((*oemDiagnosticDataType != "System") || 978a43be80fSAsmitha Karunanithi (*diagnosticDataType != "OEM")) 979a43be80fSAsmitha Karunanithi { 98062598e31SEd Tanous BMCWEB_LOG_ERROR("Wrong parameter values passed"); 981ace85d60SEd Tanous messages::internalError(asyncResp->res); 982a43be80fSAsmitha Karunanithi return; 983a43be80fSAsmitha Karunanithi } 984253f11b8SEd Tanous dumpPath = std::format("/redfish/v1/Systems/{}/LogServices/Dump/", 985253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 986a43be80fSAsmitha Karunanithi } 987a43be80fSAsmitha Karunanithi else if (dumpType == "BMC") 988a43be80fSAsmitha Karunanithi { 989a43be80fSAsmitha Karunanithi if (!diagnosticDataType) 990a43be80fSAsmitha Karunanithi { 99162598e31SEd Tanous BMCWEB_LOG_ERROR( 99262598e31SEd Tanous "CreateDump action parameter 'DiagnosticDataType' not found!"); 993a43be80fSAsmitha Karunanithi messages::actionParameterMissing( 994a43be80fSAsmitha Karunanithi asyncResp->res, "CollectDiagnosticData", "DiagnosticDataType"); 995a43be80fSAsmitha Karunanithi return; 996a43be80fSAsmitha Karunanithi } 9973174e4dfSEd Tanous if (*diagnosticDataType != "Manager") 998a43be80fSAsmitha Karunanithi { 99962598e31SEd Tanous BMCWEB_LOG_ERROR( 100062598e31SEd Tanous "Wrong parameter value passed for 'DiagnosticDataType'"); 1001ace85d60SEd Tanous messages::internalError(asyncResp->res); 1002a43be80fSAsmitha Karunanithi return; 1003a43be80fSAsmitha Karunanithi } 1004253f11b8SEd Tanous dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/Dump/", 1005253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 10065907571dSAsmitha Karunanithi } 10075907571dSAsmitha Karunanithi else 10085907571dSAsmitha Karunanithi { 100962598e31SEd Tanous BMCWEB_LOG_ERROR("CreateDump failed. Unknown dump type"); 10105907571dSAsmitha Karunanithi messages::internalError(asyncResp->res); 10115907571dSAsmitha Karunanithi return; 1012a43be80fSAsmitha Karunanithi } 1013a43be80fSAsmitha Karunanithi 10148e31778eSAsmitha Karunanithi std::vector<std::pair<std::string, std::variant<std::string, uint64_t>>> 10158e31778eSAsmitha Karunanithi createDumpParamVec; 10168e31778eSAsmitha Karunanithi 1017f574a8e1SCarson Labrado if (req.session != nullptr) 1018f574a8e1SCarson Labrado { 101968dd075aSAsmitha Karunanithi createDumpParamVec.emplace_back( 102068dd075aSAsmitha Karunanithi "xyz.openbmc_project.Dump.Create.CreateParameters.OriginatorId", 102168dd075aSAsmitha Karunanithi req.session->clientIp); 102268dd075aSAsmitha Karunanithi createDumpParamVec.emplace_back( 102368dd075aSAsmitha Karunanithi "xyz.openbmc_project.Dump.Create.CreateParameters.OriginatorType", 102468dd075aSAsmitha Karunanithi "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Client"); 1025f574a8e1SCarson Labrado } 102668dd075aSAsmitha Karunanithi 1027177612aaSEd Tanous dbus::utility::async_method_call( 1028177612aaSEd Tanous asyncResp, 10295e7e2dc5SEd Tanous [asyncResp, payload(task::Payload(req)), 10305e7e2dc5SEd Tanous dumpPath](const boost::system::error_code& ec, 10315e7e2dc5SEd Tanous const sdbusplus::message_t& msg, 10328e31778eSAsmitha Karunanithi const sdbusplus::message::object_path& objPath) mutable { 1033a43be80fSAsmitha Karunanithi if (ec) 1034a43be80fSAsmitha Karunanithi { 103562598e31SEd Tanous BMCWEB_LOG_ERROR("CreateDump resp_handler got error {}", ec); 10365907571dSAsmitha Karunanithi const sd_bus_error* dbusError = msg.get_error(); 10375907571dSAsmitha Karunanithi if (dbusError == nullptr) 10385907571dSAsmitha Karunanithi { 10395907571dSAsmitha Karunanithi messages::internalError(asyncResp->res); 10405907571dSAsmitha Karunanithi return; 10415907571dSAsmitha Karunanithi } 10425907571dSAsmitha Karunanithi 104362598e31SEd Tanous BMCWEB_LOG_ERROR("CreateDump DBus error: {} and error msg: {}", 104462598e31SEd Tanous dbusError->name, dbusError->message); 10455907571dSAsmitha Karunanithi if (std::string_view( 10465907571dSAsmitha Karunanithi "xyz.openbmc_project.Common.Error.NotAllowed") == 10475907571dSAsmitha Karunanithi dbusError->name) 10485907571dSAsmitha Karunanithi { 10495907571dSAsmitha Karunanithi messages::resourceInStandby(asyncResp->res); 10505907571dSAsmitha Karunanithi return; 10515907571dSAsmitha Karunanithi } 10525907571dSAsmitha Karunanithi if (std::string_view( 10535907571dSAsmitha Karunanithi "xyz.openbmc_project.Dump.Create.Error.Disabled") == 10545907571dSAsmitha Karunanithi dbusError->name) 10555907571dSAsmitha Karunanithi { 10565907571dSAsmitha Karunanithi messages::serviceDisabled(asyncResp->res, dumpPath); 10575907571dSAsmitha Karunanithi return; 10585907571dSAsmitha Karunanithi } 10595907571dSAsmitha Karunanithi if (std::string_view( 10605907571dSAsmitha Karunanithi "xyz.openbmc_project.Common.Error.Unavailable") == 10615907571dSAsmitha Karunanithi dbusError->name) 10625907571dSAsmitha Karunanithi { 10635907571dSAsmitha Karunanithi messages::resourceInUse(asyncResp->res); 10645907571dSAsmitha Karunanithi return; 10655907571dSAsmitha Karunanithi } 10665907571dSAsmitha Karunanithi // Other Dbus errors such as: 10675907571dSAsmitha Karunanithi // xyz.openbmc_project.Common.Error.InvalidArgument & 10685907571dSAsmitha Karunanithi // org.freedesktop.DBus.Error.InvalidArgs are all related to 10695907571dSAsmitha Karunanithi // the dbus call that is made here in the bmcweb 10705907571dSAsmitha Karunanithi // implementation and has nothing to do with the client's 10715907571dSAsmitha Karunanithi // input in the request. Hence, returning internal error 10725907571dSAsmitha Karunanithi // back to the client. 1073a43be80fSAsmitha Karunanithi messages::internalError(asyncResp->res); 1074a43be80fSAsmitha Karunanithi return; 1075a43be80fSAsmitha Karunanithi } 107662598e31SEd Tanous BMCWEB_LOG_DEBUG("Dump Created. Path: {}", objPath.str); 10778e31778eSAsmitha Karunanithi createDumpTaskCallback(std::move(payload), asyncResp, objPath); 1078a43be80fSAsmitha Karunanithi }, 107918f8f608SEd Tanous "xyz.openbmc_project.Dump.Manager", getDumpPath(dumpType), 10808e31778eSAsmitha Karunanithi "xyz.openbmc_project.Dump.Create", "CreateDump", createDumpParamVec); 1081a43be80fSAsmitha Karunanithi } 1082a43be80fSAsmitha Karunanithi 10838d1b46d7Szhanghch05 inline void clearDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 10848d1b46d7Szhanghch05 const std::string& dumpType) 108580319af1SAsmitha Karunanithi { 1086177612aaSEd Tanous dbus::utility::async_method_call( 1087177612aaSEd Tanous asyncResp, 10880d946211SClaire Weinan [asyncResp](const boost::system::error_code& ec) { 108980319af1SAsmitha Karunanithi if (ec) 109080319af1SAsmitha Karunanithi { 109162598e31SEd Tanous BMCWEB_LOG_ERROR("clearDump resp_handler got error {}", ec); 109280319af1SAsmitha Karunanithi messages::internalError(asyncResp->res); 109380319af1SAsmitha Karunanithi return; 109480319af1SAsmitha Karunanithi } 1095e2460466SAmy Chang messages::success(asyncResp->res); 10960d946211SClaire Weinan }, 109718f8f608SEd Tanous "xyz.openbmc_project.Dump.Manager", getDumpPath(dumpType), 10980d946211SClaire Weinan "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll"); 109980319af1SAsmitha Karunanithi } 110080319af1SAsmitha Karunanithi 1101bd79bce8SPatrick Williams inline void parseCrashdumpParameters( 1102bd79bce8SPatrick Williams const dbus::utility::DBusPropertiesMap& params, std::string& filename, 1103bd79bce8SPatrick Williams std::string& timestamp, std::string& logfile) 1104043a0536SJohnathan Mantey { 1105d1bde9e5SKrzysztof Grobelny const std::string* filenamePtr = nullptr; 1106d1bde9e5SKrzysztof Grobelny const std::string* timestampPtr = nullptr; 1107d1bde9e5SKrzysztof Grobelny const std::string* logfilePtr = nullptr; 1108d1bde9e5SKrzysztof Grobelny 1109d1bde9e5SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 1110d1bde9e5SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), params, "Timestamp", timestampPtr, 1111d1bde9e5SKrzysztof Grobelny "Filename", filenamePtr, "Log", logfilePtr); 1112d1bde9e5SKrzysztof Grobelny 1113d1bde9e5SKrzysztof Grobelny if (!success) 1114043a0536SJohnathan Mantey { 1115d1bde9e5SKrzysztof Grobelny return; 1116043a0536SJohnathan Mantey } 1117d1bde9e5SKrzysztof Grobelny 1118d1bde9e5SKrzysztof Grobelny if (filenamePtr != nullptr) 1119043a0536SJohnathan Mantey { 1120d1bde9e5SKrzysztof Grobelny filename = *filenamePtr; 1121d1bde9e5SKrzysztof Grobelny } 1122d1bde9e5SKrzysztof Grobelny 1123d1bde9e5SKrzysztof Grobelny if (timestampPtr != nullptr) 1124043a0536SJohnathan Mantey { 1125d1bde9e5SKrzysztof Grobelny timestamp = *timestampPtr; 1126043a0536SJohnathan Mantey } 1127d1bde9e5SKrzysztof Grobelny 1128d1bde9e5SKrzysztof Grobelny if (logfilePtr != nullptr) 1129043a0536SJohnathan Mantey { 1130d1bde9e5SKrzysztof Grobelny logfile = *logfilePtr; 1131043a0536SJohnathan Mantey } 1132043a0536SJohnathan Mantey } 1133043a0536SJohnathan Mantey 11347e860f15SJohn Edward Broadbent inline void requestRoutesSystemLogServiceCollection(App& app) 11351da66f75SEd Tanous { 1136c4bf6374SJason M. Bills /** 1137c4bf6374SJason M. Bills * Functions triggers appropriate requests on DBus 1138c4bf6374SJason M. Bills */ 113922d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/") 1140ed398213SEd Tanous .privileges(redfish::privileges::getLogServiceCollection) 1141bd79bce8SPatrick Williams .methods( 1142bd79bce8SPatrick Williams boost::beast::http::verb:: 1143bd79bce8SPatrick Williams get)([&app](const crow::Request& req, 114422d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 114522d268cbSEd Tanous const std::string& systemName) { 11463ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 1147c4bf6374SJason M. Bills { 114845ca1b86SEd Tanous return; 114945ca1b86SEd Tanous } 115025b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 11517f3e84a1SEd Tanous { 11527f3e84a1SEd Tanous // Option currently returns no systems. TBD 11537f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 11547f3e84a1SEd Tanous systemName); 11557f3e84a1SEd Tanous return; 11567f3e84a1SEd Tanous } 1157253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 115822d268cbSEd Tanous { 115922d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 116022d268cbSEd Tanous systemName); 116122d268cbSEd Tanous return; 116222d268cbSEd Tanous } 116322d268cbSEd Tanous 11647e860f15SJohn Edward Broadbent // Collections don't include the static data added by SubRoute 11657e860f15SJohn Edward Broadbent // because it has a duplicate entry for members 1166c4bf6374SJason M. Bills asyncResp->res.jsonValue["@odata.type"] = 1167c4bf6374SJason M. Bills "#LogServiceCollection.LogServiceCollection"; 1168c4bf6374SJason M. Bills asyncResp->res.jsonValue["@odata.id"] = 1169253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices", 1170253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 117145ca1b86SEd Tanous asyncResp->res.jsonValue["Name"] = "System Log Services Collection"; 1172c4bf6374SJason M. Bills asyncResp->res.jsonValue["Description"] = 1173c4bf6374SJason M. Bills "Collection of LogServices for this Computer System"; 1174bd79bce8SPatrick Williams nlohmann::json& logServiceArray = 1175bd79bce8SPatrick Williams asyncResp->res.jsonValue["Members"]; 1176c4bf6374SJason M. Bills logServiceArray = nlohmann::json::array(); 11771476687dSEd Tanous nlohmann::json::object_t eventLog; 11781476687dSEd Tanous eventLog["@odata.id"] = 1179253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/EventLog", 1180253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1181b2ba3072SPatrick Williams logServiceArray.emplace_back(std::move(eventLog)); 118225b54dbaSEd Tanous if constexpr (BMCWEB_REDFISH_DUMP_LOG) 118325b54dbaSEd Tanous { 11841476687dSEd Tanous nlohmann::json::object_t dumpLog; 118525b54dbaSEd Tanous dumpLog["@odata.id"] = 1186253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/Dump", 1187253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1188b2ba3072SPatrick Williams logServiceArray.emplace_back(std::move(dumpLog)); 118925b54dbaSEd Tanous } 1190c9bb6861Sraviteja-b 11915ffd11f2SGunnar Mills if constexpr (BMCWEB_REDFISH_CPU_LOG) 119225b54dbaSEd Tanous { 11931476687dSEd Tanous nlohmann::json::object_t crashdump; 11941476687dSEd Tanous crashdump["@odata.id"] = 1195253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/Crashdump", 1196253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1197b2ba3072SPatrick Williams logServiceArray.emplace_back(std::move(crashdump)); 119825b54dbaSEd Tanous } 1199b7028ebfSSpencer Ku 120025b54dbaSEd Tanous if constexpr (BMCWEB_REDFISH_HOST_LOGGER) 120125b54dbaSEd Tanous { 12021476687dSEd Tanous nlohmann::json::object_t hostlogger; 12031476687dSEd Tanous hostlogger["@odata.id"] = 1204253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/HostLogger", 1205253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1206b2ba3072SPatrick Williams logServiceArray.emplace_back(std::move(hostlogger)); 120725b54dbaSEd Tanous } 1208c4bf6374SJason M. Bills asyncResp->res.jsonValue["Members@odata.count"] = 1209c4bf6374SJason M. Bills logServiceArray.size(); 1210a3316fc6SZhikuiRen 12117a1dbc48SGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 12127a1dbc48SGeorge Liu "xyz.openbmc_project.State.Boot.PostCode"}; 12137a1dbc48SGeorge Liu dbus::utility::getSubTreePaths( 12147a1dbc48SGeorge Liu "/", 0, interfaces, 12157a1dbc48SGeorge Liu [asyncResp](const boost::system::error_code& ec, 1216b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreePathsResponse& 1217b9d36b47SEd Tanous subtreePath) { 1218a3316fc6SZhikuiRen if (ec) 1219a3316fc6SZhikuiRen { 122062598e31SEd Tanous BMCWEB_LOG_ERROR("{}", ec); 1221a3316fc6SZhikuiRen return; 1222a3316fc6SZhikuiRen } 1223a3316fc6SZhikuiRen 122455f79e6fSEd Tanous for (const auto& pathStr : subtreePath) 1225a3316fc6SZhikuiRen { 1226a3316fc6SZhikuiRen if (pathStr.find("PostCode") != std::string::npos) 1227a3316fc6SZhikuiRen { 122823a21a1cSEd Tanous nlohmann::json& logServiceArrayLocal = 1229a3316fc6SZhikuiRen asyncResp->res.jsonValue["Members"]; 1230613dabeaSEd Tanous nlohmann::json::object_t member; 1231253f11b8SEd Tanous member["@odata.id"] = std::format( 1232253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/PostCodes", 1233253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1234613dabeaSEd Tanous 1235bd79bce8SPatrick Williams logServiceArrayLocal.emplace_back( 1236bd79bce8SPatrick Williams std::move(member)); 1237613dabeaSEd Tanous 123845ca1b86SEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = 123923a21a1cSEd Tanous logServiceArrayLocal.size(); 1240a3316fc6SZhikuiRen return; 1241a3316fc6SZhikuiRen } 1242a3316fc6SZhikuiRen } 12437a1dbc48SGeorge Liu }); 12447e860f15SJohn Edward Broadbent }); 1245c4bf6374SJason M. Bills } 1246c4bf6374SJason M. Bills 12477e860f15SJohn Edward Broadbent inline void requestRoutesEventLogService(App& app) 1248c4bf6374SJason M. Bills { 124922d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/") 1250ed398213SEd Tanous .privileges(redfish::privileges::getLogService) 1251bd79bce8SPatrick Williams .methods( 1252bd79bce8SPatrick Williams boost::beast::http::verb:: 1253bd79bce8SPatrick Williams get)([&app](const crow::Request& req, 125422d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 125522d268cbSEd Tanous const std::string& systemName) { 12563ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 125745ca1b86SEd Tanous { 125845ca1b86SEd Tanous return; 125945ca1b86SEd Tanous } 1260253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 126122d268cbSEd Tanous { 126222d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 126322d268cbSEd Tanous systemName); 126422d268cbSEd Tanous return; 126522d268cbSEd Tanous } 1266c4bf6374SJason M. Bills asyncResp->res.jsonValue["@odata.id"] = 1267253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/EventLog", 1268253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1269c4bf6374SJason M. Bills asyncResp->res.jsonValue["@odata.type"] = 1270b25644a1SJanet Adkins "#LogService.v1_2_0.LogService"; 1271c4bf6374SJason M. Bills asyncResp->res.jsonValue["Name"] = "Event Log Service"; 1272bd79bce8SPatrick Williams asyncResp->res.jsonValue["Description"] = 1273bd79bce8SPatrick Williams "System Event Log Service"; 1274c4bf6374SJason M. Bills asyncResp->res.jsonValue["Id"] = "EventLog"; 1275539d8c6bSEd Tanous asyncResp->res.jsonValue["OverWritePolicy"] = 1276539d8c6bSEd Tanous log_service::OverWritePolicy::WrapsWhenFull; 12777c8c4058STejas Patil 12787c8c4058STejas Patil std::pair<std::string, std::string> redfishDateTimeOffset = 12792b82937eSEd Tanous redfish::time_utils::getDateTimeOffsetNow(); 12807c8c4058STejas Patil 12817c8c4058STejas Patil asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first; 12827c8c4058STejas Patil asyncResp->res.jsonValue["DateTimeLocalOffset"] = 12837c8c4058STejas Patil redfishDateTimeOffset.second; 12847c8c4058STejas Patil 1285bd79bce8SPatrick Williams asyncResp->res.jsonValue["Entries"]["@odata.id"] = std::format( 1286bd79bce8SPatrick Williams "/redfish/v1/Systems/{}/LogServices/EventLog/Entries", 1287253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1288bd79bce8SPatrick Williams asyncResp->res 1289bd79bce8SPatrick Williams .jsonValue["Actions"]["#LogService.ClearLog"]["target"] 1290e7d6c8b2SGunnar Mills 129120fa6a2cSEd Tanous = std::format( 1292253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/EventLog/Actions/LogService.ClearLog", 129320fa6a2cSEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 12947e860f15SJohn Edward Broadbent }); 1295489640c6SJason M. Bills } 1296489640c6SJason M. Bills 1297599b9af3SAlexander Hansen inline void handleSystemsLogServicesEventLogActionsClearPost( 1298599b9af3SAlexander Hansen App& app, const crow::Request& req, 129922d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1300599b9af3SAlexander Hansen const std::string& systemName) 1301599b9af3SAlexander Hansen { 13023ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 130345ca1b86SEd Tanous { 130445ca1b86SEd Tanous return; 130545ca1b86SEd Tanous } 1306253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 130722d268cbSEd Tanous { 130822d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 130922d268cbSEd Tanous systemName); 131022d268cbSEd Tanous return; 131122d268cbSEd Tanous } 1312599b9af3SAlexander Hansen 1313489640c6SJason M. Bills // Clear the EventLog by deleting the log files 1314489640c6SJason M. Bills std::vector<std::filesystem::path> redfishLogFiles; 1315489640c6SJason M. Bills if (getRedfishLogFiles(redfishLogFiles)) 1316489640c6SJason M. Bills { 1317489640c6SJason M. Bills for (const std::filesystem::path& file : redfishLogFiles) 1318489640c6SJason M. Bills { 1319489640c6SJason M. Bills std::error_code ec; 1320489640c6SJason M. Bills std::filesystem::remove(file, ec); 1321489640c6SJason M. Bills } 1322489640c6SJason M. Bills } 1323489640c6SJason M. Bills 1324489640c6SJason M. Bills // Reload rsyslog so it knows to start new log files 1325177612aaSEd Tanous dbus::utility::async_method_call( 1326177612aaSEd Tanous asyncResp, 13275e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 1328489640c6SJason M. Bills if (ec) 1329489640c6SJason M. Bills { 133062598e31SEd Tanous BMCWEB_LOG_ERROR("Failed to reload rsyslog: {}", ec); 1331489640c6SJason M. Bills messages::internalError(asyncResp->res); 1332489640c6SJason M. Bills return; 1333489640c6SJason M. Bills } 1334489640c6SJason M. Bills 1335489640c6SJason M. Bills messages::success(asyncResp->res); 1336489640c6SJason M. Bills }, 1337489640c6SJason M. Bills "org.freedesktop.systemd1", "/org/freedesktop/systemd1", 1338002d39b4SEd Tanous "org.freedesktop.systemd1.Manager", "ReloadUnit", "rsyslog.service", 1339002d39b4SEd Tanous "replace"); 1340599b9af3SAlexander Hansen } 1341599b9af3SAlexander Hansen 1342599b9af3SAlexander Hansen inline void requestRoutesJournalEventLogClear(App& app) 1343599b9af3SAlexander Hansen { 1344599b9af3SAlexander Hansen BMCWEB_ROUTE( 1345599b9af3SAlexander Hansen app, 1346599b9af3SAlexander Hansen "/redfish/v1/Systems/<str>/LogServices/EventLog/Actions/LogService.ClearLog/") 1347599b9af3SAlexander Hansen .privileges({{"ConfigureComponents"}}) 1348599b9af3SAlexander Hansen .methods(boost::beast::http::verb::post)(std::bind_front( 1349599b9af3SAlexander Hansen handleSystemsLogServicesEventLogActionsClearPost, std::ref(app))); 1350c4bf6374SJason M. Bills } 1351c4bf6374SJason M. Bills 1352ac992cdeSJason M. Bills enum class LogParseError 1353ac992cdeSJason M. Bills { 1354ac992cdeSJason M. Bills success, 1355ac992cdeSJason M. Bills parseFailed, 1356ac992cdeSJason M. Bills messageIdNotInRegistry, 1357ac992cdeSJason M. Bills }; 1358ac992cdeSJason M. Bills 1359bd79bce8SPatrick Williams static LogParseError fillEventLogEntryJson( 1360bd79bce8SPatrick Williams const std::string& logEntryID, const std::string& logEntry, 1361de703c5dSJason M. Bills nlohmann::json::object_t& logEntryJson) 1362c4bf6374SJason M. Bills { 136395820184SJason M. Bills // The redfish log format is "<Timestamp> <MessageId>,<MessageArgs>" 1364cd225da8SJason M. Bills // First get the Timestamp 1365f23b7296SEd Tanous size_t space = logEntry.find_first_of(' '); 1366cd225da8SJason M. Bills if (space == std::string::npos) 136795820184SJason M. Bills { 1368ac992cdeSJason M. Bills return LogParseError::parseFailed; 136995820184SJason M. Bills } 1370cd225da8SJason M. Bills std::string timestamp = logEntry.substr(0, space); 1371cd225da8SJason M. Bills // Then get the log contents 1372f23b7296SEd Tanous size_t entryStart = logEntry.find_first_not_of(' ', space); 1373cd225da8SJason M. Bills if (entryStart == std::string::npos) 1374cd225da8SJason M. Bills { 1375ac992cdeSJason M. Bills return LogParseError::parseFailed; 1376cd225da8SJason M. Bills } 1377cd225da8SJason M. Bills std::string_view entry(logEntry); 1378cd225da8SJason M. Bills entry.remove_prefix(entryStart); 1379cd225da8SJason M. Bills // Use split to separate the entry into its fields 1380cd225da8SJason M. Bills std::vector<std::string> logEntryFields; 138150ebd4afSEd Tanous bmcweb::split(logEntryFields, entry, ','); 1382cd225da8SJason M. Bills // We need at least a MessageId to be valid 13831e6deaf6SEd Tanous auto logEntryIter = logEntryFields.begin(); 13841e6deaf6SEd Tanous if (logEntryIter == logEntryFields.end()) 1385cd225da8SJason M. Bills { 1386ac992cdeSJason M. Bills return LogParseError::parseFailed; 1387cd225da8SJason M. Bills } 13881e6deaf6SEd Tanous std::string& messageID = *logEntryIter; 13894851d45dSJason M. Bills // Get the Message from the MessageRegistry 1390fffb8c1fSEd Tanous const registries::Message* message = registries::getMessage(messageID); 1391c4bf6374SJason M. Bills 13921e6deaf6SEd Tanous logEntryIter++; 139354417b02SSui Chen if (message == nullptr) 1394c4bf6374SJason M. Bills { 139562598e31SEd Tanous BMCWEB_LOG_WARNING("Log entry not found in registry: {}", logEntry); 1396ac992cdeSJason M. Bills return LogParseError::messageIdNotInRegistry; 1397c4bf6374SJason M. Bills } 1398c4bf6374SJason M. Bills 13991e6deaf6SEd Tanous std::vector<std::string_view> messageArgs(logEntryIter, 14001e6deaf6SEd Tanous logEntryFields.end()); 1401c05bba45SEd Tanous messageArgs.resize(message->numberOfArgs); 1402c05bba45SEd Tanous 1403bd79bce8SPatrick Williams std::string msg = 1404bd79bce8SPatrick Williams redfish::registries::fillMessageArgs(messageArgs, message->message); 14051e6deaf6SEd Tanous if (msg.empty()) 140615a86ff6SJason M. Bills { 14071e6deaf6SEd Tanous return LogParseError::parseFailed; 140815a86ff6SJason M. Bills } 14094851d45dSJason M. Bills 141095820184SJason M. Bills // Get the Created time from the timestamp. The log timestamp is in RFC3339 141195820184SJason M. Bills // format which matches the Redfish format except for the fractional seconds 141295820184SJason M. Bills // between the '.' and the '+', so just remove them. 1413f23b7296SEd Tanous std::size_t dot = timestamp.find_first_of('.'); 1414f23b7296SEd Tanous std::size_t plus = timestamp.find_first_of('+'); 141595820184SJason M. Bills if (dot != std::string::npos && plus != std::string::npos) 1416c4bf6374SJason M. Bills { 141795820184SJason M. Bills timestamp.erase(dot, plus - dot); 1418c4bf6374SJason M. Bills } 1419c4bf6374SJason M. Bills 1420c4bf6374SJason M. Bills // Fill in the log entry with the gathered data 14219c11a172SVijay Lobo logEntryJson["@odata.type"] = "#LogEntry.v1_9_0.LogEntry"; 1422ef4c65b7SEd Tanous logEntryJson["@odata.id"] = boost::urls::format( 1423253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}", 1424253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, logEntryID); 142584afc48bSJason M. Bills logEntryJson["Name"] = "System Event Log Entry"; 142684afc48bSJason M. Bills logEntryJson["Id"] = logEntryID; 142784afc48bSJason M. Bills logEntryJson["Message"] = std::move(msg); 142884afc48bSJason M. Bills logEntryJson["MessageId"] = std::move(messageID); 142984afc48bSJason M. Bills logEntryJson["MessageArgs"] = messageArgs; 143084afc48bSJason M. Bills logEntryJson["EntryType"] = "Event"; 143184afc48bSJason M. Bills logEntryJson["Severity"] = message->messageSeverity; 143284afc48bSJason M. Bills logEntryJson["Created"] = std::move(timestamp); 1433ac992cdeSJason M. Bills return LogParseError::success; 1434c4bf6374SJason M. Bills } 1435c4bf6374SJason M. Bills 14367f3726a2SMyung Bae inline void fillEventLogLogEntryFromDbusLogEntry( 14377f3726a2SMyung Bae const DbusEventLogEntry& entry, nlohmann::json& objectToFillOut) 1438898f2aa2SEd Tanous { 1439898f2aa2SEd Tanous objectToFillOut["@odata.type"] = "#LogEntry.v1_9_0.LogEntry"; 1440898f2aa2SEd Tanous objectToFillOut["@odata.id"] = boost::urls::format( 1441898f2aa2SEd Tanous "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}", 1442262dcc1cSAlexander Hansen BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(entry.Id)); 1443898f2aa2SEd Tanous objectToFillOut["Name"] = "System Event Log Entry"; 1444262dcc1cSAlexander Hansen objectToFillOut["Id"] = std::to_string(entry.Id); 1445262dcc1cSAlexander Hansen objectToFillOut["Message"] = entry.Message; 1446262dcc1cSAlexander Hansen objectToFillOut["Resolved"] = entry.Resolved; 1447262dcc1cSAlexander Hansen std::optional<bool> notifyAction = 1448262dcc1cSAlexander Hansen getProviderNotifyAction(entry.ServiceProviderNotify); 1449898f2aa2SEd Tanous if (notifyAction) 1450898f2aa2SEd Tanous { 1451898f2aa2SEd Tanous objectToFillOut["ServiceProviderNotified"] = *notifyAction; 1452898f2aa2SEd Tanous } 1453262dcc1cSAlexander Hansen if ((entry.Resolution != nullptr) && !entry.Resolution->empty()) 1454898f2aa2SEd Tanous { 1455262dcc1cSAlexander Hansen objectToFillOut["Resolution"] = *entry.Resolution; 1456898f2aa2SEd Tanous } 1457898f2aa2SEd Tanous objectToFillOut["EntryType"] = "Event"; 1458262dcc1cSAlexander Hansen objectToFillOut["Severity"] = 1459262dcc1cSAlexander Hansen translateSeverityDbusToRedfish(entry.Severity); 1460898f2aa2SEd Tanous objectToFillOut["Created"] = 1461262dcc1cSAlexander Hansen redfish::time_utils::getDateTimeUintMs(entry.Timestamp); 1462898f2aa2SEd Tanous objectToFillOut["Modified"] = 1463262dcc1cSAlexander Hansen redfish::time_utils::getDateTimeUintMs(entry.UpdateTimestamp); 1464262dcc1cSAlexander Hansen if (entry.Path != nullptr) 1465898f2aa2SEd Tanous { 1466898f2aa2SEd Tanous objectToFillOut["AdditionalDataURI"] = boost::urls::format( 1467898f2aa2SEd Tanous "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}/attachment", 1468262dcc1cSAlexander Hansen BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(entry.Id)); 1469898f2aa2SEd Tanous } 1470898f2aa2SEd Tanous } 1471898f2aa2SEd Tanous 1472b729096dSEd Tanous inline void afterLogEntriesGetManagedObjects( 1473b729096dSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1474b729096dSEd Tanous const boost::system::error_code& ec, 1475b729096dSEd Tanous const dbus::utility::ManagedObjectType& resp) 1476b729096dSEd Tanous { 1477b729096dSEd Tanous if (ec) 1478b729096dSEd Tanous { 1479b729096dSEd Tanous // TODO Handle for specific error code 1480b729096dSEd Tanous BMCWEB_LOG_ERROR("getLogEntriesIfaceData resp_handler got error {}", 1481b729096dSEd Tanous ec); 1482b729096dSEd Tanous messages::internalError(asyncResp->res); 1483b729096dSEd Tanous return; 1484b729096dSEd Tanous } 1485b729096dSEd Tanous nlohmann::json::array_t entriesArray; 1486b729096dSEd Tanous for (const auto& objectPath : resp) 1487b729096dSEd Tanous { 1488898f2aa2SEd Tanous dbus::utility::DBusPropertiesMap propsFlattened; 1489bd79bce8SPatrick Williams auto isEntry = 1490bd79bce8SPatrick Williams std::ranges::find_if(objectPath.second, [](const auto& object) { 1491898f2aa2SEd Tanous return object.first == "xyz.openbmc_project.Logging.Entry"; 1492898f2aa2SEd Tanous }); 1493898f2aa2SEd Tanous if (isEntry == objectPath.second.end()) 1494b729096dSEd Tanous { 1495b729096dSEd Tanous continue; 1496b729096dSEd Tanous } 14977f3726a2SMyung Bae 1498898f2aa2SEd Tanous for (const auto& interfaceMap : objectPath.second) 1499b729096dSEd Tanous { 1500898f2aa2SEd Tanous for (const auto& propertyMap : interfaceMap.second) 1501b729096dSEd Tanous { 1502898f2aa2SEd Tanous propsFlattened.emplace_back(propertyMap.first, 1503898f2aa2SEd Tanous propertyMap.second); 1504b729096dSEd Tanous } 1505b729096dSEd Tanous } 15067f3726a2SMyung Bae std::optional<DbusEventLogEntry> optEntry = 15077f3726a2SMyung Bae fillDbusEventLogEntryFromPropertyMap(propsFlattened); 15087f3726a2SMyung Bae 15097f3726a2SMyung Bae if (!optEntry.has_value()) 151090896601SIgor Kanyuka { 15117f3726a2SMyung Bae messages::internalError(asyncResp->res); 151290896601SIgor Kanyuka return; 151390896601SIgor Kanyuka } 15147f3726a2SMyung Bae fillEventLogLogEntryFromDbusLogEntry(*optEntry, 15157f3726a2SMyung Bae entriesArray.emplace_back()); 1516b729096dSEd Tanous } 1517898f2aa2SEd Tanous 151890896601SIgor Kanyuka redfish::json_util::sortJsonArrayByKey(entriesArray, "Id"); 1519b729096dSEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = entriesArray.size(); 1520b729096dSEd Tanous asyncResp->res.jsonValue["Members"] = std::move(entriesArray); 1521b729096dSEd Tanous } 1522b729096dSEd Tanous 1523599b9af3SAlexander Hansen inline void handleSystemsLogServiceEventLogLogEntryCollection( 1524599b9af3SAlexander Hansen App& app, const crow::Request& req, 152522d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1526599b9af3SAlexander Hansen const std::string& systemName) 1527599b9af3SAlexander Hansen { 1528c937d2bfSEd Tanous query_param::QueryCapabilities capabilities = { 1529c937d2bfSEd Tanous .canDelegateTop = true, 1530c937d2bfSEd Tanous .canDelegateSkip = true, 1531c937d2bfSEd Tanous }; 1532c937d2bfSEd Tanous query_param::Query delegatedQuery; 1533599b9af3SAlexander Hansen if (!redfish::setUpRedfishRouteWithDelegation(app, req, asyncResp, 1534599b9af3SAlexander Hansen delegatedQuery, capabilities)) 1535c4bf6374SJason M. Bills { 1536c4bf6374SJason M. Bills return; 1537c4bf6374SJason M. Bills } 153825b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 15397f3e84a1SEd Tanous { 15407f3e84a1SEd Tanous // Option currently returns no systems. TBD 15417f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 15427f3e84a1SEd Tanous systemName); 15437f3e84a1SEd Tanous return; 15447f3e84a1SEd Tanous } 1545253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 154622d268cbSEd Tanous { 154722d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 154822d268cbSEd Tanous systemName); 154922d268cbSEd Tanous return; 155022d268cbSEd Tanous } 155122d268cbSEd Tanous 15525143f7a5SJiaqing Zhao size_t top = delegatedQuery.top.value_or(query_param::Query::maxTop); 15533648c8beSEd Tanous size_t skip = delegatedQuery.skip.value_or(0); 15543648c8beSEd Tanous 15557e860f15SJohn Edward Broadbent // Collections don't include the static data added by SubRoute 15567e860f15SJohn Edward Broadbent // because it has a duplicate entry for members 1557c4bf6374SJason M. Bills asyncResp->res.jsonValue["@odata.type"] = 1558c4bf6374SJason M. Bills "#LogEntryCollection.LogEntryCollection"; 1559c4bf6374SJason M. Bills asyncResp->res.jsonValue["@odata.id"] = 1560253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries", 1561253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1562c4bf6374SJason M. Bills asyncResp->res.jsonValue["Name"] = "System Event Log Entries"; 1563c4bf6374SJason M. Bills asyncResp->res.jsonValue["Description"] = 1564c4bf6374SJason M. Bills "Collection of System Event Log Entries"; 1565cb92c03bSAndrew Geissler 15664978b63fSJason M. Bills nlohmann::json& logEntryArray = asyncResp->res.jsonValue["Members"]; 1567c4bf6374SJason M. Bills logEntryArray = nlohmann::json::array(); 15687e860f15SJohn Edward Broadbent // Go through the log files and create a unique ID for each 15697e860f15SJohn Edward Broadbent // entry 157095820184SJason M. Bills std::vector<std::filesystem::path> redfishLogFiles; 157195820184SJason M. Bills getRedfishLogFiles(redfishLogFiles); 1572b01bf299SEd Tanous uint64_t entryCount = 0; 1573cd225da8SJason M. Bills std::string logEntry; 157495820184SJason M. Bills 15757e860f15SJohn Edward Broadbent // Oldest logs are in the last file, so start there and loop 15767e860f15SJohn Edward Broadbent // backwards 1577599b9af3SAlexander Hansen for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend(); it++) 1578c4bf6374SJason M. Bills { 1579cd225da8SJason M. Bills std::ifstream logStream(*it); 158095820184SJason M. Bills if (!logStream.is_open()) 1581c4bf6374SJason M. Bills { 1582c4bf6374SJason M. Bills continue; 1583c4bf6374SJason M. Bills } 1584c4bf6374SJason M. Bills 1585e85d6b16SJason M. Bills // Reset the unique ID on the first entry 1586e85d6b16SJason M. Bills bool firstEntry = true; 158795820184SJason M. Bills while (std::getline(logStream, logEntry)) 158895820184SJason M. Bills { 1589c4bf6374SJason M. Bills std::string idStr; 1590e85d6b16SJason M. Bills if (!getUniqueEntryID(logEntry, idStr, firstEntry)) 1591c4bf6374SJason M. Bills { 1592c4bf6374SJason M. Bills continue; 1593c4bf6374SJason M. Bills } 1594e85d6b16SJason M. Bills firstEntry = false; 1595e85d6b16SJason M. Bills 1596de703c5dSJason M. Bills nlohmann::json::object_t bmcLogEntry; 1597bd79bce8SPatrick Williams LogParseError status = 1598bd79bce8SPatrick Williams fillEventLogEntryJson(idStr, logEntry, bmcLogEntry); 1599ac992cdeSJason M. Bills if (status == LogParseError::messageIdNotInRegistry) 1600ac992cdeSJason M. Bills { 1601ac992cdeSJason M. Bills continue; 1602ac992cdeSJason M. Bills } 1603ac992cdeSJason M. Bills if (status != LogParseError::success) 1604c4bf6374SJason M. Bills { 1605c4bf6374SJason M. Bills messages::internalError(asyncResp->res); 1606c4bf6374SJason M. Bills return; 1607c4bf6374SJason M. Bills } 1608de703c5dSJason M. Bills 1609de703c5dSJason M. Bills entryCount++; 1610de703c5dSJason M. Bills // Handle paging using skip (number of entries to skip from the 1611de703c5dSJason M. Bills // start) and top (number of entries to display) 16123648c8beSEd Tanous if (entryCount <= skip || entryCount > skip + top) 1613de703c5dSJason M. Bills { 1614de703c5dSJason M. Bills continue; 1615de703c5dSJason M. Bills } 1616de703c5dSJason M. Bills 1617b2ba3072SPatrick Williams logEntryArray.emplace_back(std::move(bmcLogEntry)); 1618c4bf6374SJason M. Bills } 161995820184SJason M. Bills } 1620c4bf6374SJason M. Bills asyncResp->res.jsonValue["Members@odata.count"] = entryCount; 16213648c8beSEd Tanous if (skip + top < entryCount) 1622c4bf6374SJason M. Bills { 1623599b9af3SAlexander Hansen asyncResp->res.jsonValue["Members@odata.nextLink"] = 1624599b9af3SAlexander Hansen boost::urls::format( 1625253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/EventLog/Entries?$skip={}", 1626253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(skip + top)); 1627c4bf6374SJason M. Bills } 1628897967deSJason M. Bills } 1629897967deSJason M. Bills 1630599b9af3SAlexander Hansen inline void requestRoutesJournalEventLogEntryCollection(App& app) 1631897967deSJason M. Bills { 1632599b9af3SAlexander Hansen BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/") 1633599b9af3SAlexander Hansen .privileges(redfish::privileges::getLogEntryCollection) 1634599b9af3SAlexander Hansen .methods(boost::beast::http::verb::get)(std::bind_front( 1635599b9af3SAlexander Hansen handleSystemsLogServiceEventLogLogEntryCollection, std::ref(app))); 1636599b9af3SAlexander Hansen } 1637599b9af3SAlexander Hansen 1638599b9af3SAlexander Hansen inline void handleSystemsLogServiceEventLogEntriesGet( 1639599b9af3SAlexander Hansen App& app, const crow::Request& req, 16407e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1641599b9af3SAlexander Hansen const std::string& systemName, const std::string& param) 1642599b9af3SAlexander Hansen { 16433ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 164445ca1b86SEd Tanous { 164545ca1b86SEd Tanous return; 164645ca1b86SEd Tanous } 164725b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 16487f3e84a1SEd Tanous { 16497f3e84a1SEd Tanous // Option currently returns no systems. TBD 16507f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 16517f3e84a1SEd Tanous systemName); 16527f3e84a1SEd Tanous return; 16537f3e84a1SEd Tanous } 165422d268cbSEd Tanous 1655253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 165622d268cbSEd Tanous { 165722d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 165822d268cbSEd Tanous systemName); 165922d268cbSEd Tanous return; 166022d268cbSEd Tanous } 166122d268cbSEd Tanous 16627e860f15SJohn Edward Broadbent const std::string& targetID = param; 16638d1b46d7Szhanghch05 16647e860f15SJohn Edward Broadbent // Go through the log files and check the unique ID for each 16657e860f15SJohn Edward Broadbent // entry to find the target entry 1666897967deSJason M. Bills std::vector<std::filesystem::path> redfishLogFiles; 1667897967deSJason M. Bills getRedfishLogFiles(redfishLogFiles); 1668897967deSJason M. Bills std::string logEntry; 1669897967deSJason M. Bills 16707e860f15SJohn Edward Broadbent // Oldest logs are in the last file, so start there and loop 16717e860f15SJohn Edward Broadbent // backwards 1672599b9af3SAlexander Hansen for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend(); it++) 1673897967deSJason M. Bills { 1674897967deSJason M. Bills std::ifstream logStream(*it); 1675897967deSJason M. Bills if (!logStream.is_open()) 1676897967deSJason M. Bills { 1677897967deSJason M. Bills continue; 1678897967deSJason M. Bills } 1679897967deSJason M. Bills 1680897967deSJason M. Bills // Reset the unique ID on the first entry 1681897967deSJason M. Bills bool firstEntry = true; 1682897967deSJason M. Bills while (std::getline(logStream, logEntry)) 1683897967deSJason M. Bills { 1684897967deSJason M. Bills std::string idStr; 1685897967deSJason M. Bills if (!getUniqueEntryID(logEntry, idStr, firstEntry)) 1686897967deSJason M. Bills { 1687897967deSJason M. Bills continue; 1688897967deSJason M. Bills } 1689897967deSJason M. Bills firstEntry = false; 1690897967deSJason M. Bills 1691897967deSJason M. Bills if (idStr == targetID) 1692897967deSJason M. Bills { 1693de703c5dSJason M. Bills nlohmann::json::object_t bmcLogEntry; 1694bd79bce8SPatrick Williams LogParseError status = 1695bd79bce8SPatrick Williams fillEventLogEntryJson(idStr, logEntry, bmcLogEntry); 1696ac992cdeSJason M. Bills if (status != LogParseError::success) 1697897967deSJason M. Bills { 1698897967deSJason M. Bills messages::internalError(asyncResp->res); 1699897967deSJason M. Bills return; 1700897967deSJason M. Bills } 1701d405bb51SJason M. Bills asyncResp->res.jsonValue.update(bmcLogEntry); 1702897967deSJason M. Bills return; 1703897967deSJason M. Bills } 1704897967deSJason M. Bills } 1705897967deSJason M. Bills } 1706897967deSJason M. Bills // Requested ID was not found 17079db4ba25SJiaqing Zhao messages::resourceNotFound(asyncResp->res, "LogEntry", targetID); 1708599b9af3SAlexander Hansen } 1709599b9af3SAlexander Hansen 1710599b9af3SAlexander Hansen inline void requestRoutesJournalEventLogEntry(App& app) 1711599b9af3SAlexander Hansen { 1712599b9af3SAlexander Hansen BMCWEB_ROUTE( 1713599b9af3SAlexander Hansen app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/") 1714599b9af3SAlexander Hansen .privileges(redfish::privileges::getLogEntry) 1715599b9af3SAlexander Hansen .methods(boost::beast::http::verb::get)(std::bind_front( 1716599b9af3SAlexander Hansen handleSystemsLogServiceEventLogEntriesGet, std::ref(app))); 1717599b9af3SAlexander Hansen } 1718599b9af3SAlexander Hansen 1719599b9af3SAlexander Hansen inline void dBusEventLogEntryCollection( 1720599b9af3SAlexander Hansen const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1721599b9af3SAlexander Hansen { 1722599b9af3SAlexander Hansen // Collections don't include the static data added by SubRoute 1723599b9af3SAlexander Hansen // because it has a duplicate entry for members 1724599b9af3SAlexander Hansen asyncResp->res.jsonValue["@odata.type"] = 1725599b9af3SAlexander Hansen "#LogEntryCollection.LogEntryCollection"; 1726599b9af3SAlexander Hansen asyncResp->res.jsonValue["@odata.id"] = 1727599b9af3SAlexander Hansen std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries", 1728599b9af3SAlexander Hansen BMCWEB_REDFISH_SYSTEM_URI_NAME); 1729599b9af3SAlexander Hansen asyncResp->res.jsonValue["Name"] = "System Event Log Entries"; 1730599b9af3SAlexander Hansen asyncResp->res.jsonValue["Description"] = 1731599b9af3SAlexander Hansen "Collection of System Event Log Entries"; 1732599b9af3SAlexander Hansen 1733599b9af3SAlexander Hansen // DBus implementation of EventLog/Entries 1734599b9af3SAlexander Hansen // Make call to Logging Service to find all log entry objects 1735599b9af3SAlexander Hansen sdbusplus::message::object_path path("/xyz/openbmc_project/logging"); 1736599b9af3SAlexander Hansen dbus::utility::getManagedObjects( 1737599b9af3SAlexander Hansen "xyz.openbmc_project.Logging", path, 1738599b9af3SAlexander Hansen [asyncResp](const boost::system::error_code& ec, 1739599b9af3SAlexander Hansen const dbus::utility::ManagedObjectType& resp) { 1740b729096dSEd Tanous afterLogEntriesGetManagedObjects(asyncResp, ec, resp); 17417e860f15SJohn Edward Broadbent }); 174208a4e4b5SAnthony Wilson } 174308a4e4b5SAnthony Wilson 17447e860f15SJohn Edward Broadbent inline void requestRoutesDBusEventLogEntryCollection(App& app) 174508a4e4b5SAnthony Wilson { 174622d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/") 1747ed398213SEd Tanous .privileges(redfish::privileges::getLogEntryCollection) 1748002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 1749002d39b4SEd Tanous [&app](const crow::Request& req, 175022d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 175122d268cbSEd Tanous const std::string& systemName) { 17523ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 175345ca1b86SEd Tanous { 175445ca1b86SEd Tanous return; 175545ca1b86SEd Tanous } 175625b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 17577f3e84a1SEd Tanous { 17587f3e84a1SEd Tanous // Option currently returns no systems. TBD 17597f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 17607f3e84a1SEd Tanous systemName); 17617f3e84a1SEd Tanous return; 17627f3e84a1SEd Tanous } 1763253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 176422d268cbSEd Tanous { 176522d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 176622d268cbSEd Tanous systemName); 176722d268cbSEd Tanous return; 176822d268cbSEd Tanous } 1769599b9af3SAlexander Hansen dBusEventLogEntryCollection(asyncResp); 1770599b9af3SAlexander Hansen }); 1771599b9af3SAlexander Hansen } 177222d268cbSEd Tanous 1773c6b7cae2SMyung Bae inline void afterDBusEventLogEntryGet( 1774c6b7cae2SMyung Bae const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1775c6b7cae2SMyung Bae const std::string& entryID, const boost::system::error_code& ec, 1776c6b7cae2SMyung Bae const dbus::utility::DBusPropertiesMap& resp) 1777c6b7cae2SMyung Bae { 1778c6b7cae2SMyung Bae if (ec.value() == EBADR) 1779c6b7cae2SMyung Bae { 1780c6b7cae2SMyung Bae messages::resourceNotFound(asyncResp->res, "EventLogEntry", entryID); 1781c6b7cae2SMyung Bae return; 1782c6b7cae2SMyung Bae } 1783c6b7cae2SMyung Bae if (ec) 1784c6b7cae2SMyung Bae { 1785c6b7cae2SMyung Bae BMCWEB_LOG_ERROR("EventLogEntry (DBus) resp_handler got error {}", ec); 1786c6b7cae2SMyung Bae messages::internalError(asyncResp->res); 1787c6b7cae2SMyung Bae return; 1788c6b7cae2SMyung Bae } 1789c6b7cae2SMyung Bae 17907f3726a2SMyung Bae std::optional<DbusEventLogEntry> optEntry = 17917f3726a2SMyung Bae fillDbusEventLogEntryFromPropertyMap(resp); 17927f3726a2SMyung Bae 17937f3726a2SMyung Bae if (!optEntry.has_value()) 17947f3726a2SMyung Bae { 17957f3726a2SMyung Bae messages::internalError(asyncResp->res); 17967f3726a2SMyung Bae return; 17977f3726a2SMyung Bae } 17987f3726a2SMyung Bae 17997f3726a2SMyung Bae fillEventLogLogEntryFromDbusLogEntry(*optEntry, asyncResp->res.jsonValue); 1800c6b7cae2SMyung Bae } 1801c6b7cae2SMyung Bae 1802bd79bce8SPatrick Williams inline void dBusEventLogEntryGet( 1803bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID) 1804599b9af3SAlexander Hansen { 1805599b9af3SAlexander Hansen dbus::utility::escapePathForDbus(entryID); 180608a4e4b5SAnthony Wilson 1807cb92c03bSAndrew Geissler // DBus implementation of EventLog/Entries 1808cb92c03bSAndrew Geissler // Make call to Logging Service to find all log entry objects 1809deae6a78SEd Tanous dbus::utility::getAllProperties( 1810deae6a78SEd Tanous "xyz.openbmc_project.Logging", 1811599b9af3SAlexander Hansen "/xyz/openbmc_project/logging/entry/" + entryID, "", 1812c6b7cae2SMyung Bae std::bind_front(afterDBusEventLogEntryGet, asyncResp, entryID)); 18137e860f15SJohn Edward Broadbent } 1814599b9af3SAlexander Hansen 1815504af5a0SPatrick Williams inline void dBusEventLogEntryPatch( 1816504af5a0SPatrick Williams const crow::Request& req, 1817599b9af3SAlexander Hansen const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1818599b9af3SAlexander Hansen const std::string& entryId) 1819599b9af3SAlexander Hansen { 1820599b9af3SAlexander Hansen std::optional<bool> resolved; 1821599b9af3SAlexander Hansen 1822599b9af3SAlexander Hansen if (!json_util::readJsonPatch(req, asyncResp->res, "Resolved", resolved)) 1823599b9af3SAlexander Hansen { 1824599b9af3SAlexander Hansen return; 1825599b9af3SAlexander Hansen } 1826599b9af3SAlexander Hansen BMCWEB_LOG_DEBUG("Set Resolved"); 1827599b9af3SAlexander Hansen 1828599b9af3SAlexander Hansen setDbusProperty(asyncResp, "Resolved", "xyz.openbmc_project.Logging", 1829599b9af3SAlexander Hansen "/xyz/openbmc_project/logging/entry/" + entryId, 1830599b9af3SAlexander Hansen "xyz.openbmc_project.Logging.Entry", "Resolved", 1831599b9af3SAlexander Hansen resolved.value_or(false)); 1832599b9af3SAlexander Hansen } 1833599b9af3SAlexander Hansen 1834bd79bce8SPatrick Williams inline void dBusEventLogEntryDelete( 1835bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID) 1836599b9af3SAlexander Hansen { 1837599b9af3SAlexander Hansen BMCWEB_LOG_DEBUG("Do delete single event entries."); 1838599b9af3SAlexander Hansen 1839599b9af3SAlexander Hansen dbus::utility::escapePathForDbus(entryID); 1840599b9af3SAlexander Hansen 1841599b9af3SAlexander Hansen // Process response from Logging service. 1842599b9af3SAlexander Hansen auto respHandler = [asyncResp, 1843599b9af3SAlexander Hansen entryID](const boost::system::error_code& ec) { 1844599b9af3SAlexander Hansen BMCWEB_LOG_DEBUG("EventLogEntry (DBus) doDelete callback: Done"); 1845599b9af3SAlexander Hansen if (ec) 1846599b9af3SAlexander Hansen { 1847599b9af3SAlexander Hansen if (ec.value() == EBADR) 1848599b9af3SAlexander Hansen { 1849599b9af3SAlexander Hansen messages::resourceNotFound(asyncResp->res, "LogEntry", entryID); 1850599b9af3SAlexander Hansen return; 1851599b9af3SAlexander Hansen } 1852599b9af3SAlexander Hansen // TODO Handle for specific error code 1853599b9af3SAlexander Hansen BMCWEB_LOG_ERROR( 1854599b9af3SAlexander Hansen "EventLogEntry (DBus) doDelete respHandler got error {}", ec); 1855599b9af3SAlexander Hansen asyncResp->res.result( 1856599b9af3SAlexander Hansen boost::beast::http::status::internal_server_error); 1857599b9af3SAlexander Hansen return; 1858599b9af3SAlexander Hansen } 1859599b9af3SAlexander Hansen 1860599b9af3SAlexander Hansen asyncResp->res.result(boost::beast::http::status::ok); 1861599b9af3SAlexander Hansen }; 1862599b9af3SAlexander Hansen 1863599b9af3SAlexander Hansen // Make call to Logging service to request Delete Log 1864177612aaSEd Tanous dbus::utility::async_method_call( 1865177612aaSEd Tanous asyncResp, respHandler, "xyz.openbmc_project.Logging", 1866599b9af3SAlexander Hansen "/xyz/openbmc_project/logging/entry/" + entryID, 1867599b9af3SAlexander Hansen "xyz.openbmc_project.Object.Delete", "Delete"); 18687e860f15SJohn Edward Broadbent } 18697e860f15SJohn Edward Broadbent 18707e860f15SJohn Edward Broadbent inline void requestRoutesDBusEventLogEntry(App& app) 18717e860f15SJohn Edward Broadbent { 18727e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 187322d268cbSEd Tanous app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/") 1874ed398213SEd Tanous .privileges(redfish::privileges::getLogEntry) 1875002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 1876002d39b4SEd Tanous [&app](const crow::Request& req, 18777e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1878898f2aa2SEd Tanous const std::string& systemName, const std::string& entryId) { 18793ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 18807e860f15SJohn Edward Broadbent { 188145ca1b86SEd Tanous return; 188245ca1b86SEd Tanous } 188325b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 18847f3e84a1SEd Tanous { 18857f3e84a1SEd Tanous // Option currently returns no systems. TBD 18867f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 18877f3e84a1SEd Tanous systemName); 18887f3e84a1SEd Tanous return; 18897f3e84a1SEd Tanous } 1890253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 189122d268cbSEd Tanous { 189222d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 189322d268cbSEd Tanous systemName); 189422d268cbSEd Tanous return; 189522d268cbSEd Tanous } 189622d268cbSEd Tanous 1897898f2aa2SEd Tanous dBusEventLogEntryGet(asyncResp, entryId); 18987e860f15SJohn Edward Broadbent }); 1899336e96c6SChicago Duan 19007e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 190122d268cbSEd Tanous app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/") 1902ed398213SEd Tanous .privileges(redfish::privileges::patchLogEntry) 19037e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::patch)( 190445ca1b86SEd Tanous [&app](const crow::Request& req, 19057e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 190622d268cbSEd Tanous const std::string& systemName, const std::string& entryId) { 19073ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 190845ca1b86SEd Tanous { 190945ca1b86SEd Tanous return; 191045ca1b86SEd Tanous } 191125b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 19127f3e84a1SEd Tanous { 19137f3e84a1SEd Tanous // Option currently returns no systems. TBD 19147f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 19157f3e84a1SEd Tanous systemName); 19167f3e84a1SEd Tanous return; 19177f3e84a1SEd Tanous } 1918253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 191922d268cbSEd Tanous { 192022d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 192122d268cbSEd Tanous systemName); 192222d268cbSEd Tanous return; 192322d268cbSEd Tanous } 192475710de2SXiaochao Ma 1925599b9af3SAlexander Hansen dBusEventLogEntryPatch(req, asyncResp, entryId); 19267e860f15SJohn Edward Broadbent }); 192775710de2SXiaochao Ma 19287e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 192922d268cbSEd Tanous app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/") 1930ed398213SEd Tanous .privileges(redfish::privileges::deleteLogEntry) 1931ed398213SEd Tanous 1932002d39b4SEd Tanous .methods(boost::beast::http::verb::delete_)( 1933002d39b4SEd Tanous [&app](const crow::Request& req, 1934002d39b4SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 193522d268cbSEd Tanous const std::string& systemName, const std::string& param) { 19363ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 1937336e96c6SChicago Duan { 193845ca1b86SEd Tanous return; 193945ca1b86SEd Tanous } 194025b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 19417f3e84a1SEd Tanous { 19427f3e84a1SEd Tanous // Option currently returns no systems. TBD 19437f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 19447f3e84a1SEd Tanous systemName); 19457f3e84a1SEd Tanous return; 19467f3e84a1SEd Tanous } 1947253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 194822d268cbSEd Tanous { 194922d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 195022d268cbSEd Tanous systemName); 195122d268cbSEd Tanous return; 195222d268cbSEd Tanous } 1953599b9af3SAlexander Hansen dBusEventLogEntryDelete(asyncResp, param); 19547e860f15SJohn Edward Broadbent }); 1955400fd1fbSAdriana Kobylak } 1956400fd1fbSAdriana Kobylak 1957dd72e87bSClaire Weinan inline void handleBMCLogServicesCollectionGet( 1958fdd26906SClaire Weinan crow::App& app, const crow::Request& req, 1959253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1960253f11b8SEd Tanous const std::string& managerId) 19611da66f75SEd Tanous { 19623ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 196345ca1b86SEd Tanous { 196445ca1b86SEd Tanous return; 196545ca1b86SEd Tanous } 1966253f11b8SEd Tanous 1967253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 1968253f11b8SEd Tanous { 1969253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 1970253f11b8SEd Tanous return; 1971253f11b8SEd Tanous } 1972253f11b8SEd Tanous 19737e860f15SJohn Edward Broadbent // Collections don't include the static data added by SubRoute 19747e860f15SJohn Edward Broadbent // because it has a duplicate entry for members 1975e1f26343SJason M. Bills asyncResp->res.jsonValue["@odata.type"] = 19761da66f75SEd Tanous "#LogServiceCollection.LogServiceCollection"; 1977253f11b8SEd Tanous asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 1978253f11b8SEd Tanous "/redfish/v1/Managers/{}/LogServices", BMCWEB_REDFISH_MANAGER_URI_NAME); 1979002d39b4SEd Tanous asyncResp->res.jsonValue["Name"] = "Open BMC Log Services Collection"; 1980e1f26343SJason M. Bills asyncResp->res.jsonValue["Description"] = 19811da66f75SEd Tanous "Collection of LogServices for this Manager"; 1982002d39b4SEd Tanous nlohmann::json& logServiceArray = asyncResp->res.jsonValue["Members"]; 1983c4bf6374SJason M. Bills logServiceArray = nlohmann::json::array(); 1984fdd26906SClaire Weinan 198525b54dbaSEd Tanous if constexpr (BMCWEB_REDFISH_BMC_JOURNAL) 198625b54dbaSEd Tanous { 1987613dabeaSEd Tanous nlohmann::json::object_t journal; 1988253f11b8SEd Tanous journal["@odata.id"] = 1989253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}/LogServices/Journal", 1990253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 1991b2ba3072SPatrick Williams logServiceArray.emplace_back(std::move(journal)); 199225b54dbaSEd Tanous } 1993fdd26906SClaire Weinan 1994fdd26906SClaire Weinan asyncResp->res.jsonValue["Members@odata.count"] = logServiceArray.size(); 1995fdd26906SClaire Weinan 199625b54dbaSEd Tanous if constexpr (BMCWEB_REDFISH_DUMP_LOG) 199725b54dbaSEd Tanous { 199815912159SGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 19997a1dbc48SGeorge Liu "xyz.openbmc_project.Collection.DeleteAll"}; 20007a1dbc48SGeorge Liu dbus::utility::getSubTreePaths( 20017a1dbc48SGeorge Liu "/xyz/openbmc_project/dump", 0, interfaces, 200225b54dbaSEd Tanous [asyncResp](const boost::system::error_code& ec, 200325b54dbaSEd Tanous const dbus::utility::MapperGetSubTreePathsResponse& 200425b54dbaSEd Tanous subTreePaths) { 2005fdd26906SClaire Weinan if (ec) 2006fdd26906SClaire Weinan { 200762598e31SEd Tanous BMCWEB_LOG_ERROR( 200862598e31SEd Tanous "handleBMCLogServicesCollectionGet respHandler got error {}", 200962598e31SEd Tanous ec); 2010bd79bce8SPatrick Williams // Assume that getting an error simply means there are no 2011bd79bce8SPatrick Williams // dump LogServices. Return without adding any error 2012bd79bce8SPatrick Williams // response. 2013fdd26906SClaire Weinan return; 2014fdd26906SClaire Weinan } 2015fdd26906SClaire Weinan 2016fdd26906SClaire Weinan nlohmann::json& logServiceArrayLocal = 2017fdd26906SClaire Weinan asyncResp->res.jsonValue["Members"]; 2018fdd26906SClaire Weinan 2019fdd26906SClaire Weinan for (const std::string& path : subTreePaths) 2020fdd26906SClaire Weinan { 2021fdd26906SClaire Weinan if (path == "/xyz/openbmc_project/dump/bmc") 2022fdd26906SClaire Weinan { 2023613dabeaSEd Tanous nlohmann::json::object_t member; 2024253f11b8SEd Tanous member["@odata.id"] = boost::urls::format( 2025253f11b8SEd Tanous "/redfish/v1/Managers/{}/LogServices/Dump", 2026253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 2027b2ba3072SPatrick Williams logServiceArrayLocal.emplace_back(std::move(member)); 2028fdd26906SClaire Weinan } 2029fdd26906SClaire Weinan else if (path == "/xyz/openbmc_project/dump/faultlog") 2030fdd26906SClaire Weinan { 2031613dabeaSEd Tanous nlohmann::json::object_t member; 2032253f11b8SEd Tanous member["@odata.id"] = boost::urls::format( 2033253f11b8SEd Tanous "/redfish/v1/Managers/{}/LogServices/FaultLog", 2034253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 2035b2ba3072SPatrick Williams logServiceArrayLocal.emplace_back(std::move(member)); 2036fdd26906SClaire Weinan } 2037fdd26906SClaire Weinan } 2038fdd26906SClaire Weinan 2039e1f26343SJason M. Bills asyncResp->res.jsonValue["Members@odata.count"] = 2040fdd26906SClaire Weinan logServiceArrayLocal.size(); 20417a1dbc48SGeorge Liu }); 204225b54dbaSEd Tanous } 2043fdd26906SClaire Weinan } 2044fdd26906SClaire Weinan 2045fdd26906SClaire Weinan inline void requestRoutesBMCLogServiceCollection(App& app) 2046fdd26906SClaire Weinan { 2047253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/") 2048fdd26906SClaire Weinan .privileges(redfish::privileges::getLogServiceCollection) 2049fdd26906SClaire Weinan .methods(boost::beast::http::verb::get)( 2050dd72e87bSClaire Weinan std::bind_front(handleBMCLogServicesCollectionGet, std::ref(app))); 2051e1f26343SJason M. Bills } 2052e1f26343SJason M. Bills 2053504af5a0SPatrick Williams inline void getDumpServiceInfo( 2054504af5a0SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2055fdd26906SClaire Weinan const std::string& dumpType) 2056c9bb6861Sraviteja-b { 2057fdd26906SClaire Weinan std::string dumpPath; 2058539d8c6bSEd Tanous log_service::OverWritePolicy overWritePolicy = 2059539d8c6bSEd Tanous log_service::OverWritePolicy::Invalid; 2060fdd26906SClaire Weinan bool collectDiagnosticDataSupported = false; 2061fdd26906SClaire Weinan 2062fdd26906SClaire Weinan if (dumpType == "BMC") 206345ca1b86SEd Tanous { 2064253f11b8SEd Tanous dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/Dump", 2065253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 2066539d8c6bSEd Tanous overWritePolicy = log_service::OverWritePolicy::WrapsWhenFull; 2067fdd26906SClaire Weinan collectDiagnosticDataSupported = true; 2068fdd26906SClaire Weinan } 2069fdd26906SClaire Weinan else if (dumpType == "FaultLog") 2070fdd26906SClaire Weinan { 2071253f11b8SEd Tanous dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/FaultLog", 2072253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 2073539d8c6bSEd Tanous overWritePolicy = log_service::OverWritePolicy::Unknown; 2074fdd26906SClaire Weinan collectDiagnosticDataSupported = false; 2075fdd26906SClaire Weinan } 2076fdd26906SClaire Weinan else if (dumpType == "System") 2077fdd26906SClaire Weinan { 2078253f11b8SEd Tanous dumpPath = std::format("/redfish/v1/Systems/{}/LogServices/Dump", 2079253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 2080539d8c6bSEd Tanous overWritePolicy = log_service::OverWritePolicy::WrapsWhenFull; 2081fdd26906SClaire Weinan collectDiagnosticDataSupported = true; 2082fdd26906SClaire Weinan } 2083fdd26906SClaire Weinan else 2084fdd26906SClaire Weinan { 208562598e31SEd Tanous BMCWEB_LOG_ERROR("getDumpServiceInfo() invalid dump type: {}", 208662598e31SEd Tanous dumpType); 2087fdd26906SClaire Weinan messages::internalError(asyncResp->res); 208845ca1b86SEd Tanous return; 208945ca1b86SEd Tanous } 2090fdd26906SClaire Weinan 2091fdd26906SClaire Weinan asyncResp->res.jsonValue["@odata.id"] = dumpPath; 2092fdd26906SClaire Weinan asyncResp->res.jsonValue["@odata.type"] = "#LogService.v1_2_0.LogService"; 2093c9bb6861Sraviteja-b asyncResp->res.jsonValue["Name"] = "Dump LogService"; 2094fdd26906SClaire Weinan asyncResp->res.jsonValue["Description"] = dumpType + " Dump LogService"; 2095fdd26906SClaire Weinan asyncResp->res.jsonValue["Id"] = std::filesystem::path(dumpPath).filename(); 2096539d8c6bSEd Tanous asyncResp->res.jsonValue["OverWritePolicy"] = overWritePolicy; 20977c8c4058STejas Patil 20987c8c4058STejas Patil std::pair<std::string, std::string> redfishDateTimeOffset = 20992b82937eSEd Tanous redfish::time_utils::getDateTimeOffsetNow(); 21000fda0f12SGeorge Liu asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first; 21017c8c4058STejas Patil asyncResp->res.jsonValue["DateTimeLocalOffset"] = 21027c8c4058STejas Patil redfishDateTimeOffset.second; 21037c8c4058STejas Patil 2104fdd26906SClaire Weinan asyncResp->res.jsonValue["Entries"]["@odata.id"] = dumpPath + "/Entries"; 2105fdd26906SClaire Weinan 2106fdd26906SClaire Weinan if (collectDiagnosticDataSupported) 2107fdd26906SClaire Weinan { 2108002d39b4SEd Tanous asyncResp->res.jsonValue["Actions"]["#LogService.CollectDiagnosticData"] 21091476687dSEd Tanous ["target"] = 2110fdd26906SClaire Weinan dumpPath + "/Actions/LogService.CollectDiagnosticData"; 2111fdd26906SClaire Weinan } 21120d946211SClaire Weinan 21130d946211SClaire Weinan constexpr std::array<std::string_view, 1> interfaces = {deleteAllInterface}; 21140d946211SClaire Weinan dbus::utility::getSubTreePaths( 21150d946211SClaire Weinan "/xyz/openbmc_project/dump", 0, interfaces, 21160d946211SClaire Weinan [asyncResp, dumpType, dumpPath]( 21170d946211SClaire Weinan const boost::system::error_code& ec, 21180d946211SClaire Weinan const dbus::utility::MapperGetSubTreePathsResponse& subTreePaths) { 21190d946211SClaire Weinan if (ec) 21200d946211SClaire Weinan { 2121bd79bce8SPatrick Williams BMCWEB_LOG_ERROR("getDumpServiceInfo respHandler got error {}", 2122bd79bce8SPatrick Williams ec); 21230d946211SClaire Weinan // Assume that getting an error simply means there are no dump 21240d946211SClaire Weinan // LogServices. Return without adding any error response. 21250d946211SClaire Weinan return; 21260d946211SClaire Weinan } 212718f8f608SEd Tanous std::string dbusDumpPath = getDumpPath(dumpType); 21280d946211SClaire Weinan for (const std::string& path : subTreePaths) 21290d946211SClaire Weinan { 21300d946211SClaire Weinan if (path == dbusDumpPath) 21310d946211SClaire Weinan { 2132bd79bce8SPatrick Williams asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"] 2133bd79bce8SPatrick Williams ["target"] = 21340d946211SClaire Weinan dumpPath + "/Actions/LogService.ClearLog"; 21350d946211SClaire Weinan break; 21360d946211SClaire Weinan } 21370d946211SClaire Weinan } 21380d946211SClaire Weinan }); 2139c9bb6861Sraviteja-b } 2140c9bb6861Sraviteja-b 2141fdd26906SClaire Weinan inline void handleLogServicesDumpServiceGet( 2142fdd26906SClaire Weinan crow::App& app, const std::string& dumpType, const crow::Request& req, 2143253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2144253f11b8SEd Tanous const std::string& managerId) 21457e860f15SJohn Edward Broadbent { 21463ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 214745ca1b86SEd Tanous { 214845ca1b86SEd Tanous return; 214945ca1b86SEd Tanous } 2150253f11b8SEd Tanous 2151253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2152253f11b8SEd Tanous { 2153253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2154253f11b8SEd Tanous return; 2155253f11b8SEd Tanous } 2156253f11b8SEd Tanous 2157fdd26906SClaire Weinan getDumpServiceInfo(asyncResp, dumpType); 2158fdd26906SClaire Weinan } 2159c9bb6861Sraviteja-b 216022d268cbSEd Tanous inline void handleLogServicesDumpServiceComputerSystemGet( 216122d268cbSEd Tanous crow::App& app, const crow::Request& req, 216222d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 216322d268cbSEd Tanous const std::string& chassisId) 216422d268cbSEd Tanous { 216522d268cbSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 216622d268cbSEd Tanous { 216722d268cbSEd Tanous return; 216822d268cbSEd Tanous } 2169253f11b8SEd Tanous if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME) 217022d268cbSEd Tanous { 217122d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId); 217222d268cbSEd Tanous return; 217322d268cbSEd Tanous } 217422d268cbSEd Tanous getDumpServiceInfo(asyncResp, "System"); 217522d268cbSEd Tanous } 217622d268cbSEd Tanous 2177fdd26906SClaire Weinan inline void handleLogServicesDumpEntriesCollectionGet( 2178fdd26906SClaire Weinan crow::App& app, const std::string& dumpType, const crow::Request& req, 2179253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2180253f11b8SEd Tanous const std::string& managerId) 2181fdd26906SClaire Weinan { 2182fdd26906SClaire Weinan if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2183fdd26906SClaire Weinan { 2184fdd26906SClaire Weinan return; 2185fdd26906SClaire Weinan } 2186253f11b8SEd Tanous 2187253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2188253f11b8SEd Tanous { 2189253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2190253f11b8SEd Tanous return; 2191253f11b8SEd Tanous } 2192fdd26906SClaire Weinan getDumpEntryCollection(asyncResp, dumpType); 2193fdd26906SClaire Weinan } 2194fdd26906SClaire Weinan 219522d268cbSEd Tanous inline void handleLogServicesDumpEntriesCollectionComputerSystemGet( 219622d268cbSEd Tanous crow::App& app, const crow::Request& req, 219722d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 219822d268cbSEd Tanous const std::string& chassisId) 219922d268cbSEd Tanous { 220022d268cbSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 220122d268cbSEd Tanous { 220222d268cbSEd Tanous return; 220322d268cbSEd Tanous } 2204253f11b8SEd Tanous if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME) 220522d268cbSEd Tanous { 220622d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId); 220722d268cbSEd Tanous return; 220822d268cbSEd Tanous } 220922d268cbSEd Tanous getDumpEntryCollection(asyncResp, "System"); 221022d268cbSEd Tanous } 221122d268cbSEd Tanous 2212fdd26906SClaire Weinan inline void handleLogServicesDumpEntryGet( 2213fdd26906SClaire Weinan crow::App& app, const std::string& dumpType, const crow::Request& req, 2214fdd26906SClaire Weinan const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2215253f11b8SEd Tanous const std::string& managerId, const std::string& dumpId) 2216fdd26906SClaire Weinan { 2217fdd26906SClaire Weinan if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2218fdd26906SClaire Weinan { 2219fdd26906SClaire Weinan return; 2220fdd26906SClaire Weinan } 2221253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2222253f11b8SEd Tanous { 2223253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2224253f11b8SEd Tanous return; 2225253f11b8SEd Tanous } 2226fdd26906SClaire Weinan getDumpEntryById(asyncResp, dumpId, dumpType); 2227fdd26906SClaire Weinan } 2228168d1b1aSCarson Labrado 222922d268cbSEd Tanous inline void handleLogServicesDumpEntryComputerSystemGet( 223022d268cbSEd Tanous crow::App& app, const crow::Request& req, 223122d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 223222d268cbSEd Tanous const std::string& chassisId, const std::string& dumpId) 223322d268cbSEd Tanous { 223422d268cbSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 223522d268cbSEd Tanous { 223622d268cbSEd Tanous return; 223722d268cbSEd Tanous } 2238253f11b8SEd Tanous if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME) 223922d268cbSEd Tanous { 224022d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId); 224122d268cbSEd Tanous return; 224222d268cbSEd Tanous } 224322d268cbSEd Tanous getDumpEntryById(asyncResp, dumpId, "System"); 224422d268cbSEd Tanous } 2245fdd26906SClaire Weinan 2246fdd26906SClaire Weinan inline void handleLogServicesDumpEntryDelete( 2247fdd26906SClaire Weinan crow::App& app, const std::string& dumpType, const crow::Request& req, 2248fdd26906SClaire Weinan const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2249253f11b8SEd Tanous const std::string& managerId, const std::string& dumpId) 2250fdd26906SClaire Weinan { 2251fdd26906SClaire Weinan if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2252fdd26906SClaire Weinan { 2253fdd26906SClaire Weinan return; 2254fdd26906SClaire Weinan } 2255253f11b8SEd Tanous 2256253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2257253f11b8SEd Tanous { 2258253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2259253f11b8SEd Tanous return; 2260253f11b8SEd Tanous } 2261fdd26906SClaire Weinan deleteDumpEntry(asyncResp, dumpId, dumpType); 2262fdd26906SClaire Weinan } 2263fdd26906SClaire Weinan 226422d268cbSEd Tanous inline void handleLogServicesDumpEntryComputerSystemDelete( 226522d268cbSEd Tanous crow::App& app, const crow::Request& req, 226622d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 226722d268cbSEd Tanous const std::string& chassisId, const std::string& dumpId) 226822d268cbSEd Tanous { 226922d268cbSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 227022d268cbSEd Tanous { 227122d268cbSEd Tanous return; 227222d268cbSEd Tanous } 2273253f11b8SEd Tanous if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME) 227422d268cbSEd Tanous { 227522d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId); 227622d268cbSEd Tanous return; 227722d268cbSEd Tanous } 227822d268cbSEd Tanous deleteDumpEntry(asyncResp, dumpId, "System"); 227922d268cbSEd Tanous } 228022d268cbSEd Tanous 2281168d1b1aSCarson Labrado inline void handleLogServicesDumpEntryDownloadGet( 2282168d1b1aSCarson Labrado crow::App& app, const std::string& dumpType, const crow::Request& req, 2283168d1b1aSCarson Labrado const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2284253f11b8SEd Tanous const std::string& managerId, const std::string& dumpId) 2285168d1b1aSCarson Labrado { 2286168d1b1aSCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2287168d1b1aSCarson Labrado { 2288168d1b1aSCarson Labrado return; 2289168d1b1aSCarson Labrado } 2290253f11b8SEd Tanous 2291253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2292253f11b8SEd Tanous { 2293253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2294253f11b8SEd Tanous return; 2295253f11b8SEd Tanous } 2296168d1b1aSCarson Labrado downloadDumpEntry(asyncResp, dumpId, dumpType); 2297168d1b1aSCarson Labrado } 2298168d1b1aSCarson Labrado 2299168d1b1aSCarson Labrado inline void handleDBusEventLogEntryDownloadGet( 2300168d1b1aSCarson Labrado crow::App& app, const std::string& dumpType, const crow::Request& req, 2301168d1b1aSCarson Labrado const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2302168d1b1aSCarson Labrado const std::string& systemName, const std::string& entryID) 2303168d1b1aSCarson Labrado { 2304168d1b1aSCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2305168d1b1aSCarson Labrado { 2306168d1b1aSCarson Labrado return; 2307168d1b1aSCarson Labrado } 2308168d1b1aSCarson Labrado if (!http_helpers::isContentTypeAllowed( 2309168d1b1aSCarson Labrado req.getHeaderValue("Accept"), 2310168d1b1aSCarson Labrado http_helpers::ContentType::OctetStream, true)) 2311168d1b1aSCarson Labrado { 2312168d1b1aSCarson Labrado asyncResp->res.result(boost::beast::http::status::bad_request); 2313168d1b1aSCarson Labrado return; 2314168d1b1aSCarson Labrado } 2315168d1b1aSCarson Labrado downloadEventLogEntry(asyncResp, systemName, entryID, dumpType); 2316168d1b1aSCarson Labrado } 2317168d1b1aSCarson Labrado 2318fdd26906SClaire Weinan inline void handleLogServicesDumpCollectDiagnosticDataPost( 2319fdd26906SClaire Weinan crow::App& app, const std::string& dumpType, const crow::Request& req, 2320253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2321253f11b8SEd Tanous const std::string& managerId) 2322fdd26906SClaire Weinan { 2323fdd26906SClaire Weinan if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2324fdd26906SClaire Weinan { 2325fdd26906SClaire Weinan return; 2326fdd26906SClaire Weinan } 2327253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2328253f11b8SEd Tanous { 2329253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2330253f11b8SEd Tanous return; 2331253f11b8SEd Tanous } 2332253f11b8SEd Tanous 2333fdd26906SClaire Weinan createDump(asyncResp, req, dumpType); 2334fdd26906SClaire Weinan } 2335fdd26906SClaire Weinan 233622d268cbSEd Tanous inline void handleLogServicesDumpCollectDiagnosticDataComputerSystemPost( 233722d268cbSEd Tanous crow::App& app, const crow::Request& req, 233822d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 23397f3e84a1SEd Tanous const std::string& systemName) 234022d268cbSEd Tanous { 234122d268cbSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 234222d268cbSEd Tanous { 234322d268cbSEd Tanous return; 234422d268cbSEd Tanous } 23457f3e84a1SEd Tanous 234625b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 234722d268cbSEd Tanous { 23487f3e84a1SEd Tanous // Option currently returns no systems. TBD 23497f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 23507f3e84a1SEd Tanous systemName); 23517f3e84a1SEd Tanous return; 23527f3e84a1SEd Tanous } 2353253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 23547f3e84a1SEd Tanous { 23557f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 23567f3e84a1SEd Tanous systemName); 235722d268cbSEd Tanous return; 235822d268cbSEd Tanous } 235922d268cbSEd Tanous createDump(asyncResp, req, "System"); 236022d268cbSEd Tanous } 236122d268cbSEd Tanous 2362fdd26906SClaire Weinan inline void handleLogServicesDumpClearLogPost( 2363fdd26906SClaire Weinan crow::App& app, const std::string& dumpType, const crow::Request& req, 2364253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2365253f11b8SEd Tanous const std::string& managerId) 2366fdd26906SClaire Weinan { 2367fdd26906SClaire Weinan if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2368fdd26906SClaire Weinan { 2369fdd26906SClaire Weinan return; 2370fdd26906SClaire Weinan } 2371253f11b8SEd Tanous 2372253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2373253f11b8SEd Tanous { 2374253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2375253f11b8SEd Tanous return; 2376253f11b8SEd Tanous } 2377fdd26906SClaire Weinan clearDump(asyncResp, dumpType); 2378fdd26906SClaire Weinan } 2379fdd26906SClaire Weinan 238022d268cbSEd Tanous inline void handleLogServicesDumpClearLogComputerSystemPost( 238122d268cbSEd Tanous crow::App& app, const crow::Request& req, 238222d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 23837f3e84a1SEd Tanous const std::string& systemName) 238422d268cbSEd Tanous { 238522d268cbSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 238622d268cbSEd Tanous { 238722d268cbSEd Tanous return; 238822d268cbSEd Tanous } 238925b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 239022d268cbSEd Tanous { 23917f3e84a1SEd Tanous // Option currently returns no systems. TBD 23927f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 23937f3e84a1SEd Tanous systemName); 23947f3e84a1SEd Tanous return; 23957f3e84a1SEd Tanous } 2396253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 23977f3e84a1SEd Tanous { 23987f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 23997f3e84a1SEd Tanous systemName); 240022d268cbSEd Tanous return; 240122d268cbSEd Tanous } 240222d268cbSEd Tanous clearDump(asyncResp, "System"); 240322d268cbSEd Tanous } 240422d268cbSEd Tanous 2405fdd26906SClaire Weinan inline void requestRoutesBMCDumpService(App& app) 2406fdd26906SClaire Weinan { 2407253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/Dump/") 2408fdd26906SClaire Weinan .privileges(redfish::privileges::getLogService) 2409fdd26906SClaire Weinan .methods(boost::beast::http::verb::get)(std::bind_front( 2410fdd26906SClaire Weinan handleLogServicesDumpServiceGet, std::ref(app), "BMC")); 2411fdd26906SClaire Weinan } 2412fdd26906SClaire Weinan 2413fdd26906SClaire Weinan inline void requestRoutesBMCDumpEntryCollection(App& app) 2414fdd26906SClaire Weinan { 2415253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/") 2416fdd26906SClaire Weinan .privileges(redfish::privileges::getLogEntryCollection) 2417fdd26906SClaire Weinan .methods(boost::beast::http::verb::get)(std::bind_front( 2418fdd26906SClaire Weinan handleLogServicesDumpEntriesCollectionGet, std::ref(app), "BMC")); 2419c9bb6861Sraviteja-b } 2420c9bb6861Sraviteja-b 24217e860f15SJohn Edward Broadbent inline void requestRoutesBMCDumpEntry(App& app) 2422c9bb6861Sraviteja-b { 24237e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 2424253f11b8SEd Tanous "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/") 2425ed398213SEd Tanous .privileges(redfish::privileges::getLogEntry) 2426fdd26906SClaire Weinan .methods(boost::beast::http::verb::get)(std::bind_front( 2427fdd26906SClaire Weinan handleLogServicesDumpEntryGet, std::ref(app), "BMC")); 2428fdd26906SClaire Weinan 24297e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 2430253f11b8SEd Tanous "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/") 2431ed398213SEd Tanous .privileges(redfish::privileges::deleteLogEntry) 2432fdd26906SClaire Weinan .methods(boost::beast::http::verb::delete_)(std::bind_front( 2433fdd26906SClaire Weinan handleLogServicesDumpEntryDelete, std::ref(app), "BMC")); 2434c9bb6861Sraviteja-b } 2435c9bb6861Sraviteja-b 2436168d1b1aSCarson Labrado inline void requestRoutesBMCDumpEntryDownload(App& app) 2437168d1b1aSCarson Labrado { 2438168d1b1aSCarson Labrado BMCWEB_ROUTE( 2439168d1b1aSCarson Labrado app, 2440253f11b8SEd Tanous "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/attachment/") 2441168d1b1aSCarson Labrado .privileges(redfish::privileges::getLogEntry) 2442168d1b1aSCarson Labrado .methods(boost::beast::http::verb::get)(std::bind_front( 2443168d1b1aSCarson Labrado handleLogServicesDumpEntryDownloadGet, std::ref(app), "BMC")); 2444168d1b1aSCarson Labrado } 2445168d1b1aSCarson Labrado 24467e860f15SJohn Edward Broadbent inline void requestRoutesBMCDumpCreate(App& app) 2447c9bb6861Sraviteja-b { 24480fda0f12SGeorge Liu BMCWEB_ROUTE( 24490fda0f12SGeorge Liu app, 2450253f11b8SEd Tanous "/redfish/v1/Managers/<str>/LogServices/Dump/Actions/LogService.CollectDiagnosticData/") 2451ed398213SEd Tanous .privileges(redfish::privileges::postLogService) 24527e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 2453fdd26906SClaire Weinan std::bind_front(handleLogServicesDumpCollectDiagnosticDataPost, 2454fdd26906SClaire Weinan std::ref(app), "BMC")); 2455a43be80fSAsmitha Karunanithi } 2456a43be80fSAsmitha Karunanithi 24577e860f15SJohn Edward Broadbent inline void requestRoutesBMCDumpClear(App& app) 245880319af1SAsmitha Karunanithi { 24590fda0f12SGeorge Liu BMCWEB_ROUTE( 24600fda0f12SGeorge Liu app, 2461253f11b8SEd Tanous "/redfish/v1/Managers/<str>/LogServices/Dump/Actions/LogService.ClearLog/") 2462ed398213SEd Tanous .privileges(redfish::privileges::postLogService) 2463fdd26906SClaire Weinan .methods(boost::beast::http::verb::post)(std::bind_front( 2464fdd26906SClaire Weinan handleLogServicesDumpClearLogPost, std::ref(app), "BMC")); 246545ca1b86SEd Tanous } 2466fdd26906SClaire Weinan 2467168d1b1aSCarson Labrado inline void requestRoutesDBusEventLogEntryDownload(App& app) 2468168d1b1aSCarson Labrado { 2469168d1b1aSCarson Labrado BMCWEB_ROUTE( 2470168d1b1aSCarson Labrado app, 24719e9d99daSRavi Teja "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/attachment/") 2472168d1b1aSCarson Labrado .privileges(redfish::privileges::getLogEntry) 2473168d1b1aSCarson Labrado .methods(boost::beast::http::verb::get)(std::bind_front( 2474168d1b1aSCarson Labrado handleDBusEventLogEntryDownloadGet, std::ref(app), "System")); 2475168d1b1aSCarson Labrado } 2476168d1b1aSCarson Labrado 2477fdd26906SClaire Weinan inline void requestRoutesFaultLogDumpService(App& app) 2478fdd26906SClaire Weinan { 2479253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/") 2480fdd26906SClaire Weinan .privileges(redfish::privileges::getLogService) 2481fdd26906SClaire Weinan .methods(boost::beast::http::verb::get)(std::bind_front( 2482fdd26906SClaire Weinan handleLogServicesDumpServiceGet, std::ref(app), "FaultLog")); 2483fdd26906SClaire Weinan } 2484fdd26906SClaire Weinan 2485fdd26906SClaire Weinan inline void requestRoutesFaultLogDumpEntryCollection(App& app) 2486fdd26906SClaire Weinan { 2487253f11b8SEd Tanous BMCWEB_ROUTE(app, 2488253f11b8SEd Tanous "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/") 2489fdd26906SClaire Weinan .privileges(redfish::privileges::getLogEntryCollection) 2490fdd26906SClaire Weinan .methods(boost::beast::http::verb::get)( 2491fdd26906SClaire Weinan std::bind_front(handleLogServicesDumpEntriesCollectionGet, 2492fdd26906SClaire Weinan std::ref(app), "FaultLog")); 2493fdd26906SClaire Weinan } 2494fdd26906SClaire Weinan 2495fdd26906SClaire Weinan inline void requestRoutesFaultLogDumpEntry(App& app) 2496fdd26906SClaire Weinan { 2497253f11b8SEd Tanous BMCWEB_ROUTE( 2498253f11b8SEd Tanous app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/<str>/") 2499fdd26906SClaire Weinan .privileges(redfish::privileges::getLogEntry) 2500fdd26906SClaire Weinan .methods(boost::beast::http::verb::get)(std::bind_front( 2501fdd26906SClaire Weinan handleLogServicesDumpEntryGet, std::ref(app), "FaultLog")); 2502fdd26906SClaire Weinan 2503253f11b8SEd Tanous BMCWEB_ROUTE( 2504253f11b8SEd Tanous app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/<str>/") 2505fdd26906SClaire Weinan .privileges(redfish::privileges::deleteLogEntry) 2506fdd26906SClaire Weinan .methods(boost::beast::http::verb::delete_)(std::bind_front( 2507fdd26906SClaire Weinan handleLogServicesDumpEntryDelete, std::ref(app), "FaultLog")); 2508fdd26906SClaire Weinan } 2509fdd26906SClaire Weinan 2510fdd26906SClaire Weinan inline void requestRoutesFaultLogDumpClear(App& app) 2511fdd26906SClaire Weinan { 2512fdd26906SClaire Weinan BMCWEB_ROUTE( 2513fdd26906SClaire Weinan app, 2514253f11b8SEd Tanous "/redfish/v1/Managers/<str>/LogServices/FaultLog/Actions/LogService.ClearLog/") 2515fdd26906SClaire Weinan .privileges(redfish::privileges::postLogService) 2516fdd26906SClaire Weinan .methods(boost::beast::http::verb::post)(std::bind_front( 2517fdd26906SClaire Weinan handleLogServicesDumpClearLogPost, std::ref(app), "FaultLog")); 25185cb1dd27SAsmitha Karunanithi } 25195cb1dd27SAsmitha Karunanithi 25207e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpService(App& app) 25215cb1dd27SAsmitha Karunanithi { 252222d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Dump/") 2523ed398213SEd Tanous .privileges(redfish::privileges::getLogService) 25246ab9ad54SClaire Weinan .methods(boost::beast::http::verb::get)(std::bind_front( 252522d268cbSEd Tanous handleLogServicesDumpServiceComputerSystemGet, std::ref(app))); 25265cb1dd27SAsmitha Karunanithi } 25275cb1dd27SAsmitha Karunanithi 25287e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpEntryCollection(App& app) 25297e860f15SJohn Edward Broadbent { 253022d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/") 2531ed398213SEd Tanous .privileges(redfish::privileges::getLogEntryCollection) 253222d268cbSEd Tanous .methods(boost::beast::http::verb::get)(std::bind_front( 253322d268cbSEd Tanous handleLogServicesDumpEntriesCollectionComputerSystemGet, 253422d268cbSEd Tanous std::ref(app))); 25355cb1dd27SAsmitha Karunanithi } 25365cb1dd27SAsmitha Karunanithi 25377e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpEntry(App& app) 25385cb1dd27SAsmitha Karunanithi { 25397e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 254022d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/<str>/") 2541ed398213SEd Tanous .privileges(redfish::privileges::getLogEntry) 25426ab9ad54SClaire Weinan .methods(boost::beast::http::verb::get)(std::bind_front( 254322d268cbSEd Tanous handleLogServicesDumpEntryComputerSystemGet, std::ref(app))); 25448d1b46d7Szhanghch05 25457e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 254622d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/<str>/") 2547ed398213SEd Tanous .privileges(redfish::privileges::deleteLogEntry) 25486ab9ad54SClaire Weinan .methods(boost::beast::http::verb::delete_)(std::bind_front( 254922d268cbSEd Tanous handleLogServicesDumpEntryComputerSystemDelete, std::ref(app))); 25505cb1dd27SAsmitha Karunanithi } 2551c9bb6861Sraviteja-b 25527e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpCreate(App& app) 2553c9bb6861Sraviteja-b { 25540fda0f12SGeorge Liu BMCWEB_ROUTE( 25550fda0f12SGeorge Liu app, 255622d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Dump/Actions/LogService.CollectDiagnosticData/") 2557ed398213SEd Tanous .privileges(redfish::privileges::postLogService) 255822d268cbSEd Tanous .methods(boost::beast::http::verb::post)(std::bind_front( 255922d268cbSEd Tanous handleLogServicesDumpCollectDiagnosticDataComputerSystemPost, 256022d268cbSEd Tanous std::ref(app))); 2561a43be80fSAsmitha Karunanithi } 2562a43be80fSAsmitha Karunanithi 25637e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpClear(App& app) 2564a43be80fSAsmitha Karunanithi { 25650fda0f12SGeorge Liu BMCWEB_ROUTE( 25660fda0f12SGeorge Liu app, 256722d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Dump/Actions/LogService.ClearLog/") 2568ed398213SEd Tanous .privileges(redfish::privileges::postLogService) 25696ab9ad54SClaire Weinan .methods(boost::beast::http::verb::post)(std::bind_front( 257022d268cbSEd Tanous handleLogServicesDumpClearLogComputerSystemPost, std::ref(app))); 2571013487e5Sraviteja-b } 2572013487e5Sraviteja-b 25737e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpService(App& app) 25741da66f75SEd Tanous { 25753946028dSAppaRao Puli // Note: Deviated from redfish privilege registry for GET & HEAD 25763946028dSAppaRao Puli // method for security reasons. 25771da66f75SEd Tanous /** 25781da66f75SEd Tanous * Functions triggers appropriate requests on DBus 25791da66f75SEd Tanous */ 258022d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Crashdump/") 2581ed398213SEd Tanous // This is incorrect, should be: 2582ed398213SEd Tanous //.privileges(redfish::privileges::getLogService) 2583432a890cSEd Tanous .privileges({{"ConfigureManager"}}) 2584bd79bce8SPatrick Williams .methods( 2585bd79bce8SPatrick Williams boost::beast::http::verb:: 2586bd79bce8SPatrick Williams get)([&app](const crow::Request& req, 258722d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 258822d268cbSEd Tanous const std::string& systemName) { 25893ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 259045ca1b86SEd Tanous { 259145ca1b86SEd Tanous return; 259245ca1b86SEd Tanous } 259325b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 25947f3e84a1SEd Tanous { 25957f3e84a1SEd Tanous // Option currently returns no systems. TBD 25967f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 25977f3e84a1SEd Tanous systemName); 25987f3e84a1SEd Tanous return; 25997f3e84a1SEd Tanous } 2600253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 260122d268cbSEd Tanous { 260222d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 260322d268cbSEd Tanous systemName); 260422d268cbSEd Tanous return; 260522d268cbSEd Tanous } 260622d268cbSEd Tanous 26077e860f15SJohn Edward Broadbent // Copy over the static data to include the entries added by 26087e860f15SJohn Edward Broadbent // SubRoute 26090f74e643SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 2610253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/Crashdump", 2611253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 2612e1f26343SJason M. Bills asyncResp->res.jsonValue["@odata.type"] = 26138e6c099aSJason M. Bills "#LogService.v1_2_0.LogService"; 26144f50ae4bSGunnar Mills asyncResp->res.jsonValue["Name"] = "Open BMC Oem Crashdump Service"; 26154f50ae4bSGunnar Mills asyncResp->res.jsonValue["Description"] = "Oem Crashdump Service"; 261615b89725SV-Sanjana asyncResp->res.jsonValue["Id"] = "Crashdump"; 2617539d8c6bSEd Tanous asyncResp->res.jsonValue["OverWritePolicy"] = 2618539d8c6bSEd Tanous log_service::OverWritePolicy::WrapsWhenFull; 2619e1f26343SJason M. Bills asyncResp->res.jsonValue["MaxNumberOfRecords"] = 3; 26207c8c4058STejas Patil 26217c8c4058STejas Patil std::pair<std::string, std::string> redfishDateTimeOffset = 26222b82937eSEd Tanous redfish::time_utils::getDateTimeOffsetNow(); 26237c8c4058STejas Patil asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first; 26247c8c4058STejas Patil asyncResp->res.jsonValue["DateTimeLocalOffset"] = 26257c8c4058STejas Patil redfishDateTimeOffset.second; 26267c8c4058STejas Patil 2627bd79bce8SPatrick Williams asyncResp->res.jsonValue["Entries"]["@odata.id"] = std::format( 2628bd79bce8SPatrick Williams "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries", 2629253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 2630253f11b8SEd Tanous asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"] 2631253f11b8SEd Tanous ["target"] = std::format( 2632253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/Crashdump/Actions/LogService.ClearLog", 2633253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 2634bd79bce8SPatrick Williams asyncResp->res 2635bd79bce8SPatrick Williams .jsonValue["Actions"]["#LogService.CollectDiagnosticData"] 2636253f11b8SEd Tanous ["target"] = std::format( 2637253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/Crashdump/Actions/LogService.CollectDiagnosticData", 2638253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 26397e860f15SJohn Edward Broadbent }); 26401da66f75SEd Tanous } 26411da66f75SEd Tanous 26427e860f15SJohn Edward Broadbent void inline requestRoutesCrashdumpClear(App& app) 26435b61b5e8SJason M. Bills { 26440fda0f12SGeorge Liu BMCWEB_ROUTE( 26450fda0f12SGeorge Liu app, 264622d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Crashdump/Actions/LogService.ClearLog/") 2647ed398213SEd Tanous // This is incorrect, should be: 2648ed398213SEd Tanous //.privileges(redfish::privileges::postLogService) 2649432a890cSEd Tanous .privileges({{"ConfigureComponents"}}) 26507e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 265145ca1b86SEd Tanous [&app](const crow::Request& req, 265222d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 265322d268cbSEd Tanous const std::string& systemName) { 26543ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 265545ca1b86SEd Tanous { 265645ca1b86SEd Tanous return; 265745ca1b86SEd Tanous } 265825b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 26597f3e84a1SEd Tanous { 26607f3e84a1SEd Tanous // Option currently returns no systems. TBD 26617f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 26627f3e84a1SEd Tanous systemName); 26637f3e84a1SEd Tanous return; 26647f3e84a1SEd Tanous } 2665253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 266622d268cbSEd Tanous { 266722d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 266822d268cbSEd Tanous systemName); 266922d268cbSEd Tanous return; 267022d268cbSEd Tanous } 2671177612aaSEd Tanous dbus::utility::async_method_call( 2672177612aaSEd Tanous asyncResp, 26735e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec, 2674cb13a392SEd Tanous const std::string&) { 26755b61b5e8SJason M. Bills if (ec) 26765b61b5e8SJason M. Bills { 26775b61b5e8SJason M. Bills messages::internalError(asyncResp->res); 26785b61b5e8SJason M. Bills return; 26795b61b5e8SJason M. Bills } 26805b61b5e8SJason M. Bills messages::success(asyncResp->res); 26815b61b5e8SJason M. Bills }, 2682bd79bce8SPatrick Williams crashdumpObject, crashdumpPath, deleteAllInterface, 2683bd79bce8SPatrick Williams "DeleteAll"); 26847e860f15SJohn Edward Broadbent }); 26855b61b5e8SJason M. Bills } 26865b61b5e8SJason M. Bills 2687504af5a0SPatrick Williams inline void logCrashdumpEntry( 2688504af5a0SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 26898d1b46d7Szhanghch05 const std::string& logID, nlohmann::json& logEntryJson) 2690e855dd28SJason M. Bills { 2691043a0536SJohnathan Mantey auto getStoredLogCallback = 2692b9d36b47SEd Tanous [asyncResp, logID, 26935e7e2dc5SEd Tanous &logEntryJson](const boost::system::error_code& ec, 2694b9d36b47SEd Tanous const dbus::utility::DBusPropertiesMap& params) { 2695e855dd28SJason M. Bills if (ec) 2696e855dd28SJason M. Bills { 269762598e31SEd Tanous BMCWEB_LOG_DEBUG("failed to get log ec: {}", ec.message()); 26981ddcf01aSJason M. Bills if (ec.value() == 26991ddcf01aSJason M. Bills boost::system::linux_error::bad_request_descriptor) 27001ddcf01aSJason M. Bills { 2701bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "LogEntry", 2702bd79bce8SPatrick Williams logID); 27031ddcf01aSJason M. Bills } 27041ddcf01aSJason M. Bills else 27051ddcf01aSJason M. Bills { 2706e855dd28SJason M. Bills messages::internalError(asyncResp->res); 27071ddcf01aSJason M. Bills } 2708e855dd28SJason M. Bills return; 2709e855dd28SJason M. Bills } 2710043a0536SJohnathan Mantey 2711043a0536SJohnathan Mantey std::string timestamp{}; 2712043a0536SJohnathan Mantey std::string filename{}; 2713043a0536SJohnathan Mantey std::string logfile{}; 27142c70f800SEd Tanous parseCrashdumpParameters(params, filename, timestamp, logfile); 2715043a0536SJohnathan Mantey 2716043a0536SJohnathan Mantey if (filename.empty() || timestamp.empty()) 2717e855dd28SJason M. Bills { 27189db4ba25SJiaqing Zhao messages::resourceNotFound(asyncResp->res, "LogEntry", logID); 2719e855dd28SJason M. Bills return; 2720e855dd28SJason M. Bills } 2721e855dd28SJason M. Bills 2722043a0536SJohnathan Mantey std::string crashdumpURI = 2723bd79bce8SPatrick Williams std::format( 2724bd79bce8SPatrick Williams "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries/", 2725253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME) + 2726043a0536SJohnathan Mantey logID + "/" + filename; 272784afc48bSJason M. Bills nlohmann::json::object_t logEntry; 27289c11a172SVijay Lobo logEntry["@odata.type"] = "#LogEntry.v1_9_0.LogEntry"; 2729ef4c65b7SEd Tanous logEntry["@odata.id"] = boost::urls::format( 2730253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries/{}", 2731253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, logID); 273284afc48bSJason M. Bills logEntry["Name"] = "CPU Crashdump"; 273384afc48bSJason M. Bills logEntry["Id"] = logID; 2734539d8c6bSEd Tanous logEntry["EntryType"] = log_entry::LogEntryType::Oem; 273584afc48bSJason M. Bills logEntry["AdditionalDataURI"] = std::move(crashdumpURI); 273684afc48bSJason M. Bills logEntry["DiagnosticDataType"] = "OEM"; 273784afc48bSJason M. Bills logEntry["OEMDiagnosticDataType"] = "PECICrashdump"; 273884afc48bSJason M. Bills logEntry["Created"] = std::move(timestamp); 27392b20ef6eSJason M. Bills 27402b20ef6eSJason M. Bills // If logEntryJson references an array of LogEntry resources 27412b20ef6eSJason M. Bills // ('Members' list), then push this as a new entry, otherwise set it 27422b20ef6eSJason M. Bills // directly 27432b20ef6eSJason M. Bills if (logEntryJson.is_array()) 27442b20ef6eSJason M. Bills { 27452b20ef6eSJason M. Bills logEntryJson.push_back(logEntry); 27462b20ef6eSJason M. Bills asyncResp->res.jsonValue["Members@odata.count"] = 27472b20ef6eSJason M. Bills logEntryJson.size(); 27482b20ef6eSJason M. Bills } 27492b20ef6eSJason M. Bills else 27502b20ef6eSJason M. Bills { 2751d405bb51SJason M. Bills logEntryJson.update(logEntry); 27522b20ef6eSJason M. Bills } 2753e855dd28SJason M. Bills }; 2754deae6a78SEd Tanous dbus::utility::getAllProperties( 2755deae6a78SEd Tanous crashdumpObject, crashdumpPath + std::string("/") + logID, 2756deae6a78SEd Tanous crashdumpInterface, std::move(getStoredLogCallback)); 2757e855dd28SJason M. Bills } 2758e855dd28SJason M. Bills 27597e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpEntryCollection(App& app) 27601da66f75SEd Tanous { 27613946028dSAppaRao Puli // Note: Deviated from redfish privilege registry for GET & HEAD 27623946028dSAppaRao Puli // method for security reasons. 27631da66f75SEd Tanous /** 27641da66f75SEd Tanous * Functions triggers appropriate requests on DBus 27651da66f75SEd Tanous */ 27667e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 276722d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/") 2768ed398213SEd Tanous // This is incorrect, should be. 2769ed398213SEd Tanous //.privileges(redfish::privileges::postLogEntryCollection) 2770432a890cSEd Tanous .privileges({{"ConfigureComponents"}}) 2771bd79bce8SPatrick Williams .methods( 2772bd79bce8SPatrick Williams boost::beast::http::verb:: 2773bd79bce8SPatrick Williams get)([&app](const crow::Request& req, 277422d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 277522d268cbSEd Tanous const std::string& systemName) { 27763ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 277745ca1b86SEd Tanous { 277845ca1b86SEd Tanous return; 277945ca1b86SEd Tanous } 278025b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 27817f3e84a1SEd Tanous { 27827f3e84a1SEd Tanous // Option currently returns no systems. TBD 27837f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 27847f3e84a1SEd Tanous systemName); 27857f3e84a1SEd Tanous return; 27867f3e84a1SEd Tanous } 2787253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 278822d268cbSEd Tanous { 278922d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 279022d268cbSEd Tanous systemName); 279122d268cbSEd Tanous return; 279222d268cbSEd Tanous } 279322d268cbSEd Tanous 27947a1dbc48SGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 27957a1dbc48SGeorge Liu crashdumpInterface}; 27967a1dbc48SGeorge Liu dbus::utility::getSubTreePaths( 27977a1dbc48SGeorge Liu "/", 0, interfaces, 27987a1dbc48SGeorge Liu [asyncResp](const boost::system::error_code& ec, 27992b20ef6eSJason M. Bills const std::vector<std::string>& resp) { 28001da66f75SEd Tanous if (ec) 28011da66f75SEd Tanous { 28021da66f75SEd Tanous if (ec.value() != 28031da66f75SEd Tanous boost::system::errc::no_such_file_or_directory) 28041da66f75SEd Tanous { 280562598e31SEd Tanous BMCWEB_LOG_DEBUG("failed to get entries ec: {}", 280662598e31SEd Tanous ec.message()); 2807f12894f8SJason M. Bills messages::internalError(asyncResp->res); 28081da66f75SEd Tanous return; 28091da66f75SEd Tanous } 28101da66f75SEd Tanous } 2811e1f26343SJason M. Bills asyncResp->res.jsonValue["@odata.type"] = 28121da66f75SEd Tanous "#LogEntryCollection.LogEntryCollection"; 2813253f11b8SEd Tanous asyncResp->res.jsonValue["@odata.id"] = std::format( 2814253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries", 2815253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 2816bd79bce8SPatrick Williams asyncResp->res.jsonValue["Name"] = 2817bd79bce8SPatrick Williams "Open BMC Crashdump Entries"; 2818e1f26343SJason M. Bills asyncResp->res.jsonValue["Description"] = 2819424c4176SJason M. Bills "Collection of Crashdump Entries"; 2820bd79bce8SPatrick Williams asyncResp->res.jsonValue["Members"] = 2821bd79bce8SPatrick Williams nlohmann::json::array(); 2822a2dd60a6SBrandon Kim asyncResp->res.jsonValue["Members@odata.count"] = 0; 28232b20ef6eSJason M. Bills 28242b20ef6eSJason M. Bills for (const std::string& path : resp) 28251da66f75SEd Tanous { 28262b20ef6eSJason M. Bills const sdbusplus::message::object_path objPath(path); 2827e855dd28SJason M. Bills // Get the log ID 28282b20ef6eSJason M. Bills std::string logID = objPath.filename(); 28292b20ef6eSJason M. Bills if (logID.empty()) 28301da66f75SEd Tanous { 2831e855dd28SJason M. Bills continue; 28321da66f75SEd Tanous } 2833e855dd28SJason M. Bills // Add the log entry to the array 28342b20ef6eSJason M. Bills logCrashdumpEntry(asyncResp, logID, 28352b20ef6eSJason M. Bills asyncResp->res.jsonValue["Members"]); 28361da66f75SEd Tanous } 28377a1dbc48SGeorge Liu }); 28387e860f15SJohn Edward Broadbent }); 28391da66f75SEd Tanous } 28401da66f75SEd Tanous 28417e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpEntry(App& app) 28421da66f75SEd Tanous { 28433946028dSAppaRao Puli // Note: Deviated from redfish privilege registry for GET & HEAD 28443946028dSAppaRao Puli // method for security reasons. 28451da66f75SEd Tanous 28467e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 284722d268cbSEd Tanous app, "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/<str>/") 2848ed398213SEd Tanous // this is incorrect, should be 2849ed398213SEd Tanous // .privileges(redfish::privileges::getLogEntry) 2850432a890cSEd Tanous .privileges({{"ConfigureComponents"}}) 28517e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 285245ca1b86SEd Tanous [&app](const crow::Request& req, 28537e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 285422d268cbSEd Tanous const std::string& systemName, const std::string& param) { 28553ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 285645ca1b86SEd Tanous { 285745ca1b86SEd Tanous return; 285845ca1b86SEd Tanous } 285925b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 28607f3e84a1SEd Tanous { 28617f3e84a1SEd Tanous // Option currently returns no systems. TBD 28627f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 28637f3e84a1SEd Tanous systemName); 28647f3e84a1SEd Tanous return; 28657f3e84a1SEd Tanous } 2866253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 286722d268cbSEd Tanous { 286822d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 286922d268cbSEd Tanous systemName); 287022d268cbSEd Tanous return; 287122d268cbSEd Tanous } 28727e860f15SJohn Edward Broadbent const std::string& logID = param; 2873e855dd28SJason M. Bills logCrashdumpEntry(asyncResp, logID, asyncResp->res.jsonValue); 28747e860f15SJohn Edward Broadbent }); 2875e855dd28SJason M. Bills } 2876e855dd28SJason M. Bills 28777e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpFile(App& app) 2878e855dd28SJason M. Bills { 28793946028dSAppaRao Puli // Note: Deviated from redfish privilege registry for GET & HEAD 28803946028dSAppaRao Puli // method for security reasons. 28817e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 28827e860f15SJohn Edward Broadbent app, 288322d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/<str>/<str>/") 2884ed398213SEd Tanous .privileges(redfish::privileges::getLogEntry) 28857e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 2886a4ce114aSNan Zhou [](const crow::Request& req, 28877e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 288822d268cbSEd Tanous const std::string& systemName, const std::string& logID, 288922d268cbSEd Tanous const std::string& fileName) { 2890bd79bce8SPatrick Williams // Do not call getRedfishRoute here since the crashdump file is 2891bd79bce8SPatrick Williams // not a Redfish resource. 289222d268cbSEd Tanous 289325b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 28947f3e84a1SEd Tanous { 28957f3e84a1SEd Tanous // Option currently returns no systems. TBD 28967f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 28977f3e84a1SEd Tanous systemName); 28987f3e84a1SEd Tanous return; 28997f3e84a1SEd Tanous } 2900253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 290122d268cbSEd Tanous { 290222d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 290322d268cbSEd Tanous systemName); 290422d268cbSEd Tanous return; 290522d268cbSEd Tanous } 290622d268cbSEd Tanous 2907043a0536SJohnathan Mantey auto getStoredLogCallback = 2908bd79bce8SPatrick Williams [asyncResp, logID, fileName, 2909bd79bce8SPatrick Williams url(boost::urls::url(req.url()))]( 29105e7e2dc5SEd Tanous const boost::system::error_code& ec, 2911bd79bce8SPatrick Williams const std::vector<std::pair< 2912bd79bce8SPatrick Williams std::string, dbus::utility::DbusVariantType>>& 29137e860f15SJohn Edward Broadbent resp) { 29141da66f75SEd Tanous if (ec) 29151da66f75SEd Tanous { 2916bd79bce8SPatrick Williams BMCWEB_LOG_DEBUG("failed to get log ec: {}", 2917bd79bce8SPatrick Williams ec.message()); 2918f12894f8SJason M. Bills messages::internalError(asyncResp->res); 29191da66f75SEd Tanous return; 29201da66f75SEd Tanous } 2921e855dd28SJason M. Bills 2922043a0536SJohnathan Mantey std::string dbusFilename{}; 2923043a0536SJohnathan Mantey std::string dbusTimestamp{}; 2924043a0536SJohnathan Mantey std::string dbusFilepath{}; 2925043a0536SJohnathan Mantey 2926bd79bce8SPatrick Williams parseCrashdumpParameters(resp, dbusFilename, 2927bd79bce8SPatrick Williams dbusTimestamp, dbusFilepath); 2928043a0536SJohnathan Mantey 2929043a0536SJohnathan Mantey if (dbusFilename.empty() || dbusTimestamp.empty() || 2930043a0536SJohnathan Mantey dbusFilepath.empty()) 29311da66f75SEd Tanous { 2932bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, 2933bd79bce8SPatrick Williams "LogEntry", logID); 29341da66f75SEd Tanous return; 29351da66f75SEd Tanous } 2936e855dd28SJason M. Bills 2937043a0536SJohnathan Mantey // Verify the file name parameter is correct 2938043a0536SJohnathan Mantey if (fileName != dbusFilename) 2939043a0536SJohnathan Mantey { 2940bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, 2941bd79bce8SPatrick Williams "LogEntry", logID); 2942043a0536SJohnathan Mantey return; 2943043a0536SJohnathan Mantey } 2944043a0536SJohnathan Mantey 2945d51c61b4SMyung Bae if (asyncResp->res.openFile(dbusFilepath) != 2946d51c61b4SMyung Bae crow::OpenCode::Success) 2947043a0536SJohnathan Mantey { 2948bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, 2949bd79bce8SPatrick Williams "LogEntry", logID); 2950043a0536SJohnathan Mantey return; 2951043a0536SJohnathan Mantey } 2952043a0536SJohnathan Mantey 29537e860f15SJohn Edward Broadbent // Configure this to be a file download when accessed 29547e860f15SJohn Edward Broadbent // from a browser 2955d9f6c621SEd Tanous asyncResp->res.addHeader( 2956bd79bce8SPatrick Williams boost::beast::http::field::content_disposition, 2957bd79bce8SPatrick Williams "attachment"); 29581da66f75SEd Tanous }; 2959deae6a78SEd Tanous dbus::utility::getAllProperties( 2960d1bde9e5SKrzysztof Grobelny *crow::connections::systemBus, crashdumpObject, 2961bd79bce8SPatrick Williams crashdumpPath + std::string("/") + logID, 2962bd79bce8SPatrick Williams crashdumpInterface, std::move(getStoredLogCallback)); 29637e860f15SJohn Edward Broadbent }); 29641da66f75SEd Tanous } 29651da66f75SEd Tanous 2966c5a4c82aSJason M. Bills enum class OEMDiagnosticType 2967c5a4c82aSJason M. Bills { 2968c5a4c82aSJason M. Bills onDemand, 2969c5a4c82aSJason M. Bills telemetry, 2970c5a4c82aSJason M. Bills invalid, 2971c5a4c82aSJason M. Bills }; 2972c5a4c82aSJason M. Bills 297326ccae32SEd Tanous inline OEMDiagnosticType getOEMDiagnosticType(std::string_view oemDiagStr) 2974c5a4c82aSJason M. Bills { 2975c5a4c82aSJason M. Bills if (oemDiagStr == "OnDemand") 2976c5a4c82aSJason M. Bills { 2977c5a4c82aSJason M. Bills return OEMDiagnosticType::onDemand; 2978c5a4c82aSJason M. Bills } 2979c5a4c82aSJason M. Bills if (oemDiagStr == "Telemetry") 2980c5a4c82aSJason M. Bills { 2981c5a4c82aSJason M. Bills return OEMDiagnosticType::telemetry; 2982c5a4c82aSJason M. Bills } 2983c5a4c82aSJason M. Bills 2984c5a4c82aSJason M. Bills return OEMDiagnosticType::invalid; 2985c5a4c82aSJason M. Bills } 2986c5a4c82aSJason M. Bills 29877e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpCollect(App& app) 29881da66f75SEd Tanous { 29893946028dSAppaRao Puli // Note: Deviated from redfish privilege registry for GET & HEAD 29903946028dSAppaRao Puli // method for security reasons. 29910fda0f12SGeorge Liu BMCWEB_ROUTE( 29920fda0f12SGeorge Liu app, 299322d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Crashdump/Actions/LogService.CollectDiagnosticData/") 2994ed398213SEd Tanous // The below is incorrect; Should be ConfigureManager 2995ed398213SEd Tanous //.privileges(redfish::privileges::postLogService) 2996432a890cSEd Tanous .privileges({{"ConfigureComponents"}}) 2997002d39b4SEd Tanous .methods(boost::beast::http::verb::post)( 2998002d39b4SEd Tanous [&app](const crow::Request& req, 299922d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 300022d268cbSEd Tanous const std::string& systemName) { 30013ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 300245ca1b86SEd Tanous { 300345ca1b86SEd Tanous return; 300445ca1b86SEd Tanous } 300522d268cbSEd Tanous 300625b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 30077f3e84a1SEd Tanous { 30087f3e84a1SEd Tanous // Option currently returns no systems. TBD 30097f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 30107f3e84a1SEd Tanous systemName); 30117f3e84a1SEd Tanous return; 30127f3e84a1SEd Tanous } 3013253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 301422d268cbSEd Tanous { 301522d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 301622d268cbSEd Tanous systemName); 301722d268cbSEd Tanous return; 301822d268cbSEd Tanous } 301922d268cbSEd Tanous 30208e6c099aSJason M. Bills std::string diagnosticDataType; 30218e6c099aSJason M. Bills std::string oemDiagnosticDataType; 3022afc474aeSMyung Bae if (!redfish::json_util::readJsonAction( // 3023afc474aeSMyung Bae req, asyncResp->res, // 3024afc474aeSMyung Bae "DiagnosticDataType", diagnosticDataType, // 3025afc474aeSMyung Bae "OEMDiagnosticDataType", oemDiagnosticDataType // 3026afc474aeSMyung Bae )) 30278e6c099aSJason M. Bills { 30288e6c099aSJason M. Bills return; 30298e6c099aSJason M. Bills } 30308e6c099aSJason M. Bills 30318e6c099aSJason M. Bills if (diagnosticDataType != "OEM") 30328e6c099aSJason M. Bills { 303362598e31SEd Tanous BMCWEB_LOG_ERROR( 303462598e31SEd Tanous "Only OEM DiagnosticDataType supported for Crashdump"); 30358e6c099aSJason M. Bills messages::actionParameterValueFormatError( 3036bd79bce8SPatrick Williams asyncResp->res, diagnosticDataType, 3037bd79bce8SPatrick Williams "DiagnosticDataType", "CollectDiagnosticData"); 30388e6c099aSJason M. Bills return; 30398e6c099aSJason M. Bills } 30408e6c099aSJason M. Bills 3041c5a4c82aSJason M. Bills OEMDiagnosticType oemDiagType = 3042c5a4c82aSJason M. Bills getOEMDiagnosticType(oemDiagnosticDataType); 3043c5a4c82aSJason M. Bills 3044c5a4c82aSJason M. Bills std::string iface; 3045c5a4c82aSJason M. Bills std::string method; 3046c5a4c82aSJason M. Bills std::string taskMatchStr; 3047c5a4c82aSJason M. Bills if (oemDiagType == OEMDiagnosticType::onDemand) 3048c5a4c82aSJason M. Bills { 3049c5a4c82aSJason M. Bills iface = crashdumpOnDemandInterface; 3050c5a4c82aSJason M. Bills method = "GenerateOnDemandLog"; 3051bd79bce8SPatrick Williams taskMatchStr = 3052bd79bce8SPatrick Williams "type='signal'," 3053c5a4c82aSJason M. Bills "interface='org.freedesktop.DBus.Properties'," 3054c5a4c82aSJason M. Bills "member='PropertiesChanged'," 3055c5a4c82aSJason M. Bills "arg0namespace='com.intel.crashdump'"; 3056c5a4c82aSJason M. Bills } 3057c5a4c82aSJason M. Bills else if (oemDiagType == OEMDiagnosticType::telemetry) 3058c5a4c82aSJason M. Bills { 3059c5a4c82aSJason M. Bills iface = crashdumpTelemetryInterface; 3060c5a4c82aSJason M. Bills method = "GenerateTelemetryLog"; 3061bd79bce8SPatrick Williams taskMatchStr = 3062bd79bce8SPatrick Williams "type='signal'," 3063c5a4c82aSJason M. Bills "interface='org.freedesktop.DBus.Properties'," 3064c5a4c82aSJason M. Bills "member='PropertiesChanged'," 3065c5a4c82aSJason M. Bills "arg0namespace='com.intel.crashdump'"; 3066c5a4c82aSJason M. Bills } 3067c5a4c82aSJason M. Bills else 3068c5a4c82aSJason M. Bills { 306962598e31SEd Tanous BMCWEB_LOG_ERROR("Unsupported OEMDiagnosticDataType: {}", 307062598e31SEd Tanous oemDiagnosticDataType); 3071c5a4c82aSJason M. Bills messages::actionParameterValueFormatError( 3072bd79bce8SPatrick Williams asyncResp->res, oemDiagnosticDataType, 3073bd79bce8SPatrick Williams "OEMDiagnosticDataType", "CollectDiagnosticData"); 3074c5a4c82aSJason M. Bills return; 3075c5a4c82aSJason M. Bills } 3076c5a4c82aSJason M. Bills 3077c5a4c82aSJason M. Bills auto collectCrashdumpCallback = 3078c5a4c82aSJason M. Bills [asyncResp, payload(task::Payload(req)), 30795e7e2dc5SEd Tanous taskMatchStr](const boost::system::error_code& ec, 308098be3e39SEd Tanous const std::string&) mutable { 30811da66f75SEd Tanous if (ec) 30821da66f75SEd Tanous { 3083bd79bce8SPatrick Williams if (ec.value() == 3084bd79bce8SPatrick Williams boost::system::errc::operation_not_supported) 30851da66f75SEd Tanous { 3086f12894f8SJason M. Bills messages::resourceInStandby(asyncResp->res); 30871da66f75SEd Tanous } 3088bd79bce8SPatrick Williams else if (ec.value() == boost::system::errc:: 3089bd79bce8SPatrick Williams device_or_resource_busy) 30904363d3b2SJason M. Bills { 3091bd79bce8SPatrick Williams messages::serviceTemporarilyUnavailable( 3092bd79bce8SPatrick Williams asyncResp->res, "60"); 30934363d3b2SJason M. Bills } 30941da66f75SEd Tanous else 30951da66f75SEd Tanous { 3096f12894f8SJason M. Bills messages::internalError(asyncResp->res); 30971da66f75SEd Tanous } 30981da66f75SEd Tanous return; 30991da66f75SEd Tanous } 3100bd79bce8SPatrick Williams std::shared_ptr<task::TaskData> task = 3101bd79bce8SPatrick Williams task::TaskData::createTask( 3102bd79bce8SPatrick Williams [](const boost::system::error_code& ec2, 3103bd79bce8SPatrick Williams sdbusplus::message_t&, 3104bd79bce8SPatrick Williams const std::shared_ptr<task::TaskData>& 3105bd79bce8SPatrick Williams taskData) { 31068b24275dSEd Tanous if (!ec2) 310766afe4faSJames Feist { 3108bd79bce8SPatrick Williams taskData->messages.emplace_back( 3109bd79bce8SPatrick Williams messages::taskCompletedOK( 3110bd79bce8SPatrick Williams std::to_string( 3111bd79bce8SPatrick Williams taskData->index))); 3112831d6b09SJames Feist taskData->state = "Completed"; 311366afe4faSJames Feist } 311432898ceaSJames Feist return task::completed; 311566afe4faSJames Feist }, 3116c5a4c82aSJason M. Bills taskMatchStr); 3117c5a4c82aSJason M. Bills 311846229577SJames Feist task->startTimer(std::chrono::minutes(5)); 311998be3e39SEd Tanous task->payload.emplace(std::move(payload)); 3120*29e2bdd7SChinmay Shripad Hegde task->populateResp(asyncResp->res); 31211da66f75SEd Tanous }; 31228e6c099aSJason M. Bills 3123177612aaSEd Tanous dbus::utility::async_method_call( 3124177612aaSEd Tanous asyncResp, std::move(collectCrashdumpCallback), 3125177612aaSEd Tanous crashdumpObject, crashdumpPath, iface, method); 31267e860f15SJohn Edward Broadbent }); 31276eda7685SKenny L. Ku } 31286eda7685SKenny L. Ku 3129599b9af3SAlexander Hansen inline void dBusLogServiceActionsClear( 3130599b9af3SAlexander Hansen const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 3131599b9af3SAlexander Hansen { 3132599b9af3SAlexander Hansen BMCWEB_LOG_DEBUG("Do delete all entries."); 3133599b9af3SAlexander Hansen 3134599b9af3SAlexander Hansen // Process response from Logging service. 3135599b9af3SAlexander Hansen auto respHandler = [asyncResp](const boost::system::error_code& ec) { 3136599b9af3SAlexander Hansen BMCWEB_LOG_DEBUG("doClearLog resp_handler callback: Done"); 3137599b9af3SAlexander Hansen if (ec) 3138599b9af3SAlexander Hansen { 3139599b9af3SAlexander Hansen // TODO Handle for specific error code 3140599b9af3SAlexander Hansen BMCWEB_LOG_ERROR("doClearLog resp_handler got error {}", ec); 3141599b9af3SAlexander Hansen asyncResp->res.result( 3142599b9af3SAlexander Hansen boost::beast::http::status::internal_server_error); 3143599b9af3SAlexander Hansen return; 3144599b9af3SAlexander Hansen } 3145599b9af3SAlexander Hansen 3146e2460466SAmy Chang messages::success(asyncResp->res); 3147599b9af3SAlexander Hansen }; 3148599b9af3SAlexander Hansen 3149599b9af3SAlexander Hansen // Make call to Logging service to request Clear Log 3150177612aaSEd Tanous dbus::utility::async_method_call( 3151177612aaSEd Tanous asyncResp, respHandler, "xyz.openbmc_project.Logging", 3152599b9af3SAlexander Hansen "/xyz/openbmc_project/logging", 3153599b9af3SAlexander Hansen "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll"); 3154599b9af3SAlexander Hansen } 3155599b9af3SAlexander Hansen 3156cb92c03bSAndrew Geissler /** 3157cb92c03bSAndrew Geissler * DBusLogServiceActionsClear class supports POST method for ClearLog action. 3158cb92c03bSAndrew Geissler */ 31597e860f15SJohn Edward Broadbent inline void requestRoutesDBusLogServiceActionsClear(App& app) 3160cb92c03bSAndrew Geissler { 3161cb92c03bSAndrew Geissler /** 3162cb92c03bSAndrew Geissler * Function handles POST method request. 3163cb92c03bSAndrew Geissler * The Clear Log actions does not require any parameter.The action deletes 3164cb92c03bSAndrew Geissler * all entries found in the Entries collection for this Log Service. 3165cb92c03bSAndrew Geissler */ 31667e860f15SJohn Edward Broadbent 31670fda0f12SGeorge Liu BMCWEB_ROUTE( 31680fda0f12SGeorge Liu app, 316922d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/EventLog/Actions/LogService.ClearLog/") 3170ed398213SEd Tanous .privileges(redfish::privileges::postLogService) 31717e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 317245ca1b86SEd Tanous [&app](const crow::Request& req, 317322d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 317422d268cbSEd Tanous const std::string& systemName) { 31753ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 317645ca1b86SEd Tanous { 317745ca1b86SEd Tanous return; 317845ca1b86SEd Tanous } 317925b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 31807f3e84a1SEd Tanous { 31817f3e84a1SEd Tanous // Option currently returns no systems. TBD 31827f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 31837f3e84a1SEd Tanous systemName); 31847f3e84a1SEd Tanous return; 31857f3e84a1SEd Tanous } 3186253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 318722d268cbSEd Tanous { 318822d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 318922d268cbSEd Tanous systemName); 319022d268cbSEd Tanous return; 319122d268cbSEd Tanous } 3192599b9af3SAlexander Hansen dBusLogServiceActionsClear(asyncResp); 31937e860f15SJohn Edward Broadbent }); 3194cb92c03bSAndrew Geissler } 3195a3316fc6SZhikuiRen 31961da66f75SEd Tanous } // namespace redfish 3197