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" 30*ff35df94SOliver Brewka #include "utils/log_services_utils.hpp" 31d7857201SEd Tanous #include "utils/query_param.hpp" 323ccb3adbSEd Tanous #include "utils/time_utils.hpp" 331da66f75SEd Tanous 34d7857201SEd Tanous #include <asm-generic/errno.h> 35d7857201SEd Tanous #include <systemd/sd-bus.h> 368e31778eSAsmitha Karunanithi #include <tinyxml2.h> 37400fd1fbSAdriana Kobylak #include <unistd.h> 38e1f26343SJason M. Bills 39d7857201SEd Tanous #include <boost/beast/http/field.hpp> 40d7857201SEd Tanous #include <boost/beast/http/status.hpp> 4107c8c20dSEd Tanous #include <boost/beast/http/verb.hpp> 421ddcf01aSJason M. Bills #include <boost/system/linux_error.hpp> 43ef4c65b7SEd Tanous #include <boost/url/format.hpp> 44d7857201SEd Tanous #include <boost/url/url.hpp> 45d7857201SEd Tanous #include <sdbusplus/message.hpp> 46d7857201SEd Tanous #include <sdbusplus/message/native_types.hpp> 47d1bde9e5SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp> 481214b7e7SGunnar Mills 49d7857201SEd Tanous #include <algorithm> 507a1dbc48SGeorge Liu #include <array> 51d7857201SEd Tanous #include <chrono> 52b5f288d2SAbhilash Raju #include <cstddef> 53d7857201SEd Tanous #include <cstdint> 54d7857201SEd Tanous #include <cstdio> 55d7857201SEd Tanous #include <ctime> 564418c7f0SJames Feist #include <filesystem> 57d7857201SEd Tanous #include <format> 58d7857201SEd Tanous #include <fstream> 59d7857201SEd Tanous #include <functional> 60d7857201SEd Tanous #include <iomanip> 6118f8f608SEd Tanous #include <iterator> 62d7857201SEd Tanous #include <memory> 6375710de2SXiaochao Ma #include <optional> 643544d2a7SEd Tanous #include <ranges> 6526702d01SEd Tanous #include <span> 66d7857201SEd Tanous #include <sstream> 6718f8f608SEd Tanous #include <string> 68cd225da8SJason M. Bills #include <string_view> 69d7857201SEd Tanous #include <system_error> 70d7857201SEd Tanous #include <utility> 71abf2add6SEd Tanous #include <variant> 72d7857201SEd Tanous #include <vector> 731da66f75SEd Tanous 741da66f75SEd Tanous namespace redfish 751da66f75SEd Tanous { 761da66f75SEd Tanous 7789492a15SPatrick Williams constexpr const char* crashdumpObject = "com.intel.crashdump"; 7889492a15SPatrick Williams constexpr const char* crashdumpPath = "/com/intel/crashdump"; 7989492a15SPatrick Williams constexpr const char* crashdumpInterface = "com.intel.crashdump"; 8089492a15SPatrick Williams constexpr const char* deleteAllInterface = 815b61b5e8SJason M. Bills "xyz.openbmc_project.Collection.DeleteAll"; 8289492a15SPatrick Williams constexpr const char* crashdumpOnDemandInterface = 83424c4176SJason M. Bills "com.intel.crashdump.OnDemand"; 8489492a15SPatrick Williams constexpr const char* crashdumpTelemetryInterface = 856eda7685SKenny L. Ku "com.intel.crashdump.Telemetry"; 861da66f75SEd Tanous 878e31778eSAsmitha Karunanithi enum class DumpCreationProgress 888e31778eSAsmitha Karunanithi { 898e31778eSAsmitha Karunanithi DUMP_CREATE_SUCCESS, 908e31778eSAsmitha Karunanithi DUMP_CREATE_FAILED, 918e31778eSAsmitha Karunanithi DUMP_CREATE_INPROGRESS 928e31778eSAsmitha Karunanithi }; 938e31778eSAsmitha Karunanithi 94cb92c03bSAndrew Geissler inline std::string translateSeverityDbusToRedfish(const std::string& s) 95cb92c03bSAndrew Geissler { 96d4d25793SEd Tanous if ((s == "xyz.openbmc_project.Logging.Entry.Level.Alert") || 97d4d25793SEd Tanous (s == "xyz.openbmc_project.Logging.Entry.Level.Critical") || 98d4d25793SEd Tanous (s == "xyz.openbmc_project.Logging.Entry.Level.Emergency") || 99d4d25793SEd Tanous (s == "xyz.openbmc_project.Logging.Entry.Level.Error")) 100cb92c03bSAndrew Geissler { 101cb92c03bSAndrew Geissler return "Critical"; 102cb92c03bSAndrew Geissler } 1033174e4dfSEd Tanous if ((s == "xyz.openbmc_project.Logging.Entry.Level.Debug") || 104d4d25793SEd Tanous (s == "xyz.openbmc_project.Logging.Entry.Level.Informational") || 105d4d25793SEd Tanous (s == "xyz.openbmc_project.Logging.Entry.Level.Notice")) 106cb92c03bSAndrew Geissler { 107cb92c03bSAndrew Geissler return "OK"; 108cb92c03bSAndrew Geissler } 1093174e4dfSEd Tanous if (s == "xyz.openbmc_project.Logging.Entry.Level.Warning") 110cb92c03bSAndrew Geissler { 111cb92c03bSAndrew Geissler return "Warning"; 112cb92c03bSAndrew Geissler } 113cb92c03bSAndrew Geissler return ""; 114cb92c03bSAndrew Geissler } 115cb92c03bSAndrew Geissler 1169017faf2SAbhishek Patel inline std::optional<bool> getProviderNotifyAction(const std::string& notify) 1179017faf2SAbhishek Patel { 1189017faf2SAbhishek Patel std::optional<bool> notifyAction; 1199017faf2SAbhishek Patel if (notify == "xyz.openbmc_project.Logging.Entry.Notify.Notify") 1209017faf2SAbhishek Patel { 1219017faf2SAbhishek Patel notifyAction = true; 1229017faf2SAbhishek Patel } 1239017faf2SAbhishek Patel else if (notify == "xyz.openbmc_project.Logging.Entry.Notify.Inhibit") 1249017faf2SAbhishek Patel { 1259017faf2SAbhishek Patel notifyAction = false; 1269017faf2SAbhishek Patel } 1279017faf2SAbhishek Patel 1289017faf2SAbhishek Patel return notifyAction; 1299017faf2SAbhishek Patel } 1309017faf2SAbhishek Patel 13118f8f608SEd Tanous inline std::string getDumpPath(std::string_view dumpType) 13218f8f608SEd Tanous { 13318f8f608SEd Tanous std::string dbusDumpPath = "/xyz/openbmc_project/dump/"; 13418f8f608SEd Tanous std::ranges::transform(dumpType, std::back_inserter(dbusDumpPath), 13518f8f608SEd Tanous bmcweb::asciiToLower); 13618f8f608SEd Tanous 13718f8f608SEd Tanous return dbusDumpPath; 13818f8f608SEd Tanous } 13918f8f608SEd Tanous 140055713e4SEd Tanous inline bool getUniqueEntryID(const std::string& logEntry, std::string& entryID, 141e85d6b16SJason M. Bills const bool firstEntry = true) 14295820184SJason M. Bills { 143271584abSEd Tanous static time_t prevTs = 0; 14495820184SJason M. Bills static int index = 0; 145e85d6b16SJason M. Bills if (firstEntry) 146e85d6b16SJason M. Bills { 147e85d6b16SJason M. Bills prevTs = 0; 148e85d6b16SJason M. Bills } 149e85d6b16SJason M. Bills 15095820184SJason M. Bills // Get the entry timestamp 151271584abSEd Tanous std::time_t curTs = 0; 15295820184SJason M. Bills std::tm timeStruct = {}; 15395820184SJason M. Bills std::istringstream entryStream(logEntry); 15495820184SJason M. Bills if (entryStream >> std::get_time(&timeStruct, "%Y-%m-%dT%H:%M:%S")) 15595820184SJason M. Bills { 15695820184SJason M. Bills curTs = std::mktime(&timeStruct); 15795820184SJason M. Bills } 15895820184SJason M. Bills // If the timestamp isn't unique, increment the index 15995820184SJason M. Bills if (curTs == prevTs) 16095820184SJason M. Bills { 16195820184SJason M. Bills index++; 16295820184SJason M. Bills } 16395820184SJason M. Bills else 16495820184SJason M. Bills { 16595820184SJason M. Bills // Otherwise, reset it 16695820184SJason M. Bills index = 0; 16795820184SJason M. Bills } 16895820184SJason M. Bills // Save the timestamp 16995820184SJason M. Bills prevTs = curTs; 17095820184SJason M. Bills 17195820184SJason M. Bills entryID = std::to_string(curTs); 17295820184SJason M. Bills if (index > 0) 17395820184SJason M. Bills { 17495820184SJason M. Bills entryID += "_" + std::to_string(index); 17595820184SJason M. Bills } 17695820184SJason M. Bills return true; 17795820184SJason M. Bills } 17895820184SJason M. Bills 179504af5a0SPatrick Williams inline bool getRedfishLogFiles( 180504af5a0SPatrick Williams std::vector<std::filesystem::path>& redfishLogFiles) 18195820184SJason M. Bills { 18295820184SJason M. Bills static const std::filesystem::path redfishLogDir = "/var/log"; 18395820184SJason M. Bills static const std::string redfishLogFilename = "redfish"; 18495820184SJason M. Bills 18595820184SJason M. Bills // Loop through the directory looking for redfish log files 18695820184SJason M. Bills for (const std::filesystem::directory_entry& dirEnt : 18795820184SJason M. Bills std::filesystem::directory_iterator(redfishLogDir)) 18895820184SJason M. Bills { 18995820184SJason M. Bills // If we find a redfish log file, save the path 19095820184SJason M. Bills std::string filename = dirEnt.path().filename(); 19111ba3979SEd Tanous if (filename.starts_with(redfishLogFilename)) 19295820184SJason M. Bills { 19395820184SJason M. Bills redfishLogFiles.emplace_back(redfishLogDir / filename); 19495820184SJason M. Bills } 19595820184SJason M. Bills } 19695820184SJason M. Bills // As the log files rotate, they are appended with a ".#" that is higher for 19795820184SJason M. Bills // the older logs. Since we don't expect more than 10 log files, we 19895820184SJason M. Bills // can just sort the list to get them in order from newest to oldest 1993544d2a7SEd Tanous std::ranges::sort(redfishLogFiles); 20095820184SJason M. Bills 20195820184SJason M. Bills return !redfishLogFiles.empty(); 20295820184SJason M. Bills } 20395820184SJason M. Bills 204504af5a0SPatrick Williams inline log_entry::OriginatorTypes mapDbusOriginatorTypeToRedfish( 205504af5a0SPatrick Williams const std::string& originatorType) 20668dd075aSAsmitha Karunanithi { 20768dd075aSAsmitha Karunanithi if (originatorType == 20868dd075aSAsmitha Karunanithi "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Client") 20968dd075aSAsmitha Karunanithi { 21068dd075aSAsmitha Karunanithi return log_entry::OriginatorTypes::Client; 21168dd075aSAsmitha Karunanithi } 21268dd075aSAsmitha Karunanithi if (originatorType == 21368dd075aSAsmitha Karunanithi "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Internal") 21468dd075aSAsmitha Karunanithi { 21568dd075aSAsmitha Karunanithi return log_entry::OriginatorTypes::Internal; 21668dd075aSAsmitha Karunanithi } 21768dd075aSAsmitha Karunanithi if (originatorType == 21868dd075aSAsmitha Karunanithi "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.SupportingService") 21968dd075aSAsmitha Karunanithi { 22068dd075aSAsmitha Karunanithi return log_entry::OriginatorTypes::SupportingService; 22168dd075aSAsmitha Karunanithi } 22268dd075aSAsmitha Karunanithi return log_entry::OriginatorTypes::Invalid; 22368dd075aSAsmitha Karunanithi } 22468dd075aSAsmitha Karunanithi 225aefe3786SClaire Weinan inline void parseDumpEntryFromDbusObject( 2262d613eb6SJiaqing Zhao const dbus::utility::ManagedObjectType::value_type& object, 227c6fecdabSClaire Weinan std::string& dumpStatus, uint64_t& size, uint64_t& timestampUs, 22868dd075aSAsmitha Karunanithi std::string& originatorId, log_entry::OriginatorTypes& originatorType, 229aefe3786SClaire Weinan const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 230aefe3786SClaire Weinan { 231aefe3786SClaire Weinan for (const auto& interfaceMap : object.second) 232aefe3786SClaire Weinan { 233aefe3786SClaire Weinan if (interfaceMap.first == "xyz.openbmc_project.Common.Progress") 234aefe3786SClaire Weinan { 235aefe3786SClaire Weinan for (const auto& propertyMap : interfaceMap.second) 236aefe3786SClaire Weinan { 237aefe3786SClaire Weinan if (propertyMap.first == "Status") 238aefe3786SClaire Weinan { 239aefe3786SClaire Weinan const auto* status = 240aefe3786SClaire Weinan std::get_if<std::string>(&propertyMap.second); 241aefe3786SClaire Weinan if (status == nullptr) 242aefe3786SClaire Weinan { 243aefe3786SClaire Weinan messages::internalError(asyncResp->res); 244aefe3786SClaire Weinan break; 245aefe3786SClaire Weinan } 246aefe3786SClaire Weinan dumpStatus = *status; 247aefe3786SClaire Weinan } 248aefe3786SClaire Weinan } 249aefe3786SClaire Weinan } 250aefe3786SClaire Weinan else if (interfaceMap.first == "xyz.openbmc_project.Dump.Entry") 251aefe3786SClaire Weinan { 252aefe3786SClaire Weinan for (const auto& propertyMap : interfaceMap.second) 253aefe3786SClaire Weinan { 254aefe3786SClaire Weinan if (propertyMap.first == "Size") 255aefe3786SClaire Weinan { 256aefe3786SClaire Weinan const auto* sizePtr = 257aefe3786SClaire Weinan std::get_if<uint64_t>(&propertyMap.second); 258aefe3786SClaire Weinan if (sizePtr == nullptr) 259aefe3786SClaire Weinan { 260aefe3786SClaire Weinan messages::internalError(asyncResp->res); 261aefe3786SClaire Weinan break; 262aefe3786SClaire Weinan } 263aefe3786SClaire Weinan size = *sizePtr; 264aefe3786SClaire Weinan break; 265aefe3786SClaire Weinan } 266aefe3786SClaire Weinan } 267aefe3786SClaire Weinan } 268aefe3786SClaire Weinan else if (interfaceMap.first == "xyz.openbmc_project.Time.EpochTime") 269aefe3786SClaire Weinan { 270aefe3786SClaire Weinan for (const auto& propertyMap : interfaceMap.second) 271aefe3786SClaire Weinan { 272aefe3786SClaire Weinan if (propertyMap.first == "Elapsed") 273aefe3786SClaire Weinan { 274aefe3786SClaire Weinan const uint64_t* usecsTimeStamp = 275aefe3786SClaire Weinan std::get_if<uint64_t>(&propertyMap.second); 276aefe3786SClaire Weinan if (usecsTimeStamp == nullptr) 277aefe3786SClaire Weinan { 278aefe3786SClaire Weinan messages::internalError(asyncResp->res); 279aefe3786SClaire Weinan break; 280aefe3786SClaire Weinan } 281c6fecdabSClaire Weinan timestampUs = *usecsTimeStamp; 282aefe3786SClaire Weinan break; 283aefe3786SClaire Weinan } 284aefe3786SClaire Weinan } 285aefe3786SClaire Weinan } 28668dd075aSAsmitha Karunanithi else if (interfaceMap.first == 28768dd075aSAsmitha Karunanithi "xyz.openbmc_project.Common.OriginatedBy") 28868dd075aSAsmitha Karunanithi { 28968dd075aSAsmitha Karunanithi for (const auto& propertyMap : interfaceMap.second) 29068dd075aSAsmitha Karunanithi { 29168dd075aSAsmitha Karunanithi if (propertyMap.first == "OriginatorId") 29268dd075aSAsmitha Karunanithi { 29368dd075aSAsmitha Karunanithi const std::string* id = 29468dd075aSAsmitha Karunanithi std::get_if<std::string>(&propertyMap.second); 29568dd075aSAsmitha Karunanithi if (id == nullptr) 29668dd075aSAsmitha Karunanithi { 29768dd075aSAsmitha Karunanithi messages::internalError(asyncResp->res); 29868dd075aSAsmitha Karunanithi break; 29968dd075aSAsmitha Karunanithi } 30068dd075aSAsmitha Karunanithi originatorId = *id; 30168dd075aSAsmitha Karunanithi } 30268dd075aSAsmitha Karunanithi 30368dd075aSAsmitha Karunanithi if (propertyMap.first == "OriginatorType") 30468dd075aSAsmitha Karunanithi { 30568dd075aSAsmitha Karunanithi const std::string* type = 30668dd075aSAsmitha Karunanithi std::get_if<std::string>(&propertyMap.second); 30768dd075aSAsmitha Karunanithi if (type == nullptr) 30868dd075aSAsmitha Karunanithi { 30968dd075aSAsmitha Karunanithi messages::internalError(asyncResp->res); 31068dd075aSAsmitha Karunanithi break; 31168dd075aSAsmitha Karunanithi } 31268dd075aSAsmitha Karunanithi 31368dd075aSAsmitha Karunanithi originatorType = mapDbusOriginatorTypeToRedfish(*type); 31468dd075aSAsmitha Karunanithi if (originatorType == log_entry::OriginatorTypes::Invalid) 31568dd075aSAsmitha Karunanithi { 31668dd075aSAsmitha Karunanithi messages::internalError(asyncResp->res); 31768dd075aSAsmitha Karunanithi break; 31868dd075aSAsmitha Karunanithi } 31968dd075aSAsmitha Karunanithi } 32068dd075aSAsmitha Karunanithi } 32168dd075aSAsmitha Karunanithi } 322aefe3786SClaire Weinan } 323aefe3786SClaire Weinan } 324aefe3786SClaire Weinan 32521ab404cSNan Zhou static std::string getDumpEntriesPath(const std::string& dumpType) 326fdd26906SClaire Weinan { 327fdd26906SClaire Weinan std::string entriesPath; 328fdd26906SClaire Weinan 329fdd26906SClaire Weinan if (dumpType == "BMC") 330fdd26906SClaire Weinan { 331253f11b8SEd Tanous entriesPath = 332253f11b8SEd Tanous std::format("/redfish/v1/Managers/{}/LogServices/Dump/Entries/", 333253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 334fdd26906SClaire Weinan } 335fdd26906SClaire Weinan else if (dumpType == "FaultLog") 336fdd26906SClaire Weinan { 337253f11b8SEd Tanous entriesPath = 338253f11b8SEd Tanous std::format("/redfish/v1/Managers/{}/LogServices/FaultLog/Entries/", 339253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 340fdd26906SClaire Weinan } 341fdd26906SClaire Weinan else if (dumpType == "System") 342fdd26906SClaire Weinan { 343253f11b8SEd Tanous entriesPath = 344253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/Dump/Entries/", 345253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 346fdd26906SClaire Weinan } 347fdd26906SClaire Weinan else 348fdd26906SClaire Weinan { 34962598e31SEd Tanous BMCWEB_LOG_ERROR("getDumpEntriesPath() invalid dump type: {}", 35062598e31SEd Tanous dumpType); 351fdd26906SClaire Weinan } 352fdd26906SClaire Weinan 353fdd26906SClaire Weinan // Returns empty string on error 354fdd26906SClaire Weinan return entriesPath; 355fdd26906SClaire Weinan } 356fdd26906SClaire Weinan 357504af5a0SPatrick Williams inline void getDumpEntryCollection( 358504af5a0SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 3595cb1dd27SAsmitha Karunanithi const std::string& dumpType) 3605cb1dd27SAsmitha Karunanithi { 361fdd26906SClaire Weinan std::string entriesPath = getDumpEntriesPath(dumpType); 362fdd26906SClaire Weinan if (entriesPath.empty()) 3635cb1dd27SAsmitha Karunanithi { 3645cb1dd27SAsmitha Karunanithi messages::internalError(asyncResp->res); 3655cb1dd27SAsmitha Karunanithi return; 3665cb1dd27SAsmitha Karunanithi } 3675cb1dd27SAsmitha Karunanithi 3685eb468daSGeorge Liu sdbusplus::message::object_path path("/xyz/openbmc_project/dump"); 3695eb468daSGeorge Liu dbus::utility::getManagedObjects( 3705eb468daSGeorge Liu "xyz.openbmc_project.Dump.Manager", path, 371fdd26906SClaire Weinan [asyncResp, entriesPath, 3725e7e2dc5SEd Tanous dumpType](const boost::system::error_code& ec, 3735eb468daSGeorge Liu const dbus::utility::ManagedObjectType& objects) { 3745cb1dd27SAsmitha Karunanithi if (ec) 3755cb1dd27SAsmitha Karunanithi { 37662598e31SEd Tanous BMCWEB_LOG_ERROR("DumpEntry resp_handler got error {}", ec); 3775cb1dd27SAsmitha Karunanithi messages::internalError(asyncResp->res); 3785cb1dd27SAsmitha Karunanithi return; 3795cb1dd27SAsmitha Karunanithi } 3805cb1dd27SAsmitha Karunanithi 381fdd26906SClaire Weinan // Remove ending slash 382fdd26906SClaire Weinan std::string odataIdStr = entriesPath; 383fdd26906SClaire Weinan if (!odataIdStr.empty()) 384fdd26906SClaire Weinan { 385fdd26906SClaire Weinan odataIdStr.pop_back(); 386fdd26906SClaire Weinan } 387fdd26906SClaire Weinan 388fdd26906SClaire Weinan asyncResp->res.jsonValue["@odata.type"] = 389fdd26906SClaire Weinan "#LogEntryCollection.LogEntryCollection"; 390fdd26906SClaire Weinan asyncResp->res.jsonValue["@odata.id"] = std::move(odataIdStr); 391fdd26906SClaire Weinan asyncResp->res.jsonValue["Name"] = dumpType + " Dump Entries"; 392bd79bce8SPatrick Williams asyncResp->res.jsonValue["Description"] = 393bd79bce8SPatrick Williams "Collection of " + dumpType + " Dump Entries"; 394fdd26906SClaire Weinan 3953544d2a7SEd Tanous nlohmann::json::array_t entriesArray; 39618f8f608SEd Tanous std::string dumpEntryPath = getDumpPath(dumpType) + "/entry/"; 3975cb1dd27SAsmitha Karunanithi 3985eb468daSGeorge Liu dbus::utility::ManagedObjectType resp(objects); 3993544d2a7SEd Tanous std::ranges::sort(resp, [](const auto& l, const auto& r) { 400002d39b4SEd Tanous return AlphanumLess<std::string>()(l.first.filename(), 401002d39b4SEd Tanous r.first.filename()); 402565dfb6fSClaire Weinan }); 403565dfb6fSClaire Weinan 4045cb1dd27SAsmitha Karunanithi for (auto& object : resp) 4055cb1dd27SAsmitha Karunanithi { 406b47452b2SAsmitha Karunanithi if (object.first.str.find(dumpEntryPath) == std::string::npos) 4075cb1dd27SAsmitha Karunanithi { 4085cb1dd27SAsmitha Karunanithi continue; 4095cb1dd27SAsmitha Karunanithi } 410c6fecdabSClaire Weinan uint64_t timestampUs = 0; 4115cb1dd27SAsmitha Karunanithi uint64_t size = 0; 41235440d18SAsmitha Karunanithi std::string dumpStatus; 41368dd075aSAsmitha Karunanithi std::string originatorId; 41468dd075aSAsmitha Karunanithi log_entry::OriginatorTypes originatorType = 41568dd075aSAsmitha Karunanithi log_entry::OriginatorTypes::Internal; 416433b68b4SJason M. Bills nlohmann::json::object_t thisEntry; 4172dfd18efSEd Tanous 4182dfd18efSEd Tanous std::string entryID = object.first.filename(); 4192dfd18efSEd Tanous if (entryID.empty()) 4205cb1dd27SAsmitha Karunanithi { 4215cb1dd27SAsmitha Karunanithi continue; 4225cb1dd27SAsmitha Karunanithi } 4235cb1dd27SAsmitha Karunanithi 424bd79bce8SPatrick Williams parseDumpEntryFromDbusObject(object, dumpStatus, size, 425bd79bce8SPatrick Williams timestampUs, originatorId, 426bd79bce8SPatrick Williams originatorType, asyncResp); 4275cb1dd27SAsmitha Karunanithi 4280fda0f12SGeorge Liu if (dumpStatus != 4290fda0f12SGeorge Liu "xyz.openbmc_project.Common.Progress.OperationStatus.Completed" && 43035440d18SAsmitha Karunanithi !dumpStatus.empty()) 43135440d18SAsmitha Karunanithi { 43235440d18SAsmitha Karunanithi // Dump status is not Complete, no need to enumerate 43335440d18SAsmitha Karunanithi continue; 43435440d18SAsmitha Karunanithi } 43535440d18SAsmitha Karunanithi 43668dd075aSAsmitha Karunanithi thisEntry["@odata.type"] = "#LogEntry.v1_11_0.LogEntry"; 437fdd26906SClaire Weinan thisEntry["@odata.id"] = entriesPath + entryID; 4385cb1dd27SAsmitha Karunanithi thisEntry["Id"] = entryID; 4395cb1dd27SAsmitha Karunanithi thisEntry["EntryType"] = "Event"; 4405cb1dd27SAsmitha Karunanithi thisEntry["Name"] = dumpType + " Dump Entry"; 441bbd80db8SClaire Weinan thisEntry["Created"] = 442bbd80db8SClaire Weinan redfish::time_utils::getDateTimeUintUs(timestampUs); 4435cb1dd27SAsmitha Karunanithi 44468dd075aSAsmitha Karunanithi if (!originatorId.empty()) 44568dd075aSAsmitha Karunanithi { 44668dd075aSAsmitha Karunanithi thisEntry["Originator"] = originatorId; 44768dd075aSAsmitha Karunanithi thisEntry["OriginatorType"] = originatorType; 44868dd075aSAsmitha Karunanithi } 44968dd075aSAsmitha Karunanithi 4505cb1dd27SAsmitha Karunanithi if (dumpType == "BMC") 4515cb1dd27SAsmitha Karunanithi { 452d337bb72SAsmitha Karunanithi thisEntry["DiagnosticDataType"] = "Manager"; 453bd79bce8SPatrick Williams thisEntry["AdditionalDataURI"] = 454bd79bce8SPatrick Williams entriesPath + entryID + "/attachment"; 455fdd26906SClaire Weinan thisEntry["AdditionalDataSizeBytes"] = size; 4565cb1dd27SAsmitha Karunanithi } 4575cb1dd27SAsmitha Karunanithi else if (dumpType == "System") 4585cb1dd27SAsmitha Karunanithi { 459d337bb72SAsmitha Karunanithi thisEntry["DiagnosticDataType"] = "OEM"; 460d337bb72SAsmitha Karunanithi thisEntry["OEMDiagnosticDataType"] = "System"; 461bd79bce8SPatrick Williams thisEntry["AdditionalDataURI"] = 462bd79bce8SPatrick Williams entriesPath + entryID + "/attachment"; 463fdd26906SClaire Weinan thisEntry["AdditionalDataSizeBytes"] = size; 4645cb1dd27SAsmitha Karunanithi } 465b2ba3072SPatrick Williams entriesArray.emplace_back(std::move(thisEntry)); 4665cb1dd27SAsmitha Karunanithi } 467bd79bce8SPatrick Williams asyncResp->res.jsonValue["Members@odata.count"] = 468bd79bce8SPatrick Williams entriesArray.size(); 4693544d2a7SEd Tanous asyncResp->res.jsonValue["Members"] = std::move(entriesArray); 4705eb468daSGeorge Liu }); 4715cb1dd27SAsmitha Karunanithi } 4725cb1dd27SAsmitha Karunanithi 473504af5a0SPatrick Williams inline void getDumpEntryById( 474504af5a0SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 4758d1b46d7Szhanghch05 const std::string& entryID, const std::string& dumpType) 4765cb1dd27SAsmitha Karunanithi { 477fdd26906SClaire Weinan std::string entriesPath = getDumpEntriesPath(dumpType); 478fdd26906SClaire Weinan if (entriesPath.empty()) 4795cb1dd27SAsmitha Karunanithi { 4805cb1dd27SAsmitha Karunanithi messages::internalError(asyncResp->res); 4815cb1dd27SAsmitha Karunanithi return; 4825cb1dd27SAsmitha Karunanithi } 4835cb1dd27SAsmitha Karunanithi 4845eb468daSGeorge Liu sdbusplus::message::object_path path("/xyz/openbmc_project/dump"); 4855eb468daSGeorge Liu dbus::utility::getManagedObjects( 4865eb468daSGeorge Liu "xyz.openbmc_project.Dump.Manager", path, 487fdd26906SClaire Weinan [asyncResp, entryID, dumpType, 4885e7e2dc5SEd Tanous entriesPath](const boost::system::error_code& ec, 48902cad96eSEd Tanous const dbus::utility::ManagedObjectType& resp) { 4905cb1dd27SAsmitha Karunanithi if (ec) 4915cb1dd27SAsmitha Karunanithi { 49262598e31SEd Tanous BMCWEB_LOG_ERROR("DumpEntry resp_handler got error {}", ec); 4935cb1dd27SAsmitha Karunanithi messages::internalError(asyncResp->res); 4945cb1dd27SAsmitha Karunanithi return; 4955cb1dd27SAsmitha Karunanithi } 4965cb1dd27SAsmitha Karunanithi 497b47452b2SAsmitha Karunanithi bool foundDumpEntry = false; 49818f8f608SEd Tanous std::string dumpEntryPath = getDumpPath(dumpType) + "/entry/"; 499b47452b2SAsmitha Karunanithi 5009eb808c1SEd Tanous for (const auto& objectPath : resp) 5015cb1dd27SAsmitha Karunanithi { 502b47452b2SAsmitha Karunanithi if (objectPath.first.str != dumpEntryPath + entryID) 5035cb1dd27SAsmitha Karunanithi { 5045cb1dd27SAsmitha Karunanithi continue; 5055cb1dd27SAsmitha Karunanithi } 5065cb1dd27SAsmitha Karunanithi 5075cb1dd27SAsmitha Karunanithi foundDumpEntry = true; 508c6fecdabSClaire Weinan uint64_t timestampUs = 0; 5095cb1dd27SAsmitha Karunanithi uint64_t size = 0; 51035440d18SAsmitha Karunanithi std::string dumpStatus; 51168dd075aSAsmitha Karunanithi std::string originatorId; 51268dd075aSAsmitha Karunanithi log_entry::OriginatorTypes originatorType = 51368dd075aSAsmitha Karunanithi log_entry::OriginatorTypes::Internal; 5145cb1dd27SAsmitha Karunanithi 515aefe3786SClaire Weinan parseDumpEntryFromDbusObject(objectPath, dumpStatus, size, 51668dd075aSAsmitha Karunanithi timestampUs, originatorId, 51768dd075aSAsmitha Karunanithi originatorType, asyncResp); 5185cb1dd27SAsmitha Karunanithi 5190fda0f12SGeorge Liu if (dumpStatus != 5200fda0f12SGeorge Liu "xyz.openbmc_project.Common.Progress.OperationStatus.Completed" && 52135440d18SAsmitha Karunanithi !dumpStatus.empty()) 52235440d18SAsmitha Karunanithi { 52335440d18SAsmitha Karunanithi // Dump status is not Complete 52435440d18SAsmitha Karunanithi // return not found until status is changed to Completed 525bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, 526bd79bce8SPatrick Williams dumpType + " dump", entryID); 52735440d18SAsmitha Karunanithi return; 52835440d18SAsmitha Karunanithi } 52935440d18SAsmitha Karunanithi 5305cb1dd27SAsmitha Karunanithi asyncResp->res.jsonValue["@odata.type"] = 53168dd075aSAsmitha Karunanithi "#LogEntry.v1_11_0.LogEntry"; 532fdd26906SClaire Weinan asyncResp->res.jsonValue["@odata.id"] = entriesPath + entryID; 5335cb1dd27SAsmitha Karunanithi asyncResp->res.jsonValue["Id"] = entryID; 5345cb1dd27SAsmitha Karunanithi asyncResp->res.jsonValue["EntryType"] = "Event"; 5355cb1dd27SAsmitha Karunanithi asyncResp->res.jsonValue["Name"] = dumpType + " Dump Entry"; 536bbd80db8SClaire Weinan asyncResp->res.jsonValue["Created"] = 537bbd80db8SClaire Weinan redfish::time_utils::getDateTimeUintUs(timestampUs); 5385cb1dd27SAsmitha Karunanithi 53968dd075aSAsmitha Karunanithi if (!originatorId.empty()) 54068dd075aSAsmitha Karunanithi { 54168dd075aSAsmitha Karunanithi asyncResp->res.jsonValue["Originator"] = originatorId; 54268dd075aSAsmitha Karunanithi asyncResp->res.jsonValue["OriginatorType"] = originatorType; 54368dd075aSAsmitha Karunanithi } 54468dd075aSAsmitha Karunanithi 5455cb1dd27SAsmitha Karunanithi if (dumpType == "BMC") 5465cb1dd27SAsmitha Karunanithi { 547d337bb72SAsmitha Karunanithi asyncResp->res.jsonValue["DiagnosticDataType"] = "Manager"; 548d337bb72SAsmitha Karunanithi asyncResp->res.jsonValue["AdditionalDataURI"] = 549fdd26906SClaire Weinan entriesPath + entryID + "/attachment"; 550fdd26906SClaire Weinan asyncResp->res.jsonValue["AdditionalDataSizeBytes"] = size; 5515cb1dd27SAsmitha Karunanithi } 5525cb1dd27SAsmitha Karunanithi else if (dumpType == "System") 5535cb1dd27SAsmitha Karunanithi { 554d337bb72SAsmitha Karunanithi asyncResp->res.jsonValue["DiagnosticDataType"] = "OEM"; 555bd79bce8SPatrick Williams asyncResp->res.jsonValue["OEMDiagnosticDataType"] = 556bd79bce8SPatrick Williams "System"; 557d337bb72SAsmitha Karunanithi asyncResp->res.jsonValue["AdditionalDataURI"] = 558fdd26906SClaire Weinan entriesPath + entryID + "/attachment"; 559fdd26906SClaire Weinan asyncResp->res.jsonValue["AdditionalDataSizeBytes"] = size; 5605cb1dd27SAsmitha Karunanithi } 5615cb1dd27SAsmitha Karunanithi } 562e05aec50SEd Tanous if (!foundDumpEntry) 563b47452b2SAsmitha Karunanithi { 56462598e31SEd Tanous BMCWEB_LOG_WARNING("Can't find Dump Entry {}", entryID); 565b90d14f2SMyung Bae messages::resourceNotFound(asyncResp->res, dumpType + " dump", 566b90d14f2SMyung Bae entryID); 567b47452b2SAsmitha Karunanithi return; 568b47452b2SAsmitha Karunanithi } 5695eb468daSGeorge Liu }); 5705cb1dd27SAsmitha Karunanithi } 5715cb1dd27SAsmitha Karunanithi 5728d1b46d7Szhanghch05 inline void deleteDumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 5739878256fSStanley Chu const std::string& entryID, 574b47452b2SAsmitha Karunanithi const std::string& dumpType) 5755cb1dd27SAsmitha Karunanithi { 5765a39f77aSPatrick Williams auto respHandler = [asyncResp, 5775a39f77aSPatrick Williams entryID](const boost::system::error_code& ec) { 57862598e31SEd Tanous BMCWEB_LOG_DEBUG("Dump Entry doDelete callback: Done"); 5795cb1dd27SAsmitha Karunanithi if (ec) 5805cb1dd27SAsmitha Karunanithi { 5813de8d8baSGeorge Liu if (ec.value() == EBADR) 5823de8d8baSGeorge Liu { 5833de8d8baSGeorge Liu messages::resourceNotFound(asyncResp->res, "LogEntry", entryID); 5843de8d8baSGeorge Liu return; 5853de8d8baSGeorge Liu } 58662598e31SEd Tanous BMCWEB_LOG_ERROR( 58762598e31SEd Tanous "Dump (DBus) doDelete respHandler got error {} entryID={}", ec, 58862598e31SEd Tanous entryID); 5895cb1dd27SAsmitha Karunanithi messages::internalError(asyncResp->res); 5905cb1dd27SAsmitha Karunanithi return; 5915cb1dd27SAsmitha Karunanithi } 5925cb1dd27SAsmitha Karunanithi }; 59318f8f608SEd Tanous 594177612aaSEd Tanous dbus::utility::async_method_call( 595177612aaSEd Tanous asyncResp, respHandler, "xyz.openbmc_project.Dump.Manager", 59618f8f608SEd Tanous std::format("{}/entry/{}", getDumpPath(dumpType), entryID), 5975cb1dd27SAsmitha Karunanithi "xyz.openbmc_project.Object.Delete", "Delete"); 5985cb1dd27SAsmitha Karunanithi } 599168d1b1aSCarson Labrado 600504af5a0SPatrick Williams inline void downloadDumpEntry( 601504af5a0SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 602168d1b1aSCarson Labrado const std::string& entryID, const std::string& dumpType) 603168d1b1aSCarson Labrado { 604168d1b1aSCarson Labrado if (dumpType != "BMC") 605168d1b1aSCarson Labrado { 606168d1b1aSCarson Labrado BMCWEB_LOG_WARNING("Can't find Dump Entry {}", entryID); 607168d1b1aSCarson Labrado messages::resourceNotFound(asyncResp->res, dumpType + " dump", entryID); 608168d1b1aSCarson Labrado return; 609168d1b1aSCarson Labrado } 610168d1b1aSCarson Labrado 611bd79bce8SPatrick Williams std::string dumpEntryPath = 612bd79bce8SPatrick Williams std::format("{}/entry/{}", getDumpPath(dumpType), entryID); 613168d1b1aSCarson Labrado 614168d1b1aSCarson Labrado auto downloadDumpEntryHandler = 615168d1b1aSCarson Labrado [asyncResp, entryID, 616168d1b1aSCarson Labrado dumpType](const boost::system::error_code& ec, 617168d1b1aSCarson Labrado const sdbusplus::message::unix_fd& unixfd) { 618*ff35df94SOliver Brewka log_services_utils::downloadEntryCallback(asyncResp, entryID, 619*ff35df94SOliver Brewka dumpType, ec, unixfd); 620168d1b1aSCarson Labrado }; 621168d1b1aSCarson Labrado 622177612aaSEd Tanous dbus::utility::async_method_call( 623177612aaSEd Tanous asyncResp, std::move(downloadDumpEntryHandler), 624177612aaSEd Tanous "xyz.openbmc_project.Dump.Manager", dumpEntryPath, 625177612aaSEd Tanous "xyz.openbmc_project.Dump.Entry", "GetFileHandle"); 626168d1b1aSCarson Labrado } 627168d1b1aSCarson Labrado 628bd79bce8SPatrick Williams inline void downloadEventLogEntry( 629bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 630bd79bce8SPatrick Williams const std::string& systemName, const std::string& entryID, 631168d1b1aSCarson Labrado const std::string& dumpType) 632168d1b1aSCarson Labrado { 63325b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 634168d1b1aSCarson Labrado { 635168d1b1aSCarson Labrado // Option currently returns no systems. TBD 636168d1b1aSCarson Labrado messages::resourceNotFound(asyncResp->res, "ComputerSystem", 637168d1b1aSCarson Labrado systemName); 638168d1b1aSCarson Labrado return; 639168d1b1aSCarson Labrado } 640253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 641168d1b1aSCarson Labrado { 642168d1b1aSCarson Labrado messages::resourceNotFound(asyncResp->res, "ComputerSystem", 643168d1b1aSCarson Labrado systemName); 644168d1b1aSCarson Labrado return; 645168d1b1aSCarson Labrado } 646168d1b1aSCarson Labrado 647168d1b1aSCarson Labrado std::string entryPath = 648168d1b1aSCarson Labrado sdbusplus::message::object_path("/xyz/openbmc_project/logging/entry") / 649168d1b1aSCarson Labrado entryID; 650168d1b1aSCarson Labrado 651168d1b1aSCarson Labrado auto downloadEventLogEntryHandler = 652168d1b1aSCarson Labrado [asyncResp, entryID, 653168d1b1aSCarson Labrado dumpType](const boost::system::error_code& ec, 654168d1b1aSCarson Labrado const sdbusplus::message::unix_fd& unixfd) { 655*ff35df94SOliver Brewka log_services_utils::downloadEntryCallback(asyncResp, entryID, 656*ff35df94SOliver Brewka dumpType, ec, unixfd); 657168d1b1aSCarson Labrado }; 658168d1b1aSCarson Labrado 659177612aaSEd Tanous dbus::utility::async_method_call( 660177612aaSEd Tanous asyncResp, std::move(downloadEventLogEntryHandler), 661177612aaSEd Tanous "xyz.openbmc_project.Logging", entryPath, 662177612aaSEd Tanous "xyz.openbmc_project.Logging.Entry", "GetEntry"); 663168d1b1aSCarson Labrado } 664168d1b1aSCarson Labrado 665504af5a0SPatrick Williams inline DumpCreationProgress mapDbusStatusToDumpProgress( 666504af5a0SPatrick Williams const std::string& status) 667a43be80fSAsmitha Karunanithi { 6688e31778eSAsmitha Karunanithi if (status == 6698e31778eSAsmitha Karunanithi "xyz.openbmc_project.Common.Progress.OperationStatus.Failed" || 6708e31778eSAsmitha Karunanithi status == "xyz.openbmc_project.Common.Progress.OperationStatus.Aborted") 6718e31778eSAsmitha Karunanithi { 6728e31778eSAsmitha Karunanithi return DumpCreationProgress::DUMP_CREATE_FAILED; 6738e31778eSAsmitha Karunanithi } 6748e31778eSAsmitha Karunanithi if (status == 6758e31778eSAsmitha Karunanithi "xyz.openbmc_project.Common.Progress.OperationStatus.Completed") 6768e31778eSAsmitha Karunanithi { 6778e31778eSAsmitha Karunanithi return DumpCreationProgress::DUMP_CREATE_SUCCESS; 6788e31778eSAsmitha Karunanithi } 6798e31778eSAsmitha Karunanithi return DumpCreationProgress::DUMP_CREATE_INPROGRESS; 6808e31778eSAsmitha Karunanithi } 6818e31778eSAsmitha Karunanithi 682504af5a0SPatrick Williams inline DumpCreationProgress getDumpCompletionStatus( 683504af5a0SPatrick Williams const dbus::utility::DBusPropertiesMap& values) 6848e31778eSAsmitha Karunanithi { 6858e31778eSAsmitha Karunanithi for (const auto& [key, val] : values) 6868e31778eSAsmitha Karunanithi { 6878e31778eSAsmitha Karunanithi if (key == "Status") 6888e31778eSAsmitha Karunanithi { 6898e31778eSAsmitha Karunanithi const std::string* value = std::get_if<std::string>(&val); 6908e31778eSAsmitha Karunanithi if (value == nullptr) 6918e31778eSAsmitha Karunanithi { 69262598e31SEd Tanous BMCWEB_LOG_ERROR("Status property value is null"); 6938e31778eSAsmitha Karunanithi return DumpCreationProgress::DUMP_CREATE_FAILED; 6948e31778eSAsmitha Karunanithi } 6958e31778eSAsmitha Karunanithi return mapDbusStatusToDumpProgress(*value); 6968e31778eSAsmitha Karunanithi } 6978e31778eSAsmitha Karunanithi } 6988e31778eSAsmitha Karunanithi return DumpCreationProgress::DUMP_CREATE_INPROGRESS; 6998e31778eSAsmitha Karunanithi } 7008e31778eSAsmitha Karunanithi 7018e31778eSAsmitha Karunanithi inline std::string getDumpEntryPath(const std::string& dumpPath) 7028e31778eSAsmitha Karunanithi { 7038e31778eSAsmitha Karunanithi if (dumpPath == "/xyz/openbmc_project/dump/bmc/entry") 7048e31778eSAsmitha Karunanithi { 705253f11b8SEd Tanous return std::format("/redfish/v1/Managers/{}/LogServices/Dump/Entries/", 7069f565090SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 7078e31778eSAsmitha Karunanithi } 7088e31778eSAsmitha Karunanithi if (dumpPath == "/xyz/openbmc_project/dump/system/entry") 7098e31778eSAsmitha Karunanithi { 710253f11b8SEd Tanous return std::format("/redfish/v1/Systems/{}/LogServices/Dump/Entries/", 711253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 7128e31778eSAsmitha Karunanithi } 7138e31778eSAsmitha Karunanithi return ""; 7148e31778eSAsmitha Karunanithi } 7158e31778eSAsmitha Karunanithi 7168e31778eSAsmitha Karunanithi inline void createDumpTaskCallback( 7178e31778eSAsmitha Karunanithi task::Payload&& payload, 7188e31778eSAsmitha Karunanithi const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 7198e31778eSAsmitha Karunanithi const sdbusplus::message::object_path& createdObjPath) 7208e31778eSAsmitha Karunanithi { 7218e31778eSAsmitha Karunanithi const std::string dumpPath = createdObjPath.parent_path().str; 7228e31778eSAsmitha Karunanithi const std::string dumpId = createdObjPath.filename(); 7238e31778eSAsmitha Karunanithi 7248e31778eSAsmitha Karunanithi std::string dumpEntryPath = getDumpEntryPath(dumpPath); 7258e31778eSAsmitha Karunanithi 7268e31778eSAsmitha Karunanithi if (dumpEntryPath.empty()) 7278e31778eSAsmitha Karunanithi { 72862598e31SEd Tanous BMCWEB_LOG_ERROR("Invalid dump type received"); 7298e31778eSAsmitha Karunanithi messages::internalError(asyncResp->res); 7308e31778eSAsmitha Karunanithi return; 7318e31778eSAsmitha Karunanithi } 7328e31778eSAsmitha Karunanithi 733177612aaSEd Tanous dbus::utility::async_method_call( 734177612aaSEd Tanous asyncResp, 7358cb2c024SEd Tanous [asyncResp, payload = std::move(payload), createdObjPath, 7368e31778eSAsmitha Karunanithi dumpEntryPath{std::move(dumpEntryPath)}, 7375e7e2dc5SEd Tanous dumpId](const boost::system::error_code& ec, 7388e31778eSAsmitha Karunanithi const std::string& introspectXml) { 7398e31778eSAsmitha Karunanithi if (ec) 7408e31778eSAsmitha Karunanithi { 74162598e31SEd Tanous BMCWEB_LOG_ERROR("Introspect call failed with error: {}", 74262598e31SEd Tanous ec.message()); 7438e31778eSAsmitha Karunanithi messages::internalError(asyncResp->res); 7448e31778eSAsmitha Karunanithi return; 7458e31778eSAsmitha Karunanithi } 7468e31778eSAsmitha Karunanithi 7478e31778eSAsmitha Karunanithi // Check if the created dump object has implemented Progress 7488e31778eSAsmitha Karunanithi // interface to track dump completion. If yes, fetch the "Status" 7498e31778eSAsmitha Karunanithi // property of the interface, modify the task state accordingly. 7508e31778eSAsmitha Karunanithi // Else, return task completed. 7518e31778eSAsmitha Karunanithi tinyxml2::XMLDocument doc; 7528e31778eSAsmitha Karunanithi 7538e31778eSAsmitha Karunanithi doc.Parse(introspectXml.data(), introspectXml.size()); 7548e31778eSAsmitha Karunanithi tinyxml2::XMLNode* pRoot = doc.FirstChildElement("node"); 7558e31778eSAsmitha Karunanithi if (pRoot == nullptr) 7568e31778eSAsmitha Karunanithi { 75762598e31SEd Tanous BMCWEB_LOG_ERROR("XML document failed to parse"); 7588e31778eSAsmitha Karunanithi messages::internalError(asyncResp->res); 7598e31778eSAsmitha Karunanithi return; 7608e31778eSAsmitha Karunanithi } 7618e31778eSAsmitha Karunanithi tinyxml2::XMLElement* interfaceNode = 7628e31778eSAsmitha Karunanithi pRoot->FirstChildElement("interface"); 7638e31778eSAsmitha Karunanithi 7648e31778eSAsmitha Karunanithi bool isProgressIntfPresent = false; 7658e31778eSAsmitha Karunanithi while (interfaceNode != nullptr) 7668e31778eSAsmitha Karunanithi { 767bd79bce8SPatrick Williams const char* thisInterfaceName = 768bd79bce8SPatrick Williams interfaceNode->Attribute("name"); 7698e31778eSAsmitha Karunanithi if (thisInterfaceName != nullptr) 7708e31778eSAsmitha Karunanithi { 7718e31778eSAsmitha Karunanithi if (thisInterfaceName == 7728e31778eSAsmitha Karunanithi std::string_view("xyz.openbmc_project.Common.Progress")) 7738e31778eSAsmitha Karunanithi { 7748e31778eSAsmitha Karunanithi interfaceNode = 7758e31778eSAsmitha Karunanithi interfaceNode->NextSiblingElement("interface"); 7768e31778eSAsmitha Karunanithi continue; 7778e31778eSAsmitha Karunanithi } 7788e31778eSAsmitha Karunanithi isProgressIntfPresent = true; 7798e31778eSAsmitha Karunanithi break; 7808e31778eSAsmitha Karunanithi } 7818e31778eSAsmitha Karunanithi interfaceNode = interfaceNode->NextSiblingElement("interface"); 7828e31778eSAsmitha Karunanithi } 7838e31778eSAsmitha Karunanithi 784a43be80fSAsmitha Karunanithi std::shared_ptr<task::TaskData> task = task::TaskData::createTask( 7858e31778eSAsmitha Karunanithi [createdObjPath, dumpEntryPath, dumpId, isProgressIntfPresent]( 786bd79bce8SPatrick Williams const boost::system::error_code& ec2, 787bd79bce8SPatrick Williams sdbusplus::message_t& msg, 788a43be80fSAsmitha Karunanithi const std::shared_ptr<task::TaskData>& taskData) { 7898b24275dSEd Tanous if (ec2) 790cb13a392SEd Tanous { 79162598e31SEd Tanous BMCWEB_LOG_ERROR("{}: Error in creating dump", 79262598e31SEd Tanous createdObjPath.str); 793bd79bce8SPatrick Williams taskData->messages.emplace_back( 794bd79bce8SPatrick Williams messages::internalError()); 7956145ed6fSAsmitha Karunanithi taskData->state = "Cancelled"; 7966145ed6fSAsmitha Karunanithi return task::completed; 797cb13a392SEd Tanous } 798b9d36b47SEd Tanous 7998e31778eSAsmitha Karunanithi if (isProgressIntfPresent) 800a43be80fSAsmitha Karunanithi { 8018e31778eSAsmitha Karunanithi dbus::utility::DBusPropertiesMap values; 8028e31778eSAsmitha Karunanithi std::string prop; 8038e31778eSAsmitha Karunanithi msg.read(prop, values); 8048e31778eSAsmitha Karunanithi 8058e31778eSAsmitha Karunanithi DumpCreationProgress dumpStatus = 8068e31778eSAsmitha Karunanithi getDumpCompletionStatus(values); 807bd79bce8SPatrick Williams if (dumpStatus == 808bd79bce8SPatrick Williams DumpCreationProgress::DUMP_CREATE_FAILED) 8098e31778eSAsmitha Karunanithi { 81062598e31SEd Tanous BMCWEB_LOG_ERROR("{}: Error in creating dump", 81162598e31SEd Tanous createdObjPath.str); 8128e31778eSAsmitha Karunanithi taskData->state = "Cancelled"; 8138e31778eSAsmitha Karunanithi return task::completed; 8148e31778eSAsmitha Karunanithi } 8158e31778eSAsmitha Karunanithi 816bd79bce8SPatrick Williams if (dumpStatus == 817bd79bce8SPatrick Williams DumpCreationProgress::DUMP_CREATE_INPROGRESS) 8188e31778eSAsmitha Karunanithi { 819bd79bce8SPatrick Williams BMCWEB_LOG_DEBUG( 820bd79bce8SPatrick Williams "{}: Dump creation task is in progress", 82162598e31SEd Tanous createdObjPath.str); 8228e31778eSAsmitha Karunanithi return !task::completed; 8238e31778eSAsmitha Karunanithi } 8248e31778eSAsmitha Karunanithi } 8258e31778eSAsmitha Karunanithi 826a43be80fSAsmitha Karunanithi nlohmann::json retMessage = messages::success(); 827a43be80fSAsmitha Karunanithi taskData->messages.emplace_back(retMessage); 828a43be80fSAsmitha Karunanithi 829c51a58eeSEd Tanous boost::urls::url url = boost::urls::format( 830253f11b8SEd Tanous "/redfish/v1/Managers/{}/LogServices/Dump/Entries/{}", 831253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME, dumpId); 832c51a58eeSEd Tanous 833c51a58eeSEd Tanous std::string headerLoc = "Location: "; 834c51a58eeSEd Tanous headerLoc += url.buffer(); 835c51a58eeSEd Tanous 836bd79bce8SPatrick Williams taskData->payload->httpHeaders.emplace_back( 837bd79bce8SPatrick Williams std::move(headerLoc)); 838a43be80fSAsmitha Karunanithi 83962598e31SEd Tanous BMCWEB_LOG_DEBUG("{}: Dump creation task completed", 84062598e31SEd Tanous createdObjPath.str); 841a43be80fSAsmitha Karunanithi taskData->state = "Completed"; 842b47452b2SAsmitha Karunanithi return task::completed; 843a43be80fSAsmitha Karunanithi }, 8448e31778eSAsmitha Karunanithi "type='signal',interface='org.freedesktop.DBus.Properties'," 8458e31778eSAsmitha Karunanithi "member='PropertiesChanged',path='" + 8468e31778eSAsmitha Karunanithi createdObjPath.str + "'"); 847a43be80fSAsmitha Karunanithi 8488e31778eSAsmitha Karunanithi // The task timer is set to max time limit within which the 8498e31778eSAsmitha Karunanithi // requested dump will be collected. 8508e31778eSAsmitha Karunanithi task->startTimer(std::chrono::minutes(6)); 8518e31778eSAsmitha Karunanithi task->payload.emplace(payload); 85229e2bdd7SChinmay Shripad Hegde task->populateResp(asyncResp->res); 8538e31778eSAsmitha Karunanithi }, 8548e31778eSAsmitha Karunanithi "xyz.openbmc_project.Dump.Manager", createdObjPath, 8558e31778eSAsmitha Karunanithi "org.freedesktop.DBus.Introspectable", "Introspect"); 856a43be80fSAsmitha Karunanithi } 857a43be80fSAsmitha Karunanithi 8588d1b46d7Szhanghch05 inline void createDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 8598d1b46d7Szhanghch05 const crow::Request& req, const std::string& dumpType) 860a43be80fSAsmitha Karunanithi { 861fdd26906SClaire Weinan std::string dumpPath = getDumpEntriesPath(dumpType); 862fdd26906SClaire Weinan if (dumpPath.empty()) 863a43be80fSAsmitha Karunanithi { 864a43be80fSAsmitha Karunanithi messages::internalError(asyncResp->res); 865a43be80fSAsmitha Karunanithi return; 866a43be80fSAsmitha Karunanithi } 867a43be80fSAsmitha Karunanithi 868a43be80fSAsmitha Karunanithi std::optional<std::string> diagnosticDataType; 869a43be80fSAsmitha Karunanithi std::optional<std::string> oemDiagnosticDataType; 870a43be80fSAsmitha Karunanithi 871afc474aeSMyung Bae if (!redfish::json_util::readJsonAction( // 872afc474aeSMyung Bae req, asyncResp->res, // 873afc474aeSMyung Bae "DiagnosticDataType", diagnosticDataType, // 874afc474aeSMyung Bae "OEMDiagnosticDataType", oemDiagnosticDataType // 875afc474aeSMyung Bae )) 876a43be80fSAsmitha Karunanithi { 877a43be80fSAsmitha Karunanithi return; 878a43be80fSAsmitha Karunanithi } 879a43be80fSAsmitha Karunanithi 880a43be80fSAsmitha Karunanithi if (dumpType == "System") 881a43be80fSAsmitha Karunanithi { 882a43be80fSAsmitha Karunanithi if (!oemDiagnosticDataType || !diagnosticDataType) 883a43be80fSAsmitha Karunanithi { 88462598e31SEd Tanous BMCWEB_LOG_ERROR( 88562598e31SEd Tanous "CreateDump action parameter 'DiagnosticDataType'/'OEMDiagnosticDataType' value not found!"); 886a43be80fSAsmitha Karunanithi messages::actionParameterMissing( 887a43be80fSAsmitha Karunanithi asyncResp->res, "CollectDiagnosticData", 888a43be80fSAsmitha Karunanithi "DiagnosticDataType & OEMDiagnosticDataType"); 889a43be80fSAsmitha Karunanithi return; 890a43be80fSAsmitha Karunanithi } 8913174e4dfSEd Tanous if ((*oemDiagnosticDataType != "System") || 892a43be80fSAsmitha Karunanithi (*diagnosticDataType != "OEM")) 893a43be80fSAsmitha Karunanithi { 89462598e31SEd Tanous BMCWEB_LOG_ERROR("Wrong parameter values passed"); 895ace85d60SEd Tanous messages::internalError(asyncResp->res); 896a43be80fSAsmitha Karunanithi return; 897a43be80fSAsmitha Karunanithi } 898253f11b8SEd Tanous dumpPath = std::format("/redfish/v1/Systems/{}/LogServices/Dump/", 899253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 900a43be80fSAsmitha Karunanithi } 901a43be80fSAsmitha Karunanithi else if (dumpType == "BMC") 902a43be80fSAsmitha Karunanithi { 903a43be80fSAsmitha Karunanithi if (!diagnosticDataType) 904a43be80fSAsmitha Karunanithi { 90562598e31SEd Tanous BMCWEB_LOG_ERROR( 90662598e31SEd Tanous "CreateDump action parameter 'DiagnosticDataType' not found!"); 907a43be80fSAsmitha Karunanithi messages::actionParameterMissing( 908a43be80fSAsmitha Karunanithi asyncResp->res, "CollectDiagnosticData", "DiagnosticDataType"); 909a43be80fSAsmitha Karunanithi return; 910a43be80fSAsmitha Karunanithi } 9113174e4dfSEd Tanous if (*diagnosticDataType != "Manager") 912a43be80fSAsmitha Karunanithi { 91362598e31SEd Tanous BMCWEB_LOG_ERROR( 91462598e31SEd Tanous "Wrong parameter value passed for 'DiagnosticDataType'"); 915ace85d60SEd Tanous messages::internalError(asyncResp->res); 916a43be80fSAsmitha Karunanithi return; 917a43be80fSAsmitha Karunanithi } 918253f11b8SEd Tanous dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/Dump/", 919253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 9205907571dSAsmitha Karunanithi } 9215907571dSAsmitha Karunanithi else 9225907571dSAsmitha Karunanithi { 92362598e31SEd Tanous BMCWEB_LOG_ERROR("CreateDump failed. Unknown dump type"); 9245907571dSAsmitha Karunanithi messages::internalError(asyncResp->res); 9255907571dSAsmitha Karunanithi return; 926a43be80fSAsmitha Karunanithi } 927a43be80fSAsmitha Karunanithi 9288e31778eSAsmitha Karunanithi std::vector<std::pair<std::string, std::variant<std::string, uint64_t>>> 9298e31778eSAsmitha Karunanithi createDumpParamVec; 9308e31778eSAsmitha Karunanithi 931f574a8e1SCarson Labrado if (req.session != nullptr) 932f574a8e1SCarson Labrado { 93368dd075aSAsmitha Karunanithi createDumpParamVec.emplace_back( 93468dd075aSAsmitha Karunanithi "xyz.openbmc_project.Dump.Create.CreateParameters.OriginatorId", 93568dd075aSAsmitha Karunanithi req.session->clientIp); 93668dd075aSAsmitha Karunanithi createDumpParamVec.emplace_back( 93768dd075aSAsmitha Karunanithi "xyz.openbmc_project.Dump.Create.CreateParameters.OriginatorType", 93868dd075aSAsmitha Karunanithi "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Client"); 939f574a8e1SCarson Labrado } 94068dd075aSAsmitha Karunanithi 941177612aaSEd Tanous dbus::utility::async_method_call( 942177612aaSEd Tanous asyncResp, 9435e7e2dc5SEd Tanous [asyncResp, payload(task::Payload(req)), 9445e7e2dc5SEd Tanous dumpPath](const boost::system::error_code& ec, 9455e7e2dc5SEd Tanous const sdbusplus::message_t& msg, 9468e31778eSAsmitha Karunanithi const sdbusplus::message::object_path& objPath) mutable { 947a43be80fSAsmitha Karunanithi if (ec) 948a43be80fSAsmitha Karunanithi { 94962598e31SEd Tanous BMCWEB_LOG_ERROR("CreateDump resp_handler got error {}", ec); 9505907571dSAsmitha Karunanithi const sd_bus_error* dbusError = msg.get_error(); 9515907571dSAsmitha Karunanithi if (dbusError == nullptr) 9525907571dSAsmitha Karunanithi { 9535907571dSAsmitha Karunanithi messages::internalError(asyncResp->res); 9545907571dSAsmitha Karunanithi return; 9555907571dSAsmitha Karunanithi } 9565907571dSAsmitha Karunanithi 95762598e31SEd Tanous BMCWEB_LOG_ERROR("CreateDump DBus error: {} and error msg: {}", 95862598e31SEd Tanous dbusError->name, dbusError->message); 9595907571dSAsmitha Karunanithi if (std::string_view( 9605907571dSAsmitha Karunanithi "xyz.openbmc_project.Common.Error.NotAllowed") == 9615907571dSAsmitha Karunanithi dbusError->name) 9625907571dSAsmitha Karunanithi { 9635907571dSAsmitha Karunanithi messages::resourceInStandby(asyncResp->res); 9645907571dSAsmitha Karunanithi return; 9655907571dSAsmitha Karunanithi } 9665907571dSAsmitha Karunanithi if (std::string_view( 9675907571dSAsmitha Karunanithi "xyz.openbmc_project.Dump.Create.Error.Disabled") == 9685907571dSAsmitha Karunanithi dbusError->name) 9695907571dSAsmitha Karunanithi { 9705907571dSAsmitha Karunanithi messages::serviceDisabled(asyncResp->res, dumpPath); 9715907571dSAsmitha Karunanithi return; 9725907571dSAsmitha Karunanithi } 9735907571dSAsmitha Karunanithi if (std::string_view( 9745907571dSAsmitha Karunanithi "xyz.openbmc_project.Common.Error.Unavailable") == 9755907571dSAsmitha Karunanithi dbusError->name) 9765907571dSAsmitha Karunanithi { 9775907571dSAsmitha Karunanithi messages::resourceInUse(asyncResp->res); 9785907571dSAsmitha Karunanithi return; 9795907571dSAsmitha Karunanithi } 9805907571dSAsmitha Karunanithi // Other Dbus errors such as: 9815907571dSAsmitha Karunanithi // xyz.openbmc_project.Common.Error.InvalidArgument & 9825907571dSAsmitha Karunanithi // org.freedesktop.DBus.Error.InvalidArgs are all related to 9835907571dSAsmitha Karunanithi // the dbus call that is made here in the bmcweb 9845907571dSAsmitha Karunanithi // implementation and has nothing to do with the client's 9855907571dSAsmitha Karunanithi // input in the request. Hence, returning internal error 9865907571dSAsmitha Karunanithi // back to the client. 987a43be80fSAsmitha Karunanithi messages::internalError(asyncResp->res); 988a43be80fSAsmitha Karunanithi return; 989a43be80fSAsmitha Karunanithi } 99062598e31SEd Tanous BMCWEB_LOG_DEBUG("Dump Created. Path: {}", objPath.str); 9918e31778eSAsmitha Karunanithi createDumpTaskCallback(std::move(payload), asyncResp, objPath); 992a43be80fSAsmitha Karunanithi }, 99318f8f608SEd Tanous "xyz.openbmc_project.Dump.Manager", getDumpPath(dumpType), 9948e31778eSAsmitha Karunanithi "xyz.openbmc_project.Dump.Create", "CreateDump", createDumpParamVec); 995a43be80fSAsmitha Karunanithi } 996a43be80fSAsmitha Karunanithi 9978d1b46d7Szhanghch05 inline void clearDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 9988d1b46d7Szhanghch05 const std::string& dumpType) 99980319af1SAsmitha Karunanithi { 1000177612aaSEd Tanous dbus::utility::async_method_call( 1001177612aaSEd Tanous asyncResp, 10020d946211SClaire Weinan [asyncResp](const boost::system::error_code& ec) { 100380319af1SAsmitha Karunanithi if (ec) 100480319af1SAsmitha Karunanithi { 100562598e31SEd Tanous BMCWEB_LOG_ERROR("clearDump resp_handler got error {}", ec); 100680319af1SAsmitha Karunanithi messages::internalError(asyncResp->res); 100780319af1SAsmitha Karunanithi return; 100880319af1SAsmitha Karunanithi } 1009e2460466SAmy Chang messages::success(asyncResp->res); 10100d946211SClaire Weinan }, 101118f8f608SEd Tanous "xyz.openbmc_project.Dump.Manager", getDumpPath(dumpType), 10120d946211SClaire Weinan "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll"); 101380319af1SAsmitha Karunanithi } 101480319af1SAsmitha Karunanithi 1015bd79bce8SPatrick Williams inline void parseCrashdumpParameters( 1016bd79bce8SPatrick Williams const dbus::utility::DBusPropertiesMap& params, std::string& filename, 1017bd79bce8SPatrick Williams std::string& timestamp, std::string& logfile) 1018043a0536SJohnathan Mantey { 1019d1bde9e5SKrzysztof Grobelny const std::string* filenamePtr = nullptr; 1020d1bde9e5SKrzysztof Grobelny const std::string* timestampPtr = nullptr; 1021d1bde9e5SKrzysztof Grobelny const std::string* logfilePtr = nullptr; 1022d1bde9e5SKrzysztof Grobelny 1023d1bde9e5SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 1024d1bde9e5SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), params, "Timestamp", timestampPtr, 1025d1bde9e5SKrzysztof Grobelny "Filename", filenamePtr, "Log", logfilePtr); 1026d1bde9e5SKrzysztof Grobelny 1027d1bde9e5SKrzysztof Grobelny if (!success) 1028043a0536SJohnathan Mantey { 1029d1bde9e5SKrzysztof Grobelny return; 1030043a0536SJohnathan Mantey } 1031d1bde9e5SKrzysztof Grobelny 1032d1bde9e5SKrzysztof Grobelny if (filenamePtr != nullptr) 1033043a0536SJohnathan Mantey { 1034d1bde9e5SKrzysztof Grobelny filename = *filenamePtr; 1035d1bde9e5SKrzysztof Grobelny } 1036d1bde9e5SKrzysztof Grobelny 1037d1bde9e5SKrzysztof Grobelny if (timestampPtr != nullptr) 1038043a0536SJohnathan Mantey { 1039d1bde9e5SKrzysztof Grobelny timestamp = *timestampPtr; 1040043a0536SJohnathan Mantey } 1041d1bde9e5SKrzysztof Grobelny 1042d1bde9e5SKrzysztof Grobelny if (logfilePtr != nullptr) 1043043a0536SJohnathan Mantey { 1044d1bde9e5SKrzysztof Grobelny logfile = *logfilePtr; 1045043a0536SJohnathan Mantey } 1046043a0536SJohnathan Mantey } 1047043a0536SJohnathan Mantey 10487e860f15SJohn Edward Broadbent inline void requestRoutesSystemLogServiceCollection(App& app) 10491da66f75SEd Tanous { 1050c4bf6374SJason M. Bills /** 1051c4bf6374SJason M. Bills * Functions triggers appropriate requests on DBus 1052c4bf6374SJason M. Bills */ 105322d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/") 1054ed398213SEd Tanous .privileges(redfish::privileges::getLogServiceCollection) 1055bd79bce8SPatrick Williams .methods( 1056bd79bce8SPatrick Williams boost::beast::http::verb:: 1057bd79bce8SPatrick Williams get)([&app](const crow::Request& req, 105822d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 105922d268cbSEd Tanous const std::string& systemName) { 10603ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 1061c4bf6374SJason M. Bills { 106245ca1b86SEd Tanous return; 106345ca1b86SEd Tanous } 106425b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 10657f3e84a1SEd Tanous { 10667f3e84a1SEd Tanous // Option currently returns no systems. TBD 10677f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 10687f3e84a1SEd Tanous systemName); 10697f3e84a1SEd Tanous return; 10707f3e84a1SEd Tanous } 1071253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 107222d268cbSEd Tanous { 107322d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 107422d268cbSEd Tanous systemName); 107522d268cbSEd Tanous return; 107622d268cbSEd Tanous } 107722d268cbSEd Tanous 10787e860f15SJohn Edward Broadbent // Collections don't include the static data added by SubRoute 10797e860f15SJohn Edward Broadbent // because it has a duplicate entry for members 1080c4bf6374SJason M. Bills asyncResp->res.jsonValue["@odata.type"] = 1081c4bf6374SJason M. Bills "#LogServiceCollection.LogServiceCollection"; 1082c4bf6374SJason M. Bills asyncResp->res.jsonValue["@odata.id"] = 1083253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices", 1084253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 108545ca1b86SEd Tanous asyncResp->res.jsonValue["Name"] = "System Log Services Collection"; 1086c4bf6374SJason M. Bills asyncResp->res.jsonValue["Description"] = 1087c4bf6374SJason M. Bills "Collection of LogServices for this Computer System"; 1088bd79bce8SPatrick Williams nlohmann::json& logServiceArray = 1089bd79bce8SPatrick Williams asyncResp->res.jsonValue["Members"]; 1090c4bf6374SJason M. Bills logServiceArray = nlohmann::json::array(); 10911476687dSEd Tanous nlohmann::json::object_t eventLog; 10921476687dSEd Tanous eventLog["@odata.id"] = 1093253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/EventLog", 1094253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1095b2ba3072SPatrick Williams logServiceArray.emplace_back(std::move(eventLog)); 109625b54dbaSEd Tanous if constexpr (BMCWEB_REDFISH_DUMP_LOG) 109725b54dbaSEd Tanous { 10981476687dSEd Tanous nlohmann::json::object_t dumpLog; 109925b54dbaSEd Tanous dumpLog["@odata.id"] = 1100253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/Dump", 1101253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1102b2ba3072SPatrick Williams logServiceArray.emplace_back(std::move(dumpLog)); 110325b54dbaSEd Tanous } 1104c9bb6861Sraviteja-b 11055ffd11f2SGunnar Mills if constexpr (BMCWEB_REDFISH_CPU_LOG) 110625b54dbaSEd Tanous { 11071476687dSEd Tanous nlohmann::json::object_t crashdump; 11081476687dSEd Tanous crashdump["@odata.id"] = 1109253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/Crashdump", 1110253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1111b2ba3072SPatrick Williams logServiceArray.emplace_back(std::move(crashdump)); 111225b54dbaSEd Tanous } 1113b7028ebfSSpencer Ku 111425b54dbaSEd Tanous if constexpr (BMCWEB_REDFISH_HOST_LOGGER) 111525b54dbaSEd Tanous { 11161476687dSEd Tanous nlohmann::json::object_t hostlogger; 11171476687dSEd Tanous hostlogger["@odata.id"] = 1118253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/HostLogger", 1119253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1120b2ba3072SPatrick Williams logServiceArray.emplace_back(std::move(hostlogger)); 112125b54dbaSEd Tanous } 1122c4bf6374SJason M. Bills asyncResp->res.jsonValue["Members@odata.count"] = 1123c4bf6374SJason M. Bills logServiceArray.size(); 1124a3316fc6SZhikuiRen 11257a1dbc48SGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 11267a1dbc48SGeorge Liu "xyz.openbmc_project.State.Boot.PostCode"}; 11277a1dbc48SGeorge Liu dbus::utility::getSubTreePaths( 11287a1dbc48SGeorge Liu "/", 0, interfaces, 11297a1dbc48SGeorge Liu [asyncResp](const boost::system::error_code& ec, 1130b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreePathsResponse& 1131b9d36b47SEd Tanous subtreePath) { 1132a3316fc6SZhikuiRen if (ec) 1133a3316fc6SZhikuiRen { 113462598e31SEd Tanous BMCWEB_LOG_ERROR("{}", ec); 1135a3316fc6SZhikuiRen return; 1136a3316fc6SZhikuiRen } 1137a3316fc6SZhikuiRen 113855f79e6fSEd Tanous for (const auto& pathStr : subtreePath) 1139a3316fc6SZhikuiRen { 1140a3316fc6SZhikuiRen if (pathStr.find("PostCode") != std::string::npos) 1141a3316fc6SZhikuiRen { 114223a21a1cSEd Tanous nlohmann::json& logServiceArrayLocal = 1143a3316fc6SZhikuiRen asyncResp->res.jsonValue["Members"]; 1144613dabeaSEd Tanous nlohmann::json::object_t member; 1145253f11b8SEd Tanous member["@odata.id"] = std::format( 1146253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/PostCodes", 1147253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1148613dabeaSEd Tanous 1149bd79bce8SPatrick Williams logServiceArrayLocal.emplace_back( 1150bd79bce8SPatrick Williams std::move(member)); 1151613dabeaSEd Tanous 115245ca1b86SEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = 115323a21a1cSEd Tanous logServiceArrayLocal.size(); 1154a3316fc6SZhikuiRen return; 1155a3316fc6SZhikuiRen } 1156a3316fc6SZhikuiRen } 11577a1dbc48SGeorge Liu }); 11587e860f15SJohn Edward Broadbent }); 1159c4bf6374SJason M. Bills } 1160c4bf6374SJason M. Bills 11617e860f15SJohn Edward Broadbent inline void requestRoutesEventLogService(App& app) 1162c4bf6374SJason M. Bills { 116322d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/") 1164ed398213SEd Tanous .privileges(redfish::privileges::getLogService) 1165bd79bce8SPatrick Williams .methods( 1166bd79bce8SPatrick Williams boost::beast::http::verb:: 1167bd79bce8SPatrick Williams get)([&app](const crow::Request& req, 116822d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 116922d268cbSEd Tanous const std::string& systemName) { 11703ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 117145ca1b86SEd Tanous { 117245ca1b86SEd Tanous return; 117345ca1b86SEd Tanous } 1174253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 117522d268cbSEd Tanous { 117622d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 117722d268cbSEd Tanous systemName); 117822d268cbSEd Tanous return; 117922d268cbSEd Tanous } 1180c4bf6374SJason M. Bills asyncResp->res.jsonValue["@odata.id"] = 1181253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/EventLog", 1182253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1183c4bf6374SJason M. Bills asyncResp->res.jsonValue["@odata.type"] = 1184b25644a1SJanet Adkins "#LogService.v1_2_0.LogService"; 1185c4bf6374SJason M. Bills asyncResp->res.jsonValue["Name"] = "Event Log Service"; 1186bd79bce8SPatrick Williams asyncResp->res.jsonValue["Description"] = 1187bd79bce8SPatrick Williams "System Event Log Service"; 1188c4bf6374SJason M. Bills asyncResp->res.jsonValue["Id"] = "EventLog"; 1189539d8c6bSEd Tanous asyncResp->res.jsonValue["OverWritePolicy"] = 1190539d8c6bSEd Tanous log_service::OverWritePolicy::WrapsWhenFull; 11917c8c4058STejas Patil 11927c8c4058STejas Patil std::pair<std::string, std::string> redfishDateTimeOffset = 11932b82937eSEd Tanous redfish::time_utils::getDateTimeOffsetNow(); 11947c8c4058STejas Patil 11957c8c4058STejas Patil asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first; 11967c8c4058STejas Patil asyncResp->res.jsonValue["DateTimeLocalOffset"] = 11977c8c4058STejas Patil redfishDateTimeOffset.second; 11987c8c4058STejas Patil 1199bd79bce8SPatrick Williams asyncResp->res.jsonValue["Entries"]["@odata.id"] = std::format( 1200bd79bce8SPatrick Williams "/redfish/v1/Systems/{}/LogServices/EventLog/Entries", 1201253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1202bd79bce8SPatrick Williams asyncResp->res 1203bd79bce8SPatrick Williams .jsonValue["Actions"]["#LogService.ClearLog"]["target"] 1204e7d6c8b2SGunnar Mills 120520fa6a2cSEd Tanous = std::format( 1206253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/EventLog/Actions/LogService.ClearLog", 120720fa6a2cSEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 12087e860f15SJohn Edward Broadbent }); 1209489640c6SJason M. Bills } 1210489640c6SJason M. Bills 1211599b9af3SAlexander Hansen inline void handleSystemsLogServicesEventLogActionsClearPost( 1212599b9af3SAlexander Hansen App& app, const crow::Request& req, 121322d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1214599b9af3SAlexander Hansen const std::string& systemName) 1215599b9af3SAlexander Hansen { 12163ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 121745ca1b86SEd Tanous { 121845ca1b86SEd Tanous return; 121945ca1b86SEd Tanous } 1220253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 122122d268cbSEd Tanous { 122222d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 122322d268cbSEd Tanous systemName); 122422d268cbSEd Tanous return; 122522d268cbSEd Tanous } 1226599b9af3SAlexander Hansen 1227489640c6SJason M. Bills // Clear the EventLog by deleting the log files 1228489640c6SJason M. Bills std::vector<std::filesystem::path> redfishLogFiles; 1229489640c6SJason M. Bills if (getRedfishLogFiles(redfishLogFiles)) 1230489640c6SJason M. Bills { 1231489640c6SJason M. Bills for (const std::filesystem::path& file : redfishLogFiles) 1232489640c6SJason M. Bills { 1233489640c6SJason M. Bills std::error_code ec; 1234489640c6SJason M. Bills std::filesystem::remove(file, ec); 1235489640c6SJason M. Bills } 1236489640c6SJason M. Bills } 1237489640c6SJason M. Bills 1238489640c6SJason M. Bills // Reload rsyslog so it knows to start new log files 1239177612aaSEd Tanous dbus::utility::async_method_call( 1240177612aaSEd Tanous asyncResp, 12415e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 1242489640c6SJason M. Bills if (ec) 1243489640c6SJason M. Bills { 124462598e31SEd Tanous BMCWEB_LOG_ERROR("Failed to reload rsyslog: {}", ec); 1245489640c6SJason M. Bills messages::internalError(asyncResp->res); 1246489640c6SJason M. Bills return; 1247489640c6SJason M. Bills } 1248489640c6SJason M. Bills 1249489640c6SJason M. Bills messages::success(asyncResp->res); 1250489640c6SJason M. Bills }, 1251489640c6SJason M. Bills "org.freedesktop.systemd1", "/org/freedesktop/systemd1", 1252002d39b4SEd Tanous "org.freedesktop.systemd1.Manager", "ReloadUnit", "rsyslog.service", 1253002d39b4SEd Tanous "replace"); 1254599b9af3SAlexander Hansen } 1255599b9af3SAlexander Hansen 1256599b9af3SAlexander Hansen inline void requestRoutesJournalEventLogClear(App& app) 1257599b9af3SAlexander Hansen { 1258599b9af3SAlexander Hansen BMCWEB_ROUTE( 1259599b9af3SAlexander Hansen app, 1260599b9af3SAlexander Hansen "/redfish/v1/Systems/<str>/LogServices/EventLog/Actions/LogService.ClearLog/") 1261fff6a4d3SAbhishek Patel .privileges(redfish::privileges:: 1262fff6a4d3SAbhishek Patel postLogServiceSubOverComputerSystemLogServiceCollection) 1263599b9af3SAlexander Hansen .methods(boost::beast::http::verb::post)(std::bind_front( 1264599b9af3SAlexander Hansen handleSystemsLogServicesEventLogActionsClearPost, std::ref(app))); 1265c4bf6374SJason M. Bills } 1266c4bf6374SJason M. Bills 1267ac992cdeSJason M. Bills enum class LogParseError 1268ac992cdeSJason M. Bills { 1269ac992cdeSJason M. Bills success, 1270ac992cdeSJason M. Bills parseFailed, 1271ac992cdeSJason M. Bills messageIdNotInRegistry, 1272ac992cdeSJason M. Bills }; 1273ac992cdeSJason M. Bills 1274bd79bce8SPatrick Williams static LogParseError fillEventLogEntryJson( 1275bd79bce8SPatrick Williams const std::string& logEntryID, const std::string& logEntry, 1276de703c5dSJason M. Bills nlohmann::json::object_t& logEntryJson) 1277c4bf6374SJason M. Bills { 127895820184SJason M. Bills // The redfish log format is "<Timestamp> <MessageId>,<MessageArgs>" 1279cd225da8SJason M. Bills // First get the Timestamp 1280f23b7296SEd Tanous size_t space = logEntry.find_first_of(' '); 1281cd225da8SJason M. Bills if (space == std::string::npos) 128295820184SJason M. Bills { 1283ac992cdeSJason M. Bills return LogParseError::parseFailed; 128495820184SJason M. Bills } 1285cd225da8SJason M. Bills std::string timestamp = logEntry.substr(0, space); 1286cd225da8SJason M. Bills // Then get the log contents 1287f23b7296SEd Tanous size_t entryStart = logEntry.find_first_not_of(' ', space); 1288cd225da8SJason M. Bills if (entryStart == std::string::npos) 1289cd225da8SJason M. Bills { 1290ac992cdeSJason M. Bills return LogParseError::parseFailed; 1291cd225da8SJason M. Bills } 1292cd225da8SJason M. Bills std::string_view entry(logEntry); 1293cd225da8SJason M. Bills entry.remove_prefix(entryStart); 1294cd225da8SJason M. Bills // Use split to separate the entry into its fields 1295cd225da8SJason M. Bills std::vector<std::string> logEntryFields; 129650ebd4afSEd Tanous bmcweb::split(logEntryFields, entry, ','); 1297cd225da8SJason M. Bills // We need at least a MessageId to be valid 12981e6deaf6SEd Tanous auto logEntryIter = logEntryFields.begin(); 12991e6deaf6SEd Tanous if (logEntryIter == logEntryFields.end()) 1300cd225da8SJason M. Bills { 1301ac992cdeSJason M. Bills return LogParseError::parseFailed; 1302cd225da8SJason M. Bills } 13031e6deaf6SEd Tanous std::string& messageID = *logEntryIter; 13044851d45dSJason M. Bills // Get the Message from the MessageRegistry 1305fffb8c1fSEd Tanous const registries::Message* message = registries::getMessage(messageID); 1306c4bf6374SJason M. Bills 13071e6deaf6SEd Tanous logEntryIter++; 130854417b02SSui Chen if (message == nullptr) 1309c4bf6374SJason M. Bills { 131062598e31SEd Tanous BMCWEB_LOG_WARNING("Log entry not found in registry: {}", logEntry); 1311ac992cdeSJason M. Bills return LogParseError::messageIdNotInRegistry; 1312c4bf6374SJason M. Bills } 1313c4bf6374SJason M. Bills 13141e6deaf6SEd Tanous std::vector<std::string_view> messageArgs(logEntryIter, 13151e6deaf6SEd Tanous logEntryFields.end()); 1316c05bba45SEd Tanous messageArgs.resize(message->numberOfArgs); 1317c05bba45SEd Tanous 1318bd79bce8SPatrick Williams std::string msg = 1319bd79bce8SPatrick Williams redfish::registries::fillMessageArgs(messageArgs, message->message); 13201e6deaf6SEd Tanous if (msg.empty()) 132115a86ff6SJason M. Bills { 13221e6deaf6SEd Tanous return LogParseError::parseFailed; 132315a86ff6SJason M. Bills } 13244851d45dSJason M. Bills 132595820184SJason M. Bills // Get the Created time from the timestamp. The log timestamp is in RFC3339 132695820184SJason M. Bills // format which matches the Redfish format except for the fractional seconds 132795820184SJason M. Bills // between the '.' and the '+', so just remove them. 1328f23b7296SEd Tanous std::size_t dot = timestamp.find_first_of('.'); 1329f23b7296SEd Tanous std::size_t plus = timestamp.find_first_of('+'); 133095820184SJason M. Bills if (dot != std::string::npos && plus != std::string::npos) 1331c4bf6374SJason M. Bills { 133295820184SJason M. Bills timestamp.erase(dot, plus - dot); 1333c4bf6374SJason M. Bills } 1334c4bf6374SJason M. Bills 1335c4bf6374SJason M. Bills // Fill in the log entry with the gathered data 13369c11a172SVijay Lobo logEntryJson["@odata.type"] = "#LogEntry.v1_9_0.LogEntry"; 1337ef4c65b7SEd Tanous logEntryJson["@odata.id"] = boost::urls::format( 1338253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}", 1339253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, logEntryID); 134084afc48bSJason M. Bills logEntryJson["Name"] = "System Event Log Entry"; 134184afc48bSJason M. Bills logEntryJson["Id"] = logEntryID; 134284afc48bSJason M. Bills logEntryJson["Message"] = std::move(msg); 134384afc48bSJason M. Bills logEntryJson["MessageId"] = std::move(messageID); 134484afc48bSJason M. Bills logEntryJson["MessageArgs"] = messageArgs; 134584afc48bSJason M. Bills logEntryJson["EntryType"] = "Event"; 134684afc48bSJason M. Bills logEntryJson["Severity"] = message->messageSeverity; 134784afc48bSJason M. Bills logEntryJson["Created"] = std::move(timestamp); 1348ac992cdeSJason M. Bills return LogParseError::success; 1349c4bf6374SJason M. Bills } 1350c4bf6374SJason M. Bills 13517f3726a2SMyung Bae inline void fillEventLogLogEntryFromDbusLogEntry( 13527f3726a2SMyung Bae const DbusEventLogEntry& entry, nlohmann::json& objectToFillOut) 1353898f2aa2SEd Tanous { 1354898f2aa2SEd Tanous objectToFillOut["@odata.type"] = "#LogEntry.v1_9_0.LogEntry"; 1355898f2aa2SEd Tanous objectToFillOut["@odata.id"] = boost::urls::format( 1356898f2aa2SEd Tanous "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}", 1357262dcc1cSAlexander Hansen BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(entry.Id)); 1358898f2aa2SEd Tanous objectToFillOut["Name"] = "System Event Log Entry"; 1359262dcc1cSAlexander Hansen objectToFillOut["Id"] = std::to_string(entry.Id); 1360262dcc1cSAlexander Hansen objectToFillOut["Message"] = entry.Message; 1361262dcc1cSAlexander Hansen objectToFillOut["Resolved"] = entry.Resolved; 1362262dcc1cSAlexander Hansen std::optional<bool> notifyAction = 1363262dcc1cSAlexander Hansen getProviderNotifyAction(entry.ServiceProviderNotify); 1364898f2aa2SEd Tanous if (notifyAction) 1365898f2aa2SEd Tanous { 1366898f2aa2SEd Tanous objectToFillOut["ServiceProviderNotified"] = *notifyAction; 1367898f2aa2SEd Tanous } 1368262dcc1cSAlexander Hansen if ((entry.Resolution != nullptr) && !entry.Resolution->empty()) 1369898f2aa2SEd Tanous { 1370262dcc1cSAlexander Hansen objectToFillOut["Resolution"] = *entry.Resolution; 1371898f2aa2SEd Tanous } 1372898f2aa2SEd Tanous objectToFillOut["EntryType"] = "Event"; 1373262dcc1cSAlexander Hansen objectToFillOut["Severity"] = 1374262dcc1cSAlexander Hansen translateSeverityDbusToRedfish(entry.Severity); 1375898f2aa2SEd Tanous objectToFillOut["Created"] = 1376262dcc1cSAlexander Hansen redfish::time_utils::getDateTimeUintMs(entry.Timestamp); 1377898f2aa2SEd Tanous objectToFillOut["Modified"] = 1378262dcc1cSAlexander Hansen redfish::time_utils::getDateTimeUintMs(entry.UpdateTimestamp); 1379262dcc1cSAlexander Hansen if (entry.Path != nullptr) 1380898f2aa2SEd Tanous { 1381898f2aa2SEd Tanous objectToFillOut["AdditionalDataURI"] = boost::urls::format( 1382898f2aa2SEd Tanous "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}/attachment", 1383262dcc1cSAlexander Hansen BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(entry.Id)); 1384898f2aa2SEd Tanous } 1385898f2aa2SEd Tanous } 1386898f2aa2SEd Tanous 1387b729096dSEd Tanous inline void afterLogEntriesGetManagedObjects( 1388b729096dSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1389b729096dSEd Tanous const boost::system::error_code& ec, 1390b729096dSEd Tanous const dbus::utility::ManagedObjectType& resp) 1391b729096dSEd Tanous { 1392b729096dSEd Tanous if (ec) 1393b729096dSEd Tanous { 1394b729096dSEd Tanous // TODO Handle for specific error code 1395b729096dSEd Tanous BMCWEB_LOG_ERROR("getLogEntriesIfaceData resp_handler got error {}", 1396b729096dSEd Tanous ec); 1397b729096dSEd Tanous messages::internalError(asyncResp->res); 1398b729096dSEd Tanous return; 1399b729096dSEd Tanous } 1400b729096dSEd Tanous nlohmann::json::array_t entriesArray; 1401b729096dSEd Tanous for (const auto& objectPath : resp) 1402b729096dSEd Tanous { 1403898f2aa2SEd Tanous dbus::utility::DBusPropertiesMap propsFlattened; 1404bd79bce8SPatrick Williams auto isEntry = 1405bd79bce8SPatrick Williams std::ranges::find_if(objectPath.second, [](const auto& object) { 1406898f2aa2SEd Tanous return object.first == "xyz.openbmc_project.Logging.Entry"; 1407898f2aa2SEd Tanous }); 1408898f2aa2SEd Tanous if (isEntry == objectPath.second.end()) 1409b729096dSEd Tanous { 1410b729096dSEd Tanous continue; 1411b729096dSEd Tanous } 14127f3726a2SMyung Bae 1413898f2aa2SEd Tanous for (const auto& interfaceMap : objectPath.second) 1414b729096dSEd Tanous { 1415898f2aa2SEd Tanous for (const auto& propertyMap : interfaceMap.second) 1416b729096dSEd Tanous { 1417898f2aa2SEd Tanous propsFlattened.emplace_back(propertyMap.first, 1418898f2aa2SEd Tanous propertyMap.second); 1419b729096dSEd Tanous } 1420b729096dSEd Tanous } 14217f3726a2SMyung Bae std::optional<DbusEventLogEntry> optEntry = 14227f3726a2SMyung Bae fillDbusEventLogEntryFromPropertyMap(propsFlattened); 14237f3726a2SMyung Bae 14247f3726a2SMyung Bae if (!optEntry.has_value()) 142590896601SIgor Kanyuka { 14267f3726a2SMyung Bae messages::internalError(asyncResp->res); 142790896601SIgor Kanyuka return; 142890896601SIgor Kanyuka } 14297f3726a2SMyung Bae fillEventLogLogEntryFromDbusLogEntry(*optEntry, 14307f3726a2SMyung Bae entriesArray.emplace_back()); 1431b729096dSEd Tanous } 1432898f2aa2SEd Tanous 143390896601SIgor Kanyuka redfish::json_util::sortJsonArrayByKey(entriesArray, "Id"); 1434b729096dSEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = entriesArray.size(); 1435b729096dSEd Tanous asyncResp->res.jsonValue["Members"] = std::move(entriesArray); 1436b729096dSEd Tanous } 1437b729096dSEd Tanous 1438599b9af3SAlexander Hansen inline void handleSystemsLogServiceEventLogLogEntryCollection( 1439599b9af3SAlexander Hansen App& app, const crow::Request& req, 144022d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1441599b9af3SAlexander Hansen const std::string& systemName) 1442599b9af3SAlexander Hansen { 1443c937d2bfSEd Tanous query_param::QueryCapabilities capabilities = { 1444c937d2bfSEd Tanous .canDelegateTop = true, 1445c937d2bfSEd Tanous .canDelegateSkip = true, 1446c937d2bfSEd Tanous }; 1447c937d2bfSEd Tanous query_param::Query delegatedQuery; 1448599b9af3SAlexander Hansen if (!redfish::setUpRedfishRouteWithDelegation(app, req, asyncResp, 1449599b9af3SAlexander Hansen delegatedQuery, capabilities)) 1450c4bf6374SJason M. Bills { 1451c4bf6374SJason M. Bills return; 1452c4bf6374SJason M. Bills } 145325b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 14547f3e84a1SEd Tanous { 14557f3e84a1SEd Tanous // Option currently returns no systems. TBD 14567f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 14577f3e84a1SEd Tanous systemName); 14587f3e84a1SEd Tanous return; 14597f3e84a1SEd Tanous } 1460253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 146122d268cbSEd Tanous { 146222d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 146322d268cbSEd Tanous systemName); 146422d268cbSEd Tanous return; 146522d268cbSEd Tanous } 146622d268cbSEd Tanous 14675143f7a5SJiaqing Zhao size_t top = delegatedQuery.top.value_or(query_param::Query::maxTop); 14683648c8beSEd Tanous size_t skip = delegatedQuery.skip.value_or(0); 14693648c8beSEd Tanous 14707e860f15SJohn Edward Broadbent // Collections don't include the static data added by SubRoute 14717e860f15SJohn Edward Broadbent // because it has a duplicate entry for members 1472c4bf6374SJason M. Bills asyncResp->res.jsonValue["@odata.type"] = 1473c4bf6374SJason M. Bills "#LogEntryCollection.LogEntryCollection"; 1474c4bf6374SJason M. Bills asyncResp->res.jsonValue["@odata.id"] = 1475253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries", 1476253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1477c4bf6374SJason M. Bills asyncResp->res.jsonValue["Name"] = "System Event Log Entries"; 1478c4bf6374SJason M. Bills asyncResp->res.jsonValue["Description"] = 1479c4bf6374SJason M. Bills "Collection of System Event Log Entries"; 1480cb92c03bSAndrew Geissler 14814978b63fSJason M. Bills nlohmann::json& logEntryArray = asyncResp->res.jsonValue["Members"]; 1482c4bf6374SJason M. Bills logEntryArray = nlohmann::json::array(); 14837e860f15SJohn Edward Broadbent // Go through the log files and create a unique ID for each 14847e860f15SJohn Edward Broadbent // entry 148595820184SJason M. Bills std::vector<std::filesystem::path> redfishLogFiles; 148695820184SJason M. Bills getRedfishLogFiles(redfishLogFiles); 1487b01bf299SEd Tanous uint64_t entryCount = 0; 1488cd225da8SJason M. Bills std::string logEntry; 148995820184SJason M. Bills 14907e860f15SJohn Edward Broadbent // Oldest logs are in the last file, so start there and loop 14917e860f15SJohn Edward Broadbent // backwards 1492599b9af3SAlexander Hansen for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend(); it++) 1493c4bf6374SJason M. Bills { 1494cd225da8SJason M. Bills std::ifstream logStream(*it); 149595820184SJason M. Bills if (!logStream.is_open()) 1496c4bf6374SJason M. Bills { 1497c4bf6374SJason M. Bills continue; 1498c4bf6374SJason M. Bills } 1499c4bf6374SJason M. Bills 1500e85d6b16SJason M. Bills // Reset the unique ID on the first entry 1501e85d6b16SJason M. Bills bool firstEntry = true; 150295820184SJason M. Bills while (std::getline(logStream, logEntry)) 150395820184SJason M. Bills { 1504c4bf6374SJason M. Bills std::string idStr; 1505e85d6b16SJason M. Bills if (!getUniqueEntryID(logEntry, idStr, firstEntry)) 1506c4bf6374SJason M. Bills { 1507c4bf6374SJason M. Bills continue; 1508c4bf6374SJason M. Bills } 1509e85d6b16SJason M. Bills firstEntry = false; 1510e85d6b16SJason M. Bills 1511de703c5dSJason M. Bills nlohmann::json::object_t bmcLogEntry; 1512bd79bce8SPatrick Williams LogParseError status = 1513bd79bce8SPatrick Williams fillEventLogEntryJson(idStr, logEntry, bmcLogEntry); 1514ac992cdeSJason M. Bills if (status == LogParseError::messageIdNotInRegistry) 1515ac992cdeSJason M. Bills { 1516ac992cdeSJason M. Bills continue; 1517ac992cdeSJason M. Bills } 1518ac992cdeSJason M. Bills if (status != LogParseError::success) 1519c4bf6374SJason M. Bills { 1520c4bf6374SJason M. Bills messages::internalError(asyncResp->res); 1521c4bf6374SJason M. Bills return; 1522c4bf6374SJason M. Bills } 1523de703c5dSJason M. Bills 1524de703c5dSJason M. Bills entryCount++; 1525de703c5dSJason M. Bills // Handle paging using skip (number of entries to skip from the 1526de703c5dSJason M. Bills // start) and top (number of entries to display) 15273648c8beSEd Tanous if (entryCount <= skip || entryCount > skip + top) 1528de703c5dSJason M. Bills { 1529de703c5dSJason M. Bills continue; 1530de703c5dSJason M. Bills } 1531de703c5dSJason M. Bills 1532b2ba3072SPatrick Williams logEntryArray.emplace_back(std::move(bmcLogEntry)); 1533c4bf6374SJason M. Bills } 153495820184SJason M. Bills } 1535c4bf6374SJason M. Bills asyncResp->res.jsonValue["Members@odata.count"] = entryCount; 15363648c8beSEd Tanous if (skip + top < entryCount) 1537c4bf6374SJason M. Bills { 1538599b9af3SAlexander Hansen asyncResp->res.jsonValue["Members@odata.nextLink"] = 1539599b9af3SAlexander Hansen boost::urls::format( 1540253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/EventLog/Entries?$skip={}", 1541253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(skip + top)); 1542c4bf6374SJason M. Bills } 1543897967deSJason M. Bills } 1544897967deSJason M. Bills 1545599b9af3SAlexander Hansen inline void requestRoutesJournalEventLogEntryCollection(App& app) 1546897967deSJason M. Bills { 1547599b9af3SAlexander Hansen BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/") 1548599b9af3SAlexander Hansen .privileges(redfish::privileges::getLogEntryCollection) 1549599b9af3SAlexander Hansen .methods(boost::beast::http::verb::get)(std::bind_front( 1550599b9af3SAlexander Hansen handleSystemsLogServiceEventLogLogEntryCollection, std::ref(app))); 1551599b9af3SAlexander Hansen } 1552599b9af3SAlexander Hansen 1553599b9af3SAlexander Hansen inline void handleSystemsLogServiceEventLogEntriesGet( 1554599b9af3SAlexander Hansen App& app, const crow::Request& req, 15557e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1556599b9af3SAlexander Hansen const std::string& systemName, const std::string& param) 1557599b9af3SAlexander Hansen { 15583ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 155945ca1b86SEd Tanous { 156045ca1b86SEd Tanous return; 156145ca1b86SEd Tanous } 156225b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 15637f3e84a1SEd Tanous { 15647f3e84a1SEd Tanous // Option currently returns no systems. TBD 15657f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 15667f3e84a1SEd Tanous systemName); 15677f3e84a1SEd Tanous return; 15687f3e84a1SEd Tanous } 156922d268cbSEd Tanous 1570253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 157122d268cbSEd Tanous { 157222d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 157322d268cbSEd Tanous systemName); 157422d268cbSEd Tanous return; 157522d268cbSEd Tanous } 157622d268cbSEd Tanous 15777e860f15SJohn Edward Broadbent const std::string& targetID = param; 15788d1b46d7Szhanghch05 15797e860f15SJohn Edward Broadbent // Go through the log files and check the unique ID for each 15807e860f15SJohn Edward Broadbent // entry to find the target entry 1581897967deSJason M. Bills std::vector<std::filesystem::path> redfishLogFiles; 1582897967deSJason M. Bills getRedfishLogFiles(redfishLogFiles); 1583897967deSJason M. Bills std::string logEntry; 1584897967deSJason M. Bills 15857e860f15SJohn Edward Broadbent // Oldest logs are in the last file, so start there and loop 15867e860f15SJohn Edward Broadbent // backwards 1587599b9af3SAlexander Hansen for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend(); it++) 1588897967deSJason M. Bills { 1589897967deSJason M. Bills std::ifstream logStream(*it); 1590897967deSJason M. Bills if (!logStream.is_open()) 1591897967deSJason M. Bills { 1592897967deSJason M. Bills continue; 1593897967deSJason M. Bills } 1594897967deSJason M. Bills 1595897967deSJason M. Bills // Reset the unique ID on the first entry 1596897967deSJason M. Bills bool firstEntry = true; 1597897967deSJason M. Bills while (std::getline(logStream, logEntry)) 1598897967deSJason M. Bills { 1599897967deSJason M. Bills std::string idStr; 1600897967deSJason M. Bills if (!getUniqueEntryID(logEntry, idStr, firstEntry)) 1601897967deSJason M. Bills { 1602897967deSJason M. Bills continue; 1603897967deSJason M. Bills } 1604897967deSJason M. Bills firstEntry = false; 1605897967deSJason M. Bills 1606897967deSJason M. Bills if (idStr == targetID) 1607897967deSJason M. Bills { 1608de703c5dSJason M. Bills nlohmann::json::object_t bmcLogEntry; 1609bd79bce8SPatrick Williams LogParseError status = 1610bd79bce8SPatrick Williams fillEventLogEntryJson(idStr, logEntry, bmcLogEntry); 1611ac992cdeSJason M. Bills if (status != LogParseError::success) 1612897967deSJason M. Bills { 1613897967deSJason M. Bills messages::internalError(asyncResp->res); 1614897967deSJason M. Bills return; 1615897967deSJason M. Bills } 1616d405bb51SJason M. Bills asyncResp->res.jsonValue.update(bmcLogEntry); 1617897967deSJason M. Bills return; 1618897967deSJason M. Bills } 1619897967deSJason M. Bills } 1620897967deSJason M. Bills } 1621897967deSJason M. Bills // Requested ID was not found 16229db4ba25SJiaqing Zhao messages::resourceNotFound(asyncResp->res, "LogEntry", targetID); 1623599b9af3SAlexander Hansen } 1624599b9af3SAlexander Hansen 1625599b9af3SAlexander Hansen inline void requestRoutesJournalEventLogEntry(App& app) 1626599b9af3SAlexander Hansen { 1627599b9af3SAlexander Hansen BMCWEB_ROUTE( 1628599b9af3SAlexander Hansen app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/") 1629599b9af3SAlexander Hansen .privileges(redfish::privileges::getLogEntry) 1630599b9af3SAlexander Hansen .methods(boost::beast::http::verb::get)(std::bind_front( 1631599b9af3SAlexander Hansen handleSystemsLogServiceEventLogEntriesGet, std::ref(app))); 1632599b9af3SAlexander Hansen } 1633599b9af3SAlexander Hansen 1634599b9af3SAlexander Hansen inline void dBusEventLogEntryCollection( 1635599b9af3SAlexander Hansen const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1636599b9af3SAlexander Hansen { 1637599b9af3SAlexander Hansen // Collections don't include the static data added by SubRoute 1638599b9af3SAlexander Hansen // because it has a duplicate entry for members 1639599b9af3SAlexander Hansen asyncResp->res.jsonValue["@odata.type"] = 1640599b9af3SAlexander Hansen "#LogEntryCollection.LogEntryCollection"; 1641599b9af3SAlexander Hansen asyncResp->res.jsonValue["@odata.id"] = 1642599b9af3SAlexander Hansen std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries", 1643599b9af3SAlexander Hansen BMCWEB_REDFISH_SYSTEM_URI_NAME); 1644599b9af3SAlexander Hansen asyncResp->res.jsonValue["Name"] = "System Event Log Entries"; 1645599b9af3SAlexander Hansen asyncResp->res.jsonValue["Description"] = 1646599b9af3SAlexander Hansen "Collection of System Event Log Entries"; 1647599b9af3SAlexander Hansen 1648599b9af3SAlexander Hansen // DBus implementation of EventLog/Entries 1649599b9af3SAlexander Hansen // Make call to Logging Service to find all log entry objects 1650599b9af3SAlexander Hansen sdbusplus::message::object_path path("/xyz/openbmc_project/logging"); 1651599b9af3SAlexander Hansen dbus::utility::getManagedObjects( 1652599b9af3SAlexander Hansen "xyz.openbmc_project.Logging", path, 1653599b9af3SAlexander Hansen [asyncResp](const boost::system::error_code& ec, 1654599b9af3SAlexander Hansen const dbus::utility::ManagedObjectType& resp) { 1655b729096dSEd Tanous afterLogEntriesGetManagedObjects(asyncResp, ec, resp); 16567e860f15SJohn Edward Broadbent }); 165708a4e4b5SAnthony Wilson } 165808a4e4b5SAnthony Wilson 16597e860f15SJohn Edward Broadbent inline void requestRoutesDBusEventLogEntryCollection(App& app) 166008a4e4b5SAnthony Wilson { 166122d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/") 1662ed398213SEd Tanous .privileges(redfish::privileges::getLogEntryCollection) 1663002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 1664002d39b4SEd Tanous [&app](const crow::Request& req, 166522d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 166622d268cbSEd Tanous const std::string& systemName) { 16673ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 166845ca1b86SEd Tanous { 166945ca1b86SEd Tanous return; 167045ca1b86SEd Tanous } 167125b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 16727f3e84a1SEd Tanous { 16737f3e84a1SEd Tanous // Option currently returns no systems. TBD 16747f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 16757f3e84a1SEd Tanous systemName); 16767f3e84a1SEd Tanous return; 16777f3e84a1SEd Tanous } 1678253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 167922d268cbSEd Tanous { 168022d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 168122d268cbSEd Tanous systemName); 168222d268cbSEd Tanous return; 168322d268cbSEd Tanous } 1684599b9af3SAlexander Hansen dBusEventLogEntryCollection(asyncResp); 1685599b9af3SAlexander Hansen }); 1686599b9af3SAlexander Hansen } 168722d268cbSEd Tanous 1688c6b7cae2SMyung Bae inline void afterDBusEventLogEntryGet( 1689c6b7cae2SMyung Bae const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1690c6b7cae2SMyung Bae const std::string& entryID, const boost::system::error_code& ec, 1691c6b7cae2SMyung Bae const dbus::utility::DBusPropertiesMap& resp) 1692c6b7cae2SMyung Bae { 1693c6b7cae2SMyung Bae if (ec.value() == EBADR) 1694c6b7cae2SMyung Bae { 1695c6b7cae2SMyung Bae messages::resourceNotFound(asyncResp->res, "EventLogEntry", entryID); 1696c6b7cae2SMyung Bae return; 1697c6b7cae2SMyung Bae } 1698c6b7cae2SMyung Bae if (ec) 1699c6b7cae2SMyung Bae { 1700c6b7cae2SMyung Bae BMCWEB_LOG_ERROR("EventLogEntry (DBus) resp_handler got error {}", ec); 1701c6b7cae2SMyung Bae messages::internalError(asyncResp->res); 1702c6b7cae2SMyung Bae return; 1703c6b7cae2SMyung Bae } 1704c6b7cae2SMyung Bae 17057f3726a2SMyung Bae std::optional<DbusEventLogEntry> optEntry = 17067f3726a2SMyung Bae fillDbusEventLogEntryFromPropertyMap(resp); 17077f3726a2SMyung Bae 17087f3726a2SMyung Bae if (!optEntry.has_value()) 17097f3726a2SMyung Bae { 17107f3726a2SMyung Bae messages::internalError(asyncResp->res); 17117f3726a2SMyung Bae return; 17127f3726a2SMyung Bae } 17137f3726a2SMyung Bae 17147f3726a2SMyung Bae fillEventLogLogEntryFromDbusLogEntry(*optEntry, asyncResp->res.jsonValue); 1715c6b7cae2SMyung Bae } 1716c6b7cae2SMyung Bae 1717bd79bce8SPatrick Williams inline void dBusEventLogEntryGet( 1718bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID) 1719599b9af3SAlexander Hansen { 1720599b9af3SAlexander Hansen dbus::utility::escapePathForDbus(entryID); 172108a4e4b5SAnthony Wilson 1722cb92c03bSAndrew Geissler // DBus implementation of EventLog/Entries 1723cb92c03bSAndrew Geissler // Make call to Logging Service to find all log entry objects 1724deae6a78SEd Tanous dbus::utility::getAllProperties( 1725deae6a78SEd Tanous "xyz.openbmc_project.Logging", 1726599b9af3SAlexander Hansen "/xyz/openbmc_project/logging/entry/" + entryID, "", 1727c6b7cae2SMyung Bae std::bind_front(afterDBusEventLogEntryGet, asyncResp, entryID)); 17287e860f15SJohn Edward Broadbent } 1729599b9af3SAlexander Hansen 1730504af5a0SPatrick Williams inline void dBusEventLogEntryPatch( 1731504af5a0SPatrick Williams const crow::Request& req, 1732599b9af3SAlexander Hansen const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1733599b9af3SAlexander Hansen const std::string& entryId) 1734599b9af3SAlexander Hansen { 1735599b9af3SAlexander Hansen std::optional<bool> resolved; 1736599b9af3SAlexander Hansen 1737599b9af3SAlexander Hansen if (!json_util::readJsonPatch(req, asyncResp->res, "Resolved", resolved)) 1738599b9af3SAlexander Hansen { 1739599b9af3SAlexander Hansen return; 1740599b9af3SAlexander Hansen } 1741599b9af3SAlexander Hansen BMCWEB_LOG_DEBUG("Set Resolved"); 1742599b9af3SAlexander Hansen 1743599b9af3SAlexander Hansen setDbusProperty(asyncResp, "Resolved", "xyz.openbmc_project.Logging", 1744599b9af3SAlexander Hansen "/xyz/openbmc_project/logging/entry/" + entryId, 1745599b9af3SAlexander Hansen "xyz.openbmc_project.Logging.Entry", "Resolved", 1746599b9af3SAlexander Hansen resolved.value_or(false)); 1747599b9af3SAlexander Hansen } 1748599b9af3SAlexander Hansen 1749bd79bce8SPatrick Williams inline void dBusEventLogEntryDelete( 1750bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID) 1751599b9af3SAlexander Hansen { 1752599b9af3SAlexander Hansen BMCWEB_LOG_DEBUG("Do delete single event entries."); 1753599b9af3SAlexander Hansen 1754599b9af3SAlexander Hansen dbus::utility::escapePathForDbus(entryID); 1755599b9af3SAlexander Hansen 1756599b9af3SAlexander Hansen // Process response from Logging service. 1757599b9af3SAlexander Hansen auto respHandler = [asyncResp, 1758599b9af3SAlexander Hansen entryID](const boost::system::error_code& ec) { 1759599b9af3SAlexander Hansen BMCWEB_LOG_DEBUG("EventLogEntry (DBus) doDelete callback: Done"); 1760599b9af3SAlexander Hansen if (ec) 1761599b9af3SAlexander Hansen { 1762599b9af3SAlexander Hansen if (ec.value() == EBADR) 1763599b9af3SAlexander Hansen { 1764599b9af3SAlexander Hansen messages::resourceNotFound(asyncResp->res, "LogEntry", entryID); 1765599b9af3SAlexander Hansen return; 1766599b9af3SAlexander Hansen } 1767599b9af3SAlexander Hansen // TODO Handle for specific error code 1768599b9af3SAlexander Hansen BMCWEB_LOG_ERROR( 1769599b9af3SAlexander Hansen "EventLogEntry (DBus) doDelete respHandler got error {}", ec); 1770599b9af3SAlexander Hansen asyncResp->res.result( 1771599b9af3SAlexander Hansen boost::beast::http::status::internal_server_error); 1772599b9af3SAlexander Hansen return; 1773599b9af3SAlexander Hansen } 1774599b9af3SAlexander Hansen 1775599b9af3SAlexander Hansen asyncResp->res.result(boost::beast::http::status::ok); 1776599b9af3SAlexander Hansen }; 1777599b9af3SAlexander Hansen 1778599b9af3SAlexander Hansen // Make call to Logging service to request Delete Log 1779177612aaSEd Tanous dbus::utility::async_method_call( 1780177612aaSEd Tanous asyncResp, respHandler, "xyz.openbmc_project.Logging", 1781599b9af3SAlexander Hansen "/xyz/openbmc_project/logging/entry/" + entryID, 1782599b9af3SAlexander Hansen "xyz.openbmc_project.Object.Delete", "Delete"); 17837e860f15SJohn Edward Broadbent } 17847e860f15SJohn Edward Broadbent 17857e860f15SJohn Edward Broadbent inline void requestRoutesDBusEventLogEntry(App& app) 17867e860f15SJohn Edward Broadbent { 17877e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 178822d268cbSEd Tanous app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/") 1789ed398213SEd Tanous .privileges(redfish::privileges::getLogEntry) 1790002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 1791002d39b4SEd Tanous [&app](const crow::Request& req, 17927e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1793898f2aa2SEd Tanous const std::string& systemName, const std::string& entryId) { 17943ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 17957e860f15SJohn Edward Broadbent { 179645ca1b86SEd Tanous return; 179745ca1b86SEd Tanous } 179825b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 17997f3e84a1SEd Tanous { 18007f3e84a1SEd Tanous // Option currently returns no systems. TBD 18017f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 18027f3e84a1SEd Tanous systemName); 18037f3e84a1SEd Tanous return; 18047f3e84a1SEd Tanous } 1805253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 180622d268cbSEd Tanous { 180722d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 180822d268cbSEd Tanous systemName); 180922d268cbSEd Tanous return; 181022d268cbSEd Tanous } 181122d268cbSEd Tanous 1812898f2aa2SEd Tanous dBusEventLogEntryGet(asyncResp, entryId); 18137e860f15SJohn Edward Broadbent }); 1814336e96c6SChicago Duan 18157e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 181622d268cbSEd Tanous app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/") 1817ed398213SEd Tanous .privileges(redfish::privileges::patchLogEntry) 18187e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::patch)( 181945ca1b86SEd Tanous [&app](const crow::Request& req, 18207e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 182122d268cbSEd Tanous const std::string& systemName, const std::string& entryId) { 18223ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 182345ca1b86SEd Tanous { 182445ca1b86SEd Tanous return; 182545ca1b86SEd Tanous } 182625b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 18277f3e84a1SEd Tanous { 18287f3e84a1SEd Tanous // Option currently returns no systems. TBD 18297f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 18307f3e84a1SEd Tanous systemName); 18317f3e84a1SEd Tanous return; 18327f3e84a1SEd Tanous } 1833253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 183422d268cbSEd Tanous { 183522d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 183622d268cbSEd Tanous systemName); 183722d268cbSEd Tanous return; 183822d268cbSEd Tanous } 183975710de2SXiaochao Ma 1840599b9af3SAlexander Hansen dBusEventLogEntryPatch(req, asyncResp, entryId); 18417e860f15SJohn Edward Broadbent }); 184275710de2SXiaochao Ma 18437e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 184422d268cbSEd Tanous app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/") 1845fff6a4d3SAbhishek Patel .privileges( 1846fff6a4d3SAbhishek Patel redfish::privileges:: 1847fff6a4d3SAbhishek Patel deleteLogEntrySubOverComputerSystemLogServiceCollectionLogServiceLogEntryCollection) 1848002d39b4SEd Tanous .methods(boost::beast::http::verb::delete_)( 1849002d39b4SEd Tanous [&app](const crow::Request& req, 1850002d39b4SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 185122d268cbSEd Tanous const std::string& systemName, const std::string& param) { 18523ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 1853336e96c6SChicago Duan { 185445ca1b86SEd Tanous return; 185545ca1b86SEd Tanous } 185625b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 18577f3e84a1SEd Tanous { 18587f3e84a1SEd Tanous // Option currently returns no systems. TBD 18597f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 18607f3e84a1SEd Tanous systemName); 18617f3e84a1SEd Tanous return; 18627f3e84a1SEd Tanous } 1863253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 186422d268cbSEd Tanous { 186522d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 186622d268cbSEd Tanous systemName); 186722d268cbSEd Tanous return; 186822d268cbSEd Tanous } 1869599b9af3SAlexander Hansen dBusEventLogEntryDelete(asyncResp, param); 18707e860f15SJohn Edward Broadbent }); 1871400fd1fbSAdriana Kobylak } 1872400fd1fbSAdriana Kobylak 1873dd72e87bSClaire Weinan inline void handleBMCLogServicesCollectionGet( 1874fdd26906SClaire Weinan crow::App& app, const crow::Request& req, 1875253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1876253f11b8SEd Tanous const std::string& managerId) 18771da66f75SEd Tanous { 18783ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 187945ca1b86SEd Tanous { 188045ca1b86SEd Tanous return; 188145ca1b86SEd Tanous } 1882253f11b8SEd Tanous 1883253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 1884253f11b8SEd Tanous { 1885253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 1886253f11b8SEd Tanous return; 1887253f11b8SEd Tanous } 1888253f11b8SEd Tanous 18897e860f15SJohn Edward Broadbent // Collections don't include the static data added by SubRoute 18907e860f15SJohn Edward Broadbent // because it has a duplicate entry for members 1891e1f26343SJason M. Bills asyncResp->res.jsonValue["@odata.type"] = 18921da66f75SEd Tanous "#LogServiceCollection.LogServiceCollection"; 1893253f11b8SEd Tanous asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 1894253f11b8SEd Tanous "/redfish/v1/Managers/{}/LogServices", BMCWEB_REDFISH_MANAGER_URI_NAME); 1895002d39b4SEd Tanous asyncResp->res.jsonValue["Name"] = "Open BMC Log Services Collection"; 1896e1f26343SJason M. Bills asyncResp->res.jsonValue["Description"] = 18971da66f75SEd Tanous "Collection of LogServices for this Manager"; 1898002d39b4SEd Tanous nlohmann::json& logServiceArray = asyncResp->res.jsonValue["Members"]; 1899c4bf6374SJason M. Bills logServiceArray = nlohmann::json::array(); 1900fdd26906SClaire Weinan 190125b54dbaSEd Tanous if constexpr (BMCWEB_REDFISH_BMC_JOURNAL) 190225b54dbaSEd Tanous { 1903613dabeaSEd Tanous nlohmann::json::object_t journal; 1904253f11b8SEd Tanous journal["@odata.id"] = 1905253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}/LogServices/Journal", 1906253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 1907b2ba3072SPatrick Williams logServiceArray.emplace_back(std::move(journal)); 190825b54dbaSEd Tanous } 1909fdd26906SClaire Weinan 1910fdd26906SClaire Weinan asyncResp->res.jsonValue["Members@odata.count"] = logServiceArray.size(); 1911fdd26906SClaire Weinan 191225b54dbaSEd Tanous if constexpr (BMCWEB_REDFISH_DUMP_LOG) 191325b54dbaSEd Tanous { 191415912159SGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 19157a1dbc48SGeorge Liu "xyz.openbmc_project.Collection.DeleteAll"}; 19167a1dbc48SGeorge Liu dbus::utility::getSubTreePaths( 19177a1dbc48SGeorge Liu "/xyz/openbmc_project/dump", 0, interfaces, 191825b54dbaSEd Tanous [asyncResp](const boost::system::error_code& ec, 191925b54dbaSEd Tanous const dbus::utility::MapperGetSubTreePathsResponse& 192025b54dbaSEd Tanous subTreePaths) { 1921fdd26906SClaire Weinan if (ec) 1922fdd26906SClaire Weinan { 192362598e31SEd Tanous BMCWEB_LOG_ERROR( 192462598e31SEd Tanous "handleBMCLogServicesCollectionGet respHandler got error {}", 192562598e31SEd Tanous ec); 1926bd79bce8SPatrick Williams // Assume that getting an error simply means there are no 1927bd79bce8SPatrick Williams // dump LogServices. Return without adding any error 1928bd79bce8SPatrick Williams // response. 1929fdd26906SClaire Weinan return; 1930fdd26906SClaire Weinan } 1931fdd26906SClaire Weinan 1932fdd26906SClaire Weinan nlohmann::json& logServiceArrayLocal = 1933fdd26906SClaire Weinan asyncResp->res.jsonValue["Members"]; 1934fdd26906SClaire Weinan 1935fdd26906SClaire Weinan for (const std::string& path : subTreePaths) 1936fdd26906SClaire Weinan { 1937fdd26906SClaire Weinan if (path == "/xyz/openbmc_project/dump/bmc") 1938fdd26906SClaire Weinan { 1939613dabeaSEd Tanous nlohmann::json::object_t member; 1940253f11b8SEd Tanous member["@odata.id"] = boost::urls::format( 1941253f11b8SEd Tanous "/redfish/v1/Managers/{}/LogServices/Dump", 1942253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 1943b2ba3072SPatrick Williams logServiceArrayLocal.emplace_back(std::move(member)); 1944fdd26906SClaire Weinan } 1945fdd26906SClaire Weinan else if (path == "/xyz/openbmc_project/dump/faultlog") 1946fdd26906SClaire Weinan { 1947613dabeaSEd Tanous nlohmann::json::object_t member; 1948253f11b8SEd Tanous member["@odata.id"] = boost::urls::format( 1949253f11b8SEd Tanous "/redfish/v1/Managers/{}/LogServices/FaultLog", 1950253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 1951b2ba3072SPatrick Williams logServiceArrayLocal.emplace_back(std::move(member)); 1952fdd26906SClaire Weinan } 1953fdd26906SClaire Weinan } 1954fdd26906SClaire Weinan 1955e1f26343SJason M. Bills asyncResp->res.jsonValue["Members@odata.count"] = 1956fdd26906SClaire Weinan logServiceArrayLocal.size(); 19577a1dbc48SGeorge Liu }); 195825b54dbaSEd Tanous } 1959fdd26906SClaire Weinan } 1960fdd26906SClaire Weinan 1961fdd26906SClaire Weinan inline void requestRoutesBMCLogServiceCollection(App& app) 1962fdd26906SClaire Weinan { 1963253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/") 1964fdd26906SClaire Weinan .privileges(redfish::privileges::getLogServiceCollection) 1965fdd26906SClaire Weinan .methods(boost::beast::http::verb::get)( 1966dd72e87bSClaire Weinan std::bind_front(handleBMCLogServicesCollectionGet, std::ref(app))); 1967e1f26343SJason M. Bills } 1968e1f26343SJason M. Bills 1969504af5a0SPatrick Williams inline void getDumpServiceInfo( 1970504af5a0SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1971fdd26906SClaire Weinan const std::string& dumpType) 1972c9bb6861Sraviteja-b { 1973fdd26906SClaire Weinan std::string dumpPath; 1974539d8c6bSEd Tanous log_service::OverWritePolicy overWritePolicy = 1975539d8c6bSEd Tanous log_service::OverWritePolicy::Invalid; 1976fdd26906SClaire Weinan bool collectDiagnosticDataSupported = false; 1977fdd26906SClaire Weinan 1978fdd26906SClaire Weinan if (dumpType == "BMC") 197945ca1b86SEd Tanous { 1980253f11b8SEd Tanous dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/Dump", 1981253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 1982539d8c6bSEd Tanous overWritePolicy = log_service::OverWritePolicy::WrapsWhenFull; 1983fdd26906SClaire Weinan collectDiagnosticDataSupported = true; 1984fdd26906SClaire Weinan } 1985fdd26906SClaire Weinan else if (dumpType == "FaultLog") 1986fdd26906SClaire Weinan { 1987253f11b8SEd Tanous dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/FaultLog", 1988253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 1989539d8c6bSEd Tanous overWritePolicy = log_service::OverWritePolicy::Unknown; 1990fdd26906SClaire Weinan collectDiagnosticDataSupported = false; 1991fdd26906SClaire Weinan } 1992fdd26906SClaire Weinan else if (dumpType == "System") 1993fdd26906SClaire Weinan { 1994253f11b8SEd Tanous dumpPath = std::format("/redfish/v1/Systems/{}/LogServices/Dump", 1995253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1996539d8c6bSEd Tanous overWritePolicy = log_service::OverWritePolicy::WrapsWhenFull; 1997fdd26906SClaire Weinan collectDiagnosticDataSupported = true; 1998fdd26906SClaire Weinan } 1999fdd26906SClaire Weinan else 2000fdd26906SClaire Weinan { 200162598e31SEd Tanous BMCWEB_LOG_ERROR("getDumpServiceInfo() invalid dump type: {}", 200262598e31SEd Tanous dumpType); 2003fdd26906SClaire Weinan messages::internalError(asyncResp->res); 200445ca1b86SEd Tanous return; 200545ca1b86SEd Tanous } 2006fdd26906SClaire Weinan 2007fdd26906SClaire Weinan asyncResp->res.jsonValue["@odata.id"] = dumpPath; 2008fdd26906SClaire Weinan asyncResp->res.jsonValue["@odata.type"] = "#LogService.v1_2_0.LogService"; 2009c9bb6861Sraviteja-b asyncResp->res.jsonValue["Name"] = "Dump LogService"; 2010fdd26906SClaire Weinan asyncResp->res.jsonValue["Description"] = dumpType + " Dump LogService"; 2011fdd26906SClaire Weinan asyncResp->res.jsonValue["Id"] = std::filesystem::path(dumpPath).filename(); 2012539d8c6bSEd Tanous asyncResp->res.jsonValue["OverWritePolicy"] = overWritePolicy; 20137c8c4058STejas Patil 20147c8c4058STejas Patil std::pair<std::string, std::string> redfishDateTimeOffset = 20152b82937eSEd Tanous redfish::time_utils::getDateTimeOffsetNow(); 20160fda0f12SGeorge Liu asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first; 20177c8c4058STejas Patil asyncResp->res.jsonValue["DateTimeLocalOffset"] = 20187c8c4058STejas Patil redfishDateTimeOffset.second; 20197c8c4058STejas Patil 2020fdd26906SClaire Weinan asyncResp->res.jsonValue["Entries"]["@odata.id"] = dumpPath + "/Entries"; 2021fdd26906SClaire Weinan 2022fdd26906SClaire Weinan if (collectDiagnosticDataSupported) 2023fdd26906SClaire Weinan { 2024002d39b4SEd Tanous asyncResp->res.jsonValue["Actions"]["#LogService.CollectDiagnosticData"] 20251476687dSEd Tanous ["target"] = 2026fdd26906SClaire Weinan dumpPath + "/Actions/LogService.CollectDiagnosticData"; 2027fdd26906SClaire Weinan } 20280d946211SClaire Weinan 20290d946211SClaire Weinan constexpr std::array<std::string_view, 1> interfaces = {deleteAllInterface}; 20300d946211SClaire Weinan dbus::utility::getSubTreePaths( 20310d946211SClaire Weinan "/xyz/openbmc_project/dump", 0, interfaces, 20320d946211SClaire Weinan [asyncResp, dumpType, dumpPath]( 20330d946211SClaire Weinan const boost::system::error_code& ec, 20340d946211SClaire Weinan const dbus::utility::MapperGetSubTreePathsResponse& subTreePaths) { 20350d946211SClaire Weinan if (ec) 20360d946211SClaire Weinan { 2037bd79bce8SPatrick Williams BMCWEB_LOG_ERROR("getDumpServiceInfo respHandler got error {}", 2038bd79bce8SPatrick Williams ec); 20390d946211SClaire Weinan // Assume that getting an error simply means there are no dump 20400d946211SClaire Weinan // LogServices. Return without adding any error response. 20410d946211SClaire Weinan return; 20420d946211SClaire Weinan } 204318f8f608SEd Tanous std::string dbusDumpPath = getDumpPath(dumpType); 20440d946211SClaire Weinan for (const std::string& path : subTreePaths) 20450d946211SClaire Weinan { 20460d946211SClaire Weinan if (path == dbusDumpPath) 20470d946211SClaire Weinan { 2048bd79bce8SPatrick Williams asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"] 2049bd79bce8SPatrick Williams ["target"] = 20500d946211SClaire Weinan dumpPath + "/Actions/LogService.ClearLog"; 20510d946211SClaire Weinan break; 20520d946211SClaire Weinan } 20530d946211SClaire Weinan } 20540d946211SClaire Weinan }); 2055c9bb6861Sraviteja-b } 2056c9bb6861Sraviteja-b 2057fdd26906SClaire Weinan inline void handleLogServicesDumpServiceGet( 2058fdd26906SClaire Weinan crow::App& app, const std::string& dumpType, const crow::Request& req, 2059253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2060253f11b8SEd Tanous const std::string& managerId) 20617e860f15SJohn Edward Broadbent { 20623ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 206345ca1b86SEd Tanous { 206445ca1b86SEd Tanous return; 206545ca1b86SEd Tanous } 2066253f11b8SEd Tanous 2067253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2068253f11b8SEd Tanous { 2069253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2070253f11b8SEd Tanous return; 2071253f11b8SEd Tanous } 2072253f11b8SEd Tanous 2073fdd26906SClaire Weinan getDumpServiceInfo(asyncResp, dumpType); 2074fdd26906SClaire Weinan } 2075c9bb6861Sraviteja-b 207622d268cbSEd Tanous inline void handleLogServicesDumpServiceComputerSystemGet( 207722d268cbSEd Tanous crow::App& app, const crow::Request& req, 207822d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 207922d268cbSEd Tanous const std::string& chassisId) 208022d268cbSEd Tanous { 208122d268cbSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 208222d268cbSEd Tanous { 208322d268cbSEd Tanous return; 208422d268cbSEd Tanous } 2085253f11b8SEd Tanous if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME) 208622d268cbSEd Tanous { 208722d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId); 208822d268cbSEd Tanous return; 208922d268cbSEd Tanous } 209022d268cbSEd Tanous getDumpServiceInfo(asyncResp, "System"); 209122d268cbSEd Tanous } 209222d268cbSEd Tanous 2093fdd26906SClaire Weinan inline void handleLogServicesDumpEntriesCollectionGet( 2094fdd26906SClaire Weinan crow::App& app, const std::string& dumpType, const crow::Request& req, 2095253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2096253f11b8SEd Tanous const std::string& managerId) 2097fdd26906SClaire Weinan { 2098fdd26906SClaire Weinan if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2099fdd26906SClaire Weinan { 2100fdd26906SClaire Weinan return; 2101fdd26906SClaire Weinan } 2102253f11b8SEd Tanous 2103253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2104253f11b8SEd Tanous { 2105253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2106253f11b8SEd Tanous return; 2107253f11b8SEd Tanous } 2108fdd26906SClaire Weinan getDumpEntryCollection(asyncResp, dumpType); 2109fdd26906SClaire Weinan } 2110fdd26906SClaire Weinan 211122d268cbSEd Tanous inline void handleLogServicesDumpEntriesCollectionComputerSystemGet( 211222d268cbSEd Tanous crow::App& app, const crow::Request& req, 211322d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 211422d268cbSEd Tanous const std::string& chassisId) 211522d268cbSEd Tanous { 211622d268cbSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 211722d268cbSEd Tanous { 211822d268cbSEd Tanous return; 211922d268cbSEd Tanous } 2120253f11b8SEd Tanous if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME) 212122d268cbSEd Tanous { 212222d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId); 212322d268cbSEd Tanous return; 212422d268cbSEd Tanous } 212522d268cbSEd Tanous getDumpEntryCollection(asyncResp, "System"); 212622d268cbSEd Tanous } 212722d268cbSEd Tanous 2128fdd26906SClaire Weinan inline void handleLogServicesDumpEntryGet( 2129fdd26906SClaire Weinan crow::App& app, const std::string& dumpType, const crow::Request& req, 2130fdd26906SClaire Weinan const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2131253f11b8SEd Tanous const std::string& managerId, const std::string& dumpId) 2132fdd26906SClaire Weinan { 2133fdd26906SClaire Weinan if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2134fdd26906SClaire Weinan { 2135fdd26906SClaire Weinan return; 2136fdd26906SClaire Weinan } 2137253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2138253f11b8SEd Tanous { 2139253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2140253f11b8SEd Tanous return; 2141253f11b8SEd Tanous } 2142fdd26906SClaire Weinan getDumpEntryById(asyncResp, dumpId, dumpType); 2143fdd26906SClaire Weinan } 2144168d1b1aSCarson Labrado 214522d268cbSEd Tanous inline void handleLogServicesDumpEntryComputerSystemGet( 214622d268cbSEd Tanous crow::App& app, const crow::Request& req, 214722d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 214822d268cbSEd Tanous const std::string& chassisId, const std::string& dumpId) 214922d268cbSEd Tanous { 215022d268cbSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 215122d268cbSEd Tanous { 215222d268cbSEd Tanous return; 215322d268cbSEd Tanous } 2154253f11b8SEd Tanous if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME) 215522d268cbSEd Tanous { 215622d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId); 215722d268cbSEd Tanous return; 215822d268cbSEd Tanous } 215922d268cbSEd Tanous getDumpEntryById(asyncResp, dumpId, "System"); 216022d268cbSEd Tanous } 2161fdd26906SClaire Weinan 2162fdd26906SClaire Weinan inline void handleLogServicesDumpEntryDelete( 2163fdd26906SClaire Weinan crow::App& app, const std::string& dumpType, const crow::Request& req, 2164fdd26906SClaire Weinan const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2165253f11b8SEd Tanous const std::string& managerId, const std::string& dumpId) 2166fdd26906SClaire Weinan { 2167fdd26906SClaire Weinan if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2168fdd26906SClaire Weinan { 2169fdd26906SClaire Weinan return; 2170fdd26906SClaire Weinan } 2171253f11b8SEd Tanous 2172253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2173253f11b8SEd Tanous { 2174253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2175253f11b8SEd Tanous return; 2176253f11b8SEd Tanous } 2177fdd26906SClaire Weinan deleteDumpEntry(asyncResp, dumpId, dumpType); 2178fdd26906SClaire Weinan } 2179fdd26906SClaire Weinan 218022d268cbSEd Tanous inline void handleLogServicesDumpEntryComputerSystemDelete( 218122d268cbSEd Tanous crow::App& app, const crow::Request& req, 218222d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 218322d268cbSEd Tanous const std::string& chassisId, const std::string& dumpId) 218422d268cbSEd Tanous { 218522d268cbSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 218622d268cbSEd Tanous { 218722d268cbSEd Tanous return; 218822d268cbSEd Tanous } 2189253f11b8SEd Tanous if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME) 219022d268cbSEd Tanous { 219122d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId); 219222d268cbSEd Tanous return; 219322d268cbSEd Tanous } 219422d268cbSEd Tanous deleteDumpEntry(asyncResp, dumpId, "System"); 219522d268cbSEd Tanous } 219622d268cbSEd Tanous 2197168d1b1aSCarson Labrado inline void handleLogServicesDumpEntryDownloadGet( 2198168d1b1aSCarson Labrado crow::App& app, const std::string& dumpType, const crow::Request& req, 2199168d1b1aSCarson Labrado const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2200253f11b8SEd Tanous const std::string& managerId, const std::string& dumpId) 2201168d1b1aSCarson Labrado { 2202168d1b1aSCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2203168d1b1aSCarson Labrado { 2204168d1b1aSCarson Labrado return; 2205168d1b1aSCarson Labrado } 2206253f11b8SEd Tanous 2207253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2208253f11b8SEd Tanous { 2209253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2210253f11b8SEd Tanous return; 2211253f11b8SEd Tanous } 2212168d1b1aSCarson Labrado downloadDumpEntry(asyncResp, dumpId, dumpType); 2213168d1b1aSCarson Labrado } 2214168d1b1aSCarson Labrado 2215168d1b1aSCarson Labrado inline void handleDBusEventLogEntryDownloadGet( 2216168d1b1aSCarson Labrado crow::App& app, const std::string& dumpType, const crow::Request& req, 2217168d1b1aSCarson Labrado const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2218168d1b1aSCarson Labrado const std::string& systemName, const std::string& entryID) 2219168d1b1aSCarson Labrado { 2220168d1b1aSCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2221168d1b1aSCarson Labrado { 2222168d1b1aSCarson Labrado return; 2223168d1b1aSCarson Labrado } 2224168d1b1aSCarson Labrado if (!http_helpers::isContentTypeAllowed( 2225168d1b1aSCarson Labrado req.getHeaderValue("Accept"), 2226168d1b1aSCarson Labrado http_helpers::ContentType::OctetStream, true)) 2227168d1b1aSCarson Labrado { 2228168d1b1aSCarson Labrado asyncResp->res.result(boost::beast::http::status::bad_request); 2229168d1b1aSCarson Labrado return; 2230168d1b1aSCarson Labrado } 2231168d1b1aSCarson Labrado downloadEventLogEntry(asyncResp, systemName, entryID, dumpType); 2232168d1b1aSCarson Labrado } 2233168d1b1aSCarson Labrado 2234fdd26906SClaire Weinan inline void handleLogServicesDumpCollectDiagnosticDataPost( 2235fdd26906SClaire Weinan crow::App& app, const std::string& dumpType, const crow::Request& req, 2236253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2237253f11b8SEd Tanous const std::string& managerId) 2238fdd26906SClaire Weinan { 2239fdd26906SClaire Weinan if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2240fdd26906SClaire Weinan { 2241fdd26906SClaire Weinan return; 2242fdd26906SClaire Weinan } 2243253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2244253f11b8SEd Tanous { 2245253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2246253f11b8SEd Tanous return; 2247253f11b8SEd Tanous } 2248253f11b8SEd Tanous 2249fdd26906SClaire Weinan createDump(asyncResp, req, dumpType); 2250fdd26906SClaire Weinan } 2251fdd26906SClaire Weinan 225222d268cbSEd Tanous inline void handleLogServicesDumpCollectDiagnosticDataComputerSystemPost( 225322d268cbSEd Tanous crow::App& app, const crow::Request& req, 225422d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 22557f3e84a1SEd Tanous const std::string& systemName) 225622d268cbSEd Tanous { 225722d268cbSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 225822d268cbSEd Tanous { 225922d268cbSEd Tanous return; 226022d268cbSEd Tanous } 22617f3e84a1SEd Tanous 226225b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 226322d268cbSEd Tanous { 22647f3e84a1SEd Tanous // Option currently returns no systems. TBD 22657f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 22667f3e84a1SEd Tanous systemName); 22677f3e84a1SEd Tanous return; 22687f3e84a1SEd Tanous } 2269253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 22707f3e84a1SEd Tanous { 22717f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 22727f3e84a1SEd Tanous systemName); 227322d268cbSEd Tanous return; 227422d268cbSEd Tanous } 227522d268cbSEd Tanous createDump(asyncResp, req, "System"); 227622d268cbSEd Tanous } 227722d268cbSEd Tanous 2278fdd26906SClaire Weinan inline void handleLogServicesDumpClearLogPost( 2279fdd26906SClaire Weinan crow::App& app, const std::string& dumpType, const crow::Request& req, 2280253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2281253f11b8SEd Tanous const std::string& managerId) 2282fdd26906SClaire Weinan { 2283fdd26906SClaire Weinan if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2284fdd26906SClaire Weinan { 2285fdd26906SClaire Weinan return; 2286fdd26906SClaire Weinan } 2287253f11b8SEd Tanous 2288253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2289253f11b8SEd Tanous { 2290253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2291253f11b8SEd Tanous return; 2292253f11b8SEd Tanous } 2293fdd26906SClaire Weinan clearDump(asyncResp, dumpType); 2294fdd26906SClaire Weinan } 2295fdd26906SClaire Weinan 229622d268cbSEd Tanous inline void handleLogServicesDumpClearLogComputerSystemPost( 229722d268cbSEd Tanous crow::App& app, const crow::Request& req, 229822d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 22997f3e84a1SEd Tanous const std::string& systemName) 230022d268cbSEd Tanous { 230122d268cbSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 230222d268cbSEd Tanous { 230322d268cbSEd Tanous return; 230422d268cbSEd Tanous } 230525b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 230622d268cbSEd Tanous { 23077f3e84a1SEd Tanous // Option currently returns no systems. TBD 23087f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 23097f3e84a1SEd Tanous systemName); 23107f3e84a1SEd Tanous return; 23117f3e84a1SEd Tanous } 2312253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 23137f3e84a1SEd Tanous { 23147f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 23157f3e84a1SEd Tanous systemName); 231622d268cbSEd Tanous return; 231722d268cbSEd Tanous } 231822d268cbSEd Tanous clearDump(asyncResp, "System"); 231922d268cbSEd Tanous } 232022d268cbSEd Tanous 2321fdd26906SClaire Weinan inline void requestRoutesBMCDumpService(App& app) 2322fdd26906SClaire Weinan { 2323253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/Dump/") 2324fdd26906SClaire Weinan .privileges(redfish::privileges::getLogService) 2325fdd26906SClaire Weinan .methods(boost::beast::http::verb::get)(std::bind_front( 2326fdd26906SClaire Weinan handleLogServicesDumpServiceGet, std::ref(app), "BMC")); 2327fdd26906SClaire Weinan } 2328fdd26906SClaire Weinan 2329fdd26906SClaire Weinan inline void requestRoutesBMCDumpEntryCollection(App& app) 2330fdd26906SClaire Weinan { 2331253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/") 2332fdd26906SClaire Weinan .privileges(redfish::privileges::getLogEntryCollection) 2333fdd26906SClaire Weinan .methods(boost::beast::http::verb::get)(std::bind_front( 2334fdd26906SClaire Weinan handleLogServicesDumpEntriesCollectionGet, std::ref(app), "BMC")); 2335c9bb6861Sraviteja-b } 2336c9bb6861Sraviteja-b 23377e860f15SJohn Edward Broadbent inline void requestRoutesBMCDumpEntry(App& app) 2338c9bb6861Sraviteja-b { 23397e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 2340253f11b8SEd Tanous "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/") 2341ed398213SEd Tanous .privileges(redfish::privileges::getLogEntry) 2342fdd26906SClaire Weinan .methods(boost::beast::http::verb::get)(std::bind_front( 2343fdd26906SClaire Weinan handleLogServicesDumpEntryGet, std::ref(app), "BMC")); 2344fdd26906SClaire Weinan 23457e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 2346253f11b8SEd Tanous "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/") 2347ed398213SEd Tanous .privileges(redfish::privileges::deleteLogEntry) 2348fdd26906SClaire Weinan .methods(boost::beast::http::verb::delete_)(std::bind_front( 2349fdd26906SClaire Weinan handleLogServicesDumpEntryDelete, std::ref(app), "BMC")); 2350c9bb6861Sraviteja-b } 2351c9bb6861Sraviteja-b 2352168d1b1aSCarson Labrado inline void requestRoutesBMCDumpEntryDownload(App& app) 2353168d1b1aSCarson Labrado { 2354168d1b1aSCarson Labrado BMCWEB_ROUTE( 2355168d1b1aSCarson Labrado app, 2356253f11b8SEd Tanous "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/attachment/") 2357168d1b1aSCarson Labrado .privileges(redfish::privileges::getLogEntry) 2358168d1b1aSCarson Labrado .methods(boost::beast::http::verb::get)(std::bind_front( 2359168d1b1aSCarson Labrado handleLogServicesDumpEntryDownloadGet, std::ref(app), "BMC")); 2360168d1b1aSCarson Labrado } 2361168d1b1aSCarson Labrado 23627e860f15SJohn Edward Broadbent inline void requestRoutesBMCDumpCreate(App& app) 2363c9bb6861Sraviteja-b { 23640fda0f12SGeorge Liu BMCWEB_ROUTE( 23650fda0f12SGeorge Liu app, 2366253f11b8SEd Tanous "/redfish/v1/Managers/<str>/LogServices/Dump/Actions/LogService.CollectDiagnosticData/") 2367ed398213SEd Tanous .privileges(redfish::privileges::postLogService) 23687e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 2369fdd26906SClaire Weinan std::bind_front(handleLogServicesDumpCollectDiagnosticDataPost, 2370fdd26906SClaire Weinan std::ref(app), "BMC")); 2371a43be80fSAsmitha Karunanithi } 2372a43be80fSAsmitha Karunanithi 23737e860f15SJohn Edward Broadbent inline void requestRoutesBMCDumpClear(App& app) 237480319af1SAsmitha Karunanithi { 23750fda0f12SGeorge Liu BMCWEB_ROUTE( 23760fda0f12SGeorge Liu app, 2377253f11b8SEd Tanous "/redfish/v1/Managers/<str>/LogServices/Dump/Actions/LogService.ClearLog/") 2378ed398213SEd Tanous .privileges(redfish::privileges::postLogService) 2379fdd26906SClaire Weinan .methods(boost::beast::http::verb::post)(std::bind_front( 2380fdd26906SClaire Weinan handleLogServicesDumpClearLogPost, std::ref(app), "BMC")); 238145ca1b86SEd Tanous } 2382fdd26906SClaire Weinan 2383168d1b1aSCarson Labrado inline void requestRoutesDBusEventLogEntryDownload(App& app) 2384168d1b1aSCarson Labrado { 2385168d1b1aSCarson Labrado BMCWEB_ROUTE( 2386168d1b1aSCarson Labrado app, 23879e9d99daSRavi Teja "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/attachment/") 2388168d1b1aSCarson Labrado .privileges(redfish::privileges::getLogEntry) 2389168d1b1aSCarson Labrado .methods(boost::beast::http::verb::get)(std::bind_front( 2390168d1b1aSCarson Labrado handleDBusEventLogEntryDownloadGet, std::ref(app), "System")); 2391168d1b1aSCarson Labrado } 2392168d1b1aSCarson Labrado 2393fdd26906SClaire Weinan inline void requestRoutesFaultLogDumpService(App& app) 2394fdd26906SClaire Weinan { 2395253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/") 2396fdd26906SClaire Weinan .privileges(redfish::privileges::getLogService) 2397fdd26906SClaire Weinan .methods(boost::beast::http::verb::get)(std::bind_front( 2398fdd26906SClaire Weinan handleLogServicesDumpServiceGet, std::ref(app), "FaultLog")); 2399fdd26906SClaire Weinan } 2400fdd26906SClaire Weinan 2401fdd26906SClaire Weinan inline void requestRoutesFaultLogDumpEntryCollection(App& app) 2402fdd26906SClaire Weinan { 2403253f11b8SEd Tanous BMCWEB_ROUTE(app, 2404253f11b8SEd Tanous "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/") 2405fdd26906SClaire Weinan .privileges(redfish::privileges::getLogEntryCollection) 2406fdd26906SClaire Weinan .methods(boost::beast::http::verb::get)( 2407fdd26906SClaire Weinan std::bind_front(handleLogServicesDumpEntriesCollectionGet, 2408fdd26906SClaire Weinan std::ref(app), "FaultLog")); 2409fdd26906SClaire Weinan } 2410fdd26906SClaire Weinan 2411fdd26906SClaire Weinan inline void requestRoutesFaultLogDumpEntry(App& app) 2412fdd26906SClaire Weinan { 2413253f11b8SEd Tanous BMCWEB_ROUTE( 2414253f11b8SEd Tanous app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/<str>/") 2415fdd26906SClaire Weinan .privileges(redfish::privileges::getLogEntry) 2416fdd26906SClaire Weinan .methods(boost::beast::http::verb::get)(std::bind_front( 2417fdd26906SClaire Weinan handleLogServicesDumpEntryGet, std::ref(app), "FaultLog")); 2418fdd26906SClaire Weinan 2419253f11b8SEd Tanous BMCWEB_ROUTE( 2420253f11b8SEd Tanous app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/<str>/") 2421fdd26906SClaire Weinan .privileges(redfish::privileges::deleteLogEntry) 2422fdd26906SClaire Weinan .methods(boost::beast::http::verb::delete_)(std::bind_front( 2423fdd26906SClaire Weinan handleLogServicesDumpEntryDelete, std::ref(app), "FaultLog")); 2424fdd26906SClaire Weinan } 2425fdd26906SClaire Weinan 2426fdd26906SClaire Weinan inline void requestRoutesFaultLogDumpClear(App& app) 2427fdd26906SClaire Weinan { 2428fdd26906SClaire Weinan BMCWEB_ROUTE( 2429fdd26906SClaire Weinan app, 2430253f11b8SEd Tanous "/redfish/v1/Managers/<str>/LogServices/FaultLog/Actions/LogService.ClearLog/") 2431fdd26906SClaire Weinan .privileges(redfish::privileges::postLogService) 2432fdd26906SClaire Weinan .methods(boost::beast::http::verb::post)(std::bind_front( 2433fdd26906SClaire Weinan handleLogServicesDumpClearLogPost, std::ref(app), "FaultLog")); 24345cb1dd27SAsmitha Karunanithi } 24355cb1dd27SAsmitha Karunanithi 24367e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpService(App& app) 24375cb1dd27SAsmitha Karunanithi { 243822d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Dump/") 2439ed398213SEd Tanous .privileges(redfish::privileges::getLogService) 24406ab9ad54SClaire Weinan .methods(boost::beast::http::verb::get)(std::bind_front( 244122d268cbSEd Tanous handleLogServicesDumpServiceComputerSystemGet, std::ref(app))); 24425cb1dd27SAsmitha Karunanithi } 24435cb1dd27SAsmitha Karunanithi 24447e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpEntryCollection(App& app) 24457e860f15SJohn Edward Broadbent { 244622d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/") 2447ed398213SEd Tanous .privileges(redfish::privileges::getLogEntryCollection) 244822d268cbSEd Tanous .methods(boost::beast::http::verb::get)(std::bind_front( 244922d268cbSEd Tanous handleLogServicesDumpEntriesCollectionComputerSystemGet, 245022d268cbSEd Tanous std::ref(app))); 24515cb1dd27SAsmitha Karunanithi } 24525cb1dd27SAsmitha Karunanithi 24537e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpEntry(App& app) 24545cb1dd27SAsmitha Karunanithi { 24557e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 245622d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/<str>/") 2457ed398213SEd Tanous .privileges(redfish::privileges::getLogEntry) 24586ab9ad54SClaire Weinan .methods(boost::beast::http::verb::get)(std::bind_front( 245922d268cbSEd Tanous handleLogServicesDumpEntryComputerSystemGet, std::ref(app))); 24608d1b46d7Szhanghch05 24617e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 246222d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/<str>/") 2463ed398213SEd Tanous .privileges(redfish::privileges::deleteLogEntry) 24646ab9ad54SClaire Weinan .methods(boost::beast::http::verb::delete_)(std::bind_front( 246522d268cbSEd Tanous handleLogServicesDumpEntryComputerSystemDelete, std::ref(app))); 24665cb1dd27SAsmitha Karunanithi } 2467c9bb6861Sraviteja-b 24687e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpCreate(App& app) 2469c9bb6861Sraviteja-b { 24700fda0f12SGeorge Liu BMCWEB_ROUTE( 24710fda0f12SGeorge Liu app, 247222d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Dump/Actions/LogService.CollectDiagnosticData/") 2473fff6a4d3SAbhishek Patel .privileges(redfish::privileges:: 2474fff6a4d3SAbhishek Patel postLogServiceSubOverComputerSystemLogServiceCollection) 247522d268cbSEd Tanous .methods(boost::beast::http::verb::post)(std::bind_front( 247622d268cbSEd Tanous handleLogServicesDumpCollectDiagnosticDataComputerSystemPost, 247722d268cbSEd Tanous std::ref(app))); 2478a43be80fSAsmitha Karunanithi } 2479a43be80fSAsmitha Karunanithi 24807e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpClear(App& app) 2481a43be80fSAsmitha Karunanithi { 24820fda0f12SGeorge Liu BMCWEB_ROUTE( 24830fda0f12SGeorge Liu app, 248422d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Dump/Actions/LogService.ClearLog/") 2485fff6a4d3SAbhishek Patel .privileges(redfish::privileges:: 2486fff6a4d3SAbhishek Patel postLogServiceSubOverComputerSystemLogServiceCollection) 24876ab9ad54SClaire Weinan .methods(boost::beast::http::verb::post)(std::bind_front( 248822d268cbSEd Tanous handleLogServicesDumpClearLogComputerSystemPost, std::ref(app))); 2489013487e5Sraviteja-b } 2490013487e5Sraviteja-b 24917e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpService(App& app) 24921da66f75SEd Tanous { 24931da66f75SEd Tanous /** 24941da66f75SEd Tanous * Functions triggers appropriate requests on DBus 24951da66f75SEd Tanous */ 249622d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Crashdump/") 249750d9f38aSMyung Bae .privileges(redfish::privileges::getLogService) 2498bd79bce8SPatrick Williams .methods( 2499bd79bce8SPatrick Williams boost::beast::http::verb:: 2500bd79bce8SPatrick Williams get)([&app](const crow::Request& req, 250122d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 250222d268cbSEd Tanous const std::string& systemName) { 25033ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 250445ca1b86SEd Tanous { 250545ca1b86SEd Tanous return; 250645ca1b86SEd Tanous } 250725b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 25087f3e84a1SEd Tanous { 25097f3e84a1SEd Tanous // Option currently returns no systems. TBD 25107f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 25117f3e84a1SEd Tanous systemName); 25127f3e84a1SEd Tanous return; 25137f3e84a1SEd Tanous } 2514253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 251522d268cbSEd Tanous { 251622d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 251722d268cbSEd Tanous systemName); 251822d268cbSEd Tanous return; 251922d268cbSEd Tanous } 252022d268cbSEd Tanous 25217e860f15SJohn Edward Broadbent // Copy over the static data to include the entries added by 25227e860f15SJohn Edward Broadbent // SubRoute 25230f74e643SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 2524253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/Crashdump", 2525253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 2526e1f26343SJason M. Bills asyncResp->res.jsonValue["@odata.type"] = 25278e6c099aSJason M. Bills "#LogService.v1_2_0.LogService"; 25284f50ae4bSGunnar Mills asyncResp->res.jsonValue["Name"] = "Open BMC Oem Crashdump Service"; 25294f50ae4bSGunnar Mills asyncResp->res.jsonValue["Description"] = "Oem Crashdump Service"; 253015b89725SV-Sanjana asyncResp->res.jsonValue["Id"] = "Crashdump"; 2531539d8c6bSEd Tanous asyncResp->res.jsonValue["OverWritePolicy"] = 2532539d8c6bSEd Tanous log_service::OverWritePolicy::WrapsWhenFull; 2533e1f26343SJason M. Bills asyncResp->res.jsonValue["MaxNumberOfRecords"] = 3; 25347c8c4058STejas Patil 25357c8c4058STejas Patil std::pair<std::string, std::string> redfishDateTimeOffset = 25362b82937eSEd Tanous redfish::time_utils::getDateTimeOffsetNow(); 25377c8c4058STejas Patil asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first; 25387c8c4058STejas Patil asyncResp->res.jsonValue["DateTimeLocalOffset"] = 25397c8c4058STejas Patil redfishDateTimeOffset.second; 25407c8c4058STejas Patil 2541bd79bce8SPatrick Williams asyncResp->res.jsonValue["Entries"]["@odata.id"] = std::format( 2542bd79bce8SPatrick Williams "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries", 2543253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 2544253f11b8SEd Tanous asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"] 2545253f11b8SEd Tanous ["target"] = std::format( 2546253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/Crashdump/Actions/LogService.ClearLog", 2547253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 2548bd79bce8SPatrick Williams asyncResp->res 2549bd79bce8SPatrick Williams .jsonValue["Actions"]["#LogService.CollectDiagnosticData"] 2550253f11b8SEd Tanous ["target"] = std::format( 2551253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/Crashdump/Actions/LogService.CollectDiagnosticData", 2552253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 25537e860f15SJohn Edward Broadbent }); 25541da66f75SEd Tanous } 25551da66f75SEd Tanous 25568e4736b3SEd Tanous inline void requestRoutesCrashdumpClear(App& app) 25575b61b5e8SJason M. Bills { 25580fda0f12SGeorge Liu BMCWEB_ROUTE( 25590fda0f12SGeorge Liu app, 256022d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Crashdump/Actions/LogService.ClearLog/") 256150d9f38aSMyung Bae .privileges(redfish::privileges:: 256250d9f38aSMyung Bae postLogServiceSubOverComputerSystemLogServiceCollection) 25637e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 256445ca1b86SEd Tanous [&app](const crow::Request& req, 256522d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 256622d268cbSEd Tanous const std::string& systemName) { 25673ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 256845ca1b86SEd Tanous { 256945ca1b86SEd Tanous return; 257045ca1b86SEd Tanous } 257125b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 25727f3e84a1SEd Tanous { 25737f3e84a1SEd Tanous // Option currently returns no systems. TBD 25747f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 25757f3e84a1SEd Tanous systemName); 25767f3e84a1SEd Tanous return; 25777f3e84a1SEd Tanous } 2578253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 257922d268cbSEd Tanous { 258022d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 258122d268cbSEd Tanous systemName); 258222d268cbSEd Tanous return; 258322d268cbSEd Tanous } 2584177612aaSEd Tanous dbus::utility::async_method_call( 2585177612aaSEd Tanous asyncResp, 25865e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec, 2587cb13a392SEd Tanous const std::string&) { 25885b61b5e8SJason M. Bills if (ec) 25895b61b5e8SJason M. Bills { 25905b61b5e8SJason M. Bills messages::internalError(asyncResp->res); 25915b61b5e8SJason M. Bills return; 25925b61b5e8SJason M. Bills } 25935b61b5e8SJason M. Bills messages::success(asyncResp->res); 25945b61b5e8SJason M. Bills }, 2595bd79bce8SPatrick Williams crashdumpObject, crashdumpPath, deleteAllInterface, 2596bd79bce8SPatrick Williams "DeleteAll"); 25977e860f15SJohn Edward Broadbent }); 25985b61b5e8SJason M. Bills } 25995b61b5e8SJason M. Bills 2600504af5a0SPatrick Williams inline void logCrashdumpEntry( 2601504af5a0SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 26028d1b46d7Szhanghch05 const std::string& logID, nlohmann::json& logEntryJson) 2603e855dd28SJason M. Bills { 2604043a0536SJohnathan Mantey auto getStoredLogCallback = 2605b9d36b47SEd Tanous [asyncResp, logID, 26065e7e2dc5SEd Tanous &logEntryJson](const boost::system::error_code& ec, 2607b9d36b47SEd Tanous const dbus::utility::DBusPropertiesMap& params) { 2608e855dd28SJason M. Bills if (ec) 2609e855dd28SJason M. Bills { 261062598e31SEd Tanous BMCWEB_LOG_DEBUG("failed to get log ec: {}", ec.message()); 26111ddcf01aSJason M. Bills if (ec.value() == 26121ddcf01aSJason M. Bills boost::system::linux_error::bad_request_descriptor) 26131ddcf01aSJason M. Bills { 2614bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "LogEntry", 2615bd79bce8SPatrick Williams logID); 26161ddcf01aSJason M. Bills } 26171ddcf01aSJason M. Bills else 26181ddcf01aSJason M. Bills { 2619e855dd28SJason M. Bills messages::internalError(asyncResp->res); 26201ddcf01aSJason M. Bills } 2621e855dd28SJason M. Bills return; 2622e855dd28SJason M. Bills } 2623043a0536SJohnathan Mantey 2624043a0536SJohnathan Mantey std::string timestamp{}; 2625043a0536SJohnathan Mantey std::string filename{}; 2626043a0536SJohnathan Mantey std::string logfile{}; 26272c70f800SEd Tanous parseCrashdumpParameters(params, filename, timestamp, logfile); 2628043a0536SJohnathan Mantey 2629043a0536SJohnathan Mantey if (filename.empty() || timestamp.empty()) 2630e855dd28SJason M. Bills { 26319db4ba25SJiaqing Zhao messages::resourceNotFound(asyncResp->res, "LogEntry", logID); 2632e855dd28SJason M. Bills return; 2633e855dd28SJason M. Bills } 2634e855dd28SJason M. Bills 2635043a0536SJohnathan Mantey std::string crashdumpURI = 2636bd79bce8SPatrick Williams std::format( 2637bd79bce8SPatrick Williams "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries/", 2638253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME) + 2639043a0536SJohnathan Mantey logID + "/" + filename; 264084afc48bSJason M. Bills nlohmann::json::object_t logEntry; 26419c11a172SVijay Lobo logEntry["@odata.type"] = "#LogEntry.v1_9_0.LogEntry"; 2642ef4c65b7SEd Tanous logEntry["@odata.id"] = boost::urls::format( 2643253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries/{}", 2644253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, logID); 264584afc48bSJason M. Bills logEntry["Name"] = "CPU Crashdump"; 264684afc48bSJason M. Bills logEntry["Id"] = logID; 2647539d8c6bSEd Tanous logEntry["EntryType"] = log_entry::LogEntryType::Oem; 264884afc48bSJason M. Bills logEntry["AdditionalDataURI"] = std::move(crashdumpURI); 264984afc48bSJason M. Bills logEntry["DiagnosticDataType"] = "OEM"; 265084afc48bSJason M. Bills logEntry["OEMDiagnosticDataType"] = "PECICrashdump"; 265184afc48bSJason M. Bills logEntry["Created"] = std::move(timestamp); 26522b20ef6eSJason M. Bills 26532b20ef6eSJason M. Bills // If logEntryJson references an array of LogEntry resources 26542b20ef6eSJason M. Bills // ('Members' list), then push this as a new entry, otherwise set it 26552b20ef6eSJason M. Bills // directly 26562b20ef6eSJason M. Bills if (logEntryJson.is_array()) 26572b20ef6eSJason M. Bills { 26582b20ef6eSJason M. Bills logEntryJson.push_back(logEntry); 26592b20ef6eSJason M. Bills asyncResp->res.jsonValue["Members@odata.count"] = 26602b20ef6eSJason M. Bills logEntryJson.size(); 26612b20ef6eSJason M. Bills } 26622b20ef6eSJason M. Bills else 26632b20ef6eSJason M. Bills { 2664d405bb51SJason M. Bills logEntryJson.update(logEntry); 26652b20ef6eSJason M. Bills } 2666e855dd28SJason M. Bills }; 2667deae6a78SEd Tanous dbus::utility::getAllProperties( 2668deae6a78SEd Tanous crashdumpObject, crashdumpPath + std::string("/") + logID, 2669deae6a78SEd Tanous crashdumpInterface, std::move(getStoredLogCallback)); 2670e855dd28SJason M. Bills } 2671e855dd28SJason M. Bills 26727e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpEntryCollection(App& app) 26731da66f75SEd Tanous { 26741da66f75SEd Tanous /** 26751da66f75SEd Tanous * Functions triggers appropriate requests on DBus 26761da66f75SEd Tanous */ 26777e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 267822d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/") 267950d9f38aSMyung Bae .privileges(redfish::privileges::getLogEntryCollection) 2680bd79bce8SPatrick Williams .methods( 2681bd79bce8SPatrick Williams boost::beast::http::verb:: 2682bd79bce8SPatrick Williams get)([&app](const crow::Request& req, 268322d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 268422d268cbSEd Tanous const std::string& systemName) { 26853ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 268645ca1b86SEd Tanous { 268745ca1b86SEd Tanous return; 268845ca1b86SEd Tanous } 268925b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 26907f3e84a1SEd Tanous { 26917f3e84a1SEd Tanous // Option currently returns no systems. TBD 26927f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 26937f3e84a1SEd Tanous systemName); 26947f3e84a1SEd Tanous return; 26957f3e84a1SEd Tanous } 2696253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 269722d268cbSEd Tanous { 269822d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 269922d268cbSEd Tanous systemName); 270022d268cbSEd Tanous return; 270122d268cbSEd Tanous } 270222d268cbSEd Tanous 27037a1dbc48SGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 27047a1dbc48SGeorge Liu crashdumpInterface}; 27057a1dbc48SGeorge Liu dbus::utility::getSubTreePaths( 27067a1dbc48SGeorge Liu "/", 0, interfaces, 27077a1dbc48SGeorge Liu [asyncResp](const boost::system::error_code& ec, 27082b20ef6eSJason M. Bills const std::vector<std::string>& resp) { 27091da66f75SEd Tanous if (ec) 27101da66f75SEd Tanous { 27111da66f75SEd Tanous if (ec.value() != 27121da66f75SEd Tanous boost::system::errc::no_such_file_or_directory) 27131da66f75SEd Tanous { 271462598e31SEd Tanous BMCWEB_LOG_DEBUG("failed to get entries ec: {}", 271562598e31SEd Tanous ec.message()); 2716f12894f8SJason M. Bills messages::internalError(asyncResp->res); 27171da66f75SEd Tanous return; 27181da66f75SEd Tanous } 27191da66f75SEd Tanous } 2720e1f26343SJason M. Bills asyncResp->res.jsonValue["@odata.type"] = 27211da66f75SEd Tanous "#LogEntryCollection.LogEntryCollection"; 2722253f11b8SEd Tanous asyncResp->res.jsonValue["@odata.id"] = std::format( 2723253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries", 2724253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 2725bd79bce8SPatrick Williams asyncResp->res.jsonValue["Name"] = 2726bd79bce8SPatrick Williams "Open BMC Crashdump Entries"; 2727e1f26343SJason M. Bills asyncResp->res.jsonValue["Description"] = 2728424c4176SJason M. Bills "Collection of Crashdump Entries"; 2729bd79bce8SPatrick Williams asyncResp->res.jsonValue["Members"] = 2730bd79bce8SPatrick Williams nlohmann::json::array(); 2731a2dd60a6SBrandon Kim asyncResp->res.jsonValue["Members@odata.count"] = 0; 27322b20ef6eSJason M. Bills 27332b20ef6eSJason M. Bills for (const std::string& path : resp) 27341da66f75SEd Tanous { 27352b20ef6eSJason M. Bills const sdbusplus::message::object_path objPath(path); 2736e855dd28SJason M. Bills // Get the log ID 27372b20ef6eSJason M. Bills std::string logID = objPath.filename(); 27382b20ef6eSJason M. Bills if (logID.empty()) 27391da66f75SEd Tanous { 2740e855dd28SJason M. Bills continue; 27411da66f75SEd Tanous } 2742e855dd28SJason M. Bills // Add the log entry to the array 27432b20ef6eSJason M. Bills logCrashdumpEntry(asyncResp, logID, 27442b20ef6eSJason M. Bills asyncResp->res.jsonValue["Members"]); 27451da66f75SEd Tanous } 27467a1dbc48SGeorge Liu }); 27477e860f15SJohn Edward Broadbent }); 27481da66f75SEd Tanous } 27491da66f75SEd Tanous 27507e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpEntry(App& app) 27511da66f75SEd Tanous { 27527e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 275322d268cbSEd Tanous app, "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/<str>/") 275450d9f38aSMyung Bae .privileges(redfish::privileges::getLogEntry) 27557e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 275645ca1b86SEd Tanous [&app](const crow::Request& req, 27577e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 275822d268cbSEd Tanous const std::string& systemName, const std::string& param) { 27593ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 276045ca1b86SEd Tanous { 276145ca1b86SEd Tanous return; 276245ca1b86SEd Tanous } 276325b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 27647f3e84a1SEd Tanous { 27657f3e84a1SEd Tanous // Option currently returns no systems. TBD 27667f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 27677f3e84a1SEd Tanous systemName); 27687f3e84a1SEd Tanous return; 27697f3e84a1SEd Tanous } 2770253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 277122d268cbSEd Tanous { 277222d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 277322d268cbSEd Tanous systemName); 277422d268cbSEd Tanous return; 277522d268cbSEd Tanous } 27767e860f15SJohn Edward Broadbent const std::string& logID = param; 2777e855dd28SJason M. Bills logCrashdumpEntry(asyncResp, logID, asyncResp->res.jsonValue); 27787e860f15SJohn Edward Broadbent }); 2779e855dd28SJason M. Bills } 2780e855dd28SJason M. Bills 27817e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpFile(App& app) 2782e855dd28SJason M. Bills { 27837e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 27847e860f15SJohn Edward Broadbent app, 278522d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/<str>/<str>/") 2786ed398213SEd Tanous .privileges(redfish::privileges::getLogEntry) 27877e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 2788a4ce114aSNan Zhou [](const crow::Request& req, 27897e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 279022d268cbSEd Tanous const std::string& systemName, const std::string& logID, 279122d268cbSEd Tanous const std::string& fileName) { 2792bd79bce8SPatrick Williams // Do not call getRedfishRoute here since the crashdump file is 2793bd79bce8SPatrick Williams // not a Redfish resource. 279422d268cbSEd Tanous 279525b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 27967f3e84a1SEd Tanous { 27977f3e84a1SEd Tanous // Option currently returns no systems. TBD 27987f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 27997f3e84a1SEd Tanous systemName); 28007f3e84a1SEd Tanous return; 28017f3e84a1SEd Tanous } 2802253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 280322d268cbSEd Tanous { 280422d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 280522d268cbSEd Tanous systemName); 280622d268cbSEd Tanous return; 280722d268cbSEd Tanous } 280822d268cbSEd Tanous 2809043a0536SJohnathan Mantey auto getStoredLogCallback = 2810bd79bce8SPatrick Williams [asyncResp, logID, fileName, 2811bd79bce8SPatrick Williams url(boost::urls::url(req.url()))]( 28125e7e2dc5SEd Tanous const boost::system::error_code& ec, 2813bd79bce8SPatrick Williams const std::vector<std::pair< 2814bd79bce8SPatrick Williams std::string, dbus::utility::DbusVariantType>>& 28157e860f15SJohn Edward Broadbent resp) { 28161da66f75SEd Tanous if (ec) 28171da66f75SEd Tanous { 2818bd79bce8SPatrick Williams BMCWEB_LOG_DEBUG("failed to get log ec: {}", 2819bd79bce8SPatrick Williams ec.message()); 2820f12894f8SJason M. Bills messages::internalError(asyncResp->res); 28211da66f75SEd Tanous return; 28221da66f75SEd Tanous } 2823e855dd28SJason M. Bills 2824043a0536SJohnathan Mantey std::string dbusFilename{}; 2825043a0536SJohnathan Mantey std::string dbusTimestamp{}; 2826043a0536SJohnathan Mantey std::string dbusFilepath{}; 2827043a0536SJohnathan Mantey 2828bd79bce8SPatrick Williams parseCrashdumpParameters(resp, dbusFilename, 2829bd79bce8SPatrick Williams dbusTimestamp, dbusFilepath); 2830043a0536SJohnathan Mantey 2831043a0536SJohnathan Mantey if (dbusFilename.empty() || dbusTimestamp.empty() || 2832043a0536SJohnathan Mantey dbusFilepath.empty()) 28331da66f75SEd Tanous { 2834bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, 2835bd79bce8SPatrick Williams "LogEntry", logID); 28361da66f75SEd Tanous return; 28371da66f75SEd Tanous } 2838e855dd28SJason M. Bills 2839043a0536SJohnathan Mantey // Verify the file name parameter is correct 2840043a0536SJohnathan Mantey if (fileName != dbusFilename) 2841043a0536SJohnathan Mantey { 2842bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, 2843bd79bce8SPatrick Williams "LogEntry", logID); 2844043a0536SJohnathan Mantey return; 2845043a0536SJohnathan Mantey } 2846043a0536SJohnathan Mantey 2847d51c61b4SMyung Bae if (asyncResp->res.openFile(dbusFilepath) != 2848d51c61b4SMyung Bae crow::OpenCode::Success) 2849043a0536SJohnathan Mantey { 2850bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, 2851bd79bce8SPatrick Williams "LogEntry", logID); 2852043a0536SJohnathan Mantey return; 2853043a0536SJohnathan Mantey } 2854043a0536SJohnathan Mantey 28557e860f15SJohn Edward Broadbent // Configure this to be a file download when accessed 28567e860f15SJohn Edward Broadbent // from a browser 2857d9f6c621SEd Tanous asyncResp->res.addHeader( 2858bd79bce8SPatrick Williams boost::beast::http::field::content_disposition, 2859bd79bce8SPatrick Williams "attachment"); 28601da66f75SEd Tanous }; 2861deae6a78SEd Tanous dbus::utility::getAllProperties( 2862d1bde9e5SKrzysztof Grobelny *crow::connections::systemBus, crashdumpObject, 2863bd79bce8SPatrick Williams crashdumpPath + std::string("/") + logID, 2864bd79bce8SPatrick Williams crashdumpInterface, std::move(getStoredLogCallback)); 28657e860f15SJohn Edward Broadbent }); 28661da66f75SEd Tanous } 28671da66f75SEd Tanous 2868c5a4c82aSJason M. Bills enum class OEMDiagnosticType 2869c5a4c82aSJason M. Bills { 2870c5a4c82aSJason M. Bills onDemand, 2871c5a4c82aSJason M. Bills telemetry, 2872c5a4c82aSJason M. Bills invalid, 2873c5a4c82aSJason M. Bills }; 2874c5a4c82aSJason M. Bills 287526ccae32SEd Tanous inline OEMDiagnosticType getOEMDiagnosticType(std::string_view oemDiagStr) 2876c5a4c82aSJason M. Bills { 2877c5a4c82aSJason M. Bills if (oemDiagStr == "OnDemand") 2878c5a4c82aSJason M. Bills { 2879c5a4c82aSJason M. Bills return OEMDiagnosticType::onDemand; 2880c5a4c82aSJason M. Bills } 2881c5a4c82aSJason M. Bills if (oemDiagStr == "Telemetry") 2882c5a4c82aSJason M. Bills { 2883c5a4c82aSJason M. Bills return OEMDiagnosticType::telemetry; 2884c5a4c82aSJason M. Bills } 2885c5a4c82aSJason M. Bills 2886c5a4c82aSJason M. Bills return OEMDiagnosticType::invalid; 2887c5a4c82aSJason M. Bills } 2888c5a4c82aSJason M. Bills 28897e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpCollect(App& app) 28901da66f75SEd Tanous { 28910fda0f12SGeorge Liu BMCWEB_ROUTE( 28920fda0f12SGeorge Liu app, 289322d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Crashdump/Actions/LogService.CollectDiagnosticData/") 289450d9f38aSMyung Bae .privileges(redfish::privileges:: 289550d9f38aSMyung Bae postLogServiceSubOverComputerSystemLogServiceCollection) 2896002d39b4SEd Tanous .methods(boost::beast::http::verb::post)( 2897002d39b4SEd Tanous [&app](const crow::Request& req, 289822d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 289922d268cbSEd Tanous const std::string& systemName) { 29003ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 290145ca1b86SEd Tanous { 290245ca1b86SEd Tanous return; 290345ca1b86SEd Tanous } 290422d268cbSEd Tanous 290525b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 29067f3e84a1SEd Tanous { 29077f3e84a1SEd Tanous // Option currently returns no systems. TBD 29087f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 29097f3e84a1SEd Tanous systemName); 29107f3e84a1SEd Tanous return; 29117f3e84a1SEd Tanous } 2912253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 291322d268cbSEd Tanous { 291422d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 291522d268cbSEd Tanous systemName); 291622d268cbSEd Tanous return; 291722d268cbSEd Tanous } 291822d268cbSEd Tanous 29198e6c099aSJason M. Bills std::string diagnosticDataType; 29208e6c099aSJason M. Bills std::string oemDiagnosticDataType; 2921afc474aeSMyung Bae if (!redfish::json_util::readJsonAction( // 2922afc474aeSMyung Bae req, asyncResp->res, // 2923afc474aeSMyung Bae "DiagnosticDataType", diagnosticDataType, // 2924afc474aeSMyung Bae "OEMDiagnosticDataType", oemDiagnosticDataType // 2925afc474aeSMyung Bae )) 29268e6c099aSJason M. Bills { 29278e6c099aSJason M. Bills return; 29288e6c099aSJason M. Bills } 29298e6c099aSJason M. Bills 29308e6c099aSJason M. Bills if (diagnosticDataType != "OEM") 29318e6c099aSJason M. Bills { 293262598e31SEd Tanous BMCWEB_LOG_ERROR( 293362598e31SEd Tanous "Only OEM DiagnosticDataType supported for Crashdump"); 29348e6c099aSJason M. Bills messages::actionParameterValueFormatError( 2935bd79bce8SPatrick Williams asyncResp->res, diagnosticDataType, 2936bd79bce8SPatrick Williams "DiagnosticDataType", "CollectDiagnosticData"); 29378e6c099aSJason M. Bills return; 29388e6c099aSJason M. Bills } 29398e6c099aSJason M. Bills 2940c5a4c82aSJason M. Bills OEMDiagnosticType oemDiagType = 2941c5a4c82aSJason M. Bills getOEMDiagnosticType(oemDiagnosticDataType); 2942c5a4c82aSJason M. Bills 2943c5a4c82aSJason M. Bills std::string iface; 2944c5a4c82aSJason M. Bills std::string method; 2945c5a4c82aSJason M. Bills std::string taskMatchStr; 2946c5a4c82aSJason M. Bills if (oemDiagType == OEMDiagnosticType::onDemand) 2947c5a4c82aSJason M. Bills { 2948c5a4c82aSJason M. Bills iface = crashdumpOnDemandInterface; 2949c5a4c82aSJason M. Bills method = "GenerateOnDemandLog"; 2950bd79bce8SPatrick Williams taskMatchStr = 2951bd79bce8SPatrick Williams "type='signal'," 2952c5a4c82aSJason M. Bills "interface='org.freedesktop.DBus.Properties'," 2953c5a4c82aSJason M. Bills "member='PropertiesChanged'," 2954c5a4c82aSJason M. Bills "arg0namespace='com.intel.crashdump'"; 2955c5a4c82aSJason M. Bills } 2956c5a4c82aSJason M. Bills else if (oemDiagType == OEMDiagnosticType::telemetry) 2957c5a4c82aSJason M. Bills { 2958c5a4c82aSJason M. Bills iface = crashdumpTelemetryInterface; 2959c5a4c82aSJason M. Bills method = "GenerateTelemetryLog"; 2960bd79bce8SPatrick Williams taskMatchStr = 2961bd79bce8SPatrick Williams "type='signal'," 2962c5a4c82aSJason M. Bills "interface='org.freedesktop.DBus.Properties'," 2963c5a4c82aSJason M. Bills "member='PropertiesChanged'," 2964c5a4c82aSJason M. Bills "arg0namespace='com.intel.crashdump'"; 2965c5a4c82aSJason M. Bills } 2966c5a4c82aSJason M. Bills else 2967c5a4c82aSJason M. Bills { 296862598e31SEd Tanous BMCWEB_LOG_ERROR("Unsupported OEMDiagnosticDataType: {}", 296962598e31SEd Tanous oemDiagnosticDataType); 2970c5a4c82aSJason M. Bills messages::actionParameterValueFormatError( 2971bd79bce8SPatrick Williams asyncResp->res, oemDiagnosticDataType, 2972bd79bce8SPatrick Williams "OEMDiagnosticDataType", "CollectDiagnosticData"); 2973c5a4c82aSJason M. Bills return; 2974c5a4c82aSJason M. Bills } 2975c5a4c82aSJason M. Bills 2976c5a4c82aSJason M. Bills auto collectCrashdumpCallback = 2977c5a4c82aSJason M. Bills [asyncResp, payload(task::Payload(req)), 29785e7e2dc5SEd Tanous taskMatchStr](const boost::system::error_code& ec, 297998be3e39SEd Tanous const std::string&) mutable { 29801da66f75SEd Tanous if (ec) 29811da66f75SEd Tanous { 2982bd79bce8SPatrick Williams if (ec.value() == 2983bd79bce8SPatrick Williams boost::system::errc::operation_not_supported) 29841da66f75SEd Tanous { 2985f12894f8SJason M. Bills messages::resourceInStandby(asyncResp->res); 29861da66f75SEd Tanous } 2987bd79bce8SPatrick Williams else if (ec.value() == boost::system::errc:: 2988bd79bce8SPatrick Williams device_or_resource_busy) 29894363d3b2SJason M. Bills { 2990bd79bce8SPatrick Williams messages::serviceTemporarilyUnavailable( 2991bd79bce8SPatrick Williams asyncResp->res, "60"); 29924363d3b2SJason M. Bills } 29931da66f75SEd Tanous else 29941da66f75SEd Tanous { 2995f12894f8SJason M. Bills messages::internalError(asyncResp->res); 29961da66f75SEd Tanous } 29971da66f75SEd Tanous return; 29981da66f75SEd Tanous } 2999bd79bce8SPatrick Williams std::shared_ptr<task::TaskData> task = 3000bd79bce8SPatrick Williams task::TaskData::createTask( 3001bd79bce8SPatrick Williams [](const boost::system::error_code& ec2, 3002bd79bce8SPatrick Williams sdbusplus::message_t&, 3003bd79bce8SPatrick Williams const std::shared_ptr<task::TaskData>& 3004bd79bce8SPatrick Williams taskData) { 30058b24275dSEd Tanous if (!ec2) 300666afe4faSJames Feist { 3007bd79bce8SPatrick Williams taskData->messages.emplace_back( 3008bd79bce8SPatrick Williams messages::taskCompletedOK( 3009bd79bce8SPatrick Williams std::to_string( 3010bd79bce8SPatrick Williams taskData->index))); 3011831d6b09SJames Feist taskData->state = "Completed"; 301266afe4faSJames Feist } 301332898ceaSJames Feist return task::completed; 301466afe4faSJames Feist }, 3015c5a4c82aSJason M. Bills taskMatchStr); 3016c5a4c82aSJason M. Bills 301746229577SJames Feist task->startTimer(std::chrono::minutes(5)); 301898be3e39SEd Tanous task->payload.emplace(std::move(payload)); 301929e2bdd7SChinmay Shripad Hegde task->populateResp(asyncResp->res); 30201da66f75SEd Tanous }; 30218e6c099aSJason M. Bills 3022177612aaSEd Tanous dbus::utility::async_method_call( 3023177612aaSEd Tanous asyncResp, std::move(collectCrashdumpCallback), 3024177612aaSEd Tanous crashdumpObject, crashdumpPath, iface, method); 30257e860f15SJohn Edward Broadbent }); 30266eda7685SKenny L. Ku } 30276eda7685SKenny L. Ku 3028599b9af3SAlexander Hansen inline void dBusLogServiceActionsClear( 3029599b9af3SAlexander Hansen const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 3030599b9af3SAlexander Hansen { 3031599b9af3SAlexander Hansen BMCWEB_LOG_DEBUG("Do delete all entries."); 3032599b9af3SAlexander Hansen 3033599b9af3SAlexander Hansen // Process response from Logging service. 3034599b9af3SAlexander Hansen auto respHandler = [asyncResp](const boost::system::error_code& ec) { 3035599b9af3SAlexander Hansen BMCWEB_LOG_DEBUG("doClearLog resp_handler callback: Done"); 3036599b9af3SAlexander Hansen if (ec) 3037599b9af3SAlexander Hansen { 3038599b9af3SAlexander Hansen // TODO Handle for specific error code 3039599b9af3SAlexander Hansen BMCWEB_LOG_ERROR("doClearLog resp_handler got error {}", ec); 3040599b9af3SAlexander Hansen asyncResp->res.result( 3041599b9af3SAlexander Hansen boost::beast::http::status::internal_server_error); 3042599b9af3SAlexander Hansen return; 3043599b9af3SAlexander Hansen } 3044599b9af3SAlexander Hansen 3045e2460466SAmy Chang messages::success(asyncResp->res); 3046599b9af3SAlexander Hansen }; 3047599b9af3SAlexander Hansen 3048599b9af3SAlexander Hansen // Make call to Logging service to request Clear Log 3049177612aaSEd Tanous dbus::utility::async_method_call( 3050177612aaSEd Tanous asyncResp, respHandler, "xyz.openbmc_project.Logging", 3051599b9af3SAlexander Hansen "/xyz/openbmc_project/logging", 3052599b9af3SAlexander Hansen "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll"); 3053599b9af3SAlexander Hansen } 3054599b9af3SAlexander Hansen 3055cb92c03bSAndrew Geissler /** 3056cb92c03bSAndrew Geissler * DBusLogServiceActionsClear class supports POST method for ClearLog action. 3057cb92c03bSAndrew Geissler */ 30587e860f15SJohn Edward Broadbent inline void requestRoutesDBusLogServiceActionsClear(App& app) 3059cb92c03bSAndrew Geissler { 3060cb92c03bSAndrew Geissler /** 3061cb92c03bSAndrew Geissler * Function handles POST method request. 3062cb92c03bSAndrew Geissler * The Clear Log actions does not require any parameter.The action deletes 3063cb92c03bSAndrew Geissler * all entries found in the Entries collection for this Log Service. 3064cb92c03bSAndrew Geissler */ 30657e860f15SJohn Edward Broadbent 30660fda0f12SGeorge Liu BMCWEB_ROUTE( 30670fda0f12SGeorge Liu app, 306822d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/EventLog/Actions/LogService.ClearLog/") 3069fff6a4d3SAbhishek Patel .privileges(redfish::privileges:: 3070fff6a4d3SAbhishek Patel postLogServiceSubOverComputerSystemLogServiceCollection) 30717e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 307245ca1b86SEd Tanous [&app](const crow::Request& req, 307322d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 307422d268cbSEd Tanous const std::string& systemName) { 30753ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 307645ca1b86SEd Tanous { 307745ca1b86SEd Tanous return; 307845ca1b86SEd Tanous } 307925b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 30807f3e84a1SEd Tanous { 30817f3e84a1SEd Tanous // Option currently returns no systems. TBD 30827f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 30837f3e84a1SEd Tanous systemName); 30847f3e84a1SEd Tanous return; 30857f3e84a1SEd Tanous } 3086253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 308722d268cbSEd Tanous { 308822d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 308922d268cbSEd Tanous systemName); 309022d268cbSEd Tanous return; 309122d268cbSEd Tanous } 3092599b9af3SAlexander Hansen dBusLogServiceActionsClear(asyncResp); 30937e860f15SJohn Edward Broadbent }); 3094cb92c03bSAndrew Geissler } 3095a3316fc6SZhikuiRen 30961da66f75SEd Tanous } // namespace redfish 3097