11da66f75SEd Tanous /* 26be832e2SEd Tanous Copyright (c) 2018 Intel Corporation 36be832e2SEd Tanous 46be832e2SEd Tanous Licensed under the Apache License, Version 2.0 (the "License"); 56be832e2SEd Tanous you may not use this file except in compliance with the License. 66be832e2SEd Tanous You may obtain a copy of the License at 76be832e2SEd Tanous 86be832e2SEd Tanous http://www.apache.org/licenses/LICENSE-2.0 96be832e2SEd Tanous 106be832e2SEd Tanous Unless required by applicable law or agreed to in writing, software 116be832e2SEd Tanous distributed under the License is distributed on an "AS IS" BASIS, 126be832e2SEd Tanous WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136be832e2SEd Tanous See the License for the specific language governing permissions and 146be832e2SEd Tanous limitations under the License. 151da66f75SEd Tanous */ 161da66f75SEd Tanous #pragma once 171da66f75SEd Tanous 183ccb3adbSEd Tanous #include "app.hpp" 197a1dbc48SGeorge Liu #include "dbus_utility.hpp" 203ccb3adbSEd Tanous #include "error_messages.hpp" 2168dd075aSAsmitha Karunanithi #include "generated/enums/log_entry.hpp" 22539d8c6bSEd Tanous #include "generated/enums/log_service.hpp" 23b7028ebfSSpencer Ku #include "gzfile.hpp" 24647b3cdcSGeorge Liu #include "http_utility.hpp" 25b7028ebfSSpencer Ku #include "human_sort.hpp" 263ccb3adbSEd Tanous #include "query.hpp" 274851d45dSJason M. Bills #include "registries.hpp" 284851d45dSJason M. Bills #include "registries/base_message_registry.hpp" 294851d45dSJason M. Bills #include "registries/openbmc_message_registry.hpp" 303ccb3adbSEd Tanous #include "registries/privilege_registry.hpp" 3146229577SJames Feist #include "task.hpp" 325b90429aSEd Tanous #include "task_messages.hpp" 33262dcc1cSAlexander Hansen #include "utils/dbus_event_log_entry.hpp" 343ccb3adbSEd Tanous #include "utils/dbus_utils.hpp" 355b90429aSEd Tanous #include "utils/json_utils.hpp" 363ccb3adbSEd Tanous #include "utils/time_utils.hpp" 371da66f75SEd Tanous 3875e8e218SMyung Bae #include <systemd/sd-id128.h> 398e31778eSAsmitha Karunanithi #include <tinyxml2.h> 40400fd1fbSAdriana Kobylak #include <unistd.h> 41e1f26343SJason M. Bills 4207c8c20dSEd Tanous #include <boost/beast/http/verb.hpp> 431da66f75SEd Tanous #include <boost/container/flat_map.hpp> 441ddcf01aSJason M. Bills #include <boost/system/linux_error.hpp> 45ef4c65b7SEd Tanous #include <boost/url/format.hpp> 46d1bde9e5SKrzysztof Grobelny #include <sdbusplus/asio/property.hpp> 47d1bde9e5SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp> 481214b7e7SGunnar Mills 497a1dbc48SGeorge Liu #include <array> 50647b3cdcSGeorge Liu #include <charconv> 51b5f288d2SAbhilash Raju #include <cstddef> 524418c7f0SJames Feist #include <filesystem> 5318f8f608SEd Tanous #include <iterator> 5475710de2SXiaochao Ma #include <optional> 553544d2a7SEd Tanous #include <ranges> 5626702d01SEd Tanous #include <span> 5718f8f608SEd Tanous #include <string> 58cd225da8SJason M. Bills #include <string_view> 59abf2add6SEd Tanous #include <variant> 601da66f75SEd Tanous 611da66f75SEd Tanous namespace redfish 621da66f75SEd Tanous { 631da66f75SEd Tanous 6489492a15SPatrick Williams constexpr const char* crashdumpObject = "com.intel.crashdump"; 6589492a15SPatrick Williams constexpr const char* crashdumpPath = "/com/intel/crashdump"; 6689492a15SPatrick Williams constexpr const char* crashdumpInterface = "com.intel.crashdump"; 6789492a15SPatrick Williams constexpr const char* deleteAllInterface = 685b61b5e8SJason M. Bills "xyz.openbmc_project.Collection.DeleteAll"; 6989492a15SPatrick Williams constexpr const char* crashdumpOnDemandInterface = 70424c4176SJason M. Bills "com.intel.crashdump.OnDemand"; 7189492a15SPatrick Williams constexpr const char* crashdumpTelemetryInterface = 726eda7685SKenny L. Ku "com.intel.crashdump.Telemetry"; 731da66f75SEd Tanous 748e31778eSAsmitha Karunanithi enum class DumpCreationProgress 758e31778eSAsmitha Karunanithi { 768e31778eSAsmitha Karunanithi DUMP_CREATE_SUCCESS, 778e31778eSAsmitha Karunanithi DUMP_CREATE_FAILED, 788e31778eSAsmitha Karunanithi DUMP_CREATE_INPROGRESS 798e31778eSAsmitha Karunanithi }; 808e31778eSAsmitha Karunanithi 81f6150403SJames Feist namespace fs = std::filesystem; 821da66f75SEd Tanous 83cb92c03bSAndrew Geissler inline std::string translateSeverityDbusToRedfish(const std::string& s) 84cb92c03bSAndrew Geissler { 85d4d25793SEd Tanous if ((s == "xyz.openbmc_project.Logging.Entry.Level.Alert") || 86d4d25793SEd Tanous (s == "xyz.openbmc_project.Logging.Entry.Level.Critical") || 87d4d25793SEd Tanous (s == "xyz.openbmc_project.Logging.Entry.Level.Emergency") || 88d4d25793SEd Tanous (s == "xyz.openbmc_project.Logging.Entry.Level.Error")) 89cb92c03bSAndrew Geissler { 90cb92c03bSAndrew Geissler return "Critical"; 91cb92c03bSAndrew Geissler } 923174e4dfSEd Tanous if ((s == "xyz.openbmc_project.Logging.Entry.Level.Debug") || 93d4d25793SEd Tanous (s == "xyz.openbmc_project.Logging.Entry.Level.Informational") || 94d4d25793SEd Tanous (s == "xyz.openbmc_project.Logging.Entry.Level.Notice")) 95cb92c03bSAndrew Geissler { 96cb92c03bSAndrew Geissler return "OK"; 97cb92c03bSAndrew Geissler } 983174e4dfSEd Tanous if (s == "xyz.openbmc_project.Logging.Entry.Level.Warning") 99cb92c03bSAndrew Geissler { 100cb92c03bSAndrew Geissler return "Warning"; 101cb92c03bSAndrew Geissler } 102cb92c03bSAndrew Geissler return ""; 103cb92c03bSAndrew Geissler } 104cb92c03bSAndrew Geissler 1059017faf2SAbhishek Patel inline std::optional<bool> getProviderNotifyAction(const std::string& notify) 1069017faf2SAbhishek Patel { 1079017faf2SAbhishek Patel std::optional<bool> notifyAction; 1089017faf2SAbhishek Patel if (notify == "xyz.openbmc_project.Logging.Entry.Notify.Notify") 1099017faf2SAbhishek Patel { 1109017faf2SAbhishek Patel notifyAction = true; 1119017faf2SAbhishek Patel } 1129017faf2SAbhishek Patel else if (notify == "xyz.openbmc_project.Logging.Entry.Notify.Inhibit") 1139017faf2SAbhishek Patel { 1149017faf2SAbhishek Patel notifyAction = false; 1159017faf2SAbhishek Patel } 1169017faf2SAbhishek Patel 1179017faf2SAbhishek Patel return notifyAction; 1189017faf2SAbhishek Patel } 1199017faf2SAbhishek Patel 12018f8f608SEd Tanous inline std::string getDumpPath(std::string_view dumpType) 12118f8f608SEd Tanous { 12218f8f608SEd Tanous std::string dbusDumpPath = "/xyz/openbmc_project/dump/"; 12318f8f608SEd Tanous std::ranges::transform(dumpType, std::back_inserter(dbusDumpPath), 12418f8f608SEd Tanous bmcweb::asciiToLower); 12518f8f608SEd Tanous 12618f8f608SEd Tanous return dbusDumpPath; 12718f8f608SEd Tanous } 12818f8f608SEd Tanous 129055713e4SEd Tanous inline bool getUniqueEntryID(const std::string& logEntry, std::string& entryID, 130e85d6b16SJason M. Bills const bool firstEntry = true) 13195820184SJason M. Bills { 132271584abSEd Tanous static time_t prevTs = 0; 13395820184SJason M. Bills static int index = 0; 134e85d6b16SJason M. Bills if (firstEntry) 135e85d6b16SJason M. Bills { 136e85d6b16SJason M. Bills prevTs = 0; 137e85d6b16SJason M. Bills } 138e85d6b16SJason M. Bills 13995820184SJason M. Bills // Get the entry timestamp 140271584abSEd Tanous std::time_t curTs = 0; 14195820184SJason M. Bills std::tm timeStruct = {}; 14295820184SJason M. Bills std::istringstream entryStream(logEntry); 14395820184SJason M. Bills if (entryStream >> std::get_time(&timeStruct, "%Y-%m-%dT%H:%M:%S")) 14495820184SJason M. Bills { 14595820184SJason M. Bills curTs = std::mktime(&timeStruct); 14695820184SJason M. Bills } 14795820184SJason M. Bills // If the timestamp isn't unique, increment the index 14895820184SJason M. Bills if (curTs == prevTs) 14995820184SJason M. Bills { 15095820184SJason M. Bills index++; 15195820184SJason M. Bills } 15295820184SJason M. Bills else 15395820184SJason M. Bills { 15495820184SJason M. Bills // Otherwise, reset it 15595820184SJason M. Bills index = 0; 15695820184SJason M. Bills } 15795820184SJason M. Bills // Save the timestamp 15895820184SJason M. Bills prevTs = curTs; 15995820184SJason M. Bills 16095820184SJason M. Bills entryID = std::to_string(curTs); 16195820184SJason M. Bills if (index > 0) 16295820184SJason M. Bills { 16395820184SJason M. Bills entryID += "_" + std::to_string(index); 16495820184SJason M. Bills } 16595820184SJason M. Bills return true; 16695820184SJason M. Bills } 16795820184SJason M. Bills 1684ff0f1f4SEd Tanous inline bool 16995820184SJason M. Bills getRedfishLogFiles(std::vector<std::filesystem::path>& redfishLogFiles) 17095820184SJason M. Bills { 17195820184SJason M. Bills static const std::filesystem::path redfishLogDir = "/var/log"; 17295820184SJason M. Bills static const std::string redfishLogFilename = "redfish"; 17395820184SJason M. Bills 17495820184SJason M. Bills // Loop through the directory looking for redfish log files 17595820184SJason M. Bills for (const std::filesystem::directory_entry& dirEnt : 17695820184SJason M. Bills std::filesystem::directory_iterator(redfishLogDir)) 17795820184SJason M. Bills { 17895820184SJason M. Bills // If we find a redfish log file, save the path 17995820184SJason M. Bills std::string filename = dirEnt.path().filename(); 18011ba3979SEd Tanous if (filename.starts_with(redfishLogFilename)) 18195820184SJason M. Bills { 18295820184SJason M. Bills redfishLogFiles.emplace_back(redfishLogDir / filename); 18395820184SJason M. Bills } 18495820184SJason M. Bills } 18595820184SJason M. Bills // As the log files rotate, they are appended with a ".#" that is higher for 18695820184SJason M. Bills // the older logs. Since we don't expect more than 10 log files, we 18795820184SJason M. Bills // can just sort the list to get them in order from newest to oldest 1883544d2a7SEd Tanous std::ranges::sort(redfishLogFiles); 18995820184SJason M. Bills 19095820184SJason M. Bills return !redfishLogFiles.empty(); 19195820184SJason M. Bills } 19295820184SJason M. Bills 19368dd075aSAsmitha Karunanithi inline log_entry::OriginatorTypes 19468dd075aSAsmitha Karunanithi mapDbusOriginatorTypeToRedfish(const std::string& originatorType) 19568dd075aSAsmitha Karunanithi { 19668dd075aSAsmitha Karunanithi if (originatorType == 19768dd075aSAsmitha Karunanithi "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Client") 19868dd075aSAsmitha Karunanithi { 19968dd075aSAsmitha Karunanithi return log_entry::OriginatorTypes::Client; 20068dd075aSAsmitha Karunanithi } 20168dd075aSAsmitha Karunanithi if (originatorType == 20268dd075aSAsmitha Karunanithi "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Internal") 20368dd075aSAsmitha Karunanithi { 20468dd075aSAsmitha Karunanithi return log_entry::OriginatorTypes::Internal; 20568dd075aSAsmitha Karunanithi } 20668dd075aSAsmitha Karunanithi if (originatorType == 20768dd075aSAsmitha Karunanithi "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.SupportingService") 20868dd075aSAsmitha Karunanithi { 20968dd075aSAsmitha Karunanithi return log_entry::OriginatorTypes::SupportingService; 21068dd075aSAsmitha Karunanithi } 21168dd075aSAsmitha Karunanithi return log_entry::OriginatorTypes::Invalid; 21268dd075aSAsmitha Karunanithi } 21368dd075aSAsmitha Karunanithi 214aefe3786SClaire Weinan inline void parseDumpEntryFromDbusObject( 2152d613eb6SJiaqing Zhao const dbus::utility::ManagedObjectType::value_type& object, 216c6fecdabSClaire Weinan std::string& dumpStatus, uint64_t& size, uint64_t& timestampUs, 21768dd075aSAsmitha Karunanithi std::string& originatorId, log_entry::OriginatorTypes& originatorType, 218aefe3786SClaire Weinan const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 219aefe3786SClaire Weinan { 220aefe3786SClaire Weinan for (const auto& interfaceMap : object.second) 221aefe3786SClaire Weinan { 222aefe3786SClaire Weinan if (interfaceMap.first == "xyz.openbmc_project.Common.Progress") 223aefe3786SClaire Weinan { 224aefe3786SClaire Weinan for (const auto& propertyMap : interfaceMap.second) 225aefe3786SClaire Weinan { 226aefe3786SClaire Weinan if (propertyMap.first == "Status") 227aefe3786SClaire Weinan { 228aefe3786SClaire Weinan const auto* status = 229aefe3786SClaire Weinan std::get_if<std::string>(&propertyMap.second); 230aefe3786SClaire Weinan if (status == nullptr) 231aefe3786SClaire Weinan { 232aefe3786SClaire Weinan messages::internalError(asyncResp->res); 233aefe3786SClaire Weinan break; 234aefe3786SClaire Weinan } 235aefe3786SClaire Weinan dumpStatus = *status; 236aefe3786SClaire Weinan } 237aefe3786SClaire Weinan } 238aefe3786SClaire Weinan } 239aefe3786SClaire Weinan else if (interfaceMap.first == "xyz.openbmc_project.Dump.Entry") 240aefe3786SClaire Weinan { 241aefe3786SClaire Weinan for (const auto& propertyMap : interfaceMap.second) 242aefe3786SClaire Weinan { 243aefe3786SClaire Weinan if (propertyMap.first == "Size") 244aefe3786SClaire Weinan { 245aefe3786SClaire Weinan const auto* sizePtr = 246aefe3786SClaire Weinan std::get_if<uint64_t>(&propertyMap.second); 247aefe3786SClaire Weinan if (sizePtr == nullptr) 248aefe3786SClaire Weinan { 249aefe3786SClaire Weinan messages::internalError(asyncResp->res); 250aefe3786SClaire Weinan break; 251aefe3786SClaire Weinan } 252aefe3786SClaire Weinan size = *sizePtr; 253aefe3786SClaire Weinan break; 254aefe3786SClaire Weinan } 255aefe3786SClaire Weinan } 256aefe3786SClaire Weinan } 257aefe3786SClaire Weinan else if (interfaceMap.first == "xyz.openbmc_project.Time.EpochTime") 258aefe3786SClaire Weinan { 259aefe3786SClaire Weinan for (const auto& propertyMap : interfaceMap.second) 260aefe3786SClaire Weinan { 261aefe3786SClaire Weinan if (propertyMap.first == "Elapsed") 262aefe3786SClaire Weinan { 263aefe3786SClaire Weinan const uint64_t* usecsTimeStamp = 264aefe3786SClaire Weinan std::get_if<uint64_t>(&propertyMap.second); 265aefe3786SClaire Weinan if (usecsTimeStamp == nullptr) 266aefe3786SClaire Weinan { 267aefe3786SClaire Weinan messages::internalError(asyncResp->res); 268aefe3786SClaire Weinan break; 269aefe3786SClaire Weinan } 270c6fecdabSClaire Weinan timestampUs = *usecsTimeStamp; 271aefe3786SClaire Weinan break; 272aefe3786SClaire Weinan } 273aefe3786SClaire Weinan } 274aefe3786SClaire Weinan } 27568dd075aSAsmitha Karunanithi else if (interfaceMap.first == 27668dd075aSAsmitha Karunanithi "xyz.openbmc_project.Common.OriginatedBy") 27768dd075aSAsmitha Karunanithi { 27868dd075aSAsmitha Karunanithi for (const auto& propertyMap : interfaceMap.second) 27968dd075aSAsmitha Karunanithi { 28068dd075aSAsmitha Karunanithi if (propertyMap.first == "OriginatorId") 28168dd075aSAsmitha Karunanithi { 28268dd075aSAsmitha Karunanithi const std::string* id = 28368dd075aSAsmitha Karunanithi std::get_if<std::string>(&propertyMap.second); 28468dd075aSAsmitha Karunanithi if (id == nullptr) 28568dd075aSAsmitha Karunanithi { 28668dd075aSAsmitha Karunanithi messages::internalError(asyncResp->res); 28768dd075aSAsmitha Karunanithi break; 28868dd075aSAsmitha Karunanithi } 28968dd075aSAsmitha Karunanithi originatorId = *id; 29068dd075aSAsmitha Karunanithi } 29168dd075aSAsmitha Karunanithi 29268dd075aSAsmitha Karunanithi if (propertyMap.first == "OriginatorType") 29368dd075aSAsmitha Karunanithi { 29468dd075aSAsmitha Karunanithi const std::string* type = 29568dd075aSAsmitha Karunanithi std::get_if<std::string>(&propertyMap.second); 29668dd075aSAsmitha Karunanithi if (type == nullptr) 29768dd075aSAsmitha Karunanithi { 29868dd075aSAsmitha Karunanithi messages::internalError(asyncResp->res); 29968dd075aSAsmitha Karunanithi break; 30068dd075aSAsmitha Karunanithi } 30168dd075aSAsmitha Karunanithi 30268dd075aSAsmitha Karunanithi originatorType = mapDbusOriginatorTypeToRedfish(*type); 30368dd075aSAsmitha Karunanithi if (originatorType == log_entry::OriginatorTypes::Invalid) 30468dd075aSAsmitha Karunanithi { 30568dd075aSAsmitha Karunanithi messages::internalError(asyncResp->res); 30668dd075aSAsmitha Karunanithi break; 30768dd075aSAsmitha Karunanithi } 30868dd075aSAsmitha Karunanithi } 30968dd075aSAsmitha Karunanithi } 31068dd075aSAsmitha Karunanithi } 311aefe3786SClaire Weinan } 312aefe3786SClaire Weinan } 313aefe3786SClaire Weinan 31421ab404cSNan Zhou static std::string getDumpEntriesPath(const std::string& dumpType) 315fdd26906SClaire Weinan { 316fdd26906SClaire Weinan std::string entriesPath; 317fdd26906SClaire Weinan 318fdd26906SClaire Weinan if (dumpType == "BMC") 319fdd26906SClaire Weinan { 320253f11b8SEd Tanous entriesPath = 321253f11b8SEd Tanous std::format("/redfish/v1/Managers/{}/LogServices/Dump/Entries/", 322253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 323fdd26906SClaire Weinan } 324fdd26906SClaire Weinan else if (dumpType == "FaultLog") 325fdd26906SClaire Weinan { 326253f11b8SEd Tanous entriesPath = 327253f11b8SEd Tanous std::format("/redfish/v1/Managers/{}/LogServices/FaultLog/Entries/", 328253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 329fdd26906SClaire Weinan } 330fdd26906SClaire Weinan else if (dumpType == "System") 331fdd26906SClaire Weinan { 332253f11b8SEd Tanous entriesPath = 333253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/Dump/Entries/", 334253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 335fdd26906SClaire Weinan } 336fdd26906SClaire Weinan else 337fdd26906SClaire Weinan { 33862598e31SEd Tanous BMCWEB_LOG_ERROR("getDumpEntriesPath() invalid dump type: {}", 33962598e31SEd Tanous dumpType); 340fdd26906SClaire Weinan } 341fdd26906SClaire Weinan 342fdd26906SClaire Weinan // Returns empty string on error 343fdd26906SClaire Weinan return entriesPath; 344fdd26906SClaire Weinan } 345fdd26906SClaire Weinan 3468d1b46d7Szhanghch05 inline void 3478d1b46d7Szhanghch05 getDumpEntryCollection(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 3485cb1dd27SAsmitha Karunanithi const std::string& dumpType) 3495cb1dd27SAsmitha Karunanithi { 350fdd26906SClaire Weinan std::string entriesPath = getDumpEntriesPath(dumpType); 351fdd26906SClaire Weinan if (entriesPath.empty()) 3525cb1dd27SAsmitha Karunanithi { 3535cb1dd27SAsmitha Karunanithi messages::internalError(asyncResp->res); 3545cb1dd27SAsmitha Karunanithi return; 3555cb1dd27SAsmitha Karunanithi } 3565cb1dd27SAsmitha Karunanithi 3575eb468daSGeorge Liu sdbusplus::message::object_path path("/xyz/openbmc_project/dump"); 3585eb468daSGeorge Liu dbus::utility::getManagedObjects( 3595eb468daSGeorge Liu "xyz.openbmc_project.Dump.Manager", path, 360fdd26906SClaire Weinan [asyncResp, entriesPath, 3615e7e2dc5SEd Tanous dumpType](const boost::system::error_code& ec, 3625eb468daSGeorge Liu const dbus::utility::ManagedObjectType& objects) { 3635cb1dd27SAsmitha Karunanithi if (ec) 3645cb1dd27SAsmitha Karunanithi { 36562598e31SEd Tanous BMCWEB_LOG_ERROR("DumpEntry resp_handler got error {}", ec); 3665cb1dd27SAsmitha Karunanithi messages::internalError(asyncResp->res); 3675cb1dd27SAsmitha Karunanithi return; 3685cb1dd27SAsmitha Karunanithi } 3695cb1dd27SAsmitha Karunanithi 370fdd26906SClaire Weinan // Remove ending slash 371fdd26906SClaire Weinan std::string odataIdStr = entriesPath; 372fdd26906SClaire Weinan if (!odataIdStr.empty()) 373fdd26906SClaire Weinan { 374fdd26906SClaire Weinan odataIdStr.pop_back(); 375fdd26906SClaire Weinan } 376fdd26906SClaire Weinan 377fdd26906SClaire Weinan asyncResp->res.jsonValue["@odata.type"] = 378fdd26906SClaire Weinan "#LogEntryCollection.LogEntryCollection"; 379fdd26906SClaire Weinan asyncResp->res.jsonValue["@odata.id"] = std::move(odataIdStr); 380fdd26906SClaire Weinan asyncResp->res.jsonValue["Name"] = dumpType + " Dump Entries"; 381bd79bce8SPatrick Williams asyncResp->res.jsonValue["Description"] = 382bd79bce8SPatrick Williams "Collection of " + dumpType + " Dump Entries"; 383fdd26906SClaire Weinan 3843544d2a7SEd Tanous nlohmann::json::array_t entriesArray; 38518f8f608SEd Tanous std::string dumpEntryPath = getDumpPath(dumpType) + "/entry/"; 3865cb1dd27SAsmitha Karunanithi 3875eb468daSGeorge Liu dbus::utility::ManagedObjectType resp(objects); 3883544d2a7SEd Tanous std::ranges::sort(resp, [](const auto& l, const auto& r) { 389002d39b4SEd Tanous return AlphanumLess<std::string>()(l.first.filename(), 390002d39b4SEd Tanous r.first.filename()); 391565dfb6fSClaire Weinan }); 392565dfb6fSClaire Weinan 3935cb1dd27SAsmitha Karunanithi for (auto& object : resp) 3945cb1dd27SAsmitha Karunanithi { 395b47452b2SAsmitha Karunanithi if (object.first.str.find(dumpEntryPath) == std::string::npos) 3965cb1dd27SAsmitha Karunanithi { 3975cb1dd27SAsmitha Karunanithi continue; 3985cb1dd27SAsmitha Karunanithi } 399c6fecdabSClaire Weinan uint64_t timestampUs = 0; 4005cb1dd27SAsmitha Karunanithi uint64_t size = 0; 40135440d18SAsmitha Karunanithi std::string dumpStatus; 40268dd075aSAsmitha Karunanithi std::string originatorId; 40368dd075aSAsmitha Karunanithi log_entry::OriginatorTypes originatorType = 40468dd075aSAsmitha Karunanithi log_entry::OriginatorTypes::Internal; 405433b68b4SJason M. Bills nlohmann::json::object_t thisEntry; 4062dfd18efSEd Tanous 4072dfd18efSEd Tanous std::string entryID = object.first.filename(); 4082dfd18efSEd Tanous if (entryID.empty()) 4095cb1dd27SAsmitha Karunanithi { 4105cb1dd27SAsmitha Karunanithi continue; 4115cb1dd27SAsmitha Karunanithi } 4125cb1dd27SAsmitha Karunanithi 413bd79bce8SPatrick Williams parseDumpEntryFromDbusObject(object, dumpStatus, size, 414bd79bce8SPatrick Williams timestampUs, originatorId, 415bd79bce8SPatrick Williams originatorType, asyncResp); 4165cb1dd27SAsmitha Karunanithi 4170fda0f12SGeorge Liu if (dumpStatus != 4180fda0f12SGeorge Liu "xyz.openbmc_project.Common.Progress.OperationStatus.Completed" && 41935440d18SAsmitha Karunanithi !dumpStatus.empty()) 42035440d18SAsmitha Karunanithi { 42135440d18SAsmitha Karunanithi // Dump status is not Complete, no need to enumerate 42235440d18SAsmitha Karunanithi continue; 42335440d18SAsmitha Karunanithi } 42435440d18SAsmitha Karunanithi 42568dd075aSAsmitha Karunanithi thisEntry["@odata.type"] = "#LogEntry.v1_11_0.LogEntry"; 426fdd26906SClaire Weinan thisEntry["@odata.id"] = entriesPath + entryID; 4275cb1dd27SAsmitha Karunanithi thisEntry["Id"] = entryID; 4285cb1dd27SAsmitha Karunanithi thisEntry["EntryType"] = "Event"; 4295cb1dd27SAsmitha Karunanithi thisEntry["Name"] = dumpType + " Dump Entry"; 430bbd80db8SClaire Weinan thisEntry["Created"] = 431bbd80db8SClaire Weinan redfish::time_utils::getDateTimeUintUs(timestampUs); 4325cb1dd27SAsmitha Karunanithi 43368dd075aSAsmitha Karunanithi if (!originatorId.empty()) 43468dd075aSAsmitha Karunanithi { 43568dd075aSAsmitha Karunanithi thisEntry["Originator"] = originatorId; 43668dd075aSAsmitha Karunanithi thisEntry["OriginatorType"] = originatorType; 43768dd075aSAsmitha Karunanithi } 43868dd075aSAsmitha Karunanithi 4395cb1dd27SAsmitha Karunanithi if (dumpType == "BMC") 4405cb1dd27SAsmitha Karunanithi { 441d337bb72SAsmitha Karunanithi thisEntry["DiagnosticDataType"] = "Manager"; 442bd79bce8SPatrick Williams thisEntry["AdditionalDataURI"] = 443bd79bce8SPatrick Williams entriesPath + entryID + "/attachment"; 444fdd26906SClaire Weinan thisEntry["AdditionalDataSizeBytes"] = size; 4455cb1dd27SAsmitha Karunanithi } 4465cb1dd27SAsmitha Karunanithi else if (dumpType == "System") 4475cb1dd27SAsmitha Karunanithi { 448d337bb72SAsmitha Karunanithi thisEntry["DiagnosticDataType"] = "OEM"; 449d337bb72SAsmitha Karunanithi thisEntry["OEMDiagnosticDataType"] = "System"; 450bd79bce8SPatrick Williams thisEntry["AdditionalDataURI"] = 451bd79bce8SPatrick Williams entriesPath + entryID + "/attachment"; 452fdd26906SClaire Weinan thisEntry["AdditionalDataSizeBytes"] = size; 4535cb1dd27SAsmitha Karunanithi } 454b2ba3072SPatrick Williams entriesArray.emplace_back(std::move(thisEntry)); 4555cb1dd27SAsmitha Karunanithi } 456bd79bce8SPatrick Williams asyncResp->res.jsonValue["Members@odata.count"] = 457bd79bce8SPatrick Williams entriesArray.size(); 4583544d2a7SEd Tanous asyncResp->res.jsonValue["Members"] = std::move(entriesArray); 4595eb468daSGeorge Liu }); 4605cb1dd27SAsmitha Karunanithi } 4615cb1dd27SAsmitha Karunanithi 4628d1b46d7Szhanghch05 inline void 463c7a6d660SClaire Weinan getDumpEntryById(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 4648d1b46d7Szhanghch05 const std::string& entryID, const std::string& dumpType) 4655cb1dd27SAsmitha Karunanithi { 466fdd26906SClaire Weinan std::string entriesPath = getDumpEntriesPath(dumpType); 467fdd26906SClaire Weinan if (entriesPath.empty()) 4685cb1dd27SAsmitha Karunanithi { 4695cb1dd27SAsmitha Karunanithi messages::internalError(asyncResp->res); 4705cb1dd27SAsmitha Karunanithi return; 4715cb1dd27SAsmitha Karunanithi } 4725cb1dd27SAsmitha Karunanithi 4735eb468daSGeorge Liu sdbusplus::message::object_path path("/xyz/openbmc_project/dump"); 4745eb468daSGeorge Liu dbus::utility::getManagedObjects( 4755eb468daSGeorge Liu "xyz.openbmc_project.Dump.Manager", path, 476fdd26906SClaire Weinan [asyncResp, entryID, dumpType, 4775e7e2dc5SEd Tanous entriesPath](const boost::system::error_code& ec, 47802cad96eSEd Tanous const dbus::utility::ManagedObjectType& resp) { 4795cb1dd27SAsmitha Karunanithi if (ec) 4805cb1dd27SAsmitha Karunanithi { 48162598e31SEd Tanous BMCWEB_LOG_ERROR("DumpEntry resp_handler got error {}", ec); 4825cb1dd27SAsmitha Karunanithi messages::internalError(asyncResp->res); 4835cb1dd27SAsmitha Karunanithi return; 4845cb1dd27SAsmitha Karunanithi } 4855cb1dd27SAsmitha Karunanithi 486b47452b2SAsmitha Karunanithi bool foundDumpEntry = false; 48718f8f608SEd Tanous std::string dumpEntryPath = getDumpPath(dumpType) + "/entry/"; 488b47452b2SAsmitha Karunanithi 4899eb808c1SEd Tanous for (const auto& objectPath : resp) 4905cb1dd27SAsmitha Karunanithi { 491b47452b2SAsmitha Karunanithi if (objectPath.first.str != dumpEntryPath + entryID) 4925cb1dd27SAsmitha Karunanithi { 4935cb1dd27SAsmitha Karunanithi continue; 4945cb1dd27SAsmitha Karunanithi } 4955cb1dd27SAsmitha Karunanithi 4965cb1dd27SAsmitha Karunanithi foundDumpEntry = true; 497c6fecdabSClaire Weinan uint64_t timestampUs = 0; 4985cb1dd27SAsmitha Karunanithi uint64_t size = 0; 49935440d18SAsmitha Karunanithi std::string dumpStatus; 50068dd075aSAsmitha Karunanithi std::string originatorId; 50168dd075aSAsmitha Karunanithi log_entry::OriginatorTypes originatorType = 50268dd075aSAsmitha Karunanithi log_entry::OriginatorTypes::Internal; 5035cb1dd27SAsmitha Karunanithi 504aefe3786SClaire Weinan parseDumpEntryFromDbusObject(objectPath, dumpStatus, size, 50568dd075aSAsmitha Karunanithi timestampUs, originatorId, 50668dd075aSAsmitha Karunanithi originatorType, asyncResp); 5075cb1dd27SAsmitha Karunanithi 5080fda0f12SGeorge Liu if (dumpStatus != 5090fda0f12SGeorge Liu "xyz.openbmc_project.Common.Progress.OperationStatus.Completed" && 51035440d18SAsmitha Karunanithi !dumpStatus.empty()) 51135440d18SAsmitha Karunanithi { 51235440d18SAsmitha Karunanithi // Dump status is not Complete 51335440d18SAsmitha Karunanithi // return not found until status is changed to Completed 514bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, 515bd79bce8SPatrick Williams dumpType + " dump", entryID); 51635440d18SAsmitha Karunanithi return; 51735440d18SAsmitha Karunanithi } 51835440d18SAsmitha Karunanithi 5195cb1dd27SAsmitha Karunanithi asyncResp->res.jsonValue["@odata.type"] = 52068dd075aSAsmitha Karunanithi "#LogEntry.v1_11_0.LogEntry"; 521fdd26906SClaire Weinan asyncResp->res.jsonValue["@odata.id"] = entriesPath + entryID; 5225cb1dd27SAsmitha Karunanithi asyncResp->res.jsonValue["Id"] = entryID; 5235cb1dd27SAsmitha Karunanithi asyncResp->res.jsonValue["EntryType"] = "Event"; 5245cb1dd27SAsmitha Karunanithi asyncResp->res.jsonValue["Name"] = dumpType + " Dump Entry"; 525bbd80db8SClaire Weinan asyncResp->res.jsonValue["Created"] = 526bbd80db8SClaire Weinan redfish::time_utils::getDateTimeUintUs(timestampUs); 5275cb1dd27SAsmitha Karunanithi 52868dd075aSAsmitha Karunanithi if (!originatorId.empty()) 52968dd075aSAsmitha Karunanithi { 53068dd075aSAsmitha Karunanithi asyncResp->res.jsonValue["Originator"] = originatorId; 53168dd075aSAsmitha Karunanithi asyncResp->res.jsonValue["OriginatorType"] = originatorType; 53268dd075aSAsmitha Karunanithi } 53368dd075aSAsmitha Karunanithi 5345cb1dd27SAsmitha Karunanithi if (dumpType == "BMC") 5355cb1dd27SAsmitha Karunanithi { 536d337bb72SAsmitha Karunanithi asyncResp->res.jsonValue["DiagnosticDataType"] = "Manager"; 537d337bb72SAsmitha Karunanithi asyncResp->res.jsonValue["AdditionalDataURI"] = 538fdd26906SClaire Weinan entriesPath + entryID + "/attachment"; 539fdd26906SClaire Weinan asyncResp->res.jsonValue["AdditionalDataSizeBytes"] = size; 5405cb1dd27SAsmitha Karunanithi } 5415cb1dd27SAsmitha Karunanithi else if (dumpType == "System") 5425cb1dd27SAsmitha Karunanithi { 543d337bb72SAsmitha Karunanithi asyncResp->res.jsonValue["DiagnosticDataType"] = "OEM"; 544bd79bce8SPatrick Williams asyncResp->res.jsonValue["OEMDiagnosticDataType"] = 545bd79bce8SPatrick Williams "System"; 546d337bb72SAsmitha Karunanithi asyncResp->res.jsonValue["AdditionalDataURI"] = 547fdd26906SClaire Weinan entriesPath + entryID + "/attachment"; 548fdd26906SClaire Weinan asyncResp->res.jsonValue["AdditionalDataSizeBytes"] = size; 5495cb1dd27SAsmitha Karunanithi } 5505cb1dd27SAsmitha Karunanithi } 551e05aec50SEd Tanous if (!foundDumpEntry) 552b47452b2SAsmitha Karunanithi { 55362598e31SEd Tanous BMCWEB_LOG_WARNING("Can't find Dump Entry {}", entryID); 554b90d14f2SMyung Bae messages::resourceNotFound(asyncResp->res, dumpType + " dump", 555b90d14f2SMyung Bae entryID); 556b47452b2SAsmitha Karunanithi return; 557b47452b2SAsmitha Karunanithi } 5585eb468daSGeorge Liu }); 5595cb1dd27SAsmitha Karunanithi } 5605cb1dd27SAsmitha Karunanithi 5618d1b46d7Szhanghch05 inline void deleteDumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 5629878256fSStanley Chu const std::string& entryID, 563b47452b2SAsmitha Karunanithi const std::string& dumpType) 5645cb1dd27SAsmitha Karunanithi { 5655a39f77aSPatrick Williams auto respHandler = [asyncResp, 5665a39f77aSPatrick Williams entryID](const boost::system::error_code& ec) { 56762598e31SEd Tanous BMCWEB_LOG_DEBUG("Dump Entry doDelete callback: Done"); 5685cb1dd27SAsmitha Karunanithi if (ec) 5695cb1dd27SAsmitha Karunanithi { 5703de8d8baSGeorge Liu if (ec.value() == EBADR) 5713de8d8baSGeorge Liu { 5723de8d8baSGeorge Liu messages::resourceNotFound(asyncResp->res, "LogEntry", entryID); 5733de8d8baSGeorge Liu return; 5743de8d8baSGeorge Liu } 57562598e31SEd Tanous BMCWEB_LOG_ERROR( 57662598e31SEd Tanous "Dump (DBus) doDelete respHandler got error {} entryID={}", ec, 57762598e31SEd Tanous entryID); 5785cb1dd27SAsmitha Karunanithi messages::internalError(asyncResp->res); 5795cb1dd27SAsmitha Karunanithi return; 5805cb1dd27SAsmitha Karunanithi } 5815cb1dd27SAsmitha Karunanithi }; 58218f8f608SEd Tanous 5835cb1dd27SAsmitha Karunanithi crow::connections::systemBus->async_method_call( 5845cb1dd27SAsmitha Karunanithi respHandler, "xyz.openbmc_project.Dump.Manager", 58518f8f608SEd Tanous std::format("{}/entry/{}", getDumpPath(dumpType), entryID), 5865cb1dd27SAsmitha Karunanithi "xyz.openbmc_project.Object.Delete", "Delete"); 5875cb1dd27SAsmitha Karunanithi } 588b5f288d2SAbhilash Raju inline bool checkSizeLimit(int fd, crow::Response& res) 589b5f288d2SAbhilash Raju { 590b5f288d2SAbhilash Raju long long int size = lseek(fd, 0, SEEK_END); 591b5f288d2SAbhilash Raju if (size <= 0) 592b5f288d2SAbhilash Raju { 593b5f288d2SAbhilash Raju BMCWEB_LOG_ERROR("Failed to get size of file, lseek() returned {}", 594b5f288d2SAbhilash Raju size); 595b5f288d2SAbhilash Raju messages::internalError(res); 596b5f288d2SAbhilash Raju return false; 597b5f288d2SAbhilash Raju } 5985cb1dd27SAsmitha Karunanithi 599b5f288d2SAbhilash Raju // Arbitrary max size of 20MB to accommodate BMC dumps 600b5f288d2SAbhilash Raju constexpr long long int maxFileSize = 20LL * 1024LL * 1024LL; 601b5f288d2SAbhilash Raju if (size > maxFileSize) 602b5f288d2SAbhilash Raju { 603b5f288d2SAbhilash Raju BMCWEB_LOG_ERROR("File size {} exceeds maximum allowed size of {}", 604b5f288d2SAbhilash Raju size, maxFileSize); 605b5f288d2SAbhilash Raju messages::internalError(res); 606b5f288d2SAbhilash Raju return false; 607b5f288d2SAbhilash Raju } 608b5f288d2SAbhilash Raju off_t rc = lseek(fd, 0, SEEK_SET); 609b5f288d2SAbhilash Raju if (rc < 0) 610b5f288d2SAbhilash Raju { 611b5f288d2SAbhilash Raju BMCWEB_LOG_ERROR("Failed to reset file offset to 0"); 612b5f288d2SAbhilash Raju messages::internalError(res); 613b5f288d2SAbhilash Raju return false; 614b5f288d2SAbhilash Raju } 615b5f288d2SAbhilash Raju return true; 616b5f288d2SAbhilash Raju } 617bd79bce8SPatrick Williams inline void downloadEntryCallback( 618bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 619bd79bce8SPatrick Williams const std::string& entryID, const std::string& downloadEntryType, 620168d1b1aSCarson Labrado const boost::system::error_code& ec, 621168d1b1aSCarson Labrado const sdbusplus::message::unix_fd& unixfd) 622168d1b1aSCarson Labrado { 623168d1b1aSCarson Labrado if (ec.value() == EBADR) 624168d1b1aSCarson Labrado { 625168d1b1aSCarson Labrado messages::resourceNotFound(asyncResp->res, "EntryAttachment", entryID); 626168d1b1aSCarson Labrado return; 627168d1b1aSCarson Labrado } 628168d1b1aSCarson Labrado if (ec) 629168d1b1aSCarson Labrado { 630168d1b1aSCarson Labrado BMCWEB_LOG_ERROR("DBUS response error: {}", ec); 631168d1b1aSCarson Labrado messages::internalError(asyncResp->res); 632168d1b1aSCarson Labrado return; 633168d1b1aSCarson Labrado } 634168d1b1aSCarson Labrado 635168d1b1aSCarson Labrado // Make sure we know how to process the retrieved entry attachment 636168d1b1aSCarson Labrado if ((downloadEntryType != "BMC") && (downloadEntryType != "System")) 637168d1b1aSCarson Labrado { 638168d1b1aSCarson Labrado BMCWEB_LOG_ERROR("downloadEntryCallback() invalid entry type: {}", 639168d1b1aSCarson Labrado downloadEntryType); 640168d1b1aSCarson Labrado messages::internalError(asyncResp->res); 641168d1b1aSCarson Labrado } 642168d1b1aSCarson Labrado 643168d1b1aSCarson Labrado int fd = -1; 644168d1b1aSCarson Labrado fd = dup(unixfd); 645168d1b1aSCarson Labrado if (fd < 0) 646168d1b1aSCarson Labrado { 647168d1b1aSCarson Labrado BMCWEB_LOG_ERROR("Failed to open file"); 648168d1b1aSCarson Labrado messages::internalError(asyncResp->res); 649168d1b1aSCarson Labrado return; 650168d1b1aSCarson Labrado } 651b5f288d2SAbhilash Raju if (!checkSizeLimit(fd, asyncResp->res)) 652168d1b1aSCarson Labrado { 653168d1b1aSCarson Labrado close(fd); 654168d1b1aSCarson Labrado return; 655168d1b1aSCarson Labrado } 656168d1b1aSCarson Labrado if (downloadEntryType == "System") 657168d1b1aSCarson Labrado { 658b5f288d2SAbhilash Raju if (!asyncResp->res.openFd(fd, bmcweb::EncodingType::Base64)) 659b5f288d2SAbhilash Raju { 660b5f288d2SAbhilash Raju messages::internalError(asyncResp->res); 661b5f288d2SAbhilash Raju close(fd); 662b5f288d2SAbhilash Raju return; 663b5f288d2SAbhilash Raju } 664168d1b1aSCarson Labrado asyncResp->res.addHeader( 665168d1b1aSCarson Labrado boost::beast::http::field::content_transfer_encoding, "Base64"); 666b5f288d2SAbhilash Raju return; 667168d1b1aSCarson Labrado } 668b5f288d2SAbhilash Raju if (!asyncResp->res.openFd(fd)) 66927b0cf90SEd Tanous { 670b5f288d2SAbhilash Raju messages::internalError(asyncResp->res); 671b5f288d2SAbhilash Raju close(fd); 672b5f288d2SAbhilash Raju return; 67327b0cf90SEd Tanous } 674168d1b1aSCarson Labrado asyncResp->res.addHeader(boost::beast::http::field::content_type, 675168d1b1aSCarson Labrado "application/octet-stream"); 676168d1b1aSCarson Labrado } 677168d1b1aSCarson Labrado 678168d1b1aSCarson Labrado inline void 679168d1b1aSCarson Labrado downloadDumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 680168d1b1aSCarson Labrado const std::string& entryID, const std::string& dumpType) 681168d1b1aSCarson Labrado { 682168d1b1aSCarson Labrado if (dumpType != "BMC") 683168d1b1aSCarson Labrado { 684168d1b1aSCarson Labrado BMCWEB_LOG_WARNING("Can't find Dump Entry {}", entryID); 685168d1b1aSCarson Labrado messages::resourceNotFound(asyncResp->res, dumpType + " dump", entryID); 686168d1b1aSCarson Labrado return; 687168d1b1aSCarson Labrado } 688168d1b1aSCarson Labrado 689bd79bce8SPatrick Williams std::string dumpEntryPath = 690bd79bce8SPatrick Williams std::format("{}/entry/{}", getDumpPath(dumpType), entryID); 691168d1b1aSCarson Labrado 692168d1b1aSCarson Labrado auto downloadDumpEntryHandler = 693168d1b1aSCarson Labrado [asyncResp, entryID, 694168d1b1aSCarson Labrado dumpType](const boost::system::error_code& ec, 695168d1b1aSCarson Labrado const sdbusplus::message::unix_fd& unixfd) { 696168d1b1aSCarson Labrado downloadEntryCallback(asyncResp, entryID, dumpType, ec, unixfd); 697168d1b1aSCarson Labrado }; 698168d1b1aSCarson Labrado 699168d1b1aSCarson Labrado crow::connections::systemBus->async_method_call( 700168d1b1aSCarson Labrado std::move(downloadDumpEntryHandler), "xyz.openbmc_project.Dump.Manager", 701168d1b1aSCarson Labrado dumpEntryPath, "xyz.openbmc_project.Dump.Entry", "GetFileHandle"); 702168d1b1aSCarson Labrado } 703168d1b1aSCarson Labrado 704bd79bce8SPatrick Williams inline void downloadEventLogEntry( 705bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 706bd79bce8SPatrick Williams const std::string& systemName, const std::string& entryID, 707168d1b1aSCarson Labrado const std::string& dumpType) 708168d1b1aSCarson Labrado { 70925b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 710168d1b1aSCarson Labrado { 711168d1b1aSCarson Labrado // Option currently returns no systems. TBD 712168d1b1aSCarson Labrado messages::resourceNotFound(asyncResp->res, "ComputerSystem", 713168d1b1aSCarson Labrado systemName); 714168d1b1aSCarson Labrado return; 715168d1b1aSCarson Labrado } 716253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 717168d1b1aSCarson Labrado { 718168d1b1aSCarson Labrado messages::resourceNotFound(asyncResp->res, "ComputerSystem", 719168d1b1aSCarson Labrado systemName); 720168d1b1aSCarson Labrado return; 721168d1b1aSCarson Labrado } 722168d1b1aSCarson Labrado 723168d1b1aSCarson Labrado std::string entryPath = 724168d1b1aSCarson Labrado sdbusplus::message::object_path("/xyz/openbmc_project/logging/entry") / 725168d1b1aSCarson Labrado entryID; 726168d1b1aSCarson Labrado 727168d1b1aSCarson Labrado auto downloadEventLogEntryHandler = 728168d1b1aSCarson Labrado [asyncResp, entryID, 729168d1b1aSCarson Labrado dumpType](const boost::system::error_code& ec, 730168d1b1aSCarson Labrado const sdbusplus::message::unix_fd& unixfd) { 731168d1b1aSCarson Labrado downloadEntryCallback(asyncResp, entryID, dumpType, ec, unixfd); 732168d1b1aSCarson Labrado }; 733168d1b1aSCarson Labrado 734168d1b1aSCarson Labrado crow::connections::systemBus->async_method_call( 735168d1b1aSCarson Labrado std::move(downloadEventLogEntryHandler), "xyz.openbmc_project.Logging", 736168d1b1aSCarson Labrado entryPath, "xyz.openbmc_project.Logging.Entry", "GetEntry"); 737168d1b1aSCarson Labrado } 738168d1b1aSCarson Labrado 7398e31778eSAsmitha Karunanithi inline DumpCreationProgress 7408e31778eSAsmitha Karunanithi mapDbusStatusToDumpProgress(const std::string& status) 741a43be80fSAsmitha Karunanithi { 7428e31778eSAsmitha Karunanithi if (status == 7438e31778eSAsmitha Karunanithi "xyz.openbmc_project.Common.Progress.OperationStatus.Failed" || 7448e31778eSAsmitha Karunanithi status == "xyz.openbmc_project.Common.Progress.OperationStatus.Aborted") 7458e31778eSAsmitha Karunanithi { 7468e31778eSAsmitha Karunanithi return DumpCreationProgress::DUMP_CREATE_FAILED; 7478e31778eSAsmitha Karunanithi } 7488e31778eSAsmitha Karunanithi if (status == 7498e31778eSAsmitha Karunanithi "xyz.openbmc_project.Common.Progress.OperationStatus.Completed") 7508e31778eSAsmitha Karunanithi { 7518e31778eSAsmitha Karunanithi return DumpCreationProgress::DUMP_CREATE_SUCCESS; 7528e31778eSAsmitha Karunanithi } 7538e31778eSAsmitha Karunanithi return DumpCreationProgress::DUMP_CREATE_INPROGRESS; 7548e31778eSAsmitha Karunanithi } 7558e31778eSAsmitha Karunanithi 7568e31778eSAsmitha Karunanithi inline DumpCreationProgress 7578e31778eSAsmitha Karunanithi getDumpCompletionStatus(const dbus::utility::DBusPropertiesMap& values) 7588e31778eSAsmitha Karunanithi { 7598e31778eSAsmitha Karunanithi for (const auto& [key, val] : values) 7608e31778eSAsmitha Karunanithi { 7618e31778eSAsmitha Karunanithi if (key == "Status") 7628e31778eSAsmitha Karunanithi { 7638e31778eSAsmitha Karunanithi const std::string* value = std::get_if<std::string>(&val); 7648e31778eSAsmitha Karunanithi if (value == nullptr) 7658e31778eSAsmitha Karunanithi { 76662598e31SEd Tanous BMCWEB_LOG_ERROR("Status property value is null"); 7678e31778eSAsmitha Karunanithi return DumpCreationProgress::DUMP_CREATE_FAILED; 7688e31778eSAsmitha Karunanithi } 7698e31778eSAsmitha Karunanithi return mapDbusStatusToDumpProgress(*value); 7708e31778eSAsmitha Karunanithi } 7718e31778eSAsmitha Karunanithi } 7728e31778eSAsmitha Karunanithi return DumpCreationProgress::DUMP_CREATE_INPROGRESS; 7738e31778eSAsmitha Karunanithi } 7748e31778eSAsmitha Karunanithi 7758e31778eSAsmitha Karunanithi inline std::string getDumpEntryPath(const std::string& dumpPath) 7768e31778eSAsmitha Karunanithi { 7778e31778eSAsmitha Karunanithi if (dumpPath == "/xyz/openbmc_project/dump/bmc/entry") 7788e31778eSAsmitha Karunanithi { 779253f11b8SEd Tanous return std::format("/redfish/v1/Managers/{}/LogServices/Dump/Entries/", 7809f565090SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 7818e31778eSAsmitha Karunanithi } 7828e31778eSAsmitha Karunanithi if (dumpPath == "/xyz/openbmc_project/dump/system/entry") 7838e31778eSAsmitha Karunanithi { 784253f11b8SEd Tanous return std::format("/redfish/v1/Systems/{}/LogServices/Dump/Entries/", 785253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 7868e31778eSAsmitha Karunanithi } 7878e31778eSAsmitha Karunanithi return ""; 7888e31778eSAsmitha Karunanithi } 7898e31778eSAsmitha Karunanithi 7908e31778eSAsmitha Karunanithi inline void createDumpTaskCallback( 7918e31778eSAsmitha Karunanithi task::Payload&& payload, 7928e31778eSAsmitha Karunanithi const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 7938e31778eSAsmitha Karunanithi const sdbusplus::message::object_path& createdObjPath) 7948e31778eSAsmitha Karunanithi { 7958e31778eSAsmitha Karunanithi const std::string dumpPath = createdObjPath.parent_path().str; 7968e31778eSAsmitha Karunanithi const std::string dumpId = createdObjPath.filename(); 7978e31778eSAsmitha Karunanithi 7988e31778eSAsmitha Karunanithi std::string dumpEntryPath = getDumpEntryPath(dumpPath); 7998e31778eSAsmitha Karunanithi 8008e31778eSAsmitha Karunanithi if (dumpEntryPath.empty()) 8018e31778eSAsmitha Karunanithi { 80262598e31SEd Tanous BMCWEB_LOG_ERROR("Invalid dump type received"); 8038e31778eSAsmitha Karunanithi messages::internalError(asyncResp->res); 8048e31778eSAsmitha Karunanithi return; 8058e31778eSAsmitha Karunanithi } 8068e31778eSAsmitha Karunanithi 8078e31778eSAsmitha Karunanithi crow::connections::systemBus->async_method_call( 8088cb2c024SEd Tanous [asyncResp, payload = std::move(payload), createdObjPath, 8098e31778eSAsmitha Karunanithi dumpEntryPath{std::move(dumpEntryPath)}, 8105e7e2dc5SEd Tanous dumpId](const boost::system::error_code& ec, 8118e31778eSAsmitha Karunanithi const std::string& introspectXml) { 8128e31778eSAsmitha Karunanithi if (ec) 8138e31778eSAsmitha Karunanithi { 81462598e31SEd Tanous BMCWEB_LOG_ERROR("Introspect call failed with error: {}", 81562598e31SEd Tanous ec.message()); 8168e31778eSAsmitha Karunanithi messages::internalError(asyncResp->res); 8178e31778eSAsmitha Karunanithi return; 8188e31778eSAsmitha Karunanithi } 8198e31778eSAsmitha Karunanithi 8208e31778eSAsmitha Karunanithi // Check if the created dump object has implemented Progress 8218e31778eSAsmitha Karunanithi // interface to track dump completion. If yes, fetch the "Status" 8228e31778eSAsmitha Karunanithi // property of the interface, modify the task state accordingly. 8238e31778eSAsmitha Karunanithi // Else, return task completed. 8248e31778eSAsmitha Karunanithi tinyxml2::XMLDocument doc; 8258e31778eSAsmitha Karunanithi 8268e31778eSAsmitha Karunanithi doc.Parse(introspectXml.data(), introspectXml.size()); 8278e31778eSAsmitha Karunanithi tinyxml2::XMLNode* pRoot = doc.FirstChildElement("node"); 8288e31778eSAsmitha Karunanithi if (pRoot == nullptr) 8298e31778eSAsmitha Karunanithi { 83062598e31SEd Tanous BMCWEB_LOG_ERROR("XML document failed to parse"); 8318e31778eSAsmitha Karunanithi messages::internalError(asyncResp->res); 8328e31778eSAsmitha Karunanithi return; 8338e31778eSAsmitha Karunanithi } 8348e31778eSAsmitha Karunanithi tinyxml2::XMLElement* interfaceNode = 8358e31778eSAsmitha Karunanithi pRoot->FirstChildElement("interface"); 8368e31778eSAsmitha Karunanithi 8378e31778eSAsmitha Karunanithi bool isProgressIntfPresent = false; 8388e31778eSAsmitha Karunanithi while (interfaceNode != nullptr) 8398e31778eSAsmitha Karunanithi { 840bd79bce8SPatrick Williams const char* thisInterfaceName = 841bd79bce8SPatrick Williams interfaceNode->Attribute("name"); 8428e31778eSAsmitha Karunanithi if (thisInterfaceName != nullptr) 8438e31778eSAsmitha Karunanithi { 8448e31778eSAsmitha Karunanithi if (thisInterfaceName == 8458e31778eSAsmitha Karunanithi std::string_view("xyz.openbmc_project.Common.Progress")) 8468e31778eSAsmitha Karunanithi { 8478e31778eSAsmitha Karunanithi interfaceNode = 8488e31778eSAsmitha Karunanithi interfaceNode->NextSiblingElement("interface"); 8498e31778eSAsmitha Karunanithi continue; 8508e31778eSAsmitha Karunanithi } 8518e31778eSAsmitha Karunanithi isProgressIntfPresent = true; 8528e31778eSAsmitha Karunanithi break; 8538e31778eSAsmitha Karunanithi } 8548e31778eSAsmitha Karunanithi interfaceNode = interfaceNode->NextSiblingElement("interface"); 8558e31778eSAsmitha Karunanithi } 8568e31778eSAsmitha Karunanithi 857a43be80fSAsmitha Karunanithi std::shared_ptr<task::TaskData> task = task::TaskData::createTask( 8588e31778eSAsmitha Karunanithi [createdObjPath, dumpEntryPath, dumpId, isProgressIntfPresent]( 859bd79bce8SPatrick Williams const boost::system::error_code& ec2, 860bd79bce8SPatrick Williams sdbusplus::message_t& msg, 861a43be80fSAsmitha Karunanithi const std::shared_ptr<task::TaskData>& taskData) { 8628b24275dSEd Tanous if (ec2) 863cb13a392SEd Tanous { 86462598e31SEd Tanous BMCWEB_LOG_ERROR("{}: Error in creating dump", 86562598e31SEd Tanous createdObjPath.str); 866bd79bce8SPatrick Williams taskData->messages.emplace_back( 867bd79bce8SPatrick Williams messages::internalError()); 8686145ed6fSAsmitha Karunanithi taskData->state = "Cancelled"; 8696145ed6fSAsmitha Karunanithi return task::completed; 870cb13a392SEd Tanous } 871b9d36b47SEd Tanous 8728e31778eSAsmitha Karunanithi if (isProgressIntfPresent) 873a43be80fSAsmitha Karunanithi { 8748e31778eSAsmitha Karunanithi dbus::utility::DBusPropertiesMap values; 8758e31778eSAsmitha Karunanithi std::string prop; 8768e31778eSAsmitha Karunanithi msg.read(prop, values); 8778e31778eSAsmitha Karunanithi 8788e31778eSAsmitha Karunanithi DumpCreationProgress dumpStatus = 8798e31778eSAsmitha Karunanithi getDumpCompletionStatus(values); 880bd79bce8SPatrick Williams if (dumpStatus == 881bd79bce8SPatrick Williams DumpCreationProgress::DUMP_CREATE_FAILED) 8828e31778eSAsmitha Karunanithi { 88362598e31SEd Tanous BMCWEB_LOG_ERROR("{}: Error in creating dump", 88462598e31SEd Tanous createdObjPath.str); 8858e31778eSAsmitha Karunanithi taskData->state = "Cancelled"; 8868e31778eSAsmitha Karunanithi return task::completed; 8878e31778eSAsmitha Karunanithi } 8888e31778eSAsmitha Karunanithi 889bd79bce8SPatrick Williams if (dumpStatus == 890bd79bce8SPatrick Williams DumpCreationProgress::DUMP_CREATE_INPROGRESS) 8918e31778eSAsmitha Karunanithi { 892bd79bce8SPatrick Williams BMCWEB_LOG_DEBUG( 893bd79bce8SPatrick Williams "{}: Dump creation task is in progress", 89462598e31SEd Tanous createdObjPath.str); 8958e31778eSAsmitha Karunanithi return !task::completed; 8968e31778eSAsmitha Karunanithi } 8978e31778eSAsmitha Karunanithi } 8988e31778eSAsmitha Karunanithi 899a43be80fSAsmitha Karunanithi nlohmann::json retMessage = messages::success(); 900a43be80fSAsmitha Karunanithi taskData->messages.emplace_back(retMessage); 901a43be80fSAsmitha Karunanithi 902c51a58eeSEd Tanous boost::urls::url url = boost::urls::format( 903253f11b8SEd Tanous "/redfish/v1/Managers/{}/LogServices/Dump/Entries/{}", 904253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME, dumpId); 905c51a58eeSEd Tanous 906c51a58eeSEd Tanous std::string headerLoc = "Location: "; 907c51a58eeSEd Tanous headerLoc += url.buffer(); 908c51a58eeSEd Tanous 909bd79bce8SPatrick Williams taskData->payload->httpHeaders.emplace_back( 910bd79bce8SPatrick Williams std::move(headerLoc)); 911a43be80fSAsmitha Karunanithi 91262598e31SEd Tanous BMCWEB_LOG_DEBUG("{}: Dump creation task completed", 91362598e31SEd Tanous createdObjPath.str); 914a43be80fSAsmitha Karunanithi taskData->state = "Completed"; 915b47452b2SAsmitha Karunanithi return task::completed; 916a43be80fSAsmitha Karunanithi }, 9178e31778eSAsmitha Karunanithi "type='signal',interface='org.freedesktop.DBus.Properties'," 9188e31778eSAsmitha Karunanithi "member='PropertiesChanged',path='" + 9198e31778eSAsmitha Karunanithi createdObjPath.str + "'"); 920a43be80fSAsmitha Karunanithi 9218e31778eSAsmitha Karunanithi // The task timer is set to max time limit within which the 9228e31778eSAsmitha Karunanithi // requested dump will be collected. 9238e31778eSAsmitha Karunanithi task->startTimer(std::chrono::minutes(6)); 924a43be80fSAsmitha Karunanithi task->populateResp(asyncResp->res); 9258e31778eSAsmitha Karunanithi task->payload.emplace(payload); 9268e31778eSAsmitha Karunanithi }, 9278e31778eSAsmitha Karunanithi "xyz.openbmc_project.Dump.Manager", createdObjPath, 9288e31778eSAsmitha Karunanithi "org.freedesktop.DBus.Introspectable", "Introspect"); 929a43be80fSAsmitha Karunanithi } 930a43be80fSAsmitha Karunanithi 9318d1b46d7Szhanghch05 inline void createDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 9328d1b46d7Szhanghch05 const crow::Request& req, const std::string& dumpType) 933a43be80fSAsmitha Karunanithi { 934fdd26906SClaire Weinan std::string dumpPath = getDumpEntriesPath(dumpType); 935fdd26906SClaire Weinan if (dumpPath.empty()) 936a43be80fSAsmitha Karunanithi { 937a43be80fSAsmitha Karunanithi messages::internalError(asyncResp->res); 938a43be80fSAsmitha Karunanithi return; 939a43be80fSAsmitha Karunanithi } 940a43be80fSAsmitha Karunanithi 941a43be80fSAsmitha Karunanithi std::optional<std::string> diagnosticDataType; 942a43be80fSAsmitha Karunanithi std::optional<std::string> oemDiagnosticDataType; 943a43be80fSAsmitha Karunanithi 944*afc474aeSMyung Bae if (!redfish::json_util::readJsonAction( // 945*afc474aeSMyung Bae req, asyncResp->res, // 946*afc474aeSMyung Bae "DiagnosticDataType", diagnosticDataType, // 947*afc474aeSMyung Bae "OEMDiagnosticDataType", oemDiagnosticDataType // 948*afc474aeSMyung Bae )) 949a43be80fSAsmitha Karunanithi { 950a43be80fSAsmitha Karunanithi return; 951a43be80fSAsmitha Karunanithi } 952a43be80fSAsmitha Karunanithi 953a43be80fSAsmitha Karunanithi if (dumpType == "System") 954a43be80fSAsmitha Karunanithi { 955a43be80fSAsmitha Karunanithi if (!oemDiagnosticDataType || !diagnosticDataType) 956a43be80fSAsmitha Karunanithi { 95762598e31SEd Tanous BMCWEB_LOG_ERROR( 95862598e31SEd Tanous "CreateDump action parameter 'DiagnosticDataType'/'OEMDiagnosticDataType' value not found!"); 959a43be80fSAsmitha Karunanithi messages::actionParameterMissing( 960a43be80fSAsmitha Karunanithi asyncResp->res, "CollectDiagnosticData", 961a43be80fSAsmitha Karunanithi "DiagnosticDataType & OEMDiagnosticDataType"); 962a43be80fSAsmitha Karunanithi return; 963a43be80fSAsmitha Karunanithi } 9643174e4dfSEd Tanous if ((*oemDiagnosticDataType != "System") || 965a43be80fSAsmitha Karunanithi (*diagnosticDataType != "OEM")) 966a43be80fSAsmitha Karunanithi { 96762598e31SEd Tanous BMCWEB_LOG_ERROR("Wrong parameter values passed"); 968ace85d60SEd Tanous messages::internalError(asyncResp->res); 969a43be80fSAsmitha Karunanithi return; 970a43be80fSAsmitha Karunanithi } 971253f11b8SEd Tanous dumpPath = std::format("/redfish/v1/Systems/{}/LogServices/Dump/", 972253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 973a43be80fSAsmitha Karunanithi } 974a43be80fSAsmitha Karunanithi else if (dumpType == "BMC") 975a43be80fSAsmitha Karunanithi { 976a43be80fSAsmitha Karunanithi if (!diagnosticDataType) 977a43be80fSAsmitha Karunanithi { 97862598e31SEd Tanous BMCWEB_LOG_ERROR( 97962598e31SEd Tanous "CreateDump action parameter 'DiagnosticDataType' not found!"); 980a43be80fSAsmitha Karunanithi messages::actionParameterMissing( 981a43be80fSAsmitha Karunanithi asyncResp->res, "CollectDiagnosticData", "DiagnosticDataType"); 982a43be80fSAsmitha Karunanithi return; 983a43be80fSAsmitha Karunanithi } 9843174e4dfSEd Tanous if (*diagnosticDataType != "Manager") 985a43be80fSAsmitha Karunanithi { 98662598e31SEd Tanous BMCWEB_LOG_ERROR( 98762598e31SEd Tanous "Wrong parameter value passed for 'DiagnosticDataType'"); 988ace85d60SEd Tanous messages::internalError(asyncResp->res); 989a43be80fSAsmitha Karunanithi return; 990a43be80fSAsmitha Karunanithi } 991253f11b8SEd Tanous dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/Dump/", 992253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 9935907571dSAsmitha Karunanithi } 9945907571dSAsmitha Karunanithi else 9955907571dSAsmitha Karunanithi { 99662598e31SEd Tanous BMCWEB_LOG_ERROR("CreateDump failed. Unknown dump type"); 9975907571dSAsmitha Karunanithi messages::internalError(asyncResp->res); 9985907571dSAsmitha Karunanithi return; 999a43be80fSAsmitha Karunanithi } 1000a43be80fSAsmitha Karunanithi 10018e31778eSAsmitha Karunanithi std::vector<std::pair<std::string, std::variant<std::string, uint64_t>>> 10028e31778eSAsmitha Karunanithi createDumpParamVec; 10038e31778eSAsmitha Karunanithi 1004f574a8e1SCarson Labrado if (req.session != nullptr) 1005f574a8e1SCarson Labrado { 100668dd075aSAsmitha Karunanithi createDumpParamVec.emplace_back( 100768dd075aSAsmitha Karunanithi "xyz.openbmc_project.Dump.Create.CreateParameters.OriginatorId", 100868dd075aSAsmitha Karunanithi req.session->clientIp); 100968dd075aSAsmitha Karunanithi createDumpParamVec.emplace_back( 101068dd075aSAsmitha Karunanithi "xyz.openbmc_project.Dump.Create.CreateParameters.OriginatorType", 101168dd075aSAsmitha Karunanithi "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Client"); 1012f574a8e1SCarson Labrado } 101368dd075aSAsmitha Karunanithi 1014a43be80fSAsmitha Karunanithi crow::connections::systemBus->async_method_call( 10155e7e2dc5SEd Tanous [asyncResp, payload(task::Payload(req)), 10165e7e2dc5SEd Tanous dumpPath](const boost::system::error_code& ec, 10175e7e2dc5SEd Tanous const sdbusplus::message_t& msg, 10188e31778eSAsmitha Karunanithi const sdbusplus::message::object_path& objPath) mutable { 1019a43be80fSAsmitha Karunanithi if (ec) 1020a43be80fSAsmitha Karunanithi { 102162598e31SEd Tanous BMCWEB_LOG_ERROR("CreateDump resp_handler got error {}", ec); 10225907571dSAsmitha Karunanithi const sd_bus_error* dbusError = msg.get_error(); 10235907571dSAsmitha Karunanithi if (dbusError == nullptr) 10245907571dSAsmitha Karunanithi { 10255907571dSAsmitha Karunanithi messages::internalError(asyncResp->res); 10265907571dSAsmitha Karunanithi return; 10275907571dSAsmitha Karunanithi } 10285907571dSAsmitha Karunanithi 102962598e31SEd Tanous BMCWEB_LOG_ERROR("CreateDump DBus error: {} and error msg: {}", 103062598e31SEd Tanous dbusError->name, dbusError->message); 10315907571dSAsmitha Karunanithi if (std::string_view( 10325907571dSAsmitha Karunanithi "xyz.openbmc_project.Common.Error.NotAllowed") == 10335907571dSAsmitha Karunanithi dbusError->name) 10345907571dSAsmitha Karunanithi { 10355907571dSAsmitha Karunanithi messages::resourceInStandby(asyncResp->res); 10365907571dSAsmitha Karunanithi return; 10375907571dSAsmitha Karunanithi } 10385907571dSAsmitha Karunanithi if (std::string_view( 10395907571dSAsmitha Karunanithi "xyz.openbmc_project.Dump.Create.Error.Disabled") == 10405907571dSAsmitha Karunanithi dbusError->name) 10415907571dSAsmitha Karunanithi { 10425907571dSAsmitha Karunanithi messages::serviceDisabled(asyncResp->res, dumpPath); 10435907571dSAsmitha Karunanithi return; 10445907571dSAsmitha Karunanithi } 10455907571dSAsmitha Karunanithi if (std::string_view( 10465907571dSAsmitha Karunanithi "xyz.openbmc_project.Common.Error.Unavailable") == 10475907571dSAsmitha Karunanithi dbusError->name) 10485907571dSAsmitha Karunanithi { 10495907571dSAsmitha Karunanithi messages::resourceInUse(asyncResp->res); 10505907571dSAsmitha Karunanithi return; 10515907571dSAsmitha Karunanithi } 10525907571dSAsmitha Karunanithi // Other Dbus errors such as: 10535907571dSAsmitha Karunanithi // xyz.openbmc_project.Common.Error.InvalidArgument & 10545907571dSAsmitha Karunanithi // org.freedesktop.DBus.Error.InvalidArgs are all related to 10555907571dSAsmitha Karunanithi // the dbus call that is made here in the bmcweb 10565907571dSAsmitha Karunanithi // implementation and has nothing to do with the client's 10575907571dSAsmitha Karunanithi // input in the request. Hence, returning internal error 10585907571dSAsmitha Karunanithi // back to the client. 1059a43be80fSAsmitha Karunanithi messages::internalError(asyncResp->res); 1060a43be80fSAsmitha Karunanithi return; 1061a43be80fSAsmitha Karunanithi } 106262598e31SEd Tanous BMCWEB_LOG_DEBUG("Dump Created. Path: {}", objPath.str); 10638e31778eSAsmitha Karunanithi createDumpTaskCallback(std::move(payload), asyncResp, objPath); 1064a43be80fSAsmitha Karunanithi }, 106518f8f608SEd Tanous "xyz.openbmc_project.Dump.Manager", getDumpPath(dumpType), 10668e31778eSAsmitha Karunanithi "xyz.openbmc_project.Dump.Create", "CreateDump", createDumpParamVec); 1067a43be80fSAsmitha Karunanithi } 1068a43be80fSAsmitha Karunanithi 10698d1b46d7Szhanghch05 inline void clearDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 10708d1b46d7Szhanghch05 const std::string& dumpType) 107180319af1SAsmitha Karunanithi { 10720d946211SClaire Weinan crow::connections::systemBus->async_method_call( 10730d946211SClaire Weinan [asyncResp](const boost::system::error_code& ec) { 107480319af1SAsmitha Karunanithi if (ec) 107580319af1SAsmitha Karunanithi { 107662598e31SEd Tanous BMCWEB_LOG_ERROR("clearDump resp_handler got error {}", ec); 107780319af1SAsmitha Karunanithi messages::internalError(asyncResp->res); 107880319af1SAsmitha Karunanithi return; 107980319af1SAsmitha Karunanithi } 10800d946211SClaire Weinan }, 108118f8f608SEd Tanous "xyz.openbmc_project.Dump.Manager", getDumpPath(dumpType), 10820d946211SClaire Weinan "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll"); 108380319af1SAsmitha Karunanithi } 108480319af1SAsmitha Karunanithi 1085bd79bce8SPatrick Williams inline void parseCrashdumpParameters( 1086bd79bce8SPatrick Williams const dbus::utility::DBusPropertiesMap& params, std::string& filename, 1087bd79bce8SPatrick Williams std::string& timestamp, std::string& logfile) 1088043a0536SJohnathan Mantey { 1089d1bde9e5SKrzysztof Grobelny const std::string* filenamePtr = nullptr; 1090d1bde9e5SKrzysztof Grobelny const std::string* timestampPtr = nullptr; 1091d1bde9e5SKrzysztof Grobelny const std::string* logfilePtr = nullptr; 1092d1bde9e5SKrzysztof Grobelny 1093d1bde9e5SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 1094d1bde9e5SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), params, "Timestamp", timestampPtr, 1095d1bde9e5SKrzysztof Grobelny "Filename", filenamePtr, "Log", logfilePtr); 1096d1bde9e5SKrzysztof Grobelny 1097d1bde9e5SKrzysztof Grobelny if (!success) 1098043a0536SJohnathan Mantey { 1099d1bde9e5SKrzysztof Grobelny return; 1100043a0536SJohnathan Mantey } 1101d1bde9e5SKrzysztof Grobelny 1102d1bde9e5SKrzysztof Grobelny if (filenamePtr != nullptr) 1103043a0536SJohnathan Mantey { 1104d1bde9e5SKrzysztof Grobelny filename = *filenamePtr; 1105d1bde9e5SKrzysztof Grobelny } 1106d1bde9e5SKrzysztof Grobelny 1107d1bde9e5SKrzysztof Grobelny if (timestampPtr != nullptr) 1108043a0536SJohnathan Mantey { 1109d1bde9e5SKrzysztof Grobelny timestamp = *timestampPtr; 1110043a0536SJohnathan Mantey } 1111d1bde9e5SKrzysztof Grobelny 1112d1bde9e5SKrzysztof Grobelny if (logfilePtr != nullptr) 1113043a0536SJohnathan Mantey { 1114d1bde9e5SKrzysztof Grobelny logfile = *logfilePtr; 1115043a0536SJohnathan Mantey } 1116043a0536SJohnathan Mantey } 1117043a0536SJohnathan Mantey 11187e860f15SJohn Edward Broadbent inline void requestRoutesSystemLogServiceCollection(App& app) 11191da66f75SEd Tanous { 1120c4bf6374SJason M. Bills /** 1121c4bf6374SJason M. Bills * Functions triggers appropriate requests on DBus 1122c4bf6374SJason M. Bills */ 112322d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/") 1124ed398213SEd Tanous .privileges(redfish::privileges::getLogServiceCollection) 1125bd79bce8SPatrick Williams .methods( 1126bd79bce8SPatrick Williams boost::beast::http::verb:: 1127bd79bce8SPatrick Williams get)([&app](const crow::Request& req, 112822d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 112922d268cbSEd Tanous const std::string& systemName) { 11303ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 1131c4bf6374SJason M. Bills { 113245ca1b86SEd Tanous return; 113345ca1b86SEd Tanous } 113425b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 11357f3e84a1SEd Tanous { 11367f3e84a1SEd Tanous // Option currently returns no systems. TBD 11377f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 11387f3e84a1SEd Tanous systemName); 11397f3e84a1SEd Tanous return; 11407f3e84a1SEd Tanous } 1141253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 114222d268cbSEd Tanous { 114322d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 114422d268cbSEd Tanous systemName); 114522d268cbSEd Tanous return; 114622d268cbSEd Tanous } 114722d268cbSEd Tanous 11487e860f15SJohn Edward Broadbent // Collections don't include the static data added by SubRoute 11497e860f15SJohn Edward Broadbent // because it has a duplicate entry for members 1150c4bf6374SJason M. Bills asyncResp->res.jsonValue["@odata.type"] = 1151c4bf6374SJason M. Bills "#LogServiceCollection.LogServiceCollection"; 1152c4bf6374SJason M. Bills asyncResp->res.jsonValue["@odata.id"] = 1153253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices", 1154253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 115545ca1b86SEd Tanous asyncResp->res.jsonValue["Name"] = "System Log Services Collection"; 1156c4bf6374SJason M. Bills asyncResp->res.jsonValue["Description"] = 1157c4bf6374SJason M. Bills "Collection of LogServices for this Computer System"; 1158bd79bce8SPatrick Williams nlohmann::json& logServiceArray = 1159bd79bce8SPatrick Williams asyncResp->res.jsonValue["Members"]; 1160c4bf6374SJason M. Bills logServiceArray = nlohmann::json::array(); 11611476687dSEd Tanous nlohmann::json::object_t eventLog; 11621476687dSEd Tanous eventLog["@odata.id"] = 1163253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/EventLog", 1164253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1165b2ba3072SPatrick Williams logServiceArray.emplace_back(std::move(eventLog)); 116625b54dbaSEd Tanous if constexpr (BMCWEB_REDFISH_DUMP_LOG) 116725b54dbaSEd Tanous { 11681476687dSEd Tanous nlohmann::json::object_t dumpLog; 116925b54dbaSEd Tanous dumpLog["@odata.id"] = 1170253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/Dump", 1171253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1172b2ba3072SPatrick Williams logServiceArray.emplace_back(std::move(dumpLog)); 117325b54dbaSEd Tanous } 1174c9bb6861Sraviteja-b 11755ffd11f2SGunnar Mills if constexpr (BMCWEB_REDFISH_CPU_LOG) 117625b54dbaSEd Tanous { 11771476687dSEd Tanous nlohmann::json::object_t crashdump; 11781476687dSEd Tanous crashdump["@odata.id"] = 1179253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/Crashdump", 1180253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1181b2ba3072SPatrick Williams logServiceArray.emplace_back(std::move(crashdump)); 118225b54dbaSEd Tanous } 1183b7028ebfSSpencer Ku 118425b54dbaSEd Tanous if constexpr (BMCWEB_REDFISH_HOST_LOGGER) 118525b54dbaSEd Tanous { 11861476687dSEd Tanous nlohmann::json::object_t hostlogger; 11871476687dSEd Tanous hostlogger["@odata.id"] = 1188253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/HostLogger", 1189253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1190b2ba3072SPatrick Williams logServiceArray.emplace_back(std::move(hostlogger)); 119125b54dbaSEd Tanous } 1192c4bf6374SJason M. Bills asyncResp->res.jsonValue["Members@odata.count"] = 1193c4bf6374SJason M. Bills logServiceArray.size(); 1194a3316fc6SZhikuiRen 11957a1dbc48SGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 11967a1dbc48SGeorge Liu "xyz.openbmc_project.State.Boot.PostCode"}; 11977a1dbc48SGeorge Liu dbus::utility::getSubTreePaths( 11987a1dbc48SGeorge Liu "/", 0, interfaces, 11997a1dbc48SGeorge Liu [asyncResp](const boost::system::error_code& ec, 1200b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreePathsResponse& 1201b9d36b47SEd Tanous subtreePath) { 1202a3316fc6SZhikuiRen if (ec) 1203a3316fc6SZhikuiRen { 120462598e31SEd Tanous BMCWEB_LOG_ERROR("{}", ec); 1205a3316fc6SZhikuiRen return; 1206a3316fc6SZhikuiRen } 1207a3316fc6SZhikuiRen 120855f79e6fSEd Tanous for (const auto& pathStr : subtreePath) 1209a3316fc6SZhikuiRen { 1210a3316fc6SZhikuiRen if (pathStr.find("PostCode") != std::string::npos) 1211a3316fc6SZhikuiRen { 121223a21a1cSEd Tanous nlohmann::json& logServiceArrayLocal = 1213a3316fc6SZhikuiRen asyncResp->res.jsonValue["Members"]; 1214613dabeaSEd Tanous nlohmann::json::object_t member; 1215253f11b8SEd Tanous member["@odata.id"] = std::format( 1216253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/PostCodes", 1217253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1218613dabeaSEd Tanous 1219bd79bce8SPatrick Williams logServiceArrayLocal.emplace_back( 1220bd79bce8SPatrick Williams std::move(member)); 1221613dabeaSEd Tanous 122245ca1b86SEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = 122323a21a1cSEd Tanous logServiceArrayLocal.size(); 1224a3316fc6SZhikuiRen return; 1225a3316fc6SZhikuiRen } 1226a3316fc6SZhikuiRen } 12277a1dbc48SGeorge Liu }); 12287e860f15SJohn Edward Broadbent }); 1229c4bf6374SJason M. Bills } 1230c4bf6374SJason M. Bills 12317e860f15SJohn Edward Broadbent inline void requestRoutesEventLogService(App& app) 1232c4bf6374SJason M. Bills { 123322d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/") 1234ed398213SEd Tanous .privileges(redfish::privileges::getLogService) 1235bd79bce8SPatrick Williams .methods( 1236bd79bce8SPatrick Williams boost::beast::http::verb:: 1237bd79bce8SPatrick Williams get)([&app](const crow::Request& req, 123822d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 123922d268cbSEd Tanous const std::string& systemName) { 12403ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 124145ca1b86SEd Tanous { 124245ca1b86SEd Tanous return; 124345ca1b86SEd Tanous } 1244253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 124522d268cbSEd Tanous { 124622d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 124722d268cbSEd Tanous systemName); 124822d268cbSEd Tanous return; 124922d268cbSEd Tanous } 1250c4bf6374SJason M. Bills asyncResp->res.jsonValue["@odata.id"] = 1251253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/EventLog", 1252253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1253c4bf6374SJason M. Bills asyncResp->res.jsonValue["@odata.type"] = 1254b25644a1SJanet Adkins "#LogService.v1_2_0.LogService"; 1255c4bf6374SJason M. Bills asyncResp->res.jsonValue["Name"] = "Event Log Service"; 1256bd79bce8SPatrick Williams asyncResp->res.jsonValue["Description"] = 1257bd79bce8SPatrick Williams "System Event Log Service"; 1258c4bf6374SJason M. Bills asyncResp->res.jsonValue["Id"] = "EventLog"; 1259539d8c6bSEd Tanous asyncResp->res.jsonValue["OverWritePolicy"] = 1260539d8c6bSEd Tanous log_service::OverWritePolicy::WrapsWhenFull; 12617c8c4058STejas Patil 12627c8c4058STejas Patil std::pair<std::string, std::string> redfishDateTimeOffset = 12632b82937eSEd Tanous redfish::time_utils::getDateTimeOffsetNow(); 12647c8c4058STejas Patil 12657c8c4058STejas Patil asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first; 12667c8c4058STejas Patil asyncResp->res.jsonValue["DateTimeLocalOffset"] = 12677c8c4058STejas Patil redfishDateTimeOffset.second; 12687c8c4058STejas Patil 1269bd79bce8SPatrick Williams asyncResp->res.jsonValue["Entries"]["@odata.id"] = std::format( 1270bd79bce8SPatrick Williams "/redfish/v1/Systems/{}/LogServices/EventLog/Entries", 1271253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1272bd79bce8SPatrick Williams asyncResp->res 1273bd79bce8SPatrick Williams .jsonValue["Actions"]["#LogService.ClearLog"]["target"] 1274e7d6c8b2SGunnar Mills 127520fa6a2cSEd Tanous = std::format( 1276253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/EventLog/Actions/LogService.ClearLog", 127720fa6a2cSEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 12787e860f15SJohn Edward Broadbent }); 1279489640c6SJason M. Bills } 1280489640c6SJason M. Bills 1281599b9af3SAlexander Hansen inline void handleSystemsLogServicesEventLogActionsClearPost( 1282599b9af3SAlexander Hansen App& app, const crow::Request& req, 128322d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1284599b9af3SAlexander Hansen const std::string& systemName) 1285599b9af3SAlexander Hansen { 12863ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 128745ca1b86SEd Tanous { 128845ca1b86SEd Tanous return; 128945ca1b86SEd Tanous } 1290253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 129122d268cbSEd Tanous { 129222d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 129322d268cbSEd Tanous systemName); 129422d268cbSEd Tanous return; 129522d268cbSEd Tanous } 1296599b9af3SAlexander Hansen 1297489640c6SJason M. Bills // Clear the EventLog by deleting the log files 1298489640c6SJason M. Bills std::vector<std::filesystem::path> redfishLogFiles; 1299489640c6SJason M. Bills if (getRedfishLogFiles(redfishLogFiles)) 1300489640c6SJason M. Bills { 1301489640c6SJason M. Bills for (const std::filesystem::path& file : redfishLogFiles) 1302489640c6SJason M. Bills { 1303489640c6SJason M. Bills std::error_code ec; 1304489640c6SJason M. Bills std::filesystem::remove(file, ec); 1305489640c6SJason M. Bills } 1306489640c6SJason M. Bills } 1307489640c6SJason M. Bills 1308489640c6SJason M. Bills // Reload rsyslog so it knows to start new log files 1309489640c6SJason M. Bills crow::connections::systemBus->async_method_call( 13105e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 1311489640c6SJason M. Bills if (ec) 1312489640c6SJason M. Bills { 131362598e31SEd Tanous BMCWEB_LOG_ERROR("Failed to reload rsyslog: {}", ec); 1314489640c6SJason M. Bills messages::internalError(asyncResp->res); 1315489640c6SJason M. Bills return; 1316489640c6SJason M. Bills } 1317489640c6SJason M. Bills 1318489640c6SJason M. Bills messages::success(asyncResp->res); 1319489640c6SJason M. Bills }, 1320489640c6SJason M. Bills "org.freedesktop.systemd1", "/org/freedesktop/systemd1", 1321002d39b4SEd Tanous "org.freedesktop.systemd1.Manager", "ReloadUnit", "rsyslog.service", 1322002d39b4SEd Tanous "replace"); 1323599b9af3SAlexander Hansen } 1324599b9af3SAlexander Hansen 1325599b9af3SAlexander Hansen inline void requestRoutesJournalEventLogClear(App& app) 1326599b9af3SAlexander Hansen { 1327599b9af3SAlexander Hansen BMCWEB_ROUTE( 1328599b9af3SAlexander Hansen app, 1329599b9af3SAlexander Hansen "/redfish/v1/Systems/<str>/LogServices/EventLog/Actions/LogService.ClearLog/") 1330599b9af3SAlexander Hansen .privileges({{"ConfigureComponents"}}) 1331599b9af3SAlexander Hansen .methods(boost::beast::http::verb::post)(std::bind_front( 1332599b9af3SAlexander Hansen handleSystemsLogServicesEventLogActionsClearPost, std::ref(app))); 1333c4bf6374SJason M. Bills } 1334c4bf6374SJason M. Bills 1335ac992cdeSJason M. Bills enum class LogParseError 1336ac992cdeSJason M. Bills { 1337ac992cdeSJason M. Bills success, 1338ac992cdeSJason M. Bills parseFailed, 1339ac992cdeSJason M. Bills messageIdNotInRegistry, 1340ac992cdeSJason M. Bills }; 1341ac992cdeSJason M. Bills 1342bd79bce8SPatrick Williams static LogParseError fillEventLogEntryJson( 1343bd79bce8SPatrick Williams const std::string& logEntryID, const std::string& logEntry, 1344de703c5dSJason M. Bills nlohmann::json::object_t& logEntryJson) 1345c4bf6374SJason M. Bills { 134695820184SJason M. Bills // The redfish log format is "<Timestamp> <MessageId>,<MessageArgs>" 1347cd225da8SJason M. Bills // First get the Timestamp 1348f23b7296SEd Tanous size_t space = logEntry.find_first_of(' '); 1349cd225da8SJason M. Bills if (space == std::string::npos) 135095820184SJason M. Bills { 1351ac992cdeSJason M. Bills return LogParseError::parseFailed; 135295820184SJason M. Bills } 1353cd225da8SJason M. Bills std::string timestamp = logEntry.substr(0, space); 1354cd225da8SJason M. Bills // Then get the log contents 1355f23b7296SEd Tanous size_t entryStart = logEntry.find_first_not_of(' ', space); 1356cd225da8SJason M. Bills if (entryStart == std::string::npos) 1357cd225da8SJason M. Bills { 1358ac992cdeSJason M. Bills return LogParseError::parseFailed; 1359cd225da8SJason M. Bills } 1360cd225da8SJason M. Bills std::string_view entry(logEntry); 1361cd225da8SJason M. Bills entry.remove_prefix(entryStart); 1362cd225da8SJason M. Bills // Use split to separate the entry into its fields 1363cd225da8SJason M. Bills std::vector<std::string> logEntryFields; 136450ebd4afSEd Tanous bmcweb::split(logEntryFields, entry, ','); 1365cd225da8SJason M. Bills // We need at least a MessageId to be valid 13661e6deaf6SEd Tanous auto logEntryIter = logEntryFields.begin(); 13671e6deaf6SEd Tanous if (logEntryIter == logEntryFields.end()) 1368cd225da8SJason M. Bills { 1369ac992cdeSJason M. Bills return LogParseError::parseFailed; 1370cd225da8SJason M. Bills } 13711e6deaf6SEd Tanous std::string& messageID = *logEntryIter; 13724851d45dSJason M. Bills // Get the Message from the MessageRegistry 1373fffb8c1fSEd Tanous const registries::Message* message = registries::getMessage(messageID); 1374c4bf6374SJason M. Bills 13751e6deaf6SEd Tanous logEntryIter++; 137654417b02SSui Chen if (message == nullptr) 1377c4bf6374SJason M. Bills { 137862598e31SEd Tanous BMCWEB_LOG_WARNING("Log entry not found in registry: {}", logEntry); 1379ac992cdeSJason M. Bills return LogParseError::messageIdNotInRegistry; 1380c4bf6374SJason M. Bills } 1381c4bf6374SJason M. Bills 13821e6deaf6SEd Tanous std::vector<std::string_view> messageArgs(logEntryIter, 13831e6deaf6SEd Tanous logEntryFields.end()); 1384c05bba45SEd Tanous messageArgs.resize(message->numberOfArgs); 1385c05bba45SEd Tanous 1386bd79bce8SPatrick Williams std::string msg = 1387bd79bce8SPatrick Williams redfish::registries::fillMessageArgs(messageArgs, message->message); 13881e6deaf6SEd Tanous if (msg.empty()) 138915a86ff6SJason M. Bills { 13901e6deaf6SEd Tanous return LogParseError::parseFailed; 139115a86ff6SJason M. Bills } 13924851d45dSJason M. Bills 139395820184SJason M. Bills // Get the Created time from the timestamp. The log timestamp is in RFC3339 139495820184SJason M. Bills // format which matches the Redfish format except for the fractional seconds 139595820184SJason M. Bills // between the '.' and the '+', so just remove them. 1396f23b7296SEd Tanous std::size_t dot = timestamp.find_first_of('.'); 1397f23b7296SEd Tanous std::size_t plus = timestamp.find_first_of('+'); 139895820184SJason M. Bills if (dot != std::string::npos && plus != std::string::npos) 1399c4bf6374SJason M. Bills { 140095820184SJason M. Bills timestamp.erase(dot, plus - dot); 1401c4bf6374SJason M. Bills } 1402c4bf6374SJason M. Bills 1403c4bf6374SJason M. Bills // Fill in the log entry with the gathered data 14049c11a172SVijay Lobo logEntryJson["@odata.type"] = "#LogEntry.v1_9_0.LogEntry"; 1405ef4c65b7SEd Tanous logEntryJson["@odata.id"] = boost::urls::format( 1406253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}", 1407253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, logEntryID); 140884afc48bSJason M. Bills logEntryJson["Name"] = "System Event Log Entry"; 140984afc48bSJason M. Bills logEntryJson["Id"] = logEntryID; 141084afc48bSJason M. Bills logEntryJson["Message"] = std::move(msg); 141184afc48bSJason M. Bills logEntryJson["MessageId"] = std::move(messageID); 141284afc48bSJason M. Bills logEntryJson["MessageArgs"] = messageArgs; 141384afc48bSJason M. Bills logEntryJson["EntryType"] = "Event"; 141484afc48bSJason M. Bills logEntryJson["Severity"] = message->messageSeverity; 141584afc48bSJason M. Bills logEntryJson["Created"] = std::move(timestamp); 1416ac992cdeSJason M. Bills return LogParseError::success; 1417c4bf6374SJason M. Bills } 1418c4bf6374SJason M. Bills 1419898f2aa2SEd Tanous inline void fillEventLogLogEntryFromPropertyMap( 1420898f2aa2SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1421898f2aa2SEd Tanous const dbus::utility::DBusPropertiesMap& resp, 1422898f2aa2SEd Tanous nlohmann::json& objectToFillOut) 1423898f2aa2SEd Tanous { 1424262dcc1cSAlexander Hansen std::optional<DbusEventLogEntry> optEntry = 1425262dcc1cSAlexander Hansen fillDbusEventLogEntryFromPropertyMap(resp); 1426898f2aa2SEd Tanous 1427262dcc1cSAlexander Hansen if (!optEntry.has_value()) 1428898f2aa2SEd Tanous { 1429898f2aa2SEd Tanous messages::internalError(asyncResp->res); 1430898f2aa2SEd Tanous return; 1431898f2aa2SEd Tanous } 1432262dcc1cSAlexander Hansen DbusEventLogEntry entry = optEntry.value(); 1433898f2aa2SEd Tanous 1434898f2aa2SEd Tanous objectToFillOut["@odata.type"] = "#LogEntry.v1_9_0.LogEntry"; 1435898f2aa2SEd Tanous objectToFillOut["@odata.id"] = boost::urls::format( 1436898f2aa2SEd Tanous "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}", 1437262dcc1cSAlexander Hansen BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(entry.Id)); 1438898f2aa2SEd Tanous objectToFillOut["Name"] = "System Event Log Entry"; 1439262dcc1cSAlexander Hansen objectToFillOut["Id"] = std::to_string(entry.Id); 1440262dcc1cSAlexander Hansen objectToFillOut["Message"] = entry.Message; 1441262dcc1cSAlexander Hansen objectToFillOut["Resolved"] = entry.Resolved; 1442262dcc1cSAlexander Hansen std::optional<bool> notifyAction = 1443262dcc1cSAlexander Hansen getProviderNotifyAction(entry.ServiceProviderNotify); 1444898f2aa2SEd Tanous if (notifyAction) 1445898f2aa2SEd Tanous { 1446898f2aa2SEd Tanous objectToFillOut["ServiceProviderNotified"] = *notifyAction; 1447898f2aa2SEd Tanous } 1448262dcc1cSAlexander Hansen if ((entry.Resolution != nullptr) && !entry.Resolution->empty()) 1449898f2aa2SEd Tanous { 1450262dcc1cSAlexander Hansen objectToFillOut["Resolution"] = *entry.Resolution; 1451898f2aa2SEd Tanous } 1452898f2aa2SEd Tanous objectToFillOut["EntryType"] = "Event"; 1453262dcc1cSAlexander Hansen objectToFillOut["Severity"] = 1454262dcc1cSAlexander Hansen translateSeverityDbusToRedfish(entry.Severity); 1455898f2aa2SEd Tanous objectToFillOut["Created"] = 1456262dcc1cSAlexander Hansen redfish::time_utils::getDateTimeUintMs(entry.Timestamp); 1457898f2aa2SEd Tanous objectToFillOut["Modified"] = 1458262dcc1cSAlexander Hansen redfish::time_utils::getDateTimeUintMs(entry.UpdateTimestamp); 1459262dcc1cSAlexander Hansen if (entry.Path != nullptr) 1460898f2aa2SEd Tanous { 1461898f2aa2SEd Tanous objectToFillOut["AdditionalDataURI"] = boost::urls::format( 1462898f2aa2SEd Tanous "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}/attachment", 1463262dcc1cSAlexander Hansen BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(entry.Id)); 1464898f2aa2SEd Tanous } 1465898f2aa2SEd Tanous } 1466898f2aa2SEd Tanous 1467b729096dSEd Tanous inline void afterLogEntriesGetManagedObjects( 1468b729096dSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1469b729096dSEd Tanous const boost::system::error_code& ec, 1470b729096dSEd Tanous const dbus::utility::ManagedObjectType& resp) 1471b729096dSEd Tanous { 1472b729096dSEd Tanous if (ec) 1473b729096dSEd Tanous { 1474b729096dSEd Tanous // TODO Handle for specific error code 1475b729096dSEd Tanous BMCWEB_LOG_ERROR("getLogEntriesIfaceData resp_handler got error {}", 1476b729096dSEd Tanous ec); 1477b729096dSEd Tanous messages::internalError(asyncResp->res); 1478b729096dSEd Tanous return; 1479b729096dSEd Tanous } 1480b729096dSEd Tanous nlohmann::json::array_t entriesArray; 1481b729096dSEd Tanous for (const auto& objectPath : resp) 1482b729096dSEd Tanous { 1483898f2aa2SEd Tanous dbus::utility::DBusPropertiesMap propsFlattened; 1484bd79bce8SPatrick Williams auto isEntry = 1485bd79bce8SPatrick Williams std::ranges::find_if(objectPath.second, [](const auto& object) { 1486898f2aa2SEd Tanous return object.first == "xyz.openbmc_project.Logging.Entry"; 1487898f2aa2SEd Tanous }); 1488898f2aa2SEd Tanous if (isEntry == objectPath.second.end()) 1489b729096dSEd Tanous { 1490b729096dSEd Tanous continue; 1491b729096dSEd Tanous } 1492898f2aa2SEd Tanous for (const auto& interfaceMap : objectPath.second) 1493b729096dSEd Tanous { 1494898f2aa2SEd Tanous for (const auto& propertyMap : interfaceMap.second) 1495b729096dSEd Tanous { 1496898f2aa2SEd Tanous propsFlattened.emplace_back(propertyMap.first, 1497898f2aa2SEd Tanous propertyMap.second); 1498b729096dSEd Tanous } 1499b729096dSEd Tanous } 1500898f2aa2SEd Tanous fillEventLogLogEntryFromPropertyMap(asyncResp, propsFlattened, 1501898f2aa2SEd Tanous entriesArray.emplace_back()); 1502b729096dSEd Tanous } 1503898f2aa2SEd Tanous 1504b729096dSEd Tanous std::ranges::sort(entriesArray, [](const nlohmann::json& left, 1505b729096dSEd Tanous const nlohmann::json& right) { 1506b729096dSEd Tanous return (left["Id"] <= right["Id"]); 1507b729096dSEd Tanous }); 1508b729096dSEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = entriesArray.size(); 1509b729096dSEd Tanous asyncResp->res.jsonValue["Members"] = std::move(entriesArray); 1510b729096dSEd Tanous } 1511b729096dSEd Tanous 1512599b9af3SAlexander Hansen inline void handleSystemsLogServiceEventLogLogEntryCollection( 1513599b9af3SAlexander Hansen App& app, const crow::Request& req, 151422d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1515599b9af3SAlexander Hansen const std::string& systemName) 1516599b9af3SAlexander Hansen { 1517c937d2bfSEd Tanous query_param::QueryCapabilities capabilities = { 1518c937d2bfSEd Tanous .canDelegateTop = true, 1519c937d2bfSEd Tanous .canDelegateSkip = true, 1520c937d2bfSEd Tanous }; 1521c937d2bfSEd Tanous query_param::Query delegatedQuery; 1522599b9af3SAlexander Hansen if (!redfish::setUpRedfishRouteWithDelegation(app, req, asyncResp, 1523599b9af3SAlexander Hansen delegatedQuery, capabilities)) 1524c4bf6374SJason M. Bills { 1525c4bf6374SJason M. Bills return; 1526c4bf6374SJason M. Bills } 152725b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 15287f3e84a1SEd Tanous { 15297f3e84a1SEd Tanous // Option currently returns no systems. TBD 15307f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 15317f3e84a1SEd Tanous systemName); 15327f3e84a1SEd Tanous return; 15337f3e84a1SEd Tanous } 1534253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 153522d268cbSEd Tanous { 153622d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 153722d268cbSEd Tanous systemName); 153822d268cbSEd Tanous return; 153922d268cbSEd Tanous } 154022d268cbSEd Tanous 15415143f7a5SJiaqing Zhao size_t top = delegatedQuery.top.value_or(query_param::Query::maxTop); 15423648c8beSEd Tanous size_t skip = delegatedQuery.skip.value_or(0); 15433648c8beSEd Tanous 15447e860f15SJohn Edward Broadbent // Collections don't include the static data added by SubRoute 15457e860f15SJohn Edward Broadbent // because it has a duplicate entry for members 1546c4bf6374SJason M. Bills asyncResp->res.jsonValue["@odata.type"] = 1547c4bf6374SJason M. Bills "#LogEntryCollection.LogEntryCollection"; 1548c4bf6374SJason M. Bills asyncResp->res.jsonValue["@odata.id"] = 1549253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries", 1550253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1551c4bf6374SJason M. Bills asyncResp->res.jsonValue["Name"] = "System Event Log Entries"; 1552c4bf6374SJason M. Bills asyncResp->res.jsonValue["Description"] = 1553c4bf6374SJason M. Bills "Collection of System Event Log Entries"; 1554cb92c03bSAndrew Geissler 15554978b63fSJason M. Bills nlohmann::json& logEntryArray = asyncResp->res.jsonValue["Members"]; 1556c4bf6374SJason M. Bills logEntryArray = nlohmann::json::array(); 15577e860f15SJohn Edward Broadbent // Go through the log files and create a unique ID for each 15587e860f15SJohn Edward Broadbent // entry 155995820184SJason M. Bills std::vector<std::filesystem::path> redfishLogFiles; 156095820184SJason M. Bills getRedfishLogFiles(redfishLogFiles); 1561b01bf299SEd Tanous uint64_t entryCount = 0; 1562cd225da8SJason M. Bills std::string logEntry; 156395820184SJason M. Bills 15647e860f15SJohn Edward Broadbent // Oldest logs are in the last file, so start there and loop 15657e860f15SJohn Edward Broadbent // backwards 1566599b9af3SAlexander Hansen for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend(); it++) 1567c4bf6374SJason M. Bills { 1568cd225da8SJason M. Bills std::ifstream logStream(*it); 156995820184SJason M. Bills if (!logStream.is_open()) 1570c4bf6374SJason M. Bills { 1571c4bf6374SJason M. Bills continue; 1572c4bf6374SJason M. Bills } 1573c4bf6374SJason M. Bills 1574e85d6b16SJason M. Bills // Reset the unique ID on the first entry 1575e85d6b16SJason M. Bills bool firstEntry = true; 157695820184SJason M. Bills while (std::getline(logStream, logEntry)) 157795820184SJason M. Bills { 1578c4bf6374SJason M. Bills std::string idStr; 1579e85d6b16SJason M. Bills if (!getUniqueEntryID(logEntry, idStr, firstEntry)) 1580c4bf6374SJason M. Bills { 1581c4bf6374SJason M. Bills continue; 1582c4bf6374SJason M. Bills } 1583e85d6b16SJason M. Bills firstEntry = false; 1584e85d6b16SJason M. Bills 1585de703c5dSJason M. Bills nlohmann::json::object_t bmcLogEntry; 1586bd79bce8SPatrick Williams LogParseError status = 1587bd79bce8SPatrick Williams fillEventLogEntryJson(idStr, logEntry, bmcLogEntry); 1588ac992cdeSJason M. Bills if (status == LogParseError::messageIdNotInRegistry) 1589ac992cdeSJason M. Bills { 1590ac992cdeSJason M. Bills continue; 1591ac992cdeSJason M. Bills } 1592ac992cdeSJason M. Bills if (status != LogParseError::success) 1593c4bf6374SJason M. Bills { 1594c4bf6374SJason M. Bills messages::internalError(asyncResp->res); 1595c4bf6374SJason M. Bills return; 1596c4bf6374SJason M. Bills } 1597de703c5dSJason M. Bills 1598de703c5dSJason M. Bills entryCount++; 1599de703c5dSJason M. Bills // Handle paging using skip (number of entries to skip from the 1600de703c5dSJason M. Bills // start) and top (number of entries to display) 16013648c8beSEd Tanous if (entryCount <= skip || entryCount > skip + top) 1602de703c5dSJason M. Bills { 1603de703c5dSJason M. Bills continue; 1604de703c5dSJason M. Bills } 1605de703c5dSJason M. Bills 1606b2ba3072SPatrick Williams logEntryArray.emplace_back(std::move(bmcLogEntry)); 1607c4bf6374SJason M. Bills } 160895820184SJason M. Bills } 1609c4bf6374SJason M. Bills asyncResp->res.jsonValue["Members@odata.count"] = entryCount; 16103648c8beSEd Tanous if (skip + top < entryCount) 1611c4bf6374SJason M. Bills { 1612599b9af3SAlexander Hansen asyncResp->res.jsonValue["Members@odata.nextLink"] = 1613599b9af3SAlexander Hansen boost::urls::format( 1614253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/EventLog/Entries?$skip={}", 1615253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(skip + top)); 1616c4bf6374SJason M. Bills } 1617897967deSJason M. Bills } 1618897967deSJason M. Bills 1619599b9af3SAlexander Hansen inline void requestRoutesJournalEventLogEntryCollection(App& app) 1620897967deSJason M. Bills { 1621599b9af3SAlexander Hansen BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/") 1622599b9af3SAlexander Hansen .privileges(redfish::privileges::getLogEntryCollection) 1623599b9af3SAlexander Hansen .methods(boost::beast::http::verb::get)(std::bind_front( 1624599b9af3SAlexander Hansen handleSystemsLogServiceEventLogLogEntryCollection, std::ref(app))); 1625599b9af3SAlexander Hansen } 1626599b9af3SAlexander Hansen 1627599b9af3SAlexander Hansen inline void handleSystemsLogServiceEventLogEntriesGet( 1628599b9af3SAlexander Hansen App& app, const crow::Request& req, 16297e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1630599b9af3SAlexander Hansen const std::string& systemName, const std::string& param) 1631599b9af3SAlexander Hansen { 16323ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 163345ca1b86SEd Tanous { 163445ca1b86SEd Tanous return; 163545ca1b86SEd Tanous } 163625b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 16377f3e84a1SEd Tanous { 16387f3e84a1SEd Tanous // Option currently returns no systems. TBD 16397f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 16407f3e84a1SEd Tanous systemName); 16417f3e84a1SEd Tanous return; 16427f3e84a1SEd Tanous } 164322d268cbSEd Tanous 1644253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 164522d268cbSEd Tanous { 164622d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 164722d268cbSEd Tanous systemName); 164822d268cbSEd Tanous return; 164922d268cbSEd Tanous } 165022d268cbSEd Tanous 16517e860f15SJohn Edward Broadbent const std::string& targetID = param; 16528d1b46d7Szhanghch05 16537e860f15SJohn Edward Broadbent // Go through the log files and check the unique ID for each 16547e860f15SJohn Edward Broadbent // entry to find the target entry 1655897967deSJason M. Bills std::vector<std::filesystem::path> redfishLogFiles; 1656897967deSJason M. Bills getRedfishLogFiles(redfishLogFiles); 1657897967deSJason M. Bills std::string logEntry; 1658897967deSJason M. Bills 16597e860f15SJohn Edward Broadbent // Oldest logs are in the last file, so start there and loop 16607e860f15SJohn Edward Broadbent // backwards 1661599b9af3SAlexander Hansen for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend(); it++) 1662897967deSJason M. Bills { 1663897967deSJason M. Bills std::ifstream logStream(*it); 1664897967deSJason M. Bills if (!logStream.is_open()) 1665897967deSJason M. Bills { 1666897967deSJason M. Bills continue; 1667897967deSJason M. Bills } 1668897967deSJason M. Bills 1669897967deSJason M. Bills // Reset the unique ID on the first entry 1670897967deSJason M. Bills bool firstEntry = true; 1671897967deSJason M. Bills while (std::getline(logStream, logEntry)) 1672897967deSJason M. Bills { 1673897967deSJason M. Bills std::string idStr; 1674897967deSJason M. Bills if (!getUniqueEntryID(logEntry, idStr, firstEntry)) 1675897967deSJason M. Bills { 1676897967deSJason M. Bills continue; 1677897967deSJason M. Bills } 1678897967deSJason M. Bills firstEntry = false; 1679897967deSJason M. Bills 1680897967deSJason M. Bills if (idStr == targetID) 1681897967deSJason M. Bills { 1682de703c5dSJason M. Bills nlohmann::json::object_t bmcLogEntry; 1683bd79bce8SPatrick Williams LogParseError status = 1684bd79bce8SPatrick Williams fillEventLogEntryJson(idStr, logEntry, bmcLogEntry); 1685ac992cdeSJason M. Bills if (status != LogParseError::success) 1686897967deSJason M. Bills { 1687897967deSJason M. Bills messages::internalError(asyncResp->res); 1688897967deSJason M. Bills return; 1689897967deSJason M. Bills } 1690d405bb51SJason M. Bills asyncResp->res.jsonValue.update(bmcLogEntry); 1691897967deSJason M. Bills return; 1692897967deSJason M. Bills } 1693897967deSJason M. Bills } 1694897967deSJason M. Bills } 1695897967deSJason M. Bills // Requested ID was not found 16969db4ba25SJiaqing Zhao messages::resourceNotFound(asyncResp->res, "LogEntry", targetID); 1697599b9af3SAlexander Hansen } 1698599b9af3SAlexander Hansen 1699599b9af3SAlexander Hansen inline void requestRoutesJournalEventLogEntry(App& app) 1700599b9af3SAlexander Hansen { 1701599b9af3SAlexander Hansen BMCWEB_ROUTE( 1702599b9af3SAlexander Hansen app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/") 1703599b9af3SAlexander Hansen .privileges(redfish::privileges::getLogEntry) 1704599b9af3SAlexander Hansen .methods(boost::beast::http::verb::get)(std::bind_front( 1705599b9af3SAlexander Hansen handleSystemsLogServiceEventLogEntriesGet, std::ref(app))); 1706599b9af3SAlexander Hansen } 1707599b9af3SAlexander Hansen 1708599b9af3SAlexander Hansen inline void dBusEventLogEntryCollection( 1709599b9af3SAlexander Hansen const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1710599b9af3SAlexander Hansen { 1711599b9af3SAlexander Hansen // Collections don't include the static data added by SubRoute 1712599b9af3SAlexander Hansen // because it has a duplicate entry for members 1713599b9af3SAlexander Hansen asyncResp->res.jsonValue["@odata.type"] = 1714599b9af3SAlexander Hansen "#LogEntryCollection.LogEntryCollection"; 1715599b9af3SAlexander Hansen asyncResp->res.jsonValue["@odata.id"] = 1716599b9af3SAlexander Hansen std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries", 1717599b9af3SAlexander Hansen BMCWEB_REDFISH_SYSTEM_URI_NAME); 1718599b9af3SAlexander Hansen asyncResp->res.jsonValue["Name"] = "System Event Log Entries"; 1719599b9af3SAlexander Hansen asyncResp->res.jsonValue["Description"] = 1720599b9af3SAlexander Hansen "Collection of System Event Log Entries"; 1721599b9af3SAlexander Hansen 1722599b9af3SAlexander Hansen // DBus implementation of EventLog/Entries 1723599b9af3SAlexander Hansen // Make call to Logging Service to find all log entry objects 1724599b9af3SAlexander Hansen sdbusplus::message::object_path path("/xyz/openbmc_project/logging"); 1725599b9af3SAlexander Hansen dbus::utility::getManagedObjects( 1726599b9af3SAlexander Hansen "xyz.openbmc_project.Logging", path, 1727599b9af3SAlexander Hansen [asyncResp](const boost::system::error_code& ec, 1728599b9af3SAlexander Hansen const dbus::utility::ManagedObjectType& resp) { 1729b729096dSEd Tanous afterLogEntriesGetManagedObjects(asyncResp, ec, resp); 17307e860f15SJohn Edward Broadbent }); 173108a4e4b5SAnthony Wilson } 173208a4e4b5SAnthony Wilson 17337e860f15SJohn Edward Broadbent inline void requestRoutesDBusEventLogEntryCollection(App& app) 173408a4e4b5SAnthony Wilson { 173522d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/") 1736ed398213SEd Tanous .privileges(redfish::privileges::getLogEntryCollection) 1737002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 1738002d39b4SEd Tanous [&app](const crow::Request& req, 173922d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 174022d268cbSEd Tanous const std::string& systemName) { 17413ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 174245ca1b86SEd Tanous { 174345ca1b86SEd Tanous return; 174445ca1b86SEd Tanous } 174525b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 17467f3e84a1SEd Tanous { 17477f3e84a1SEd Tanous // Option currently returns no systems. TBD 17487f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 17497f3e84a1SEd Tanous systemName); 17507f3e84a1SEd Tanous return; 17517f3e84a1SEd Tanous } 1752253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 175322d268cbSEd Tanous { 175422d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 175522d268cbSEd Tanous systemName); 175622d268cbSEd Tanous return; 175722d268cbSEd Tanous } 1758599b9af3SAlexander Hansen dBusEventLogEntryCollection(asyncResp); 1759599b9af3SAlexander Hansen }); 1760599b9af3SAlexander Hansen } 176122d268cbSEd Tanous 1762bd79bce8SPatrick Williams inline void dBusEventLogEntryGet( 1763bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID) 1764599b9af3SAlexander Hansen { 1765599b9af3SAlexander Hansen dbus::utility::escapePathForDbus(entryID); 176608a4e4b5SAnthony Wilson 1767cb92c03bSAndrew Geissler // DBus implementation of EventLog/Entries 1768cb92c03bSAndrew Geissler // Make call to Logging Service to find all log entry objects 1769599b9af3SAlexander Hansen sdbusplus::asio::getAllProperties( 1770599b9af3SAlexander Hansen *crow::connections::systemBus, "xyz.openbmc_project.Logging", 1771599b9af3SAlexander Hansen "/xyz/openbmc_project/logging/entry/" + entryID, "", 1772599b9af3SAlexander Hansen [asyncResp, entryID](const boost::system::error_code& ec, 1773599b9af3SAlexander Hansen const dbus::utility::DBusPropertiesMap& resp) { 1774599b9af3SAlexander Hansen if (ec.value() == EBADR) 1775599b9af3SAlexander Hansen { 1776599b9af3SAlexander Hansen messages::resourceNotFound(asyncResp->res, "EventLogEntry", 1777599b9af3SAlexander Hansen entryID); 1778599b9af3SAlexander Hansen return; 1779599b9af3SAlexander Hansen } 1780cb92c03bSAndrew Geissler if (ec) 1781cb92c03bSAndrew Geissler { 1782bd79bce8SPatrick Williams BMCWEB_LOG_ERROR( 1783bd79bce8SPatrick Williams "EventLogEntry (DBus) resp_handler got error {}", ec); 1784cb92c03bSAndrew Geissler messages::internalError(asyncResp->res); 1785cb92c03bSAndrew Geissler return; 1786cb92c03bSAndrew Geissler } 17879017faf2SAbhishek Patel 1788898f2aa2SEd Tanous fillEventLogLogEntryFromPropertyMap(asyncResp, resp, 1789898f2aa2SEd Tanous asyncResp->res.jsonValue); 1790599b9af3SAlexander Hansen }); 17917e860f15SJohn Edward Broadbent } 1792599b9af3SAlexander Hansen 1793599b9af3SAlexander Hansen inline void 1794599b9af3SAlexander Hansen dBusEventLogEntryPatch(const crow::Request& req, 1795599b9af3SAlexander Hansen const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1796599b9af3SAlexander Hansen const std::string& entryId) 1797599b9af3SAlexander Hansen { 1798599b9af3SAlexander Hansen std::optional<bool> resolved; 1799599b9af3SAlexander Hansen 1800599b9af3SAlexander Hansen if (!json_util::readJsonPatch(req, asyncResp->res, "Resolved", resolved)) 1801599b9af3SAlexander Hansen { 1802599b9af3SAlexander Hansen return; 1803599b9af3SAlexander Hansen } 1804599b9af3SAlexander Hansen BMCWEB_LOG_DEBUG("Set Resolved"); 1805599b9af3SAlexander Hansen 1806599b9af3SAlexander Hansen setDbusProperty(asyncResp, "Resolved", "xyz.openbmc_project.Logging", 1807599b9af3SAlexander Hansen "/xyz/openbmc_project/logging/entry/" + entryId, 1808599b9af3SAlexander Hansen "xyz.openbmc_project.Logging.Entry", "Resolved", 1809599b9af3SAlexander Hansen resolved.value_or(false)); 1810599b9af3SAlexander Hansen } 1811599b9af3SAlexander Hansen 1812bd79bce8SPatrick Williams inline void dBusEventLogEntryDelete( 1813bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID) 1814599b9af3SAlexander Hansen { 1815599b9af3SAlexander Hansen BMCWEB_LOG_DEBUG("Do delete single event entries."); 1816599b9af3SAlexander Hansen 1817599b9af3SAlexander Hansen dbus::utility::escapePathForDbus(entryID); 1818599b9af3SAlexander Hansen 1819599b9af3SAlexander Hansen // Process response from Logging service. 1820599b9af3SAlexander Hansen auto respHandler = [asyncResp, 1821599b9af3SAlexander Hansen entryID](const boost::system::error_code& ec) { 1822599b9af3SAlexander Hansen BMCWEB_LOG_DEBUG("EventLogEntry (DBus) doDelete callback: Done"); 1823599b9af3SAlexander Hansen if (ec) 1824599b9af3SAlexander Hansen { 1825599b9af3SAlexander Hansen if (ec.value() == EBADR) 1826599b9af3SAlexander Hansen { 1827599b9af3SAlexander Hansen messages::resourceNotFound(asyncResp->res, "LogEntry", entryID); 1828599b9af3SAlexander Hansen return; 1829599b9af3SAlexander Hansen } 1830599b9af3SAlexander Hansen // TODO Handle for specific error code 1831599b9af3SAlexander Hansen BMCWEB_LOG_ERROR( 1832599b9af3SAlexander Hansen "EventLogEntry (DBus) doDelete respHandler got error {}", ec); 1833599b9af3SAlexander Hansen asyncResp->res.result( 1834599b9af3SAlexander Hansen boost::beast::http::status::internal_server_error); 1835599b9af3SAlexander Hansen return; 1836599b9af3SAlexander Hansen } 1837599b9af3SAlexander Hansen 1838599b9af3SAlexander Hansen asyncResp->res.result(boost::beast::http::status::ok); 1839599b9af3SAlexander Hansen }; 1840599b9af3SAlexander Hansen 1841599b9af3SAlexander Hansen // Make call to Logging service to request Delete Log 1842599b9af3SAlexander Hansen crow::connections::systemBus->async_method_call( 1843599b9af3SAlexander Hansen respHandler, "xyz.openbmc_project.Logging", 1844599b9af3SAlexander Hansen "/xyz/openbmc_project/logging/entry/" + entryID, 1845599b9af3SAlexander Hansen "xyz.openbmc_project.Object.Delete", "Delete"); 18467e860f15SJohn Edward Broadbent } 18477e860f15SJohn Edward Broadbent 18487e860f15SJohn Edward Broadbent inline void requestRoutesDBusEventLogEntry(App& app) 18497e860f15SJohn Edward Broadbent { 18507e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 185122d268cbSEd Tanous app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/") 1852ed398213SEd Tanous .privileges(redfish::privileges::getLogEntry) 1853002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 1854002d39b4SEd Tanous [&app](const crow::Request& req, 18557e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1856898f2aa2SEd Tanous const std::string& systemName, const std::string& entryId) { 18573ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 18587e860f15SJohn Edward Broadbent { 185945ca1b86SEd Tanous return; 186045ca1b86SEd Tanous } 186125b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 18627f3e84a1SEd Tanous { 18637f3e84a1SEd Tanous // Option currently returns no systems. TBD 18647f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 18657f3e84a1SEd Tanous systemName); 18667f3e84a1SEd Tanous return; 18677f3e84a1SEd Tanous } 1868253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 186922d268cbSEd Tanous { 187022d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 187122d268cbSEd Tanous systemName); 187222d268cbSEd Tanous return; 187322d268cbSEd Tanous } 187422d268cbSEd Tanous 1875898f2aa2SEd Tanous dBusEventLogEntryGet(asyncResp, entryId); 18767e860f15SJohn Edward Broadbent }); 1877336e96c6SChicago Duan 18787e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 187922d268cbSEd Tanous app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/") 1880ed398213SEd Tanous .privileges(redfish::privileges::patchLogEntry) 18817e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::patch)( 188245ca1b86SEd Tanous [&app](const crow::Request& req, 18837e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 188422d268cbSEd Tanous const std::string& systemName, const std::string& entryId) { 18853ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 188645ca1b86SEd Tanous { 188745ca1b86SEd Tanous return; 188845ca1b86SEd Tanous } 188925b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 18907f3e84a1SEd Tanous { 18917f3e84a1SEd Tanous // Option currently returns no systems. TBD 18927f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 18937f3e84a1SEd Tanous systemName); 18947f3e84a1SEd Tanous return; 18957f3e84a1SEd Tanous } 1896253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 189722d268cbSEd Tanous { 189822d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 189922d268cbSEd Tanous systemName); 190022d268cbSEd Tanous return; 190122d268cbSEd Tanous } 190275710de2SXiaochao Ma 1903599b9af3SAlexander Hansen dBusEventLogEntryPatch(req, asyncResp, entryId); 19047e860f15SJohn Edward Broadbent }); 190575710de2SXiaochao Ma 19067e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 190722d268cbSEd Tanous app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/") 1908ed398213SEd Tanous .privileges(redfish::privileges::deleteLogEntry) 1909ed398213SEd Tanous 1910002d39b4SEd Tanous .methods(boost::beast::http::verb::delete_)( 1911002d39b4SEd Tanous [&app](const crow::Request& req, 1912002d39b4SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 191322d268cbSEd Tanous const std::string& systemName, const std::string& param) { 19143ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 1915336e96c6SChicago Duan { 191645ca1b86SEd Tanous return; 191745ca1b86SEd Tanous } 191825b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 19197f3e84a1SEd Tanous { 19207f3e84a1SEd Tanous // Option currently returns no systems. TBD 19217f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 19227f3e84a1SEd Tanous systemName); 19237f3e84a1SEd Tanous return; 19247f3e84a1SEd Tanous } 1925253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 192622d268cbSEd Tanous { 192722d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 192822d268cbSEd Tanous systemName); 192922d268cbSEd Tanous return; 193022d268cbSEd Tanous } 1931599b9af3SAlexander Hansen dBusEventLogEntryDelete(asyncResp, param); 19327e860f15SJohn Edward Broadbent }); 1933400fd1fbSAdriana Kobylak } 1934400fd1fbSAdriana Kobylak 1935b7028ebfSSpencer Ku constexpr const char* hostLoggerFolderPath = "/var/log/console"; 1936b7028ebfSSpencer Ku 1937b7028ebfSSpencer Ku inline bool 1938b7028ebfSSpencer Ku getHostLoggerFiles(const std::string& hostLoggerFilePath, 1939b7028ebfSSpencer Ku std::vector<std::filesystem::path>& hostLoggerFiles) 1940b7028ebfSSpencer Ku { 1941b7028ebfSSpencer Ku std::error_code ec; 1942b7028ebfSSpencer Ku std::filesystem::directory_iterator logPath(hostLoggerFilePath, ec); 1943b7028ebfSSpencer Ku if (ec) 1944b7028ebfSSpencer Ku { 1945bf2ddedeSCarson Labrado BMCWEB_LOG_WARNING("{}", ec.message()); 1946b7028ebfSSpencer Ku return false; 1947b7028ebfSSpencer Ku } 1948b7028ebfSSpencer Ku for (const std::filesystem::directory_entry& it : logPath) 1949b7028ebfSSpencer Ku { 1950b7028ebfSSpencer Ku std::string filename = it.path().filename(); 1951b7028ebfSSpencer Ku // Prefix of each log files is "log". Find the file and save the 1952b7028ebfSSpencer Ku // path 195311ba3979SEd Tanous if (filename.starts_with("log")) 1954b7028ebfSSpencer Ku { 1955b7028ebfSSpencer Ku hostLoggerFiles.emplace_back(it.path()); 1956b7028ebfSSpencer Ku } 1957b7028ebfSSpencer Ku } 1958b7028ebfSSpencer Ku // As the log files rotate, they are appended with a ".#" that is higher for 1959b7028ebfSSpencer Ku // the older logs. Since we start from oldest logs, sort the name in 1960b7028ebfSSpencer Ku // descending order. 1961b7028ebfSSpencer Ku std::sort(hostLoggerFiles.rbegin(), hostLoggerFiles.rend(), 1962b7028ebfSSpencer Ku AlphanumLess<std::string>()); 1963b7028ebfSSpencer Ku 1964b7028ebfSSpencer Ku return true; 1965b7028ebfSSpencer Ku } 1966b7028ebfSSpencer Ku 196702cad96eSEd Tanous inline bool getHostLoggerEntries( 196802cad96eSEd Tanous const std::vector<std::filesystem::path>& hostLoggerFiles, uint64_t skip, 196902cad96eSEd Tanous uint64_t top, std::vector<std::string>& logEntries, size_t& logCount) 1970b7028ebfSSpencer Ku { 1971b7028ebfSSpencer Ku GzFileReader logFile; 1972b7028ebfSSpencer Ku 1973b7028ebfSSpencer Ku // Go though all log files and expose host logs. 1974b7028ebfSSpencer Ku for (const std::filesystem::path& it : hostLoggerFiles) 1975b7028ebfSSpencer Ku { 1976b7028ebfSSpencer Ku if (!logFile.gzGetLines(it.string(), skip, top, logEntries, logCount)) 1977b7028ebfSSpencer Ku { 197862598e31SEd Tanous BMCWEB_LOG_ERROR("fail to expose host logs"); 1979b7028ebfSSpencer Ku return false; 1980b7028ebfSSpencer Ku } 1981b7028ebfSSpencer Ku } 1982b7028ebfSSpencer Ku // Get lastMessage from constructor by getter 1983b7028ebfSSpencer Ku std::string lastMessage = logFile.getLastMessage(); 1984b7028ebfSSpencer Ku if (!lastMessage.empty()) 1985b7028ebfSSpencer Ku { 1986b7028ebfSSpencer Ku logCount++; 1987b7028ebfSSpencer Ku if (logCount > skip && logCount <= (skip + top)) 1988b7028ebfSSpencer Ku { 1989b7028ebfSSpencer Ku logEntries.push_back(lastMessage); 1990b7028ebfSSpencer Ku } 1991b7028ebfSSpencer Ku } 1992b7028ebfSSpencer Ku return true; 1993b7028ebfSSpencer Ku } 1994b7028ebfSSpencer Ku 1995dd72e87bSClaire Weinan inline void handleBMCLogServicesCollectionGet( 1996fdd26906SClaire Weinan crow::App& app, const crow::Request& req, 1997253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1998253f11b8SEd Tanous const std::string& managerId) 19991da66f75SEd Tanous { 20003ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 200145ca1b86SEd Tanous { 200245ca1b86SEd Tanous return; 200345ca1b86SEd Tanous } 2004253f11b8SEd Tanous 2005253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2006253f11b8SEd Tanous { 2007253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2008253f11b8SEd Tanous return; 2009253f11b8SEd Tanous } 2010253f11b8SEd Tanous 20117e860f15SJohn Edward Broadbent // Collections don't include the static data added by SubRoute 20127e860f15SJohn Edward Broadbent // because it has a duplicate entry for members 2013e1f26343SJason M. Bills asyncResp->res.jsonValue["@odata.type"] = 20141da66f75SEd Tanous "#LogServiceCollection.LogServiceCollection"; 2015253f11b8SEd Tanous asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 2016253f11b8SEd Tanous "/redfish/v1/Managers/{}/LogServices", BMCWEB_REDFISH_MANAGER_URI_NAME); 2017002d39b4SEd Tanous asyncResp->res.jsonValue["Name"] = "Open BMC Log Services Collection"; 2018e1f26343SJason M. Bills asyncResp->res.jsonValue["Description"] = 20191da66f75SEd Tanous "Collection of LogServices for this Manager"; 2020002d39b4SEd Tanous nlohmann::json& logServiceArray = asyncResp->res.jsonValue["Members"]; 2021c4bf6374SJason M. Bills logServiceArray = nlohmann::json::array(); 2022fdd26906SClaire Weinan 202325b54dbaSEd Tanous if constexpr (BMCWEB_REDFISH_BMC_JOURNAL) 202425b54dbaSEd Tanous { 2025613dabeaSEd Tanous nlohmann::json::object_t journal; 2026253f11b8SEd Tanous journal["@odata.id"] = 2027253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}/LogServices/Journal", 2028253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 2029b2ba3072SPatrick Williams logServiceArray.emplace_back(std::move(journal)); 203025b54dbaSEd Tanous } 2031fdd26906SClaire Weinan 2032fdd26906SClaire Weinan asyncResp->res.jsonValue["Members@odata.count"] = logServiceArray.size(); 2033fdd26906SClaire Weinan 203425b54dbaSEd Tanous if constexpr (BMCWEB_REDFISH_DUMP_LOG) 203525b54dbaSEd Tanous { 203615912159SGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 20377a1dbc48SGeorge Liu "xyz.openbmc_project.Collection.DeleteAll"}; 20387a1dbc48SGeorge Liu dbus::utility::getSubTreePaths( 20397a1dbc48SGeorge Liu "/xyz/openbmc_project/dump", 0, interfaces, 204025b54dbaSEd Tanous [asyncResp](const boost::system::error_code& ec, 204125b54dbaSEd Tanous const dbus::utility::MapperGetSubTreePathsResponse& 204225b54dbaSEd Tanous subTreePaths) { 2043fdd26906SClaire Weinan if (ec) 2044fdd26906SClaire Weinan { 204562598e31SEd Tanous BMCWEB_LOG_ERROR( 204662598e31SEd Tanous "handleBMCLogServicesCollectionGet respHandler got error {}", 204762598e31SEd Tanous ec); 2048bd79bce8SPatrick Williams // Assume that getting an error simply means there are no 2049bd79bce8SPatrick Williams // dump LogServices. Return without adding any error 2050bd79bce8SPatrick Williams // response. 2051fdd26906SClaire Weinan return; 2052fdd26906SClaire Weinan } 2053fdd26906SClaire Weinan 2054fdd26906SClaire Weinan nlohmann::json& logServiceArrayLocal = 2055fdd26906SClaire Weinan asyncResp->res.jsonValue["Members"]; 2056fdd26906SClaire Weinan 2057fdd26906SClaire Weinan for (const std::string& path : subTreePaths) 2058fdd26906SClaire Weinan { 2059fdd26906SClaire Weinan if (path == "/xyz/openbmc_project/dump/bmc") 2060fdd26906SClaire Weinan { 2061613dabeaSEd Tanous nlohmann::json::object_t member; 2062253f11b8SEd Tanous member["@odata.id"] = boost::urls::format( 2063253f11b8SEd Tanous "/redfish/v1/Managers/{}/LogServices/Dump", 2064253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 2065b2ba3072SPatrick Williams logServiceArrayLocal.emplace_back(std::move(member)); 2066fdd26906SClaire Weinan } 2067fdd26906SClaire Weinan else if (path == "/xyz/openbmc_project/dump/faultlog") 2068fdd26906SClaire Weinan { 2069613dabeaSEd Tanous nlohmann::json::object_t member; 2070253f11b8SEd Tanous member["@odata.id"] = boost::urls::format( 2071253f11b8SEd Tanous "/redfish/v1/Managers/{}/LogServices/FaultLog", 2072253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 2073b2ba3072SPatrick Williams logServiceArrayLocal.emplace_back(std::move(member)); 2074fdd26906SClaire Weinan } 2075fdd26906SClaire Weinan } 2076fdd26906SClaire Weinan 2077e1f26343SJason M. Bills asyncResp->res.jsonValue["Members@odata.count"] = 2078fdd26906SClaire Weinan logServiceArrayLocal.size(); 20797a1dbc48SGeorge Liu }); 208025b54dbaSEd Tanous } 2081fdd26906SClaire Weinan } 2082fdd26906SClaire Weinan 2083fdd26906SClaire Weinan inline void requestRoutesBMCLogServiceCollection(App& app) 2084fdd26906SClaire Weinan { 2085253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/") 2086fdd26906SClaire Weinan .privileges(redfish::privileges::getLogServiceCollection) 2087fdd26906SClaire Weinan .methods(boost::beast::http::verb::get)( 2088dd72e87bSClaire Weinan std::bind_front(handleBMCLogServicesCollectionGet, std::ref(app))); 2089e1f26343SJason M. Bills } 2090e1f26343SJason M. Bills 2091fdd26906SClaire Weinan inline void 2092fdd26906SClaire Weinan getDumpServiceInfo(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2093fdd26906SClaire Weinan const std::string& dumpType) 2094c9bb6861Sraviteja-b { 2095fdd26906SClaire Weinan std::string dumpPath; 2096539d8c6bSEd Tanous log_service::OverWritePolicy overWritePolicy = 2097539d8c6bSEd Tanous log_service::OverWritePolicy::Invalid; 2098fdd26906SClaire Weinan bool collectDiagnosticDataSupported = false; 2099fdd26906SClaire Weinan 2100fdd26906SClaire Weinan if (dumpType == "BMC") 210145ca1b86SEd Tanous { 2102253f11b8SEd Tanous dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/Dump", 2103253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 2104539d8c6bSEd Tanous overWritePolicy = log_service::OverWritePolicy::WrapsWhenFull; 2105fdd26906SClaire Weinan collectDiagnosticDataSupported = true; 2106fdd26906SClaire Weinan } 2107fdd26906SClaire Weinan else if (dumpType == "FaultLog") 2108fdd26906SClaire Weinan { 2109253f11b8SEd Tanous dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/FaultLog", 2110253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 2111539d8c6bSEd Tanous overWritePolicy = log_service::OverWritePolicy::Unknown; 2112fdd26906SClaire Weinan collectDiagnosticDataSupported = false; 2113fdd26906SClaire Weinan } 2114fdd26906SClaire Weinan else if (dumpType == "System") 2115fdd26906SClaire Weinan { 2116253f11b8SEd Tanous dumpPath = std::format("/redfish/v1/Systems/{}/LogServices/Dump", 2117253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 2118539d8c6bSEd Tanous overWritePolicy = log_service::OverWritePolicy::WrapsWhenFull; 2119fdd26906SClaire Weinan collectDiagnosticDataSupported = true; 2120fdd26906SClaire Weinan } 2121fdd26906SClaire Weinan else 2122fdd26906SClaire Weinan { 212362598e31SEd Tanous BMCWEB_LOG_ERROR("getDumpServiceInfo() invalid dump type: {}", 212462598e31SEd Tanous dumpType); 2125fdd26906SClaire Weinan messages::internalError(asyncResp->res); 212645ca1b86SEd Tanous return; 212745ca1b86SEd Tanous } 2128fdd26906SClaire Weinan 2129fdd26906SClaire Weinan asyncResp->res.jsonValue["@odata.id"] = dumpPath; 2130fdd26906SClaire Weinan asyncResp->res.jsonValue["@odata.type"] = "#LogService.v1_2_0.LogService"; 2131c9bb6861Sraviteja-b asyncResp->res.jsonValue["Name"] = "Dump LogService"; 2132fdd26906SClaire Weinan asyncResp->res.jsonValue["Description"] = dumpType + " Dump LogService"; 2133fdd26906SClaire Weinan asyncResp->res.jsonValue["Id"] = std::filesystem::path(dumpPath).filename(); 2134539d8c6bSEd Tanous asyncResp->res.jsonValue["OverWritePolicy"] = overWritePolicy; 21357c8c4058STejas Patil 21367c8c4058STejas Patil std::pair<std::string, std::string> redfishDateTimeOffset = 21372b82937eSEd Tanous redfish::time_utils::getDateTimeOffsetNow(); 21380fda0f12SGeorge Liu asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first; 21397c8c4058STejas Patil asyncResp->res.jsonValue["DateTimeLocalOffset"] = 21407c8c4058STejas Patil redfishDateTimeOffset.second; 21417c8c4058STejas Patil 2142fdd26906SClaire Weinan asyncResp->res.jsonValue["Entries"]["@odata.id"] = dumpPath + "/Entries"; 2143fdd26906SClaire Weinan 2144fdd26906SClaire Weinan if (collectDiagnosticDataSupported) 2145fdd26906SClaire Weinan { 2146002d39b4SEd Tanous asyncResp->res.jsonValue["Actions"]["#LogService.CollectDiagnosticData"] 21471476687dSEd Tanous ["target"] = 2148fdd26906SClaire Weinan dumpPath + "/Actions/LogService.CollectDiagnosticData"; 2149fdd26906SClaire Weinan } 21500d946211SClaire Weinan 21510d946211SClaire Weinan constexpr std::array<std::string_view, 1> interfaces = {deleteAllInterface}; 21520d946211SClaire Weinan dbus::utility::getSubTreePaths( 21530d946211SClaire Weinan "/xyz/openbmc_project/dump", 0, interfaces, 21540d946211SClaire Weinan [asyncResp, dumpType, dumpPath]( 21550d946211SClaire Weinan const boost::system::error_code& ec, 21560d946211SClaire Weinan const dbus::utility::MapperGetSubTreePathsResponse& subTreePaths) { 21570d946211SClaire Weinan if (ec) 21580d946211SClaire Weinan { 2159bd79bce8SPatrick Williams BMCWEB_LOG_ERROR("getDumpServiceInfo respHandler got error {}", 2160bd79bce8SPatrick Williams ec); 21610d946211SClaire Weinan // Assume that getting an error simply means there are no dump 21620d946211SClaire Weinan // LogServices. Return without adding any error response. 21630d946211SClaire Weinan return; 21640d946211SClaire Weinan } 216518f8f608SEd Tanous std::string dbusDumpPath = getDumpPath(dumpType); 21660d946211SClaire Weinan for (const std::string& path : subTreePaths) 21670d946211SClaire Weinan { 21680d946211SClaire Weinan if (path == dbusDumpPath) 21690d946211SClaire Weinan { 2170bd79bce8SPatrick Williams asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"] 2171bd79bce8SPatrick Williams ["target"] = 21720d946211SClaire Weinan dumpPath + "/Actions/LogService.ClearLog"; 21730d946211SClaire Weinan break; 21740d946211SClaire Weinan } 21750d946211SClaire Weinan } 21760d946211SClaire Weinan }); 2177c9bb6861Sraviteja-b } 2178c9bb6861Sraviteja-b 2179fdd26906SClaire Weinan inline void handleLogServicesDumpServiceGet( 2180fdd26906SClaire Weinan crow::App& app, const std::string& dumpType, const crow::Request& req, 2181253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2182253f11b8SEd Tanous const std::string& managerId) 21837e860f15SJohn Edward Broadbent { 21843ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 218545ca1b86SEd Tanous { 218645ca1b86SEd Tanous return; 218745ca1b86SEd Tanous } 2188253f11b8SEd Tanous 2189253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2190253f11b8SEd Tanous { 2191253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2192253f11b8SEd Tanous return; 2193253f11b8SEd Tanous } 2194253f11b8SEd Tanous 2195fdd26906SClaire Weinan getDumpServiceInfo(asyncResp, dumpType); 2196fdd26906SClaire Weinan } 2197c9bb6861Sraviteja-b 219822d268cbSEd Tanous inline void handleLogServicesDumpServiceComputerSystemGet( 219922d268cbSEd Tanous crow::App& app, const crow::Request& req, 220022d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 220122d268cbSEd Tanous const std::string& chassisId) 220222d268cbSEd Tanous { 220322d268cbSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 220422d268cbSEd Tanous { 220522d268cbSEd Tanous return; 220622d268cbSEd Tanous } 2207253f11b8SEd Tanous if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME) 220822d268cbSEd Tanous { 220922d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId); 221022d268cbSEd Tanous return; 221122d268cbSEd Tanous } 221222d268cbSEd Tanous getDumpServiceInfo(asyncResp, "System"); 221322d268cbSEd Tanous } 221422d268cbSEd Tanous 2215fdd26906SClaire Weinan inline void handleLogServicesDumpEntriesCollectionGet( 2216fdd26906SClaire Weinan crow::App& app, const std::string& dumpType, const crow::Request& req, 2217253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2218253f11b8SEd Tanous const std::string& managerId) 2219fdd26906SClaire Weinan { 2220fdd26906SClaire Weinan if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2221fdd26906SClaire Weinan { 2222fdd26906SClaire Weinan return; 2223fdd26906SClaire Weinan } 2224253f11b8SEd Tanous 2225253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2226253f11b8SEd Tanous { 2227253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2228253f11b8SEd Tanous return; 2229253f11b8SEd Tanous } 2230fdd26906SClaire Weinan getDumpEntryCollection(asyncResp, dumpType); 2231fdd26906SClaire Weinan } 2232fdd26906SClaire Weinan 223322d268cbSEd Tanous inline void handleLogServicesDumpEntriesCollectionComputerSystemGet( 223422d268cbSEd Tanous crow::App& app, const crow::Request& req, 223522d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 223622d268cbSEd Tanous const std::string& chassisId) 223722d268cbSEd Tanous { 223822d268cbSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 223922d268cbSEd Tanous { 224022d268cbSEd Tanous return; 224122d268cbSEd Tanous } 2242253f11b8SEd Tanous if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME) 224322d268cbSEd Tanous { 224422d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId); 224522d268cbSEd Tanous return; 224622d268cbSEd Tanous } 224722d268cbSEd Tanous getDumpEntryCollection(asyncResp, "System"); 224822d268cbSEd Tanous } 224922d268cbSEd Tanous 2250fdd26906SClaire Weinan inline void handleLogServicesDumpEntryGet( 2251fdd26906SClaire Weinan crow::App& app, const std::string& dumpType, const crow::Request& req, 2252fdd26906SClaire Weinan const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2253253f11b8SEd Tanous const std::string& managerId, const std::string& dumpId) 2254fdd26906SClaire Weinan { 2255fdd26906SClaire Weinan if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2256fdd26906SClaire Weinan { 2257fdd26906SClaire Weinan return; 2258fdd26906SClaire Weinan } 2259253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2260253f11b8SEd Tanous { 2261253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2262253f11b8SEd Tanous return; 2263253f11b8SEd Tanous } 2264fdd26906SClaire Weinan getDumpEntryById(asyncResp, dumpId, dumpType); 2265fdd26906SClaire Weinan } 2266168d1b1aSCarson Labrado 226722d268cbSEd Tanous inline void handleLogServicesDumpEntryComputerSystemGet( 226822d268cbSEd Tanous crow::App& app, const crow::Request& req, 226922d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 227022d268cbSEd Tanous const std::string& chassisId, const std::string& dumpId) 227122d268cbSEd Tanous { 227222d268cbSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 227322d268cbSEd Tanous { 227422d268cbSEd Tanous return; 227522d268cbSEd Tanous } 2276253f11b8SEd Tanous if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME) 227722d268cbSEd Tanous { 227822d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId); 227922d268cbSEd Tanous return; 228022d268cbSEd Tanous } 228122d268cbSEd Tanous getDumpEntryById(asyncResp, dumpId, "System"); 228222d268cbSEd Tanous } 2283fdd26906SClaire Weinan 2284fdd26906SClaire Weinan inline void handleLogServicesDumpEntryDelete( 2285fdd26906SClaire Weinan crow::App& app, const std::string& dumpType, const crow::Request& req, 2286fdd26906SClaire Weinan const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2287253f11b8SEd Tanous const std::string& managerId, const std::string& dumpId) 2288fdd26906SClaire Weinan { 2289fdd26906SClaire Weinan if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2290fdd26906SClaire Weinan { 2291fdd26906SClaire Weinan return; 2292fdd26906SClaire Weinan } 2293253f11b8SEd Tanous 2294253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2295253f11b8SEd Tanous { 2296253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2297253f11b8SEd Tanous return; 2298253f11b8SEd Tanous } 2299fdd26906SClaire Weinan deleteDumpEntry(asyncResp, dumpId, dumpType); 2300fdd26906SClaire Weinan } 2301fdd26906SClaire Weinan 230222d268cbSEd Tanous inline void handleLogServicesDumpEntryComputerSystemDelete( 230322d268cbSEd Tanous crow::App& app, const crow::Request& req, 230422d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 230522d268cbSEd Tanous const std::string& chassisId, const std::string& dumpId) 230622d268cbSEd Tanous { 230722d268cbSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 230822d268cbSEd Tanous { 230922d268cbSEd Tanous return; 231022d268cbSEd Tanous } 2311253f11b8SEd Tanous if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME) 231222d268cbSEd Tanous { 231322d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId); 231422d268cbSEd Tanous return; 231522d268cbSEd Tanous } 231622d268cbSEd Tanous deleteDumpEntry(asyncResp, dumpId, "System"); 231722d268cbSEd Tanous } 231822d268cbSEd Tanous 2319168d1b1aSCarson Labrado inline void handleLogServicesDumpEntryDownloadGet( 2320168d1b1aSCarson Labrado crow::App& app, const std::string& dumpType, const crow::Request& req, 2321168d1b1aSCarson Labrado const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2322253f11b8SEd Tanous const std::string& managerId, const std::string& dumpId) 2323168d1b1aSCarson Labrado { 2324168d1b1aSCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2325168d1b1aSCarson Labrado { 2326168d1b1aSCarson Labrado return; 2327168d1b1aSCarson Labrado } 2328253f11b8SEd Tanous 2329253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2330253f11b8SEd Tanous { 2331253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2332253f11b8SEd Tanous return; 2333253f11b8SEd Tanous } 2334168d1b1aSCarson Labrado downloadDumpEntry(asyncResp, dumpId, dumpType); 2335168d1b1aSCarson Labrado } 2336168d1b1aSCarson Labrado 2337168d1b1aSCarson Labrado inline void handleDBusEventLogEntryDownloadGet( 2338168d1b1aSCarson Labrado crow::App& app, const std::string& dumpType, const crow::Request& req, 2339168d1b1aSCarson Labrado const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2340168d1b1aSCarson Labrado const std::string& systemName, const std::string& entryID) 2341168d1b1aSCarson Labrado { 2342168d1b1aSCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2343168d1b1aSCarson Labrado { 2344168d1b1aSCarson Labrado return; 2345168d1b1aSCarson Labrado } 2346168d1b1aSCarson Labrado if (!http_helpers::isContentTypeAllowed( 2347168d1b1aSCarson Labrado req.getHeaderValue("Accept"), 2348168d1b1aSCarson Labrado http_helpers::ContentType::OctetStream, true)) 2349168d1b1aSCarson Labrado { 2350168d1b1aSCarson Labrado asyncResp->res.result(boost::beast::http::status::bad_request); 2351168d1b1aSCarson Labrado return; 2352168d1b1aSCarson Labrado } 2353168d1b1aSCarson Labrado downloadEventLogEntry(asyncResp, systemName, entryID, dumpType); 2354168d1b1aSCarson Labrado } 2355168d1b1aSCarson Labrado 2356fdd26906SClaire Weinan inline void handleLogServicesDumpCollectDiagnosticDataPost( 2357fdd26906SClaire Weinan crow::App& app, const std::string& dumpType, const crow::Request& req, 2358253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2359253f11b8SEd Tanous const std::string& managerId) 2360fdd26906SClaire Weinan { 2361fdd26906SClaire Weinan if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2362fdd26906SClaire Weinan { 2363fdd26906SClaire Weinan return; 2364fdd26906SClaire Weinan } 2365253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2366253f11b8SEd Tanous { 2367253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2368253f11b8SEd Tanous return; 2369253f11b8SEd Tanous } 2370253f11b8SEd Tanous 2371fdd26906SClaire Weinan createDump(asyncResp, req, dumpType); 2372fdd26906SClaire Weinan } 2373fdd26906SClaire Weinan 237422d268cbSEd Tanous inline void handleLogServicesDumpCollectDiagnosticDataComputerSystemPost( 237522d268cbSEd Tanous crow::App& app, const crow::Request& req, 237622d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 23777f3e84a1SEd Tanous const std::string& systemName) 237822d268cbSEd Tanous { 237922d268cbSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 238022d268cbSEd Tanous { 238122d268cbSEd Tanous return; 238222d268cbSEd Tanous } 23837f3e84a1SEd Tanous 238425b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 238522d268cbSEd Tanous { 23867f3e84a1SEd Tanous // Option currently returns no systems. TBD 23877f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 23887f3e84a1SEd Tanous systemName); 23897f3e84a1SEd Tanous return; 23907f3e84a1SEd Tanous } 2391253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 23927f3e84a1SEd Tanous { 23937f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 23947f3e84a1SEd Tanous systemName); 239522d268cbSEd Tanous return; 239622d268cbSEd Tanous } 239722d268cbSEd Tanous createDump(asyncResp, req, "System"); 239822d268cbSEd Tanous } 239922d268cbSEd Tanous 2400fdd26906SClaire Weinan inline void handleLogServicesDumpClearLogPost( 2401fdd26906SClaire Weinan crow::App& app, const std::string& dumpType, const crow::Request& req, 2402253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2403253f11b8SEd Tanous const std::string& managerId) 2404fdd26906SClaire Weinan { 2405fdd26906SClaire Weinan if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2406fdd26906SClaire Weinan { 2407fdd26906SClaire Weinan return; 2408fdd26906SClaire Weinan } 2409253f11b8SEd Tanous 2410253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2411253f11b8SEd Tanous { 2412253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2413253f11b8SEd Tanous return; 2414253f11b8SEd Tanous } 2415fdd26906SClaire Weinan clearDump(asyncResp, dumpType); 2416fdd26906SClaire Weinan } 2417fdd26906SClaire Weinan 241822d268cbSEd Tanous inline void handleLogServicesDumpClearLogComputerSystemPost( 241922d268cbSEd Tanous crow::App& app, const crow::Request& req, 242022d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 24217f3e84a1SEd Tanous const std::string& systemName) 242222d268cbSEd Tanous { 242322d268cbSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 242422d268cbSEd Tanous { 242522d268cbSEd Tanous return; 242622d268cbSEd Tanous } 242725b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 242822d268cbSEd Tanous { 24297f3e84a1SEd Tanous // Option currently returns no systems. TBD 24307f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 24317f3e84a1SEd Tanous systemName); 24327f3e84a1SEd Tanous return; 24337f3e84a1SEd Tanous } 2434253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 24357f3e84a1SEd Tanous { 24367f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 24377f3e84a1SEd Tanous systemName); 243822d268cbSEd Tanous return; 243922d268cbSEd Tanous } 244022d268cbSEd Tanous clearDump(asyncResp, "System"); 244122d268cbSEd Tanous } 244222d268cbSEd Tanous 2443fdd26906SClaire Weinan inline void requestRoutesBMCDumpService(App& app) 2444fdd26906SClaire Weinan { 2445253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/Dump/") 2446fdd26906SClaire Weinan .privileges(redfish::privileges::getLogService) 2447fdd26906SClaire Weinan .methods(boost::beast::http::verb::get)(std::bind_front( 2448fdd26906SClaire Weinan handleLogServicesDumpServiceGet, std::ref(app), "BMC")); 2449fdd26906SClaire Weinan } 2450fdd26906SClaire Weinan 2451fdd26906SClaire Weinan inline void requestRoutesBMCDumpEntryCollection(App& app) 2452fdd26906SClaire Weinan { 2453253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/") 2454fdd26906SClaire Weinan .privileges(redfish::privileges::getLogEntryCollection) 2455fdd26906SClaire Weinan .methods(boost::beast::http::verb::get)(std::bind_front( 2456fdd26906SClaire Weinan handleLogServicesDumpEntriesCollectionGet, std::ref(app), "BMC")); 2457c9bb6861Sraviteja-b } 2458c9bb6861Sraviteja-b 24597e860f15SJohn Edward Broadbent inline void requestRoutesBMCDumpEntry(App& app) 2460c9bb6861Sraviteja-b { 24617e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 2462253f11b8SEd Tanous "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/") 2463ed398213SEd Tanous .privileges(redfish::privileges::getLogEntry) 2464fdd26906SClaire Weinan .methods(boost::beast::http::verb::get)(std::bind_front( 2465fdd26906SClaire Weinan handleLogServicesDumpEntryGet, std::ref(app), "BMC")); 2466fdd26906SClaire Weinan 24677e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 2468253f11b8SEd Tanous "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/") 2469ed398213SEd Tanous .privileges(redfish::privileges::deleteLogEntry) 2470fdd26906SClaire Weinan .methods(boost::beast::http::verb::delete_)(std::bind_front( 2471fdd26906SClaire Weinan handleLogServicesDumpEntryDelete, std::ref(app), "BMC")); 2472c9bb6861Sraviteja-b } 2473c9bb6861Sraviteja-b 2474168d1b1aSCarson Labrado inline void requestRoutesBMCDumpEntryDownload(App& app) 2475168d1b1aSCarson Labrado { 2476168d1b1aSCarson Labrado BMCWEB_ROUTE( 2477168d1b1aSCarson Labrado app, 2478253f11b8SEd Tanous "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/attachment/") 2479168d1b1aSCarson Labrado .privileges(redfish::privileges::getLogEntry) 2480168d1b1aSCarson Labrado .methods(boost::beast::http::verb::get)(std::bind_front( 2481168d1b1aSCarson Labrado handleLogServicesDumpEntryDownloadGet, std::ref(app), "BMC")); 2482168d1b1aSCarson Labrado } 2483168d1b1aSCarson Labrado 24847e860f15SJohn Edward Broadbent inline void requestRoutesBMCDumpCreate(App& app) 2485c9bb6861Sraviteja-b { 24860fda0f12SGeorge Liu BMCWEB_ROUTE( 24870fda0f12SGeorge Liu app, 2488253f11b8SEd Tanous "/redfish/v1/Managers/<str>/LogServices/Dump/Actions/LogService.CollectDiagnosticData/") 2489ed398213SEd Tanous .privileges(redfish::privileges::postLogService) 24907e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 2491fdd26906SClaire Weinan std::bind_front(handleLogServicesDumpCollectDiagnosticDataPost, 2492fdd26906SClaire Weinan std::ref(app), "BMC")); 2493a43be80fSAsmitha Karunanithi } 2494a43be80fSAsmitha Karunanithi 24957e860f15SJohn Edward Broadbent inline void requestRoutesBMCDumpClear(App& app) 249680319af1SAsmitha Karunanithi { 24970fda0f12SGeorge Liu BMCWEB_ROUTE( 24980fda0f12SGeorge Liu app, 2499253f11b8SEd Tanous "/redfish/v1/Managers/<str>/LogServices/Dump/Actions/LogService.ClearLog/") 2500ed398213SEd Tanous .privileges(redfish::privileges::postLogService) 2501fdd26906SClaire Weinan .methods(boost::beast::http::verb::post)(std::bind_front( 2502fdd26906SClaire Weinan handleLogServicesDumpClearLogPost, std::ref(app), "BMC")); 250345ca1b86SEd Tanous } 2504fdd26906SClaire Weinan 2505168d1b1aSCarson Labrado inline void requestRoutesDBusEventLogEntryDownload(App& app) 2506168d1b1aSCarson Labrado { 2507168d1b1aSCarson Labrado BMCWEB_ROUTE( 2508168d1b1aSCarson Labrado app, 25099e9d99daSRavi Teja "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/attachment/") 2510168d1b1aSCarson Labrado .privileges(redfish::privileges::getLogEntry) 2511168d1b1aSCarson Labrado .methods(boost::beast::http::verb::get)(std::bind_front( 2512168d1b1aSCarson Labrado handleDBusEventLogEntryDownloadGet, std::ref(app), "System")); 2513168d1b1aSCarson Labrado } 2514168d1b1aSCarson Labrado 2515fdd26906SClaire Weinan inline void requestRoutesFaultLogDumpService(App& app) 2516fdd26906SClaire Weinan { 2517253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/") 2518fdd26906SClaire Weinan .privileges(redfish::privileges::getLogService) 2519fdd26906SClaire Weinan .methods(boost::beast::http::verb::get)(std::bind_front( 2520fdd26906SClaire Weinan handleLogServicesDumpServiceGet, std::ref(app), "FaultLog")); 2521fdd26906SClaire Weinan } 2522fdd26906SClaire Weinan 2523fdd26906SClaire Weinan inline void requestRoutesFaultLogDumpEntryCollection(App& app) 2524fdd26906SClaire Weinan { 2525253f11b8SEd Tanous BMCWEB_ROUTE(app, 2526253f11b8SEd Tanous "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/") 2527fdd26906SClaire Weinan .privileges(redfish::privileges::getLogEntryCollection) 2528fdd26906SClaire Weinan .methods(boost::beast::http::verb::get)( 2529fdd26906SClaire Weinan std::bind_front(handleLogServicesDumpEntriesCollectionGet, 2530fdd26906SClaire Weinan std::ref(app), "FaultLog")); 2531fdd26906SClaire Weinan } 2532fdd26906SClaire Weinan 2533fdd26906SClaire Weinan inline void requestRoutesFaultLogDumpEntry(App& app) 2534fdd26906SClaire Weinan { 2535253f11b8SEd Tanous BMCWEB_ROUTE( 2536253f11b8SEd Tanous app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/<str>/") 2537fdd26906SClaire Weinan .privileges(redfish::privileges::getLogEntry) 2538fdd26906SClaire Weinan .methods(boost::beast::http::verb::get)(std::bind_front( 2539fdd26906SClaire Weinan handleLogServicesDumpEntryGet, std::ref(app), "FaultLog")); 2540fdd26906SClaire Weinan 2541253f11b8SEd Tanous BMCWEB_ROUTE( 2542253f11b8SEd Tanous app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/<str>/") 2543fdd26906SClaire Weinan .privileges(redfish::privileges::deleteLogEntry) 2544fdd26906SClaire Weinan .methods(boost::beast::http::verb::delete_)(std::bind_front( 2545fdd26906SClaire Weinan handleLogServicesDumpEntryDelete, std::ref(app), "FaultLog")); 2546fdd26906SClaire Weinan } 2547fdd26906SClaire Weinan 2548fdd26906SClaire Weinan inline void requestRoutesFaultLogDumpClear(App& app) 2549fdd26906SClaire Weinan { 2550fdd26906SClaire Weinan BMCWEB_ROUTE( 2551fdd26906SClaire Weinan app, 2552253f11b8SEd Tanous "/redfish/v1/Managers/<str>/LogServices/FaultLog/Actions/LogService.ClearLog/") 2553fdd26906SClaire Weinan .privileges(redfish::privileges::postLogService) 2554fdd26906SClaire Weinan .methods(boost::beast::http::verb::post)(std::bind_front( 2555fdd26906SClaire Weinan handleLogServicesDumpClearLogPost, std::ref(app), "FaultLog")); 25565cb1dd27SAsmitha Karunanithi } 25575cb1dd27SAsmitha Karunanithi 25587e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpService(App& app) 25595cb1dd27SAsmitha Karunanithi { 256022d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Dump/") 2561ed398213SEd Tanous .privileges(redfish::privileges::getLogService) 25626ab9ad54SClaire Weinan .methods(boost::beast::http::verb::get)(std::bind_front( 256322d268cbSEd Tanous handleLogServicesDumpServiceComputerSystemGet, std::ref(app))); 25645cb1dd27SAsmitha Karunanithi } 25655cb1dd27SAsmitha Karunanithi 25667e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpEntryCollection(App& app) 25677e860f15SJohn Edward Broadbent { 256822d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/") 2569ed398213SEd Tanous .privileges(redfish::privileges::getLogEntryCollection) 257022d268cbSEd Tanous .methods(boost::beast::http::verb::get)(std::bind_front( 257122d268cbSEd Tanous handleLogServicesDumpEntriesCollectionComputerSystemGet, 257222d268cbSEd Tanous std::ref(app))); 25735cb1dd27SAsmitha Karunanithi } 25745cb1dd27SAsmitha Karunanithi 25757e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpEntry(App& app) 25765cb1dd27SAsmitha Karunanithi { 25777e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 257822d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/<str>/") 2579ed398213SEd Tanous .privileges(redfish::privileges::getLogEntry) 25806ab9ad54SClaire Weinan .methods(boost::beast::http::verb::get)(std::bind_front( 258122d268cbSEd Tanous handleLogServicesDumpEntryComputerSystemGet, std::ref(app))); 25828d1b46d7Szhanghch05 25837e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 258422d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/<str>/") 2585ed398213SEd Tanous .privileges(redfish::privileges::deleteLogEntry) 25866ab9ad54SClaire Weinan .methods(boost::beast::http::verb::delete_)(std::bind_front( 258722d268cbSEd Tanous handleLogServicesDumpEntryComputerSystemDelete, std::ref(app))); 25885cb1dd27SAsmitha Karunanithi } 2589c9bb6861Sraviteja-b 25907e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpCreate(App& app) 2591c9bb6861Sraviteja-b { 25920fda0f12SGeorge Liu BMCWEB_ROUTE( 25930fda0f12SGeorge Liu app, 259422d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Dump/Actions/LogService.CollectDiagnosticData/") 2595ed398213SEd Tanous .privileges(redfish::privileges::postLogService) 259622d268cbSEd Tanous .methods(boost::beast::http::verb::post)(std::bind_front( 259722d268cbSEd Tanous handleLogServicesDumpCollectDiagnosticDataComputerSystemPost, 259822d268cbSEd Tanous std::ref(app))); 2599a43be80fSAsmitha Karunanithi } 2600a43be80fSAsmitha Karunanithi 26017e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpClear(App& app) 2602a43be80fSAsmitha Karunanithi { 26030fda0f12SGeorge Liu BMCWEB_ROUTE( 26040fda0f12SGeorge Liu app, 260522d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Dump/Actions/LogService.ClearLog/") 2606ed398213SEd Tanous .privileges(redfish::privileges::postLogService) 26076ab9ad54SClaire Weinan .methods(boost::beast::http::verb::post)(std::bind_front( 260822d268cbSEd Tanous handleLogServicesDumpClearLogComputerSystemPost, std::ref(app))); 2609013487e5Sraviteja-b } 2610013487e5Sraviteja-b 26117e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpService(App& app) 26121da66f75SEd Tanous { 26133946028dSAppaRao Puli // Note: Deviated from redfish privilege registry for GET & HEAD 26143946028dSAppaRao Puli // method for security reasons. 26151da66f75SEd Tanous /** 26161da66f75SEd Tanous * Functions triggers appropriate requests on DBus 26171da66f75SEd Tanous */ 261822d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Crashdump/") 2619ed398213SEd Tanous // This is incorrect, should be: 2620ed398213SEd Tanous //.privileges(redfish::privileges::getLogService) 2621432a890cSEd Tanous .privileges({{"ConfigureManager"}}) 2622bd79bce8SPatrick Williams .methods( 2623bd79bce8SPatrick Williams boost::beast::http::verb:: 2624bd79bce8SPatrick Williams get)([&app](const crow::Request& req, 262522d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 262622d268cbSEd Tanous const std::string& systemName) { 26273ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 262845ca1b86SEd Tanous { 262945ca1b86SEd Tanous return; 263045ca1b86SEd Tanous } 263125b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 26327f3e84a1SEd Tanous { 26337f3e84a1SEd Tanous // Option currently returns no systems. TBD 26347f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 26357f3e84a1SEd Tanous systemName); 26367f3e84a1SEd Tanous return; 26377f3e84a1SEd Tanous } 2638253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 263922d268cbSEd Tanous { 264022d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 264122d268cbSEd Tanous systemName); 264222d268cbSEd Tanous return; 264322d268cbSEd Tanous } 264422d268cbSEd Tanous 26457e860f15SJohn Edward Broadbent // Copy over the static data to include the entries added by 26467e860f15SJohn Edward Broadbent // SubRoute 26470f74e643SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 2648253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/Crashdump", 2649253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 2650e1f26343SJason M. Bills asyncResp->res.jsonValue["@odata.type"] = 26518e6c099aSJason M. Bills "#LogService.v1_2_0.LogService"; 26524f50ae4bSGunnar Mills asyncResp->res.jsonValue["Name"] = "Open BMC Oem Crashdump Service"; 26534f50ae4bSGunnar Mills asyncResp->res.jsonValue["Description"] = "Oem Crashdump Service"; 265415b89725SV-Sanjana asyncResp->res.jsonValue["Id"] = "Crashdump"; 2655539d8c6bSEd Tanous asyncResp->res.jsonValue["OverWritePolicy"] = 2656539d8c6bSEd Tanous log_service::OverWritePolicy::WrapsWhenFull; 2657e1f26343SJason M. Bills asyncResp->res.jsonValue["MaxNumberOfRecords"] = 3; 26587c8c4058STejas Patil 26597c8c4058STejas Patil std::pair<std::string, std::string> redfishDateTimeOffset = 26602b82937eSEd Tanous redfish::time_utils::getDateTimeOffsetNow(); 26617c8c4058STejas Patil asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first; 26627c8c4058STejas Patil asyncResp->res.jsonValue["DateTimeLocalOffset"] = 26637c8c4058STejas Patil redfishDateTimeOffset.second; 26647c8c4058STejas Patil 2665bd79bce8SPatrick Williams asyncResp->res.jsonValue["Entries"]["@odata.id"] = std::format( 2666bd79bce8SPatrick Williams "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries", 2667253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 2668253f11b8SEd Tanous asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"] 2669253f11b8SEd Tanous ["target"] = std::format( 2670253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/Crashdump/Actions/LogService.ClearLog", 2671253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 2672bd79bce8SPatrick Williams asyncResp->res 2673bd79bce8SPatrick Williams .jsonValue["Actions"]["#LogService.CollectDiagnosticData"] 2674253f11b8SEd Tanous ["target"] = std::format( 2675253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/Crashdump/Actions/LogService.CollectDiagnosticData", 2676253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 26777e860f15SJohn Edward Broadbent }); 26781da66f75SEd Tanous } 26791da66f75SEd Tanous 26807e860f15SJohn Edward Broadbent void inline requestRoutesCrashdumpClear(App& app) 26815b61b5e8SJason M. Bills { 26820fda0f12SGeorge Liu BMCWEB_ROUTE( 26830fda0f12SGeorge Liu app, 268422d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Crashdump/Actions/LogService.ClearLog/") 2685ed398213SEd Tanous // This is incorrect, should be: 2686ed398213SEd Tanous //.privileges(redfish::privileges::postLogService) 2687432a890cSEd Tanous .privileges({{"ConfigureComponents"}}) 26887e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 268945ca1b86SEd Tanous [&app](const crow::Request& req, 269022d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 269122d268cbSEd Tanous const std::string& systemName) { 26923ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 269345ca1b86SEd Tanous { 269445ca1b86SEd Tanous return; 269545ca1b86SEd Tanous } 269625b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 26977f3e84a1SEd Tanous { 26987f3e84a1SEd Tanous // Option currently returns no systems. TBD 26997f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 27007f3e84a1SEd Tanous systemName); 27017f3e84a1SEd Tanous return; 27027f3e84a1SEd Tanous } 2703253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 270422d268cbSEd Tanous { 270522d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 270622d268cbSEd Tanous systemName); 270722d268cbSEd Tanous return; 270822d268cbSEd Tanous } 27095b61b5e8SJason M. Bills crow::connections::systemBus->async_method_call( 27105e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec, 2711cb13a392SEd Tanous const std::string&) { 27125b61b5e8SJason M. Bills if (ec) 27135b61b5e8SJason M. Bills { 27145b61b5e8SJason M. Bills messages::internalError(asyncResp->res); 27155b61b5e8SJason M. Bills return; 27165b61b5e8SJason M. Bills } 27175b61b5e8SJason M. Bills messages::success(asyncResp->res); 27185b61b5e8SJason M. Bills }, 2719bd79bce8SPatrick Williams crashdumpObject, crashdumpPath, deleteAllInterface, 2720bd79bce8SPatrick Williams "DeleteAll"); 27217e860f15SJohn Edward Broadbent }); 27225b61b5e8SJason M. Bills } 27235b61b5e8SJason M. Bills 27244ff0f1f4SEd Tanous inline void 27258d1b46d7Szhanghch05 logCrashdumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 27268d1b46d7Szhanghch05 const std::string& logID, nlohmann::json& logEntryJson) 2727e855dd28SJason M. Bills { 2728043a0536SJohnathan Mantey auto getStoredLogCallback = 2729b9d36b47SEd Tanous [asyncResp, logID, 27305e7e2dc5SEd Tanous &logEntryJson](const boost::system::error_code& ec, 2731b9d36b47SEd Tanous const dbus::utility::DBusPropertiesMap& params) { 2732e855dd28SJason M. Bills if (ec) 2733e855dd28SJason M. Bills { 273462598e31SEd Tanous BMCWEB_LOG_DEBUG("failed to get log ec: {}", ec.message()); 27351ddcf01aSJason M. Bills if (ec.value() == 27361ddcf01aSJason M. Bills boost::system::linux_error::bad_request_descriptor) 27371ddcf01aSJason M. Bills { 2738bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "LogEntry", 2739bd79bce8SPatrick Williams logID); 27401ddcf01aSJason M. Bills } 27411ddcf01aSJason M. Bills else 27421ddcf01aSJason M. Bills { 2743e855dd28SJason M. Bills messages::internalError(asyncResp->res); 27441ddcf01aSJason M. Bills } 2745e855dd28SJason M. Bills return; 2746e855dd28SJason M. Bills } 2747043a0536SJohnathan Mantey 2748043a0536SJohnathan Mantey std::string timestamp{}; 2749043a0536SJohnathan Mantey std::string filename{}; 2750043a0536SJohnathan Mantey std::string logfile{}; 27512c70f800SEd Tanous parseCrashdumpParameters(params, filename, timestamp, logfile); 2752043a0536SJohnathan Mantey 2753043a0536SJohnathan Mantey if (filename.empty() || timestamp.empty()) 2754e855dd28SJason M. Bills { 27559db4ba25SJiaqing Zhao messages::resourceNotFound(asyncResp->res, "LogEntry", logID); 2756e855dd28SJason M. Bills return; 2757e855dd28SJason M. Bills } 2758e855dd28SJason M. Bills 2759043a0536SJohnathan Mantey std::string crashdumpURI = 2760bd79bce8SPatrick Williams std::format( 2761bd79bce8SPatrick Williams "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries/", 2762253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME) + 2763043a0536SJohnathan Mantey logID + "/" + filename; 276484afc48bSJason M. Bills nlohmann::json::object_t logEntry; 27659c11a172SVijay Lobo logEntry["@odata.type"] = "#LogEntry.v1_9_0.LogEntry"; 2766ef4c65b7SEd Tanous logEntry["@odata.id"] = boost::urls::format( 2767253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries/{}", 2768253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, logID); 276984afc48bSJason M. Bills logEntry["Name"] = "CPU Crashdump"; 277084afc48bSJason M. Bills logEntry["Id"] = logID; 2771539d8c6bSEd Tanous logEntry["EntryType"] = log_entry::LogEntryType::Oem; 277284afc48bSJason M. Bills logEntry["AdditionalDataURI"] = std::move(crashdumpURI); 277384afc48bSJason M. Bills logEntry["DiagnosticDataType"] = "OEM"; 277484afc48bSJason M. Bills logEntry["OEMDiagnosticDataType"] = "PECICrashdump"; 277584afc48bSJason M. Bills logEntry["Created"] = std::move(timestamp); 27762b20ef6eSJason M. Bills 27772b20ef6eSJason M. Bills // If logEntryJson references an array of LogEntry resources 27782b20ef6eSJason M. Bills // ('Members' list), then push this as a new entry, otherwise set it 27792b20ef6eSJason M. Bills // directly 27802b20ef6eSJason M. Bills if (logEntryJson.is_array()) 27812b20ef6eSJason M. Bills { 27822b20ef6eSJason M. Bills logEntryJson.push_back(logEntry); 27832b20ef6eSJason M. Bills asyncResp->res.jsonValue["Members@odata.count"] = 27842b20ef6eSJason M. Bills logEntryJson.size(); 27852b20ef6eSJason M. Bills } 27862b20ef6eSJason M. Bills else 27872b20ef6eSJason M. Bills { 2788d405bb51SJason M. Bills logEntryJson.update(logEntry); 27892b20ef6eSJason M. Bills } 2790e855dd28SJason M. Bills }; 2791d1bde9e5SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 2792d1bde9e5SKrzysztof Grobelny *crow::connections::systemBus, crashdumpObject, 2793d1bde9e5SKrzysztof Grobelny crashdumpPath + std::string("/") + logID, crashdumpInterface, 2794d1bde9e5SKrzysztof Grobelny std::move(getStoredLogCallback)); 2795e855dd28SJason M. Bills } 2796e855dd28SJason M. Bills 27977e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpEntryCollection(App& app) 27981da66f75SEd Tanous { 27993946028dSAppaRao Puli // Note: Deviated from redfish privilege registry for GET & HEAD 28003946028dSAppaRao Puli // method for security reasons. 28011da66f75SEd Tanous /** 28021da66f75SEd Tanous * Functions triggers appropriate requests on DBus 28031da66f75SEd Tanous */ 28047e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 280522d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/") 2806ed398213SEd Tanous // This is incorrect, should be. 2807ed398213SEd Tanous //.privileges(redfish::privileges::postLogEntryCollection) 2808432a890cSEd Tanous .privileges({{"ConfigureComponents"}}) 2809bd79bce8SPatrick Williams .methods( 2810bd79bce8SPatrick Williams boost::beast::http::verb:: 2811bd79bce8SPatrick Williams get)([&app](const crow::Request& req, 281222d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 281322d268cbSEd Tanous const std::string& systemName) { 28143ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 281545ca1b86SEd Tanous { 281645ca1b86SEd Tanous return; 281745ca1b86SEd Tanous } 281825b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 28197f3e84a1SEd Tanous { 28207f3e84a1SEd Tanous // Option currently returns no systems. TBD 28217f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 28227f3e84a1SEd Tanous systemName); 28237f3e84a1SEd Tanous return; 28247f3e84a1SEd Tanous } 2825253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 282622d268cbSEd Tanous { 282722d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 282822d268cbSEd Tanous systemName); 282922d268cbSEd Tanous return; 283022d268cbSEd Tanous } 283122d268cbSEd Tanous 28327a1dbc48SGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 28337a1dbc48SGeorge Liu crashdumpInterface}; 28347a1dbc48SGeorge Liu dbus::utility::getSubTreePaths( 28357a1dbc48SGeorge Liu "/", 0, interfaces, 28367a1dbc48SGeorge Liu [asyncResp](const boost::system::error_code& ec, 28372b20ef6eSJason M. Bills const std::vector<std::string>& resp) { 28381da66f75SEd Tanous if (ec) 28391da66f75SEd Tanous { 28401da66f75SEd Tanous if (ec.value() != 28411da66f75SEd Tanous boost::system::errc::no_such_file_or_directory) 28421da66f75SEd Tanous { 284362598e31SEd Tanous BMCWEB_LOG_DEBUG("failed to get entries ec: {}", 284462598e31SEd Tanous ec.message()); 2845f12894f8SJason M. Bills messages::internalError(asyncResp->res); 28461da66f75SEd Tanous return; 28471da66f75SEd Tanous } 28481da66f75SEd Tanous } 2849e1f26343SJason M. Bills asyncResp->res.jsonValue["@odata.type"] = 28501da66f75SEd Tanous "#LogEntryCollection.LogEntryCollection"; 2851253f11b8SEd Tanous asyncResp->res.jsonValue["@odata.id"] = std::format( 2852253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries", 2853253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 2854bd79bce8SPatrick Williams asyncResp->res.jsonValue["Name"] = 2855bd79bce8SPatrick Williams "Open BMC Crashdump Entries"; 2856e1f26343SJason M. Bills asyncResp->res.jsonValue["Description"] = 2857424c4176SJason M. Bills "Collection of Crashdump Entries"; 2858bd79bce8SPatrick Williams asyncResp->res.jsonValue["Members"] = 2859bd79bce8SPatrick Williams nlohmann::json::array(); 2860a2dd60a6SBrandon Kim asyncResp->res.jsonValue["Members@odata.count"] = 0; 28612b20ef6eSJason M. Bills 28622b20ef6eSJason M. Bills for (const std::string& path : resp) 28631da66f75SEd Tanous { 28642b20ef6eSJason M. Bills const sdbusplus::message::object_path objPath(path); 2865e855dd28SJason M. Bills // Get the log ID 28662b20ef6eSJason M. Bills std::string logID = objPath.filename(); 28672b20ef6eSJason M. Bills if (logID.empty()) 28681da66f75SEd Tanous { 2869e855dd28SJason M. Bills continue; 28701da66f75SEd Tanous } 2871e855dd28SJason M. Bills // Add the log entry to the array 28722b20ef6eSJason M. Bills logCrashdumpEntry(asyncResp, logID, 28732b20ef6eSJason M. Bills asyncResp->res.jsonValue["Members"]); 28741da66f75SEd Tanous } 28757a1dbc48SGeorge Liu }); 28767e860f15SJohn Edward Broadbent }); 28771da66f75SEd Tanous } 28781da66f75SEd Tanous 28797e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpEntry(App& app) 28801da66f75SEd Tanous { 28813946028dSAppaRao Puli // Note: Deviated from redfish privilege registry for GET & HEAD 28823946028dSAppaRao Puli // method for security reasons. 28831da66f75SEd Tanous 28847e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 288522d268cbSEd Tanous app, "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/<str>/") 2886ed398213SEd Tanous // this is incorrect, should be 2887ed398213SEd Tanous // .privileges(redfish::privileges::getLogEntry) 2888432a890cSEd Tanous .privileges({{"ConfigureComponents"}}) 28897e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 289045ca1b86SEd Tanous [&app](const crow::Request& req, 28917e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 289222d268cbSEd Tanous const std::string& systemName, const std::string& param) { 28933ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 289445ca1b86SEd Tanous { 289545ca1b86SEd Tanous return; 289645ca1b86SEd Tanous } 289725b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 28987f3e84a1SEd Tanous { 28997f3e84a1SEd Tanous // Option currently returns no systems. TBD 29007f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 29017f3e84a1SEd Tanous systemName); 29027f3e84a1SEd Tanous return; 29037f3e84a1SEd Tanous } 2904253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 290522d268cbSEd Tanous { 290622d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 290722d268cbSEd Tanous systemName); 290822d268cbSEd Tanous return; 290922d268cbSEd Tanous } 29107e860f15SJohn Edward Broadbent const std::string& logID = param; 2911e855dd28SJason M. Bills logCrashdumpEntry(asyncResp, logID, asyncResp->res.jsonValue); 29127e860f15SJohn Edward Broadbent }); 2913e855dd28SJason M. Bills } 2914e855dd28SJason M. Bills 29157e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpFile(App& app) 2916e855dd28SJason M. Bills { 29173946028dSAppaRao Puli // Note: Deviated from redfish privilege registry for GET & HEAD 29183946028dSAppaRao Puli // method for security reasons. 29197e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 29207e860f15SJohn Edward Broadbent app, 292122d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/<str>/<str>/") 2922ed398213SEd Tanous .privileges(redfish::privileges::getLogEntry) 29237e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 2924a4ce114aSNan Zhou [](const crow::Request& req, 29257e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 292622d268cbSEd Tanous const std::string& systemName, const std::string& logID, 292722d268cbSEd Tanous const std::string& fileName) { 2928bd79bce8SPatrick Williams // Do not call getRedfishRoute here since the crashdump file is 2929bd79bce8SPatrick Williams // not a Redfish resource. 293022d268cbSEd Tanous 293125b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 29327f3e84a1SEd Tanous { 29337f3e84a1SEd Tanous // Option currently returns no systems. TBD 29347f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 29357f3e84a1SEd Tanous systemName); 29367f3e84a1SEd Tanous return; 29377f3e84a1SEd Tanous } 2938253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 293922d268cbSEd Tanous { 294022d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 294122d268cbSEd Tanous systemName); 294222d268cbSEd Tanous return; 294322d268cbSEd Tanous } 294422d268cbSEd Tanous 2945043a0536SJohnathan Mantey auto getStoredLogCallback = 2946bd79bce8SPatrick Williams [asyncResp, logID, fileName, 2947bd79bce8SPatrick Williams url(boost::urls::url(req.url()))]( 29485e7e2dc5SEd Tanous const boost::system::error_code& ec, 2949bd79bce8SPatrick Williams const std::vector<std::pair< 2950bd79bce8SPatrick Williams std::string, dbus::utility::DbusVariantType>>& 29517e860f15SJohn Edward Broadbent resp) { 29521da66f75SEd Tanous if (ec) 29531da66f75SEd Tanous { 2954bd79bce8SPatrick Williams BMCWEB_LOG_DEBUG("failed to get log ec: {}", 2955bd79bce8SPatrick Williams ec.message()); 2956f12894f8SJason M. Bills messages::internalError(asyncResp->res); 29571da66f75SEd Tanous return; 29581da66f75SEd Tanous } 2959e855dd28SJason M. Bills 2960043a0536SJohnathan Mantey std::string dbusFilename{}; 2961043a0536SJohnathan Mantey std::string dbusTimestamp{}; 2962043a0536SJohnathan Mantey std::string dbusFilepath{}; 2963043a0536SJohnathan Mantey 2964bd79bce8SPatrick Williams parseCrashdumpParameters(resp, dbusFilename, 2965bd79bce8SPatrick Williams dbusTimestamp, dbusFilepath); 2966043a0536SJohnathan Mantey 2967043a0536SJohnathan Mantey if (dbusFilename.empty() || dbusTimestamp.empty() || 2968043a0536SJohnathan Mantey dbusFilepath.empty()) 29691da66f75SEd Tanous { 2970bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, 2971bd79bce8SPatrick Williams "LogEntry", logID); 29721da66f75SEd Tanous return; 29731da66f75SEd Tanous } 2974e855dd28SJason M. Bills 2975043a0536SJohnathan Mantey // Verify the file name parameter is correct 2976043a0536SJohnathan Mantey if (fileName != dbusFilename) 2977043a0536SJohnathan Mantey { 2978bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, 2979bd79bce8SPatrick Williams "LogEntry", logID); 2980043a0536SJohnathan Mantey return; 2981043a0536SJohnathan Mantey } 2982043a0536SJohnathan Mantey 2983d51c61b4SMyung Bae if (asyncResp->res.openFile(dbusFilepath) != 2984d51c61b4SMyung Bae crow::OpenCode::Success) 2985043a0536SJohnathan Mantey { 2986bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, 2987bd79bce8SPatrick Williams "LogEntry", logID); 2988043a0536SJohnathan Mantey return; 2989043a0536SJohnathan Mantey } 2990043a0536SJohnathan Mantey 29917e860f15SJohn Edward Broadbent // Configure this to be a file download when accessed 29927e860f15SJohn Edward Broadbent // from a browser 2993d9f6c621SEd Tanous asyncResp->res.addHeader( 2994bd79bce8SPatrick Williams boost::beast::http::field::content_disposition, 2995bd79bce8SPatrick Williams "attachment"); 29961da66f75SEd Tanous }; 2997d1bde9e5SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 2998d1bde9e5SKrzysztof Grobelny *crow::connections::systemBus, crashdumpObject, 2999bd79bce8SPatrick Williams crashdumpPath + std::string("/") + logID, 3000bd79bce8SPatrick Williams crashdumpInterface, std::move(getStoredLogCallback)); 30017e860f15SJohn Edward Broadbent }); 30021da66f75SEd Tanous } 30031da66f75SEd Tanous 3004c5a4c82aSJason M. Bills enum class OEMDiagnosticType 3005c5a4c82aSJason M. Bills { 3006c5a4c82aSJason M. Bills onDemand, 3007c5a4c82aSJason M. Bills telemetry, 3008c5a4c82aSJason M. Bills invalid, 3009c5a4c82aSJason M. Bills }; 3010c5a4c82aSJason M. Bills 301126ccae32SEd Tanous inline OEMDiagnosticType getOEMDiagnosticType(std::string_view oemDiagStr) 3012c5a4c82aSJason M. Bills { 3013c5a4c82aSJason M. Bills if (oemDiagStr == "OnDemand") 3014c5a4c82aSJason M. Bills { 3015c5a4c82aSJason M. Bills return OEMDiagnosticType::onDemand; 3016c5a4c82aSJason M. Bills } 3017c5a4c82aSJason M. Bills if (oemDiagStr == "Telemetry") 3018c5a4c82aSJason M. Bills { 3019c5a4c82aSJason M. Bills return OEMDiagnosticType::telemetry; 3020c5a4c82aSJason M. Bills } 3021c5a4c82aSJason M. Bills 3022c5a4c82aSJason M. Bills return OEMDiagnosticType::invalid; 3023c5a4c82aSJason M. Bills } 3024c5a4c82aSJason M. Bills 30257e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpCollect(App& app) 30261da66f75SEd Tanous { 30273946028dSAppaRao Puli // Note: Deviated from redfish privilege registry for GET & HEAD 30283946028dSAppaRao Puli // method for security reasons. 30290fda0f12SGeorge Liu BMCWEB_ROUTE( 30300fda0f12SGeorge Liu app, 303122d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Crashdump/Actions/LogService.CollectDiagnosticData/") 3032ed398213SEd Tanous // The below is incorrect; Should be ConfigureManager 3033ed398213SEd Tanous //.privileges(redfish::privileges::postLogService) 3034432a890cSEd Tanous .privileges({{"ConfigureComponents"}}) 3035002d39b4SEd Tanous .methods(boost::beast::http::verb::post)( 3036002d39b4SEd Tanous [&app](const crow::Request& req, 303722d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 303822d268cbSEd Tanous const std::string& systemName) { 30393ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 304045ca1b86SEd Tanous { 304145ca1b86SEd Tanous return; 304245ca1b86SEd Tanous } 304322d268cbSEd Tanous 304425b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 30457f3e84a1SEd Tanous { 30467f3e84a1SEd Tanous // Option currently returns no systems. TBD 30477f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 30487f3e84a1SEd Tanous systemName); 30497f3e84a1SEd Tanous return; 30507f3e84a1SEd Tanous } 3051253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 305222d268cbSEd Tanous { 305322d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 305422d268cbSEd Tanous systemName); 305522d268cbSEd Tanous return; 305622d268cbSEd Tanous } 305722d268cbSEd Tanous 30588e6c099aSJason M. Bills std::string diagnosticDataType; 30598e6c099aSJason M. Bills std::string oemDiagnosticDataType; 3060*afc474aeSMyung Bae if (!redfish::json_util::readJsonAction( // 3061*afc474aeSMyung Bae req, asyncResp->res, // 3062*afc474aeSMyung Bae "DiagnosticDataType", diagnosticDataType, // 3063*afc474aeSMyung Bae "OEMDiagnosticDataType", oemDiagnosticDataType // 3064*afc474aeSMyung Bae )) 30658e6c099aSJason M. Bills { 30668e6c099aSJason M. Bills return; 30678e6c099aSJason M. Bills } 30688e6c099aSJason M. Bills 30698e6c099aSJason M. Bills if (diagnosticDataType != "OEM") 30708e6c099aSJason M. Bills { 307162598e31SEd Tanous BMCWEB_LOG_ERROR( 307262598e31SEd Tanous "Only OEM DiagnosticDataType supported for Crashdump"); 30738e6c099aSJason M. Bills messages::actionParameterValueFormatError( 3074bd79bce8SPatrick Williams asyncResp->res, diagnosticDataType, 3075bd79bce8SPatrick Williams "DiagnosticDataType", "CollectDiagnosticData"); 30768e6c099aSJason M. Bills return; 30778e6c099aSJason M. Bills } 30788e6c099aSJason M. Bills 3079c5a4c82aSJason M. Bills OEMDiagnosticType oemDiagType = 3080c5a4c82aSJason M. Bills getOEMDiagnosticType(oemDiagnosticDataType); 3081c5a4c82aSJason M. Bills 3082c5a4c82aSJason M. Bills std::string iface; 3083c5a4c82aSJason M. Bills std::string method; 3084c5a4c82aSJason M. Bills std::string taskMatchStr; 3085c5a4c82aSJason M. Bills if (oemDiagType == OEMDiagnosticType::onDemand) 3086c5a4c82aSJason M. Bills { 3087c5a4c82aSJason M. Bills iface = crashdumpOnDemandInterface; 3088c5a4c82aSJason M. Bills method = "GenerateOnDemandLog"; 3089bd79bce8SPatrick Williams taskMatchStr = 3090bd79bce8SPatrick Williams "type='signal'," 3091c5a4c82aSJason M. Bills "interface='org.freedesktop.DBus.Properties'," 3092c5a4c82aSJason M. Bills "member='PropertiesChanged'," 3093c5a4c82aSJason M. Bills "arg0namespace='com.intel.crashdump'"; 3094c5a4c82aSJason M. Bills } 3095c5a4c82aSJason M. Bills else if (oemDiagType == OEMDiagnosticType::telemetry) 3096c5a4c82aSJason M. Bills { 3097c5a4c82aSJason M. Bills iface = crashdumpTelemetryInterface; 3098c5a4c82aSJason M. Bills method = "GenerateTelemetryLog"; 3099bd79bce8SPatrick Williams taskMatchStr = 3100bd79bce8SPatrick Williams "type='signal'," 3101c5a4c82aSJason M. Bills "interface='org.freedesktop.DBus.Properties'," 3102c5a4c82aSJason M. Bills "member='PropertiesChanged'," 3103c5a4c82aSJason M. Bills "arg0namespace='com.intel.crashdump'"; 3104c5a4c82aSJason M. Bills } 3105c5a4c82aSJason M. Bills else 3106c5a4c82aSJason M. Bills { 310762598e31SEd Tanous BMCWEB_LOG_ERROR("Unsupported OEMDiagnosticDataType: {}", 310862598e31SEd Tanous oemDiagnosticDataType); 3109c5a4c82aSJason M. Bills messages::actionParameterValueFormatError( 3110bd79bce8SPatrick Williams asyncResp->res, oemDiagnosticDataType, 3111bd79bce8SPatrick Williams "OEMDiagnosticDataType", "CollectDiagnosticData"); 3112c5a4c82aSJason M. Bills return; 3113c5a4c82aSJason M. Bills } 3114c5a4c82aSJason M. Bills 3115c5a4c82aSJason M. Bills auto collectCrashdumpCallback = 3116c5a4c82aSJason M. Bills [asyncResp, payload(task::Payload(req)), 31175e7e2dc5SEd Tanous taskMatchStr](const boost::system::error_code& ec, 311898be3e39SEd Tanous const std::string&) mutable { 31191da66f75SEd Tanous if (ec) 31201da66f75SEd Tanous { 3121bd79bce8SPatrick Williams if (ec.value() == 3122bd79bce8SPatrick Williams boost::system::errc::operation_not_supported) 31231da66f75SEd Tanous { 3124f12894f8SJason M. Bills messages::resourceInStandby(asyncResp->res); 31251da66f75SEd Tanous } 3126bd79bce8SPatrick Williams else if (ec.value() == boost::system::errc:: 3127bd79bce8SPatrick Williams device_or_resource_busy) 31284363d3b2SJason M. Bills { 3129bd79bce8SPatrick Williams messages::serviceTemporarilyUnavailable( 3130bd79bce8SPatrick Williams asyncResp->res, "60"); 31314363d3b2SJason M. Bills } 31321da66f75SEd Tanous else 31331da66f75SEd Tanous { 3134f12894f8SJason M. Bills messages::internalError(asyncResp->res); 31351da66f75SEd Tanous } 31361da66f75SEd Tanous return; 31371da66f75SEd Tanous } 3138bd79bce8SPatrick Williams std::shared_ptr<task::TaskData> task = 3139bd79bce8SPatrick Williams task::TaskData::createTask( 3140bd79bce8SPatrick Williams [](const boost::system::error_code& ec2, 3141bd79bce8SPatrick Williams sdbusplus::message_t&, 3142bd79bce8SPatrick Williams const std::shared_ptr<task::TaskData>& 3143bd79bce8SPatrick Williams taskData) { 31448b24275dSEd Tanous if (!ec2) 314566afe4faSJames Feist { 3146bd79bce8SPatrick Williams taskData->messages.emplace_back( 3147bd79bce8SPatrick Williams messages::taskCompletedOK( 3148bd79bce8SPatrick Williams std::to_string( 3149bd79bce8SPatrick Williams taskData->index))); 3150831d6b09SJames Feist taskData->state = "Completed"; 315166afe4faSJames Feist } 315232898ceaSJames Feist return task::completed; 315366afe4faSJames Feist }, 3154c5a4c82aSJason M. Bills taskMatchStr); 3155c5a4c82aSJason M. Bills 315646229577SJames Feist task->startTimer(std::chrono::minutes(5)); 315746229577SJames Feist task->populateResp(asyncResp->res); 315898be3e39SEd Tanous task->payload.emplace(std::move(payload)); 31591da66f75SEd Tanous }; 31608e6c099aSJason M. Bills 31611da66f75SEd Tanous crow::connections::systemBus->async_method_call( 3162bd79bce8SPatrick Williams std::move(collectCrashdumpCallback), crashdumpObject, 3163bd79bce8SPatrick Williams crashdumpPath, iface, method); 31647e860f15SJohn Edward Broadbent }); 31656eda7685SKenny L. Ku } 31666eda7685SKenny L. Ku 3167599b9af3SAlexander Hansen inline void dBusLogServiceActionsClear( 3168599b9af3SAlexander Hansen const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 3169599b9af3SAlexander Hansen { 3170599b9af3SAlexander Hansen BMCWEB_LOG_DEBUG("Do delete all entries."); 3171599b9af3SAlexander Hansen 3172599b9af3SAlexander Hansen // Process response from Logging service. 3173599b9af3SAlexander Hansen auto respHandler = [asyncResp](const boost::system::error_code& ec) { 3174599b9af3SAlexander Hansen BMCWEB_LOG_DEBUG("doClearLog resp_handler callback: Done"); 3175599b9af3SAlexander Hansen if (ec) 3176599b9af3SAlexander Hansen { 3177599b9af3SAlexander Hansen // TODO Handle for specific error code 3178599b9af3SAlexander Hansen BMCWEB_LOG_ERROR("doClearLog resp_handler got error {}", ec); 3179599b9af3SAlexander Hansen asyncResp->res.result( 3180599b9af3SAlexander Hansen boost::beast::http::status::internal_server_error); 3181599b9af3SAlexander Hansen return; 3182599b9af3SAlexander Hansen } 3183599b9af3SAlexander Hansen 3184599b9af3SAlexander Hansen asyncResp->res.result(boost::beast::http::status::no_content); 3185599b9af3SAlexander Hansen }; 3186599b9af3SAlexander Hansen 3187599b9af3SAlexander Hansen // Make call to Logging service to request Clear Log 3188599b9af3SAlexander Hansen crow::connections::systemBus->async_method_call( 3189599b9af3SAlexander Hansen respHandler, "xyz.openbmc_project.Logging", 3190599b9af3SAlexander Hansen "/xyz/openbmc_project/logging", 3191599b9af3SAlexander Hansen "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll"); 3192599b9af3SAlexander Hansen } 3193599b9af3SAlexander Hansen 3194cb92c03bSAndrew Geissler /** 3195cb92c03bSAndrew Geissler * DBusLogServiceActionsClear class supports POST method for ClearLog action. 3196cb92c03bSAndrew Geissler */ 31977e860f15SJohn Edward Broadbent inline void requestRoutesDBusLogServiceActionsClear(App& app) 3198cb92c03bSAndrew Geissler { 3199cb92c03bSAndrew Geissler /** 3200cb92c03bSAndrew Geissler * Function handles POST method request. 3201cb92c03bSAndrew Geissler * The Clear Log actions does not require any parameter.The action deletes 3202cb92c03bSAndrew Geissler * all entries found in the Entries collection for this Log Service. 3203cb92c03bSAndrew Geissler */ 32047e860f15SJohn Edward Broadbent 32050fda0f12SGeorge Liu BMCWEB_ROUTE( 32060fda0f12SGeorge Liu app, 320722d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/EventLog/Actions/LogService.ClearLog/") 3208ed398213SEd Tanous .privileges(redfish::privileges::postLogService) 32097e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 321045ca1b86SEd Tanous [&app](const crow::Request& req, 321122d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 321222d268cbSEd Tanous const std::string& systemName) { 32133ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 321445ca1b86SEd Tanous { 321545ca1b86SEd Tanous return; 321645ca1b86SEd Tanous } 321725b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 32187f3e84a1SEd Tanous { 32197f3e84a1SEd Tanous // Option currently returns no systems. TBD 32207f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 32217f3e84a1SEd Tanous systemName); 32227f3e84a1SEd Tanous return; 32237f3e84a1SEd Tanous } 3224253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 322522d268cbSEd Tanous { 322622d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 322722d268cbSEd Tanous systemName); 322822d268cbSEd Tanous return; 322922d268cbSEd Tanous } 3230599b9af3SAlexander Hansen dBusLogServiceActionsClear(asyncResp); 32317e860f15SJohn Edward Broadbent }); 3232cb92c03bSAndrew Geissler } 3233a3316fc6SZhikuiRen 32341da66f75SEd Tanous } // namespace redfish 3235