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" 33*262dcc1cSAlexander 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 94415ed6780SWilly Tu if (!redfish::json_util::readJsonAction( 945a43be80fSAsmitha Karunanithi req, asyncResp->res, "DiagnosticDataType", diagnosticDataType, 946a43be80fSAsmitha Karunanithi "OEMDiagnosticDataType", oemDiagnosticDataType)) 947a43be80fSAsmitha Karunanithi { 948a43be80fSAsmitha Karunanithi return; 949a43be80fSAsmitha Karunanithi } 950a43be80fSAsmitha Karunanithi 951a43be80fSAsmitha Karunanithi if (dumpType == "System") 952a43be80fSAsmitha Karunanithi { 953a43be80fSAsmitha Karunanithi if (!oemDiagnosticDataType || !diagnosticDataType) 954a43be80fSAsmitha Karunanithi { 95562598e31SEd Tanous BMCWEB_LOG_ERROR( 95662598e31SEd Tanous "CreateDump action parameter 'DiagnosticDataType'/'OEMDiagnosticDataType' value not found!"); 957a43be80fSAsmitha Karunanithi messages::actionParameterMissing( 958a43be80fSAsmitha Karunanithi asyncResp->res, "CollectDiagnosticData", 959a43be80fSAsmitha Karunanithi "DiagnosticDataType & OEMDiagnosticDataType"); 960a43be80fSAsmitha Karunanithi return; 961a43be80fSAsmitha Karunanithi } 9623174e4dfSEd Tanous if ((*oemDiagnosticDataType != "System") || 963a43be80fSAsmitha Karunanithi (*diagnosticDataType != "OEM")) 964a43be80fSAsmitha Karunanithi { 96562598e31SEd Tanous BMCWEB_LOG_ERROR("Wrong parameter values passed"); 966ace85d60SEd Tanous messages::internalError(asyncResp->res); 967a43be80fSAsmitha Karunanithi return; 968a43be80fSAsmitha Karunanithi } 969253f11b8SEd Tanous dumpPath = std::format("/redfish/v1/Systems/{}/LogServices/Dump/", 970253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 971a43be80fSAsmitha Karunanithi } 972a43be80fSAsmitha Karunanithi else if (dumpType == "BMC") 973a43be80fSAsmitha Karunanithi { 974a43be80fSAsmitha Karunanithi if (!diagnosticDataType) 975a43be80fSAsmitha Karunanithi { 97662598e31SEd Tanous BMCWEB_LOG_ERROR( 97762598e31SEd Tanous "CreateDump action parameter 'DiagnosticDataType' not found!"); 978a43be80fSAsmitha Karunanithi messages::actionParameterMissing( 979a43be80fSAsmitha Karunanithi asyncResp->res, "CollectDiagnosticData", "DiagnosticDataType"); 980a43be80fSAsmitha Karunanithi return; 981a43be80fSAsmitha Karunanithi } 9823174e4dfSEd Tanous if (*diagnosticDataType != "Manager") 983a43be80fSAsmitha Karunanithi { 98462598e31SEd Tanous BMCWEB_LOG_ERROR( 98562598e31SEd Tanous "Wrong parameter value passed for 'DiagnosticDataType'"); 986ace85d60SEd Tanous messages::internalError(asyncResp->res); 987a43be80fSAsmitha Karunanithi return; 988a43be80fSAsmitha Karunanithi } 989253f11b8SEd Tanous dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/Dump/", 990253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 9915907571dSAsmitha Karunanithi } 9925907571dSAsmitha Karunanithi else 9935907571dSAsmitha Karunanithi { 99462598e31SEd Tanous BMCWEB_LOG_ERROR("CreateDump failed. Unknown dump type"); 9955907571dSAsmitha Karunanithi messages::internalError(asyncResp->res); 9965907571dSAsmitha Karunanithi return; 997a43be80fSAsmitha Karunanithi } 998a43be80fSAsmitha Karunanithi 9998e31778eSAsmitha Karunanithi std::vector<std::pair<std::string, std::variant<std::string, uint64_t>>> 10008e31778eSAsmitha Karunanithi createDumpParamVec; 10018e31778eSAsmitha Karunanithi 1002f574a8e1SCarson Labrado if (req.session != nullptr) 1003f574a8e1SCarson Labrado { 100468dd075aSAsmitha Karunanithi createDumpParamVec.emplace_back( 100568dd075aSAsmitha Karunanithi "xyz.openbmc_project.Dump.Create.CreateParameters.OriginatorId", 100668dd075aSAsmitha Karunanithi req.session->clientIp); 100768dd075aSAsmitha Karunanithi createDumpParamVec.emplace_back( 100868dd075aSAsmitha Karunanithi "xyz.openbmc_project.Dump.Create.CreateParameters.OriginatorType", 100968dd075aSAsmitha Karunanithi "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Client"); 1010f574a8e1SCarson Labrado } 101168dd075aSAsmitha Karunanithi 1012a43be80fSAsmitha Karunanithi crow::connections::systemBus->async_method_call( 10135e7e2dc5SEd Tanous [asyncResp, payload(task::Payload(req)), 10145e7e2dc5SEd Tanous dumpPath](const boost::system::error_code& ec, 10155e7e2dc5SEd Tanous const sdbusplus::message_t& msg, 10168e31778eSAsmitha Karunanithi const sdbusplus::message::object_path& objPath) mutable { 1017a43be80fSAsmitha Karunanithi if (ec) 1018a43be80fSAsmitha Karunanithi { 101962598e31SEd Tanous BMCWEB_LOG_ERROR("CreateDump resp_handler got error {}", ec); 10205907571dSAsmitha Karunanithi const sd_bus_error* dbusError = msg.get_error(); 10215907571dSAsmitha Karunanithi if (dbusError == nullptr) 10225907571dSAsmitha Karunanithi { 10235907571dSAsmitha Karunanithi messages::internalError(asyncResp->res); 10245907571dSAsmitha Karunanithi return; 10255907571dSAsmitha Karunanithi } 10265907571dSAsmitha Karunanithi 102762598e31SEd Tanous BMCWEB_LOG_ERROR("CreateDump DBus error: {} and error msg: {}", 102862598e31SEd Tanous dbusError->name, dbusError->message); 10295907571dSAsmitha Karunanithi if (std::string_view( 10305907571dSAsmitha Karunanithi "xyz.openbmc_project.Common.Error.NotAllowed") == 10315907571dSAsmitha Karunanithi dbusError->name) 10325907571dSAsmitha Karunanithi { 10335907571dSAsmitha Karunanithi messages::resourceInStandby(asyncResp->res); 10345907571dSAsmitha Karunanithi return; 10355907571dSAsmitha Karunanithi } 10365907571dSAsmitha Karunanithi if (std::string_view( 10375907571dSAsmitha Karunanithi "xyz.openbmc_project.Dump.Create.Error.Disabled") == 10385907571dSAsmitha Karunanithi dbusError->name) 10395907571dSAsmitha Karunanithi { 10405907571dSAsmitha Karunanithi messages::serviceDisabled(asyncResp->res, dumpPath); 10415907571dSAsmitha Karunanithi return; 10425907571dSAsmitha Karunanithi } 10435907571dSAsmitha Karunanithi if (std::string_view( 10445907571dSAsmitha Karunanithi "xyz.openbmc_project.Common.Error.Unavailable") == 10455907571dSAsmitha Karunanithi dbusError->name) 10465907571dSAsmitha Karunanithi { 10475907571dSAsmitha Karunanithi messages::resourceInUse(asyncResp->res); 10485907571dSAsmitha Karunanithi return; 10495907571dSAsmitha Karunanithi } 10505907571dSAsmitha Karunanithi // Other Dbus errors such as: 10515907571dSAsmitha Karunanithi // xyz.openbmc_project.Common.Error.InvalidArgument & 10525907571dSAsmitha Karunanithi // org.freedesktop.DBus.Error.InvalidArgs are all related to 10535907571dSAsmitha Karunanithi // the dbus call that is made here in the bmcweb 10545907571dSAsmitha Karunanithi // implementation and has nothing to do with the client's 10555907571dSAsmitha Karunanithi // input in the request. Hence, returning internal error 10565907571dSAsmitha Karunanithi // back to the client. 1057a43be80fSAsmitha Karunanithi messages::internalError(asyncResp->res); 1058a43be80fSAsmitha Karunanithi return; 1059a43be80fSAsmitha Karunanithi } 106062598e31SEd Tanous BMCWEB_LOG_DEBUG("Dump Created. Path: {}", objPath.str); 10618e31778eSAsmitha Karunanithi createDumpTaskCallback(std::move(payload), asyncResp, objPath); 1062a43be80fSAsmitha Karunanithi }, 106318f8f608SEd Tanous "xyz.openbmc_project.Dump.Manager", getDumpPath(dumpType), 10648e31778eSAsmitha Karunanithi "xyz.openbmc_project.Dump.Create", "CreateDump", createDumpParamVec); 1065a43be80fSAsmitha Karunanithi } 1066a43be80fSAsmitha Karunanithi 10678d1b46d7Szhanghch05 inline void clearDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 10688d1b46d7Szhanghch05 const std::string& dumpType) 106980319af1SAsmitha Karunanithi { 10700d946211SClaire Weinan crow::connections::systemBus->async_method_call( 10710d946211SClaire Weinan [asyncResp](const boost::system::error_code& ec) { 107280319af1SAsmitha Karunanithi if (ec) 107380319af1SAsmitha Karunanithi { 107462598e31SEd Tanous BMCWEB_LOG_ERROR("clearDump resp_handler got error {}", ec); 107580319af1SAsmitha Karunanithi messages::internalError(asyncResp->res); 107680319af1SAsmitha Karunanithi return; 107780319af1SAsmitha Karunanithi } 10780d946211SClaire Weinan }, 107918f8f608SEd Tanous "xyz.openbmc_project.Dump.Manager", getDumpPath(dumpType), 10800d946211SClaire Weinan "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll"); 108180319af1SAsmitha Karunanithi } 108280319af1SAsmitha Karunanithi 1083bd79bce8SPatrick Williams inline void parseCrashdumpParameters( 1084bd79bce8SPatrick Williams const dbus::utility::DBusPropertiesMap& params, std::string& filename, 1085bd79bce8SPatrick Williams std::string& timestamp, std::string& logfile) 1086043a0536SJohnathan Mantey { 1087d1bde9e5SKrzysztof Grobelny const std::string* filenamePtr = nullptr; 1088d1bde9e5SKrzysztof Grobelny const std::string* timestampPtr = nullptr; 1089d1bde9e5SKrzysztof Grobelny const std::string* logfilePtr = nullptr; 1090d1bde9e5SKrzysztof Grobelny 1091d1bde9e5SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 1092d1bde9e5SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), params, "Timestamp", timestampPtr, 1093d1bde9e5SKrzysztof Grobelny "Filename", filenamePtr, "Log", logfilePtr); 1094d1bde9e5SKrzysztof Grobelny 1095d1bde9e5SKrzysztof Grobelny if (!success) 1096043a0536SJohnathan Mantey { 1097d1bde9e5SKrzysztof Grobelny return; 1098043a0536SJohnathan Mantey } 1099d1bde9e5SKrzysztof Grobelny 1100d1bde9e5SKrzysztof Grobelny if (filenamePtr != nullptr) 1101043a0536SJohnathan Mantey { 1102d1bde9e5SKrzysztof Grobelny filename = *filenamePtr; 1103d1bde9e5SKrzysztof Grobelny } 1104d1bde9e5SKrzysztof Grobelny 1105d1bde9e5SKrzysztof Grobelny if (timestampPtr != nullptr) 1106043a0536SJohnathan Mantey { 1107d1bde9e5SKrzysztof Grobelny timestamp = *timestampPtr; 1108043a0536SJohnathan Mantey } 1109d1bde9e5SKrzysztof Grobelny 1110d1bde9e5SKrzysztof Grobelny if (logfilePtr != nullptr) 1111043a0536SJohnathan Mantey { 1112d1bde9e5SKrzysztof Grobelny logfile = *logfilePtr; 1113043a0536SJohnathan Mantey } 1114043a0536SJohnathan Mantey } 1115043a0536SJohnathan Mantey 11167e860f15SJohn Edward Broadbent inline void requestRoutesSystemLogServiceCollection(App& app) 11171da66f75SEd Tanous { 1118c4bf6374SJason M. Bills /** 1119c4bf6374SJason M. Bills * Functions triggers appropriate requests on DBus 1120c4bf6374SJason M. Bills */ 112122d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/") 1122ed398213SEd Tanous .privileges(redfish::privileges::getLogServiceCollection) 1123bd79bce8SPatrick Williams .methods( 1124bd79bce8SPatrick Williams boost::beast::http::verb:: 1125bd79bce8SPatrick Williams get)([&app](const crow::Request& req, 112622d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 112722d268cbSEd Tanous const std::string& systemName) { 11283ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 1129c4bf6374SJason M. Bills { 113045ca1b86SEd Tanous return; 113145ca1b86SEd Tanous } 113225b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 11337f3e84a1SEd Tanous { 11347f3e84a1SEd Tanous // Option currently returns no systems. TBD 11357f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 11367f3e84a1SEd Tanous systemName); 11377f3e84a1SEd Tanous return; 11387f3e84a1SEd Tanous } 1139253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 114022d268cbSEd Tanous { 114122d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 114222d268cbSEd Tanous systemName); 114322d268cbSEd Tanous return; 114422d268cbSEd Tanous } 114522d268cbSEd Tanous 11467e860f15SJohn Edward Broadbent // Collections don't include the static data added by SubRoute 11477e860f15SJohn Edward Broadbent // because it has a duplicate entry for members 1148c4bf6374SJason M. Bills asyncResp->res.jsonValue["@odata.type"] = 1149c4bf6374SJason M. Bills "#LogServiceCollection.LogServiceCollection"; 1150c4bf6374SJason M. Bills asyncResp->res.jsonValue["@odata.id"] = 1151253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices", 1152253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 115345ca1b86SEd Tanous asyncResp->res.jsonValue["Name"] = "System Log Services Collection"; 1154c4bf6374SJason M. Bills asyncResp->res.jsonValue["Description"] = 1155c4bf6374SJason M. Bills "Collection of LogServices for this Computer System"; 1156bd79bce8SPatrick Williams nlohmann::json& logServiceArray = 1157bd79bce8SPatrick Williams asyncResp->res.jsonValue["Members"]; 1158c4bf6374SJason M. Bills logServiceArray = nlohmann::json::array(); 11591476687dSEd Tanous nlohmann::json::object_t eventLog; 11601476687dSEd Tanous eventLog["@odata.id"] = 1161253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/EventLog", 1162253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1163b2ba3072SPatrick Williams logServiceArray.emplace_back(std::move(eventLog)); 116425b54dbaSEd Tanous if constexpr (BMCWEB_REDFISH_DUMP_LOG) 116525b54dbaSEd Tanous { 11661476687dSEd Tanous nlohmann::json::object_t dumpLog; 116725b54dbaSEd Tanous dumpLog["@odata.id"] = 1168253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/Dump", 1169253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1170b2ba3072SPatrick Williams logServiceArray.emplace_back(std::move(dumpLog)); 117125b54dbaSEd Tanous } 1172c9bb6861Sraviteja-b 11735ffd11f2SGunnar Mills if constexpr (BMCWEB_REDFISH_CPU_LOG) 117425b54dbaSEd Tanous { 11751476687dSEd Tanous nlohmann::json::object_t crashdump; 11761476687dSEd Tanous crashdump["@odata.id"] = 1177253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/Crashdump", 1178253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1179b2ba3072SPatrick Williams logServiceArray.emplace_back(std::move(crashdump)); 118025b54dbaSEd Tanous } 1181b7028ebfSSpencer Ku 118225b54dbaSEd Tanous if constexpr (BMCWEB_REDFISH_HOST_LOGGER) 118325b54dbaSEd Tanous { 11841476687dSEd Tanous nlohmann::json::object_t hostlogger; 11851476687dSEd Tanous hostlogger["@odata.id"] = 1186253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/HostLogger", 1187253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1188b2ba3072SPatrick Williams logServiceArray.emplace_back(std::move(hostlogger)); 118925b54dbaSEd Tanous } 1190c4bf6374SJason M. Bills asyncResp->res.jsonValue["Members@odata.count"] = 1191c4bf6374SJason M. Bills logServiceArray.size(); 1192a3316fc6SZhikuiRen 11937a1dbc48SGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 11947a1dbc48SGeorge Liu "xyz.openbmc_project.State.Boot.PostCode"}; 11957a1dbc48SGeorge Liu dbus::utility::getSubTreePaths( 11967a1dbc48SGeorge Liu "/", 0, interfaces, 11977a1dbc48SGeorge Liu [asyncResp](const boost::system::error_code& ec, 1198b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreePathsResponse& 1199b9d36b47SEd Tanous subtreePath) { 1200a3316fc6SZhikuiRen if (ec) 1201a3316fc6SZhikuiRen { 120262598e31SEd Tanous BMCWEB_LOG_ERROR("{}", ec); 1203a3316fc6SZhikuiRen return; 1204a3316fc6SZhikuiRen } 1205a3316fc6SZhikuiRen 120655f79e6fSEd Tanous for (const auto& pathStr : subtreePath) 1207a3316fc6SZhikuiRen { 1208a3316fc6SZhikuiRen if (pathStr.find("PostCode") != std::string::npos) 1209a3316fc6SZhikuiRen { 121023a21a1cSEd Tanous nlohmann::json& logServiceArrayLocal = 1211a3316fc6SZhikuiRen asyncResp->res.jsonValue["Members"]; 1212613dabeaSEd Tanous nlohmann::json::object_t member; 1213253f11b8SEd Tanous member["@odata.id"] = std::format( 1214253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/PostCodes", 1215253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1216613dabeaSEd Tanous 1217bd79bce8SPatrick Williams logServiceArrayLocal.emplace_back( 1218bd79bce8SPatrick Williams std::move(member)); 1219613dabeaSEd Tanous 122045ca1b86SEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = 122123a21a1cSEd Tanous logServiceArrayLocal.size(); 1222a3316fc6SZhikuiRen return; 1223a3316fc6SZhikuiRen } 1224a3316fc6SZhikuiRen } 12257a1dbc48SGeorge Liu }); 12267e860f15SJohn Edward Broadbent }); 1227c4bf6374SJason M. Bills } 1228c4bf6374SJason M. Bills 12297e860f15SJohn Edward Broadbent inline void requestRoutesEventLogService(App& app) 1230c4bf6374SJason M. Bills { 123122d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/") 1232ed398213SEd Tanous .privileges(redfish::privileges::getLogService) 1233bd79bce8SPatrick Williams .methods( 1234bd79bce8SPatrick Williams boost::beast::http::verb:: 1235bd79bce8SPatrick Williams get)([&app](const crow::Request& req, 123622d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 123722d268cbSEd Tanous const std::string& systemName) { 12383ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 123945ca1b86SEd Tanous { 124045ca1b86SEd Tanous return; 124145ca1b86SEd Tanous } 1242253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 124322d268cbSEd Tanous { 124422d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 124522d268cbSEd Tanous systemName); 124622d268cbSEd Tanous return; 124722d268cbSEd Tanous } 1248c4bf6374SJason M. Bills asyncResp->res.jsonValue["@odata.id"] = 1249253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/EventLog", 1250253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1251c4bf6374SJason M. Bills asyncResp->res.jsonValue["@odata.type"] = 1252b25644a1SJanet Adkins "#LogService.v1_2_0.LogService"; 1253c4bf6374SJason M. Bills asyncResp->res.jsonValue["Name"] = "Event Log Service"; 1254bd79bce8SPatrick Williams asyncResp->res.jsonValue["Description"] = 1255bd79bce8SPatrick Williams "System Event Log Service"; 1256c4bf6374SJason M. Bills asyncResp->res.jsonValue["Id"] = "EventLog"; 1257539d8c6bSEd Tanous asyncResp->res.jsonValue["OverWritePolicy"] = 1258539d8c6bSEd Tanous log_service::OverWritePolicy::WrapsWhenFull; 12597c8c4058STejas Patil 12607c8c4058STejas Patil std::pair<std::string, std::string> redfishDateTimeOffset = 12612b82937eSEd Tanous redfish::time_utils::getDateTimeOffsetNow(); 12627c8c4058STejas Patil 12637c8c4058STejas Patil asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first; 12647c8c4058STejas Patil asyncResp->res.jsonValue["DateTimeLocalOffset"] = 12657c8c4058STejas Patil redfishDateTimeOffset.second; 12667c8c4058STejas Patil 1267bd79bce8SPatrick Williams asyncResp->res.jsonValue["Entries"]["@odata.id"] = std::format( 1268bd79bce8SPatrick Williams "/redfish/v1/Systems/{}/LogServices/EventLog/Entries", 1269253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1270bd79bce8SPatrick Williams asyncResp->res 1271bd79bce8SPatrick Williams .jsonValue["Actions"]["#LogService.ClearLog"]["target"] 1272e7d6c8b2SGunnar Mills 127320fa6a2cSEd Tanous = std::format( 1274253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/EventLog/Actions/LogService.ClearLog", 127520fa6a2cSEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 12767e860f15SJohn Edward Broadbent }); 1277489640c6SJason M. Bills } 1278489640c6SJason M. Bills 1279599b9af3SAlexander Hansen inline void handleSystemsLogServicesEventLogActionsClearPost( 1280599b9af3SAlexander Hansen App& app, const crow::Request& req, 128122d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1282599b9af3SAlexander Hansen const std::string& systemName) 1283599b9af3SAlexander Hansen { 12843ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 128545ca1b86SEd Tanous { 128645ca1b86SEd Tanous return; 128745ca1b86SEd Tanous } 1288253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 128922d268cbSEd Tanous { 129022d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 129122d268cbSEd Tanous systemName); 129222d268cbSEd Tanous return; 129322d268cbSEd Tanous } 1294599b9af3SAlexander Hansen 1295489640c6SJason M. Bills // Clear the EventLog by deleting the log files 1296489640c6SJason M. Bills std::vector<std::filesystem::path> redfishLogFiles; 1297489640c6SJason M. Bills if (getRedfishLogFiles(redfishLogFiles)) 1298489640c6SJason M. Bills { 1299489640c6SJason M. Bills for (const std::filesystem::path& file : redfishLogFiles) 1300489640c6SJason M. Bills { 1301489640c6SJason M. Bills std::error_code ec; 1302489640c6SJason M. Bills std::filesystem::remove(file, ec); 1303489640c6SJason M. Bills } 1304489640c6SJason M. Bills } 1305489640c6SJason M. Bills 1306489640c6SJason M. Bills // Reload rsyslog so it knows to start new log files 1307489640c6SJason M. Bills crow::connections::systemBus->async_method_call( 13085e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 1309489640c6SJason M. Bills if (ec) 1310489640c6SJason M. Bills { 131162598e31SEd Tanous BMCWEB_LOG_ERROR("Failed to reload rsyslog: {}", ec); 1312489640c6SJason M. Bills messages::internalError(asyncResp->res); 1313489640c6SJason M. Bills return; 1314489640c6SJason M. Bills } 1315489640c6SJason M. Bills 1316489640c6SJason M. Bills messages::success(asyncResp->res); 1317489640c6SJason M. Bills }, 1318489640c6SJason M. Bills "org.freedesktop.systemd1", "/org/freedesktop/systemd1", 1319002d39b4SEd Tanous "org.freedesktop.systemd1.Manager", "ReloadUnit", "rsyslog.service", 1320002d39b4SEd Tanous "replace"); 1321599b9af3SAlexander Hansen } 1322599b9af3SAlexander Hansen 1323599b9af3SAlexander Hansen inline void requestRoutesJournalEventLogClear(App& app) 1324599b9af3SAlexander Hansen { 1325599b9af3SAlexander Hansen BMCWEB_ROUTE( 1326599b9af3SAlexander Hansen app, 1327599b9af3SAlexander Hansen "/redfish/v1/Systems/<str>/LogServices/EventLog/Actions/LogService.ClearLog/") 1328599b9af3SAlexander Hansen .privileges({{"ConfigureComponents"}}) 1329599b9af3SAlexander Hansen .methods(boost::beast::http::verb::post)(std::bind_front( 1330599b9af3SAlexander Hansen handleSystemsLogServicesEventLogActionsClearPost, std::ref(app))); 1331c4bf6374SJason M. Bills } 1332c4bf6374SJason M. Bills 1333ac992cdeSJason M. Bills enum class LogParseError 1334ac992cdeSJason M. Bills { 1335ac992cdeSJason M. Bills success, 1336ac992cdeSJason M. Bills parseFailed, 1337ac992cdeSJason M. Bills messageIdNotInRegistry, 1338ac992cdeSJason M. Bills }; 1339ac992cdeSJason M. Bills 1340bd79bce8SPatrick Williams static LogParseError fillEventLogEntryJson( 1341bd79bce8SPatrick Williams const std::string& logEntryID, const std::string& logEntry, 1342de703c5dSJason M. Bills nlohmann::json::object_t& logEntryJson) 1343c4bf6374SJason M. Bills { 134495820184SJason M. Bills // The redfish log format is "<Timestamp> <MessageId>,<MessageArgs>" 1345cd225da8SJason M. Bills // First get the Timestamp 1346f23b7296SEd Tanous size_t space = logEntry.find_first_of(' '); 1347cd225da8SJason M. Bills if (space == std::string::npos) 134895820184SJason M. Bills { 1349ac992cdeSJason M. Bills return LogParseError::parseFailed; 135095820184SJason M. Bills } 1351cd225da8SJason M. Bills std::string timestamp = logEntry.substr(0, space); 1352cd225da8SJason M. Bills // Then get the log contents 1353f23b7296SEd Tanous size_t entryStart = logEntry.find_first_not_of(' ', space); 1354cd225da8SJason M. Bills if (entryStart == std::string::npos) 1355cd225da8SJason M. Bills { 1356ac992cdeSJason M. Bills return LogParseError::parseFailed; 1357cd225da8SJason M. Bills } 1358cd225da8SJason M. Bills std::string_view entry(logEntry); 1359cd225da8SJason M. Bills entry.remove_prefix(entryStart); 1360cd225da8SJason M. Bills // Use split to separate the entry into its fields 1361cd225da8SJason M. Bills std::vector<std::string> logEntryFields; 136250ebd4afSEd Tanous bmcweb::split(logEntryFields, entry, ','); 1363cd225da8SJason M. Bills // We need at least a MessageId to be valid 13641e6deaf6SEd Tanous auto logEntryIter = logEntryFields.begin(); 13651e6deaf6SEd Tanous if (logEntryIter == logEntryFields.end()) 1366cd225da8SJason M. Bills { 1367ac992cdeSJason M. Bills return LogParseError::parseFailed; 1368cd225da8SJason M. Bills } 13691e6deaf6SEd Tanous std::string& messageID = *logEntryIter; 13704851d45dSJason M. Bills // Get the Message from the MessageRegistry 1371fffb8c1fSEd Tanous const registries::Message* message = registries::getMessage(messageID); 1372c4bf6374SJason M. Bills 13731e6deaf6SEd Tanous logEntryIter++; 137454417b02SSui Chen if (message == nullptr) 1375c4bf6374SJason M. Bills { 137662598e31SEd Tanous BMCWEB_LOG_WARNING("Log entry not found in registry: {}", logEntry); 1377ac992cdeSJason M. Bills return LogParseError::messageIdNotInRegistry; 1378c4bf6374SJason M. Bills } 1379c4bf6374SJason M. Bills 13801e6deaf6SEd Tanous std::vector<std::string_view> messageArgs(logEntryIter, 13811e6deaf6SEd Tanous logEntryFields.end()); 1382c05bba45SEd Tanous messageArgs.resize(message->numberOfArgs); 1383c05bba45SEd Tanous 1384bd79bce8SPatrick Williams std::string msg = 1385bd79bce8SPatrick Williams redfish::registries::fillMessageArgs(messageArgs, message->message); 13861e6deaf6SEd Tanous if (msg.empty()) 138715a86ff6SJason M. Bills { 13881e6deaf6SEd Tanous return LogParseError::parseFailed; 138915a86ff6SJason M. Bills } 13904851d45dSJason M. Bills 139195820184SJason M. Bills // Get the Created time from the timestamp. The log timestamp is in RFC3339 139295820184SJason M. Bills // format which matches the Redfish format except for the fractional seconds 139395820184SJason M. Bills // between the '.' and the '+', so just remove them. 1394f23b7296SEd Tanous std::size_t dot = timestamp.find_first_of('.'); 1395f23b7296SEd Tanous std::size_t plus = timestamp.find_first_of('+'); 139695820184SJason M. Bills if (dot != std::string::npos && plus != std::string::npos) 1397c4bf6374SJason M. Bills { 139895820184SJason M. Bills timestamp.erase(dot, plus - dot); 1399c4bf6374SJason M. Bills } 1400c4bf6374SJason M. Bills 1401c4bf6374SJason M. Bills // Fill in the log entry with the gathered data 14029c11a172SVijay Lobo logEntryJson["@odata.type"] = "#LogEntry.v1_9_0.LogEntry"; 1403ef4c65b7SEd Tanous logEntryJson["@odata.id"] = boost::urls::format( 1404253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}", 1405253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, logEntryID); 140684afc48bSJason M. Bills logEntryJson["Name"] = "System Event Log Entry"; 140784afc48bSJason M. Bills logEntryJson["Id"] = logEntryID; 140884afc48bSJason M. Bills logEntryJson["Message"] = std::move(msg); 140984afc48bSJason M. Bills logEntryJson["MessageId"] = std::move(messageID); 141084afc48bSJason M. Bills logEntryJson["MessageArgs"] = messageArgs; 141184afc48bSJason M. Bills logEntryJson["EntryType"] = "Event"; 141284afc48bSJason M. Bills logEntryJson["Severity"] = message->messageSeverity; 141384afc48bSJason M. Bills logEntryJson["Created"] = std::move(timestamp); 1414ac992cdeSJason M. Bills return LogParseError::success; 1415c4bf6374SJason M. Bills } 1416c4bf6374SJason M. Bills 1417898f2aa2SEd Tanous inline void fillEventLogLogEntryFromPropertyMap( 1418898f2aa2SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1419898f2aa2SEd Tanous const dbus::utility::DBusPropertiesMap& resp, 1420898f2aa2SEd Tanous nlohmann::json& objectToFillOut) 1421898f2aa2SEd Tanous { 1422*262dcc1cSAlexander Hansen std::optional<DbusEventLogEntry> optEntry = 1423*262dcc1cSAlexander Hansen fillDbusEventLogEntryFromPropertyMap(resp); 1424898f2aa2SEd Tanous 1425*262dcc1cSAlexander Hansen if (!optEntry.has_value()) 1426898f2aa2SEd Tanous { 1427898f2aa2SEd Tanous messages::internalError(asyncResp->res); 1428898f2aa2SEd Tanous return; 1429898f2aa2SEd Tanous } 1430*262dcc1cSAlexander Hansen DbusEventLogEntry entry = optEntry.value(); 1431898f2aa2SEd Tanous 1432898f2aa2SEd Tanous objectToFillOut["@odata.type"] = "#LogEntry.v1_9_0.LogEntry"; 1433898f2aa2SEd Tanous objectToFillOut["@odata.id"] = boost::urls::format( 1434898f2aa2SEd Tanous "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}", 1435*262dcc1cSAlexander Hansen BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(entry.Id)); 1436898f2aa2SEd Tanous objectToFillOut["Name"] = "System Event Log Entry"; 1437*262dcc1cSAlexander Hansen objectToFillOut["Id"] = std::to_string(entry.Id); 1438*262dcc1cSAlexander Hansen objectToFillOut["Message"] = entry.Message; 1439*262dcc1cSAlexander Hansen objectToFillOut["Resolved"] = entry.Resolved; 1440*262dcc1cSAlexander Hansen std::optional<bool> notifyAction = 1441*262dcc1cSAlexander Hansen getProviderNotifyAction(entry.ServiceProviderNotify); 1442898f2aa2SEd Tanous if (notifyAction) 1443898f2aa2SEd Tanous { 1444898f2aa2SEd Tanous objectToFillOut["ServiceProviderNotified"] = *notifyAction; 1445898f2aa2SEd Tanous } 1446*262dcc1cSAlexander Hansen if ((entry.Resolution != nullptr) && !entry.Resolution->empty()) 1447898f2aa2SEd Tanous { 1448*262dcc1cSAlexander Hansen objectToFillOut["Resolution"] = *entry.Resolution; 1449898f2aa2SEd Tanous } 1450898f2aa2SEd Tanous objectToFillOut["EntryType"] = "Event"; 1451*262dcc1cSAlexander Hansen objectToFillOut["Severity"] = 1452*262dcc1cSAlexander Hansen translateSeverityDbusToRedfish(entry.Severity); 1453898f2aa2SEd Tanous objectToFillOut["Created"] = 1454*262dcc1cSAlexander Hansen redfish::time_utils::getDateTimeUintMs(entry.Timestamp); 1455898f2aa2SEd Tanous objectToFillOut["Modified"] = 1456*262dcc1cSAlexander Hansen redfish::time_utils::getDateTimeUintMs(entry.UpdateTimestamp); 1457*262dcc1cSAlexander Hansen if (entry.Path != nullptr) 1458898f2aa2SEd Tanous { 1459898f2aa2SEd Tanous objectToFillOut["AdditionalDataURI"] = boost::urls::format( 1460898f2aa2SEd Tanous "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}/attachment", 1461*262dcc1cSAlexander Hansen BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(entry.Id)); 1462898f2aa2SEd Tanous } 1463898f2aa2SEd Tanous } 1464898f2aa2SEd Tanous 1465b729096dSEd Tanous inline void afterLogEntriesGetManagedObjects( 1466b729096dSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1467b729096dSEd Tanous const boost::system::error_code& ec, 1468b729096dSEd Tanous const dbus::utility::ManagedObjectType& resp) 1469b729096dSEd Tanous { 1470b729096dSEd Tanous if (ec) 1471b729096dSEd Tanous { 1472b729096dSEd Tanous // TODO Handle for specific error code 1473b729096dSEd Tanous BMCWEB_LOG_ERROR("getLogEntriesIfaceData resp_handler got error {}", 1474b729096dSEd Tanous ec); 1475b729096dSEd Tanous messages::internalError(asyncResp->res); 1476b729096dSEd Tanous return; 1477b729096dSEd Tanous } 1478b729096dSEd Tanous nlohmann::json::array_t entriesArray; 1479b729096dSEd Tanous for (const auto& objectPath : resp) 1480b729096dSEd Tanous { 1481898f2aa2SEd Tanous dbus::utility::DBusPropertiesMap propsFlattened; 1482bd79bce8SPatrick Williams auto isEntry = 1483bd79bce8SPatrick Williams std::ranges::find_if(objectPath.second, [](const auto& object) { 1484898f2aa2SEd Tanous return object.first == "xyz.openbmc_project.Logging.Entry"; 1485898f2aa2SEd Tanous }); 1486898f2aa2SEd Tanous if (isEntry == objectPath.second.end()) 1487b729096dSEd Tanous { 1488b729096dSEd Tanous continue; 1489b729096dSEd Tanous } 1490898f2aa2SEd Tanous for (const auto& interfaceMap : objectPath.second) 1491b729096dSEd Tanous { 1492898f2aa2SEd Tanous for (const auto& propertyMap : interfaceMap.second) 1493b729096dSEd Tanous { 1494898f2aa2SEd Tanous propsFlattened.emplace_back(propertyMap.first, 1495898f2aa2SEd Tanous propertyMap.second); 1496b729096dSEd Tanous } 1497b729096dSEd Tanous } 1498898f2aa2SEd Tanous fillEventLogLogEntryFromPropertyMap(asyncResp, propsFlattened, 1499898f2aa2SEd Tanous entriesArray.emplace_back()); 1500b729096dSEd Tanous } 1501898f2aa2SEd Tanous 1502b729096dSEd Tanous std::ranges::sort(entriesArray, [](const nlohmann::json& left, 1503b729096dSEd Tanous const nlohmann::json& right) { 1504b729096dSEd Tanous return (left["Id"] <= right["Id"]); 1505b729096dSEd Tanous }); 1506b729096dSEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = entriesArray.size(); 1507b729096dSEd Tanous asyncResp->res.jsonValue["Members"] = std::move(entriesArray); 1508b729096dSEd Tanous } 1509b729096dSEd Tanous 1510599b9af3SAlexander Hansen inline void handleSystemsLogServiceEventLogLogEntryCollection( 1511599b9af3SAlexander Hansen App& app, const crow::Request& req, 151222d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1513599b9af3SAlexander Hansen const std::string& systemName) 1514599b9af3SAlexander Hansen { 1515c937d2bfSEd Tanous query_param::QueryCapabilities capabilities = { 1516c937d2bfSEd Tanous .canDelegateTop = true, 1517c937d2bfSEd Tanous .canDelegateSkip = true, 1518c937d2bfSEd Tanous }; 1519c937d2bfSEd Tanous query_param::Query delegatedQuery; 1520599b9af3SAlexander Hansen if (!redfish::setUpRedfishRouteWithDelegation(app, req, asyncResp, 1521599b9af3SAlexander Hansen delegatedQuery, capabilities)) 1522c4bf6374SJason M. Bills { 1523c4bf6374SJason M. Bills return; 1524c4bf6374SJason M. Bills } 152525b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 15267f3e84a1SEd Tanous { 15277f3e84a1SEd Tanous // Option currently returns no systems. TBD 15287f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 15297f3e84a1SEd Tanous systemName); 15307f3e84a1SEd Tanous return; 15317f3e84a1SEd Tanous } 1532253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 153322d268cbSEd Tanous { 153422d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 153522d268cbSEd Tanous systemName); 153622d268cbSEd Tanous return; 153722d268cbSEd Tanous } 153822d268cbSEd Tanous 15395143f7a5SJiaqing Zhao size_t top = delegatedQuery.top.value_or(query_param::Query::maxTop); 15403648c8beSEd Tanous size_t skip = delegatedQuery.skip.value_or(0); 15413648c8beSEd Tanous 15427e860f15SJohn Edward Broadbent // Collections don't include the static data added by SubRoute 15437e860f15SJohn Edward Broadbent // because it has a duplicate entry for members 1544c4bf6374SJason M. Bills asyncResp->res.jsonValue["@odata.type"] = 1545c4bf6374SJason M. Bills "#LogEntryCollection.LogEntryCollection"; 1546c4bf6374SJason M. Bills asyncResp->res.jsonValue["@odata.id"] = 1547253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries", 1548253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1549c4bf6374SJason M. Bills asyncResp->res.jsonValue["Name"] = "System Event Log Entries"; 1550c4bf6374SJason M. Bills asyncResp->res.jsonValue["Description"] = 1551c4bf6374SJason M. Bills "Collection of System Event Log Entries"; 1552cb92c03bSAndrew Geissler 15534978b63fSJason M. Bills nlohmann::json& logEntryArray = asyncResp->res.jsonValue["Members"]; 1554c4bf6374SJason M. Bills logEntryArray = nlohmann::json::array(); 15557e860f15SJohn Edward Broadbent // Go through the log files and create a unique ID for each 15567e860f15SJohn Edward Broadbent // entry 155795820184SJason M. Bills std::vector<std::filesystem::path> redfishLogFiles; 155895820184SJason M. Bills getRedfishLogFiles(redfishLogFiles); 1559b01bf299SEd Tanous uint64_t entryCount = 0; 1560cd225da8SJason M. Bills std::string logEntry; 156195820184SJason M. Bills 15627e860f15SJohn Edward Broadbent // Oldest logs are in the last file, so start there and loop 15637e860f15SJohn Edward Broadbent // backwards 1564599b9af3SAlexander Hansen for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend(); it++) 1565c4bf6374SJason M. Bills { 1566cd225da8SJason M. Bills std::ifstream logStream(*it); 156795820184SJason M. Bills if (!logStream.is_open()) 1568c4bf6374SJason M. Bills { 1569c4bf6374SJason M. Bills continue; 1570c4bf6374SJason M. Bills } 1571c4bf6374SJason M. Bills 1572e85d6b16SJason M. Bills // Reset the unique ID on the first entry 1573e85d6b16SJason M. Bills bool firstEntry = true; 157495820184SJason M. Bills while (std::getline(logStream, logEntry)) 157595820184SJason M. Bills { 1576c4bf6374SJason M. Bills std::string idStr; 1577e85d6b16SJason M. Bills if (!getUniqueEntryID(logEntry, idStr, firstEntry)) 1578c4bf6374SJason M. Bills { 1579c4bf6374SJason M. Bills continue; 1580c4bf6374SJason M. Bills } 1581e85d6b16SJason M. Bills firstEntry = false; 1582e85d6b16SJason M. Bills 1583de703c5dSJason M. Bills nlohmann::json::object_t bmcLogEntry; 1584bd79bce8SPatrick Williams LogParseError status = 1585bd79bce8SPatrick Williams fillEventLogEntryJson(idStr, logEntry, bmcLogEntry); 1586ac992cdeSJason M. Bills if (status == LogParseError::messageIdNotInRegistry) 1587ac992cdeSJason M. Bills { 1588ac992cdeSJason M. Bills continue; 1589ac992cdeSJason M. Bills } 1590ac992cdeSJason M. Bills if (status != LogParseError::success) 1591c4bf6374SJason M. Bills { 1592c4bf6374SJason M. Bills messages::internalError(asyncResp->res); 1593c4bf6374SJason M. Bills return; 1594c4bf6374SJason M. Bills } 1595de703c5dSJason M. Bills 1596de703c5dSJason M. Bills entryCount++; 1597de703c5dSJason M. Bills // Handle paging using skip (number of entries to skip from the 1598de703c5dSJason M. Bills // start) and top (number of entries to display) 15993648c8beSEd Tanous if (entryCount <= skip || entryCount > skip + top) 1600de703c5dSJason M. Bills { 1601de703c5dSJason M. Bills continue; 1602de703c5dSJason M. Bills } 1603de703c5dSJason M. Bills 1604b2ba3072SPatrick Williams logEntryArray.emplace_back(std::move(bmcLogEntry)); 1605c4bf6374SJason M. Bills } 160695820184SJason M. Bills } 1607c4bf6374SJason M. Bills asyncResp->res.jsonValue["Members@odata.count"] = entryCount; 16083648c8beSEd Tanous if (skip + top < entryCount) 1609c4bf6374SJason M. Bills { 1610599b9af3SAlexander Hansen asyncResp->res.jsonValue["Members@odata.nextLink"] = 1611599b9af3SAlexander Hansen boost::urls::format( 1612253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/EventLog/Entries?$skip={}", 1613253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(skip + top)); 1614c4bf6374SJason M. Bills } 1615897967deSJason M. Bills } 1616897967deSJason M. Bills 1617599b9af3SAlexander Hansen inline void requestRoutesJournalEventLogEntryCollection(App& app) 1618897967deSJason M. Bills { 1619599b9af3SAlexander Hansen BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/") 1620599b9af3SAlexander Hansen .privileges(redfish::privileges::getLogEntryCollection) 1621599b9af3SAlexander Hansen .methods(boost::beast::http::verb::get)(std::bind_front( 1622599b9af3SAlexander Hansen handleSystemsLogServiceEventLogLogEntryCollection, std::ref(app))); 1623599b9af3SAlexander Hansen } 1624599b9af3SAlexander Hansen 1625599b9af3SAlexander Hansen inline void handleSystemsLogServiceEventLogEntriesGet( 1626599b9af3SAlexander Hansen App& app, const crow::Request& req, 16277e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1628599b9af3SAlexander Hansen const std::string& systemName, const std::string& param) 1629599b9af3SAlexander Hansen { 16303ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 163145ca1b86SEd Tanous { 163245ca1b86SEd Tanous return; 163345ca1b86SEd Tanous } 163425b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 16357f3e84a1SEd Tanous { 16367f3e84a1SEd Tanous // Option currently returns no systems. TBD 16377f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 16387f3e84a1SEd Tanous systemName); 16397f3e84a1SEd Tanous return; 16407f3e84a1SEd Tanous } 164122d268cbSEd Tanous 1642253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 164322d268cbSEd Tanous { 164422d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 164522d268cbSEd Tanous systemName); 164622d268cbSEd Tanous return; 164722d268cbSEd Tanous } 164822d268cbSEd Tanous 16497e860f15SJohn Edward Broadbent const std::string& targetID = param; 16508d1b46d7Szhanghch05 16517e860f15SJohn Edward Broadbent // Go through the log files and check the unique ID for each 16527e860f15SJohn Edward Broadbent // entry to find the target entry 1653897967deSJason M. Bills std::vector<std::filesystem::path> redfishLogFiles; 1654897967deSJason M. Bills getRedfishLogFiles(redfishLogFiles); 1655897967deSJason M. Bills std::string logEntry; 1656897967deSJason M. Bills 16577e860f15SJohn Edward Broadbent // Oldest logs are in the last file, so start there and loop 16587e860f15SJohn Edward Broadbent // backwards 1659599b9af3SAlexander Hansen for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend(); it++) 1660897967deSJason M. Bills { 1661897967deSJason M. Bills std::ifstream logStream(*it); 1662897967deSJason M. Bills if (!logStream.is_open()) 1663897967deSJason M. Bills { 1664897967deSJason M. Bills continue; 1665897967deSJason M. Bills } 1666897967deSJason M. Bills 1667897967deSJason M. Bills // Reset the unique ID on the first entry 1668897967deSJason M. Bills bool firstEntry = true; 1669897967deSJason M. Bills while (std::getline(logStream, logEntry)) 1670897967deSJason M. Bills { 1671897967deSJason M. Bills std::string idStr; 1672897967deSJason M. Bills if (!getUniqueEntryID(logEntry, idStr, firstEntry)) 1673897967deSJason M. Bills { 1674897967deSJason M. Bills continue; 1675897967deSJason M. Bills } 1676897967deSJason M. Bills firstEntry = false; 1677897967deSJason M. Bills 1678897967deSJason M. Bills if (idStr == targetID) 1679897967deSJason M. Bills { 1680de703c5dSJason M. Bills nlohmann::json::object_t bmcLogEntry; 1681bd79bce8SPatrick Williams LogParseError status = 1682bd79bce8SPatrick Williams fillEventLogEntryJson(idStr, logEntry, bmcLogEntry); 1683ac992cdeSJason M. Bills if (status != LogParseError::success) 1684897967deSJason M. Bills { 1685897967deSJason M. Bills messages::internalError(asyncResp->res); 1686897967deSJason M. Bills return; 1687897967deSJason M. Bills } 1688d405bb51SJason M. Bills asyncResp->res.jsonValue.update(bmcLogEntry); 1689897967deSJason M. Bills return; 1690897967deSJason M. Bills } 1691897967deSJason M. Bills } 1692897967deSJason M. Bills } 1693897967deSJason M. Bills // Requested ID was not found 16949db4ba25SJiaqing Zhao messages::resourceNotFound(asyncResp->res, "LogEntry", targetID); 1695599b9af3SAlexander Hansen } 1696599b9af3SAlexander Hansen 1697599b9af3SAlexander Hansen inline void requestRoutesJournalEventLogEntry(App& app) 1698599b9af3SAlexander Hansen { 1699599b9af3SAlexander Hansen BMCWEB_ROUTE( 1700599b9af3SAlexander Hansen app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/") 1701599b9af3SAlexander Hansen .privileges(redfish::privileges::getLogEntry) 1702599b9af3SAlexander Hansen .methods(boost::beast::http::verb::get)(std::bind_front( 1703599b9af3SAlexander Hansen handleSystemsLogServiceEventLogEntriesGet, std::ref(app))); 1704599b9af3SAlexander Hansen } 1705599b9af3SAlexander Hansen 1706599b9af3SAlexander Hansen inline void dBusEventLogEntryCollection( 1707599b9af3SAlexander Hansen const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1708599b9af3SAlexander Hansen { 1709599b9af3SAlexander Hansen // Collections don't include the static data added by SubRoute 1710599b9af3SAlexander Hansen // because it has a duplicate entry for members 1711599b9af3SAlexander Hansen asyncResp->res.jsonValue["@odata.type"] = 1712599b9af3SAlexander Hansen "#LogEntryCollection.LogEntryCollection"; 1713599b9af3SAlexander Hansen asyncResp->res.jsonValue["@odata.id"] = 1714599b9af3SAlexander Hansen std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries", 1715599b9af3SAlexander Hansen BMCWEB_REDFISH_SYSTEM_URI_NAME); 1716599b9af3SAlexander Hansen asyncResp->res.jsonValue["Name"] = "System Event Log Entries"; 1717599b9af3SAlexander Hansen asyncResp->res.jsonValue["Description"] = 1718599b9af3SAlexander Hansen "Collection of System Event Log Entries"; 1719599b9af3SAlexander Hansen 1720599b9af3SAlexander Hansen // DBus implementation of EventLog/Entries 1721599b9af3SAlexander Hansen // Make call to Logging Service to find all log entry objects 1722599b9af3SAlexander Hansen sdbusplus::message::object_path path("/xyz/openbmc_project/logging"); 1723599b9af3SAlexander Hansen dbus::utility::getManagedObjects( 1724599b9af3SAlexander Hansen "xyz.openbmc_project.Logging", path, 1725599b9af3SAlexander Hansen [asyncResp](const boost::system::error_code& ec, 1726599b9af3SAlexander Hansen const dbus::utility::ManagedObjectType& resp) { 1727b729096dSEd Tanous afterLogEntriesGetManagedObjects(asyncResp, ec, resp); 17287e860f15SJohn Edward Broadbent }); 172908a4e4b5SAnthony Wilson } 173008a4e4b5SAnthony Wilson 17317e860f15SJohn Edward Broadbent inline void requestRoutesDBusEventLogEntryCollection(App& app) 173208a4e4b5SAnthony Wilson { 173322d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/") 1734ed398213SEd Tanous .privileges(redfish::privileges::getLogEntryCollection) 1735002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 1736002d39b4SEd Tanous [&app](const crow::Request& req, 173722d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 173822d268cbSEd Tanous const std::string& systemName) { 17393ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 174045ca1b86SEd Tanous { 174145ca1b86SEd Tanous return; 174245ca1b86SEd Tanous } 174325b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 17447f3e84a1SEd Tanous { 17457f3e84a1SEd Tanous // Option currently returns no systems. TBD 17467f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 17477f3e84a1SEd Tanous systemName); 17487f3e84a1SEd Tanous return; 17497f3e84a1SEd Tanous } 1750253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 175122d268cbSEd Tanous { 175222d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 175322d268cbSEd Tanous systemName); 175422d268cbSEd Tanous return; 175522d268cbSEd Tanous } 1756599b9af3SAlexander Hansen dBusEventLogEntryCollection(asyncResp); 1757599b9af3SAlexander Hansen }); 1758599b9af3SAlexander Hansen } 175922d268cbSEd Tanous 1760bd79bce8SPatrick Williams inline void dBusEventLogEntryGet( 1761bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID) 1762599b9af3SAlexander Hansen { 1763599b9af3SAlexander Hansen dbus::utility::escapePathForDbus(entryID); 176408a4e4b5SAnthony Wilson 1765cb92c03bSAndrew Geissler // DBus implementation of EventLog/Entries 1766cb92c03bSAndrew Geissler // Make call to Logging Service to find all log entry objects 1767599b9af3SAlexander Hansen sdbusplus::asio::getAllProperties( 1768599b9af3SAlexander Hansen *crow::connections::systemBus, "xyz.openbmc_project.Logging", 1769599b9af3SAlexander Hansen "/xyz/openbmc_project/logging/entry/" + entryID, "", 1770599b9af3SAlexander Hansen [asyncResp, entryID](const boost::system::error_code& ec, 1771599b9af3SAlexander Hansen const dbus::utility::DBusPropertiesMap& resp) { 1772599b9af3SAlexander Hansen if (ec.value() == EBADR) 1773599b9af3SAlexander Hansen { 1774599b9af3SAlexander Hansen messages::resourceNotFound(asyncResp->res, "EventLogEntry", 1775599b9af3SAlexander Hansen entryID); 1776599b9af3SAlexander Hansen return; 1777599b9af3SAlexander Hansen } 1778cb92c03bSAndrew Geissler if (ec) 1779cb92c03bSAndrew Geissler { 1780bd79bce8SPatrick Williams BMCWEB_LOG_ERROR( 1781bd79bce8SPatrick Williams "EventLogEntry (DBus) resp_handler got error {}", ec); 1782cb92c03bSAndrew Geissler messages::internalError(asyncResp->res); 1783cb92c03bSAndrew Geissler return; 1784cb92c03bSAndrew Geissler } 17859017faf2SAbhishek Patel 1786898f2aa2SEd Tanous fillEventLogLogEntryFromPropertyMap(asyncResp, resp, 1787898f2aa2SEd Tanous asyncResp->res.jsonValue); 1788599b9af3SAlexander Hansen }); 17897e860f15SJohn Edward Broadbent } 1790599b9af3SAlexander Hansen 1791599b9af3SAlexander Hansen inline void 1792599b9af3SAlexander Hansen dBusEventLogEntryPatch(const crow::Request& req, 1793599b9af3SAlexander Hansen const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1794599b9af3SAlexander Hansen const std::string& entryId) 1795599b9af3SAlexander Hansen { 1796599b9af3SAlexander Hansen std::optional<bool> resolved; 1797599b9af3SAlexander Hansen 1798599b9af3SAlexander Hansen if (!json_util::readJsonPatch(req, asyncResp->res, "Resolved", resolved)) 1799599b9af3SAlexander Hansen { 1800599b9af3SAlexander Hansen return; 1801599b9af3SAlexander Hansen } 1802599b9af3SAlexander Hansen BMCWEB_LOG_DEBUG("Set Resolved"); 1803599b9af3SAlexander Hansen 1804599b9af3SAlexander Hansen setDbusProperty(asyncResp, "Resolved", "xyz.openbmc_project.Logging", 1805599b9af3SAlexander Hansen "/xyz/openbmc_project/logging/entry/" + entryId, 1806599b9af3SAlexander Hansen "xyz.openbmc_project.Logging.Entry", "Resolved", 1807599b9af3SAlexander Hansen resolved.value_or(false)); 1808599b9af3SAlexander Hansen } 1809599b9af3SAlexander Hansen 1810bd79bce8SPatrick Williams inline void dBusEventLogEntryDelete( 1811bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID) 1812599b9af3SAlexander Hansen { 1813599b9af3SAlexander Hansen BMCWEB_LOG_DEBUG("Do delete single event entries."); 1814599b9af3SAlexander Hansen 1815599b9af3SAlexander Hansen dbus::utility::escapePathForDbus(entryID); 1816599b9af3SAlexander Hansen 1817599b9af3SAlexander Hansen // Process response from Logging service. 1818599b9af3SAlexander Hansen auto respHandler = [asyncResp, 1819599b9af3SAlexander Hansen entryID](const boost::system::error_code& ec) { 1820599b9af3SAlexander Hansen BMCWEB_LOG_DEBUG("EventLogEntry (DBus) doDelete callback: Done"); 1821599b9af3SAlexander Hansen if (ec) 1822599b9af3SAlexander Hansen { 1823599b9af3SAlexander Hansen if (ec.value() == EBADR) 1824599b9af3SAlexander Hansen { 1825599b9af3SAlexander Hansen messages::resourceNotFound(asyncResp->res, "LogEntry", entryID); 1826599b9af3SAlexander Hansen return; 1827599b9af3SAlexander Hansen } 1828599b9af3SAlexander Hansen // TODO Handle for specific error code 1829599b9af3SAlexander Hansen BMCWEB_LOG_ERROR( 1830599b9af3SAlexander Hansen "EventLogEntry (DBus) doDelete respHandler got error {}", ec); 1831599b9af3SAlexander Hansen asyncResp->res.result( 1832599b9af3SAlexander Hansen boost::beast::http::status::internal_server_error); 1833599b9af3SAlexander Hansen return; 1834599b9af3SAlexander Hansen } 1835599b9af3SAlexander Hansen 1836599b9af3SAlexander Hansen asyncResp->res.result(boost::beast::http::status::ok); 1837599b9af3SAlexander Hansen }; 1838599b9af3SAlexander Hansen 1839599b9af3SAlexander Hansen // Make call to Logging service to request Delete Log 1840599b9af3SAlexander Hansen crow::connections::systemBus->async_method_call( 1841599b9af3SAlexander Hansen respHandler, "xyz.openbmc_project.Logging", 1842599b9af3SAlexander Hansen "/xyz/openbmc_project/logging/entry/" + entryID, 1843599b9af3SAlexander Hansen "xyz.openbmc_project.Object.Delete", "Delete"); 18447e860f15SJohn Edward Broadbent } 18457e860f15SJohn Edward Broadbent 18467e860f15SJohn Edward Broadbent inline void requestRoutesDBusEventLogEntry(App& app) 18477e860f15SJohn Edward Broadbent { 18487e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 184922d268cbSEd Tanous app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/") 1850ed398213SEd Tanous .privileges(redfish::privileges::getLogEntry) 1851002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 1852002d39b4SEd Tanous [&app](const crow::Request& req, 18537e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1854898f2aa2SEd Tanous const std::string& systemName, const std::string& entryId) { 18553ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 18567e860f15SJohn Edward Broadbent { 185745ca1b86SEd Tanous return; 185845ca1b86SEd Tanous } 185925b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 18607f3e84a1SEd Tanous { 18617f3e84a1SEd Tanous // Option currently returns no systems. TBD 18627f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 18637f3e84a1SEd Tanous systemName); 18647f3e84a1SEd Tanous return; 18657f3e84a1SEd Tanous } 1866253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 186722d268cbSEd Tanous { 186822d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 186922d268cbSEd Tanous systemName); 187022d268cbSEd Tanous return; 187122d268cbSEd Tanous } 187222d268cbSEd Tanous 1873898f2aa2SEd Tanous dBusEventLogEntryGet(asyncResp, entryId); 18747e860f15SJohn Edward Broadbent }); 1875336e96c6SChicago Duan 18767e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 187722d268cbSEd Tanous app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/") 1878ed398213SEd Tanous .privileges(redfish::privileges::patchLogEntry) 18797e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::patch)( 188045ca1b86SEd Tanous [&app](const crow::Request& req, 18817e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 188222d268cbSEd Tanous const std::string& systemName, const std::string& entryId) { 18833ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 188445ca1b86SEd Tanous { 188545ca1b86SEd Tanous return; 188645ca1b86SEd Tanous } 188725b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 18887f3e84a1SEd Tanous { 18897f3e84a1SEd Tanous // Option currently returns no systems. TBD 18907f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 18917f3e84a1SEd Tanous systemName); 18927f3e84a1SEd Tanous return; 18937f3e84a1SEd Tanous } 1894253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 189522d268cbSEd Tanous { 189622d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 189722d268cbSEd Tanous systemName); 189822d268cbSEd Tanous return; 189922d268cbSEd Tanous } 190075710de2SXiaochao Ma 1901599b9af3SAlexander Hansen dBusEventLogEntryPatch(req, asyncResp, entryId); 19027e860f15SJohn Edward Broadbent }); 190375710de2SXiaochao Ma 19047e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 190522d268cbSEd Tanous app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/") 1906ed398213SEd Tanous .privileges(redfish::privileges::deleteLogEntry) 1907ed398213SEd Tanous 1908002d39b4SEd Tanous .methods(boost::beast::http::verb::delete_)( 1909002d39b4SEd Tanous [&app](const crow::Request& req, 1910002d39b4SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 191122d268cbSEd Tanous const std::string& systemName, const std::string& param) { 19123ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 1913336e96c6SChicago Duan { 191445ca1b86SEd Tanous return; 191545ca1b86SEd Tanous } 191625b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 19177f3e84a1SEd Tanous { 19187f3e84a1SEd Tanous // Option currently returns no systems. TBD 19197f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 19207f3e84a1SEd Tanous systemName); 19217f3e84a1SEd Tanous return; 19227f3e84a1SEd Tanous } 1923253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 192422d268cbSEd Tanous { 192522d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 192622d268cbSEd Tanous systemName); 192722d268cbSEd Tanous return; 192822d268cbSEd Tanous } 1929599b9af3SAlexander Hansen dBusEventLogEntryDelete(asyncResp, param); 19307e860f15SJohn Edward Broadbent }); 1931400fd1fbSAdriana Kobylak } 1932400fd1fbSAdriana Kobylak 1933b7028ebfSSpencer Ku constexpr const char* hostLoggerFolderPath = "/var/log/console"; 1934b7028ebfSSpencer Ku 1935b7028ebfSSpencer Ku inline bool 1936b7028ebfSSpencer Ku getHostLoggerFiles(const std::string& hostLoggerFilePath, 1937b7028ebfSSpencer Ku std::vector<std::filesystem::path>& hostLoggerFiles) 1938b7028ebfSSpencer Ku { 1939b7028ebfSSpencer Ku std::error_code ec; 1940b7028ebfSSpencer Ku std::filesystem::directory_iterator logPath(hostLoggerFilePath, ec); 1941b7028ebfSSpencer Ku if (ec) 1942b7028ebfSSpencer Ku { 1943bf2ddedeSCarson Labrado BMCWEB_LOG_WARNING("{}", ec.message()); 1944b7028ebfSSpencer Ku return false; 1945b7028ebfSSpencer Ku } 1946b7028ebfSSpencer Ku for (const std::filesystem::directory_entry& it : logPath) 1947b7028ebfSSpencer Ku { 1948b7028ebfSSpencer Ku std::string filename = it.path().filename(); 1949b7028ebfSSpencer Ku // Prefix of each log files is "log". Find the file and save the 1950b7028ebfSSpencer Ku // path 195111ba3979SEd Tanous if (filename.starts_with("log")) 1952b7028ebfSSpencer Ku { 1953b7028ebfSSpencer Ku hostLoggerFiles.emplace_back(it.path()); 1954b7028ebfSSpencer Ku } 1955b7028ebfSSpencer Ku } 1956b7028ebfSSpencer Ku // As the log files rotate, they are appended with a ".#" that is higher for 1957b7028ebfSSpencer Ku // the older logs. Since we start from oldest logs, sort the name in 1958b7028ebfSSpencer Ku // descending order. 1959b7028ebfSSpencer Ku std::sort(hostLoggerFiles.rbegin(), hostLoggerFiles.rend(), 1960b7028ebfSSpencer Ku AlphanumLess<std::string>()); 1961b7028ebfSSpencer Ku 1962b7028ebfSSpencer Ku return true; 1963b7028ebfSSpencer Ku } 1964b7028ebfSSpencer Ku 196502cad96eSEd Tanous inline bool getHostLoggerEntries( 196602cad96eSEd Tanous const std::vector<std::filesystem::path>& hostLoggerFiles, uint64_t skip, 196702cad96eSEd Tanous uint64_t top, std::vector<std::string>& logEntries, size_t& logCount) 1968b7028ebfSSpencer Ku { 1969b7028ebfSSpencer Ku GzFileReader logFile; 1970b7028ebfSSpencer Ku 1971b7028ebfSSpencer Ku // Go though all log files and expose host logs. 1972b7028ebfSSpencer Ku for (const std::filesystem::path& it : hostLoggerFiles) 1973b7028ebfSSpencer Ku { 1974b7028ebfSSpencer Ku if (!logFile.gzGetLines(it.string(), skip, top, logEntries, logCount)) 1975b7028ebfSSpencer Ku { 197662598e31SEd Tanous BMCWEB_LOG_ERROR("fail to expose host logs"); 1977b7028ebfSSpencer Ku return false; 1978b7028ebfSSpencer Ku } 1979b7028ebfSSpencer Ku } 1980b7028ebfSSpencer Ku // Get lastMessage from constructor by getter 1981b7028ebfSSpencer Ku std::string lastMessage = logFile.getLastMessage(); 1982b7028ebfSSpencer Ku if (!lastMessage.empty()) 1983b7028ebfSSpencer Ku { 1984b7028ebfSSpencer Ku logCount++; 1985b7028ebfSSpencer Ku if (logCount > skip && logCount <= (skip + top)) 1986b7028ebfSSpencer Ku { 1987b7028ebfSSpencer Ku logEntries.push_back(lastMessage); 1988b7028ebfSSpencer Ku } 1989b7028ebfSSpencer Ku } 1990b7028ebfSSpencer Ku return true; 1991b7028ebfSSpencer Ku } 1992b7028ebfSSpencer Ku 1993dd72e87bSClaire Weinan inline void handleBMCLogServicesCollectionGet( 1994fdd26906SClaire Weinan crow::App& app, const crow::Request& req, 1995253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1996253f11b8SEd Tanous const std::string& managerId) 19971da66f75SEd Tanous { 19983ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 199945ca1b86SEd Tanous { 200045ca1b86SEd Tanous return; 200145ca1b86SEd Tanous } 2002253f11b8SEd Tanous 2003253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2004253f11b8SEd Tanous { 2005253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2006253f11b8SEd Tanous return; 2007253f11b8SEd Tanous } 2008253f11b8SEd Tanous 20097e860f15SJohn Edward Broadbent // Collections don't include the static data added by SubRoute 20107e860f15SJohn Edward Broadbent // because it has a duplicate entry for members 2011e1f26343SJason M. Bills asyncResp->res.jsonValue["@odata.type"] = 20121da66f75SEd Tanous "#LogServiceCollection.LogServiceCollection"; 2013253f11b8SEd Tanous asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 2014253f11b8SEd Tanous "/redfish/v1/Managers/{}/LogServices", BMCWEB_REDFISH_MANAGER_URI_NAME); 2015002d39b4SEd Tanous asyncResp->res.jsonValue["Name"] = "Open BMC Log Services Collection"; 2016e1f26343SJason M. Bills asyncResp->res.jsonValue["Description"] = 20171da66f75SEd Tanous "Collection of LogServices for this Manager"; 2018002d39b4SEd Tanous nlohmann::json& logServiceArray = asyncResp->res.jsonValue["Members"]; 2019c4bf6374SJason M. Bills logServiceArray = nlohmann::json::array(); 2020fdd26906SClaire Weinan 202125b54dbaSEd Tanous if constexpr (BMCWEB_REDFISH_BMC_JOURNAL) 202225b54dbaSEd Tanous { 2023613dabeaSEd Tanous nlohmann::json::object_t journal; 2024253f11b8SEd Tanous journal["@odata.id"] = 2025253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}/LogServices/Journal", 2026253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 2027b2ba3072SPatrick Williams logServiceArray.emplace_back(std::move(journal)); 202825b54dbaSEd Tanous } 2029fdd26906SClaire Weinan 2030fdd26906SClaire Weinan asyncResp->res.jsonValue["Members@odata.count"] = logServiceArray.size(); 2031fdd26906SClaire Weinan 203225b54dbaSEd Tanous if constexpr (BMCWEB_REDFISH_DUMP_LOG) 203325b54dbaSEd Tanous { 203415912159SGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 20357a1dbc48SGeorge Liu "xyz.openbmc_project.Collection.DeleteAll"}; 20367a1dbc48SGeorge Liu dbus::utility::getSubTreePaths( 20377a1dbc48SGeorge Liu "/xyz/openbmc_project/dump", 0, interfaces, 203825b54dbaSEd Tanous [asyncResp](const boost::system::error_code& ec, 203925b54dbaSEd Tanous const dbus::utility::MapperGetSubTreePathsResponse& 204025b54dbaSEd Tanous subTreePaths) { 2041fdd26906SClaire Weinan if (ec) 2042fdd26906SClaire Weinan { 204362598e31SEd Tanous BMCWEB_LOG_ERROR( 204462598e31SEd Tanous "handleBMCLogServicesCollectionGet respHandler got error {}", 204562598e31SEd Tanous ec); 2046bd79bce8SPatrick Williams // Assume that getting an error simply means there are no 2047bd79bce8SPatrick Williams // dump LogServices. Return without adding any error 2048bd79bce8SPatrick Williams // response. 2049fdd26906SClaire Weinan return; 2050fdd26906SClaire Weinan } 2051fdd26906SClaire Weinan 2052fdd26906SClaire Weinan nlohmann::json& logServiceArrayLocal = 2053fdd26906SClaire Weinan asyncResp->res.jsonValue["Members"]; 2054fdd26906SClaire Weinan 2055fdd26906SClaire Weinan for (const std::string& path : subTreePaths) 2056fdd26906SClaire Weinan { 2057fdd26906SClaire Weinan if (path == "/xyz/openbmc_project/dump/bmc") 2058fdd26906SClaire Weinan { 2059613dabeaSEd Tanous nlohmann::json::object_t member; 2060253f11b8SEd Tanous member["@odata.id"] = boost::urls::format( 2061253f11b8SEd Tanous "/redfish/v1/Managers/{}/LogServices/Dump", 2062253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 2063b2ba3072SPatrick Williams logServiceArrayLocal.emplace_back(std::move(member)); 2064fdd26906SClaire Weinan } 2065fdd26906SClaire Weinan else if (path == "/xyz/openbmc_project/dump/faultlog") 2066fdd26906SClaire Weinan { 2067613dabeaSEd Tanous nlohmann::json::object_t member; 2068253f11b8SEd Tanous member["@odata.id"] = boost::urls::format( 2069253f11b8SEd Tanous "/redfish/v1/Managers/{}/LogServices/FaultLog", 2070253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 2071b2ba3072SPatrick Williams logServiceArrayLocal.emplace_back(std::move(member)); 2072fdd26906SClaire Weinan } 2073fdd26906SClaire Weinan } 2074fdd26906SClaire Weinan 2075e1f26343SJason M. Bills asyncResp->res.jsonValue["Members@odata.count"] = 2076fdd26906SClaire Weinan logServiceArrayLocal.size(); 20777a1dbc48SGeorge Liu }); 207825b54dbaSEd Tanous } 2079fdd26906SClaire Weinan } 2080fdd26906SClaire Weinan 2081fdd26906SClaire Weinan inline void requestRoutesBMCLogServiceCollection(App& app) 2082fdd26906SClaire Weinan { 2083253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/") 2084fdd26906SClaire Weinan .privileges(redfish::privileges::getLogServiceCollection) 2085fdd26906SClaire Weinan .methods(boost::beast::http::verb::get)( 2086dd72e87bSClaire Weinan std::bind_front(handleBMCLogServicesCollectionGet, std::ref(app))); 2087e1f26343SJason M. Bills } 2088e1f26343SJason M. Bills 2089fdd26906SClaire Weinan inline void 2090fdd26906SClaire Weinan getDumpServiceInfo(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2091fdd26906SClaire Weinan const std::string& dumpType) 2092c9bb6861Sraviteja-b { 2093fdd26906SClaire Weinan std::string dumpPath; 2094539d8c6bSEd Tanous log_service::OverWritePolicy overWritePolicy = 2095539d8c6bSEd Tanous log_service::OverWritePolicy::Invalid; 2096fdd26906SClaire Weinan bool collectDiagnosticDataSupported = false; 2097fdd26906SClaire Weinan 2098fdd26906SClaire Weinan if (dumpType == "BMC") 209945ca1b86SEd Tanous { 2100253f11b8SEd Tanous dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/Dump", 2101253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 2102539d8c6bSEd Tanous overWritePolicy = log_service::OverWritePolicy::WrapsWhenFull; 2103fdd26906SClaire Weinan collectDiagnosticDataSupported = true; 2104fdd26906SClaire Weinan } 2105fdd26906SClaire Weinan else if (dumpType == "FaultLog") 2106fdd26906SClaire Weinan { 2107253f11b8SEd Tanous dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/FaultLog", 2108253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 2109539d8c6bSEd Tanous overWritePolicy = log_service::OverWritePolicy::Unknown; 2110fdd26906SClaire Weinan collectDiagnosticDataSupported = false; 2111fdd26906SClaire Weinan } 2112fdd26906SClaire Weinan else if (dumpType == "System") 2113fdd26906SClaire Weinan { 2114253f11b8SEd Tanous dumpPath = std::format("/redfish/v1/Systems/{}/LogServices/Dump", 2115253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 2116539d8c6bSEd Tanous overWritePolicy = log_service::OverWritePolicy::WrapsWhenFull; 2117fdd26906SClaire Weinan collectDiagnosticDataSupported = true; 2118fdd26906SClaire Weinan } 2119fdd26906SClaire Weinan else 2120fdd26906SClaire Weinan { 212162598e31SEd Tanous BMCWEB_LOG_ERROR("getDumpServiceInfo() invalid dump type: {}", 212262598e31SEd Tanous dumpType); 2123fdd26906SClaire Weinan messages::internalError(asyncResp->res); 212445ca1b86SEd Tanous return; 212545ca1b86SEd Tanous } 2126fdd26906SClaire Weinan 2127fdd26906SClaire Weinan asyncResp->res.jsonValue["@odata.id"] = dumpPath; 2128fdd26906SClaire Weinan asyncResp->res.jsonValue["@odata.type"] = "#LogService.v1_2_0.LogService"; 2129c9bb6861Sraviteja-b asyncResp->res.jsonValue["Name"] = "Dump LogService"; 2130fdd26906SClaire Weinan asyncResp->res.jsonValue["Description"] = dumpType + " Dump LogService"; 2131fdd26906SClaire Weinan asyncResp->res.jsonValue["Id"] = std::filesystem::path(dumpPath).filename(); 2132539d8c6bSEd Tanous asyncResp->res.jsonValue["OverWritePolicy"] = overWritePolicy; 21337c8c4058STejas Patil 21347c8c4058STejas Patil std::pair<std::string, std::string> redfishDateTimeOffset = 21352b82937eSEd Tanous redfish::time_utils::getDateTimeOffsetNow(); 21360fda0f12SGeorge Liu asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first; 21377c8c4058STejas Patil asyncResp->res.jsonValue["DateTimeLocalOffset"] = 21387c8c4058STejas Patil redfishDateTimeOffset.second; 21397c8c4058STejas Patil 2140fdd26906SClaire Weinan asyncResp->res.jsonValue["Entries"]["@odata.id"] = dumpPath + "/Entries"; 2141fdd26906SClaire Weinan 2142fdd26906SClaire Weinan if (collectDiagnosticDataSupported) 2143fdd26906SClaire Weinan { 2144002d39b4SEd Tanous asyncResp->res.jsonValue["Actions"]["#LogService.CollectDiagnosticData"] 21451476687dSEd Tanous ["target"] = 2146fdd26906SClaire Weinan dumpPath + "/Actions/LogService.CollectDiagnosticData"; 2147fdd26906SClaire Weinan } 21480d946211SClaire Weinan 21490d946211SClaire Weinan constexpr std::array<std::string_view, 1> interfaces = {deleteAllInterface}; 21500d946211SClaire Weinan dbus::utility::getSubTreePaths( 21510d946211SClaire Weinan "/xyz/openbmc_project/dump", 0, interfaces, 21520d946211SClaire Weinan [asyncResp, dumpType, dumpPath]( 21530d946211SClaire Weinan const boost::system::error_code& ec, 21540d946211SClaire Weinan const dbus::utility::MapperGetSubTreePathsResponse& subTreePaths) { 21550d946211SClaire Weinan if (ec) 21560d946211SClaire Weinan { 2157bd79bce8SPatrick Williams BMCWEB_LOG_ERROR("getDumpServiceInfo respHandler got error {}", 2158bd79bce8SPatrick Williams ec); 21590d946211SClaire Weinan // Assume that getting an error simply means there are no dump 21600d946211SClaire Weinan // LogServices. Return without adding any error response. 21610d946211SClaire Weinan return; 21620d946211SClaire Weinan } 216318f8f608SEd Tanous std::string dbusDumpPath = getDumpPath(dumpType); 21640d946211SClaire Weinan for (const std::string& path : subTreePaths) 21650d946211SClaire Weinan { 21660d946211SClaire Weinan if (path == dbusDumpPath) 21670d946211SClaire Weinan { 2168bd79bce8SPatrick Williams asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"] 2169bd79bce8SPatrick Williams ["target"] = 21700d946211SClaire Weinan dumpPath + "/Actions/LogService.ClearLog"; 21710d946211SClaire Weinan break; 21720d946211SClaire Weinan } 21730d946211SClaire Weinan } 21740d946211SClaire Weinan }); 2175c9bb6861Sraviteja-b } 2176c9bb6861Sraviteja-b 2177fdd26906SClaire Weinan inline void handleLogServicesDumpServiceGet( 2178fdd26906SClaire Weinan crow::App& app, const std::string& dumpType, const crow::Request& req, 2179253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2180253f11b8SEd Tanous const std::string& managerId) 21817e860f15SJohn Edward Broadbent { 21823ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 218345ca1b86SEd Tanous { 218445ca1b86SEd Tanous return; 218545ca1b86SEd Tanous } 2186253f11b8SEd Tanous 2187253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2188253f11b8SEd Tanous { 2189253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2190253f11b8SEd Tanous return; 2191253f11b8SEd Tanous } 2192253f11b8SEd Tanous 2193fdd26906SClaire Weinan getDumpServiceInfo(asyncResp, dumpType); 2194fdd26906SClaire Weinan } 2195c9bb6861Sraviteja-b 219622d268cbSEd Tanous inline void handleLogServicesDumpServiceComputerSystemGet( 219722d268cbSEd Tanous crow::App& app, const crow::Request& req, 219822d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 219922d268cbSEd Tanous const std::string& chassisId) 220022d268cbSEd Tanous { 220122d268cbSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 220222d268cbSEd Tanous { 220322d268cbSEd Tanous return; 220422d268cbSEd Tanous } 2205253f11b8SEd Tanous if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME) 220622d268cbSEd Tanous { 220722d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId); 220822d268cbSEd Tanous return; 220922d268cbSEd Tanous } 221022d268cbSEd Tanous getDumpServiceInfo(asyncResp, "System"); 221122d268cbSEd Tanous } 221222d268cbSEd Tanous 2213fdd26906SClaire Weinan inline void handleLogServicesDumpEntriesCollectionGet( 2214fdd26906SClaire Weinan crow::App& app, const std::string& dumpType, const crow::Request& req, 2215253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2216253f11b8SEd Tanous const std::string& managerId) 2217fdd26906SClaire Weinan { 2218fdd26906SClaire Weinan if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2219fdd26906SClaire Weinan { 2220fdd26906SClaire Weinan return; 2221fdd26906SClaire Weinan } 2222253f11b8SEd Tanous 2223253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2224253f11b8SEd Tanous { 2225253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2226253f11b8SEd Tanous return; 2227253f11b8SEd Tanous } 2228fdd26906SClaire Weinan getDumpEntryCollection(asyncResp, dumpType); 2229fdd26906SClaire Weinan } 2230fdd26906SClaire Weinan 223122d268cbSEd Tanous inline void handleLogServicesDumpEntriesCollectionComputerSystemGet( 223222d268cbSEd Tanous crow::App& app, const crow::Request& req, 223322d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 223422d268cbSEd Tanous const std::string& chassisId) 223522d268cbSEd Tanous { 223622d268cbSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 223722d268cbSEd Tanous { 223822d268cbSEd Tanous return; 223922d268cbSEd Tanous } 2240253f11b8SEd Tanous if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME) 224122d268cbSEd Tanous { 224222d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId); 224322d268cbSEd Tanous return; 224422d268cbSEd Tanous } 224522d268cbSEd Tanous getDumpEntryCollection(asyncResp, "System"); 224622d268cbSEd Tanous } 224722d268cbSEd Tanous 2248fdd26906SClaire Weinan inline void handleLogServicesDumpEntryGet( 2249fdd26906SClaire Weinan crow::App& app, const std::string& dumpType, const crow::Request& req, 2250fdd26906SClaire Weinan const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2251253f11b8SEd Tanous const std::string& managerId, const std::string& dumpId) 2252fdd26906SClaire Weinan { 2253fdd26906SClaire Weinan if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2254fdd26906SClaire Weinan { 2255fdd26906SClaire Weinan return; 2256fdd26906SClaire Weinan } 2257253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2258253f11b8SEd Tanous { 2259253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2260253f11b8SEd Tanous return; 2261253f11b8SEd Tanous } 2262fdd26906SClaire Weinan getDumpEntryById(asyncResp, dumpId, dumpType); 2263fdd26906SClaire Weinan } 2264168d1b1aSCarson Labrado 226522d268cbSEd Tanous inline void handleLogServicesDumpEntryComputerSystemGet( 226622d268cbSEd Tanous crow::App& app, const crow::Request& req, 226722d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 226822d268cbSEd Tanous const std::string& chassisId, const std::string& dumpId) 226922d268cbSEd Tanous { 227022d268cbSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 227122d268cbSEd Tanous { 227222d268cbSEd Tanous return; 227322d268cbSEd Tanous } 2274253f11b8SEd Tanous if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME) 227522d268cbSEd Tanous { 227622d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId); 227722d268cbSEd Tanous return; 227822d268cbSEd Tanous } 227922d268cbSEd Tanous getDumpEntryById(asyncResp, dumpId, "System"); 228022d268cbSEd Tanous } 2281fdd26906SClaire Weinan 2282fdd26906SClaire Weinan inline void handleLogServicesDumpEntryDelete( 2283fdd26906SClaire Weinan crow::App& app, const std::string& dumpType, const crow::Request& req, 2284fdd26906SClaire Weinan const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2285253f11b8SEd Tanous const std::string& managerId, const std::string& dumpId) 2286fdd26906SClaire Weinan { 2287fdd26906SClaire Weinan if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2288fdd26906SClaire Weinan { 2289fdd26906SClaire Weinan return; 2290fdd26906SClaire Weinan } 2291253f11b8SEd Tanous 2292253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2293253f11b8SEd Tanous { 2294253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2295253f11b8SEd Tanous return; 2296253f11b8SEd Tanous } 2297fdd26906SClaire Weinan deleteDumpEntry(asyncResp, dumpId, dumpType); 2298fdd26906SClaire Weinan } 2299fdd26906SClaire Weinan 230022d268cbSEd Tanous inline void handleLogServicesDumpEntryComputerSystemDelete( 230122d268cbSEd Tanous crow::App& app, const crow::Request& req, 230222d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 230322d268cbSEd Tanous const std::string& chassisId, const std::string& dumpId) 230422d268cbSEd Tanous { 230522d268cbSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 230622d268cbSEd Tanous { 230722d268cbSEd Tanous return; 230822d268cbSEd Tanous } 2309253f11b8SEd Tanous if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME) 231022d268cbSEd Tanous { 231122d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId); 231222d268cbSEd Tanous return; 231322d268cbSEd Tanous } 231422d268cbSEd Tanous deleteDumpEntry(asyncResp, dumpId, "System"); 231522d268cbSEd Tanous } 231622d268cbSEd Tanous 2317168d1b1aSCarson Labrado inline void handleLogServicesDumpEntryDownloadGet( 2318168d1b1aSCarson Labrado crow::App& app, const std::string& dumpType, const crow::Request& req, 2319168d1b1aSCarson Labrado const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2320253f11b8SEd Tanous const std::string& managerId, const std::string& dumpId) 2321168d1b1aSCarson Labrado { 2322168d1b1aSCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2323168d1b1aSCarson Labrado { 2324168d1b1aSCarson Labrado return; 2325168d1b1aSCarson Labrado } 2326253f11b8SEd Tanous 2327253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2328253f11b8SEd Tanous { 2329253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2330253f11b8SEd Tanous return; 2331253f11b8SEd Tanous } 2332168d1b1aSCarson Labrado downloadDumpEntry(asyncResp, dumpId, dumpType); 2333168d1b1aSCarson Labrado } 2334168d1b1aSCarson Labrado 2335168d1b1aSCarson Labrado inline void handleDBusEventLogEntryDownloadGet( 2336168d1b1aSCarson Labrado crow::App& app, const std::string& dumpType, const crow::Request& req, 2337168d1b1aSCarson Labrado const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2338168d1b1aSCarson Labrado const std::string& systemName, const std::string& entryID) 2339168d1b1aSCarson Labrado { 2340168d1b1aSCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2341168d1b1aSCarson Labrado { 2342168d1b1aSCarson Labrado return; 2343168d1b1aSCarson Labrado } 2344168d1b1aSCarson Labrado if (!http_helpers::isContentTypeAllowed( 2345168d1b1aSCarson Labrado req.getHeaderValue("Accept"), 2346168d1b1aSCarson Labrado http_helpers::ContentType::OctetStream, true)) 2347168d1b1aSCarson Labrado { 2348168d1b1aSCarson Labrado asyncResp->res.result(boost::beast::http::status::bad_request); 2349168d1b1aSCarson Labrado return; 2350168d1b1aSCarson Labrado } 2351168d1b1aSCarson Labrado downloadEventLogEntry(asyncResp, systemName, entryID, dumpType); 2352168d1b1aSCarson Labrado } 2353168d1b1aSCarson Labrado 2354fdd26906SClaire Weinan inline void handleLogServicesDumpCollectDiagnosticDataPost( 2355fdd26906SClaire Weinan crow::App& app, const std::string& dumpType, const crow::Request& req, 2356253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2357253f11b8SEd Tanous const std::string& managerId) 2358fdd26906SClaire Weinan { 2359fdd26906SClaire Weinan if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2360fdd26906SClaire Weinan { 2361fdd26906SClaire Weinan return; 2362fdd26906SClaire Weinan } 2363253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2364253f11b8SEd Tanous { 2365253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2366253f11b8SEd Tanous return; 2367253f11b8SEd Tanous } 2368253f11b8SEd Tanous 2369fdd26906SClaire Weinan createDump(asyncResp, req, dumpType); 2370fdd26906SClaire Weinan } 2371fdd26906SClaire Weinan 237222d268cbSEd Tanous inline void handleLogServicesDumpCollectDiagnosticDataComputerSystemPost( 237322d268cbSEd Tanous crow::App& app, const crow::Request& req, 237422d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 23757f3e84a1SEd Tanous const std::string& systemName) 237622d268cbSEd Tanous { 237722d268cbSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 237822d268cbSEd Tanous { 237922d268cbSEd Tanous return; 238022d268cbSEd Tanous } 23817f3e84a1SEd Tanous 238225b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 238322d268cbSEd Tanous { 23847f3e84a1SEd Tanous // Option currently returns no systems. TBD 23857f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 23867f3e84a1SEd Tanous systemName); 23877f3e84a1SEd Tanous return; 23887f3e84a1SEd Tanous } 2389253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 23907f3e84a1SEd Tanous { 23917f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 23927f3e84a1SEd Tanous systemName); 239322d268cbSEd Tanous return; 239422d268cbSEd Tanous } 239522d268cbSEd Tanous createDump(asyncResp, req, "System"); 239622d268cbSEd Tanous } 239722d268cbSEd Tanous 2398fdd26906SClaire Weinan inline void handleLogServicesDumpClearLogPost( 2399fdd26906SClaire Weinan crow::App& app, const std::string& dumpType, const crow::Request& req, 2400253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2401253f11b8SEd Tanous const std::string& managerId) 2402fdd26906SClaire Weinan { 2403fdd26906SClaire Weinan if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2404fdd26906SClaire Weinan { 2405fdd26906SClaire Weinan return; 2406fdd26906SClaire Weinan } 2407253f11b8SEd Tanous 2408253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2409253f11b8SEd Tanous { 2410253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2411253f11b8SEd Tanous return; 2412253f11b8SEd Tanous } 2413fdd26906SClaire Weinan clearDump(asyncResp, dumpType); 2414fdd26906SClaire Weinan } 2415fdd26906SClaire Weinan 241622d268cbSEd Tanous inline void handleLogServicesDumpClearLogComputerSystemPost( 241722d268cbSEd Tanous crow::App& app, const crow::Request& req, 241822d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 24197f3e84a1SEd Tanous const std::string& systemName) 242022d268cbSEd Tanous { 242122d268cbSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 242222d268cbSEd Tanous { 242322d268cbSEd Tanous return; 242422d268cbSEd Tanous } 242525b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 242622d268cbSEd Tanous { 24277f3e84a1SEd Tanous // Option currently returns no systems. TBD 24287f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 24297f3e84a1SEd Tanous systemName); 24307f3e84a1SEd Tanous return; 24317f3e84a1SEd Tanous } 2432253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 24337f3e84a1SEd Tanous { 24347f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 24357f3e84a1SEd Tanous systemName); 243622d268cbSEd Tanous return; 243722d268cbSEd Tanous } 243822d268cbSEd Tanous clearDump(asyncResp, "System"); 243922d268cbSEd Tanous } 244022d268cbSEd Tanous 2441fdd26906SClaire Weinan inline void requestRoutesBMCDumpService(App& app) 2442fdd26906SClaire Weinan { 2443253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/Dump/") 2444fdd26906SClaire Weinan .privileges(redfish::privileges::getLogService) 2445fdd26906SClaire Weinan .methods(boost::beast::http::verb::get)(std::bind_front( 2446fdd26906SClaire Weinan handleLogServicesDumpServiceGet, std::ref(app), "BMC")); 2447fdd26906SClaire Weinan } 2448fdd26906SClaire Weinan 2449fdd26906SClaire Weinan inline void requestRoutesBMCDumpEntryCollection(App& app) 2450fdd26906SClaire Weinan { 2451253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/") 2452fdd26906SClaire Weinan .privileges(redfish::privileges::getLogEntryCollection) 2453fdd26906SClaire Weinan .methods(boost::beast::http::verb::get)(std::bind_front( 2454fdd26906SClaire Weinan handleLogServicesDumpEntriesCollectionGet, std::ref(app), "BMC")); 2455c9bb6861Sraviteja-b } 2456c9bb6861Sraviteja-b 24577e860f15SJohn Edward Broadbent inline void requestRoutesBMCDumpEntry(App& app) 2458c9bb6861Sraviteja-b { 24597e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 2460253f11b8SEd Tanous "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/") 2461ed398213SEd Tanous .privileges(redfish::privileges::getLogEntry) 2462fdd26906SClaire Weinan .methods(boost::beast::http::verb::get)(std::bind_front( 2463fdd26906SClaire Weinan handleLogServicesDumpEntryGet, std::ref(app), "BMC")); 2464fdd26906SClaire Weinan 24657e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 2466253f11b8SEd Tanous "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/") 2467ed398213SEd Tanous .privileges(redfish::privileges::deleteLogEntry) 2468fdd26906SClaire Weinan .methods(boost::beast::http::verb::delete_)(std::bind_front( 2469fdd26906SClaire Weinan handleLogServicesDumpEntryDelete, std::ref(app), "BMC")); 2470c9bb6861Sraviteja-b } 2471c9bb6861Sraviteja-b 2472168d1b1aSCarson Labrado inline void requestRoutesBMCDumpEntryDownload(App& app) 2473168d1b1aSCarson Labrado { 2474168d1b1aSCarson Labrado BMCWEB_ROUTE( 2475168d1b1aSCarson Labrado app, 2476253f11b8SEd Tanous "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/attachment/") 2477168d1b1aSCarson Labrado .privileges(redfish::privileges::getLogEntry) 2478168d1b1aSCarson Labrado .methods(boost::beast::http::verb::get)(std::bind_front( 2479168d1b1aSCarson Labrado handleLogServicesDumpEntryDownloadGet, std::ref(app), "BMC")); 2480168d1b1aSCarson Labrado } 2481168d1b1aSCarson Labrado 24827e860f15SJohn Edward Broadbent inline void requestRoutesBMCDumpCreate(App& app) 2483c9bb6861Sraviteja-b { 24840fda0f12SGeorge Liu BMCWEB_ROUTE( 24850fda0f12SGeorge Liu app, 2486253f11b8SEd Tanous "/redfish/v1/Managers/<str>/LogServices/Dump/Actions/LogService.CollectDiagnosticData/") 2487ed398213SEd Tanous .privileges(redfish::privileges::postLogService) 24887e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 2489fdd26906SClaire Weinan std::bind_front(handleLogServicesDumpCollectDiagnosticDataPost, 2490fdd26906SClaire Weinan std::ref(app), "BMC")); 2491a43be80fSAsmitha Karunanithi } 2492a43be80fSAsmitha Karunanithi 24937e860f15SJohn Edward Broadbent inline void requestRoutesBMCDumpClear(App& app) 249480319af1SAsmitha Karunanithi { 24950fda0f12SGeorge Liu BMCWEB_ROUTE( 24960fda0f12SGeorge Liu app, 2497253f11b8SEd Tanous "/redfish/v1/Managers/<str>/LogServices/Dump/Actions/LogService.ClearLog/") 2498ed398213SEd Tanous .privileges(redfish::privileges::postLogService) 2499fdd26906SClaire Weinan .methods(boost::beast::http::verb::post)(std::bind_front( 2500fdd26906SClaire Weinan handleLogServicesDumpClearLogPost, std::ref(app), "BMC")); 250145ca1b86SEd Tanous } 2502fdd26906SClaire Weinan 2503168d1b1aSCarson Labrado inline void requestRoutesDBusEventLogEntryDownload(App& app) 2504168d1b1aSCarson Labrado { 2505168d1b1aSCarson Labrado BMCWEB_ROUTE( 2506168d1b1aSCarson Labrado app, 25079e9d99daSRavi Teja "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/attachment/") 2508168d1b1aSCarson Labrado .privileges(redfish::privileges::getLogEntry) 2509168d1b1aSCarson Labrado .methods(boost::beast::http::verb::get)(std::bind_front( 2510168d1b1aSCarson Labrado handleDBusEventLogEntryDownloadGet, std::ref(app), "System")); 2511168d1b1aSCarson Labrado } 2512168d1b1aSCarson Labrado 2513fdd26906SClaire Weinan inline void requestRoutesFaultLogDumpService(App& app) 2514fdd26906SClaire Weinan { 2515253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/") 2516fdd26906SClaire Weinan .privileges(redfish::privileges::getLogService) 2517fdd26906SClaire Weinan .methods(boost::beast::http::verb::get)(std::bind_front( 2518fdd26906SClaire Weinan handleLogServicesDumpServiceGet, std::ref(app), "FaultLog")); 2519fdd26906SClaire Weinan } 2520fdd26906SClaire Weinan 2521fdd26906SClaire Weinan inline void requestRoutesFaultLogDumpEntryCollection(App& app) 2522fdd26906SClaire Weinan { 2523253f11b8SEd Tanous BMCWEB_ROUTE(app, 2524253f11b8SEd Tanous "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/") 2525fdd26906SClaire Weinan .privileges(redfish::privileges::getLogEntryCollection) 2526fdd26906SClaire Weinan .methods(boost::beast::http::verb::get)( 2527fdd26906SClaire Weinan std::bind_front(handleLogServicesDumpEntriesCollectionGet, 2528fdd26906SClaire Weinan std::ref(app), "FaultLog")); 2529fdd26906SClaire Weinan } 2530fdd26906SClaire Weinan 2531fdd26906SClaire Weinan inline void requestRoutesFaultLogDumpEntry(App& app) 2532fdd26906SClaire Weinan { 2533253f11b8SEd Tanous BMCWEB_ROUTE( 2534253f11b8SEd Tanous app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/<str>/") 2535fdd26906SClaire Weinan .privileges(redfish::privileges::getLogEntry) 2536fdd26906SClaire Weinan .methods(boost::beast::http::verb::get)(std::bind_front( 2537fdd26906SClaire Weinan handleLogServicesDumpEntryGet, std::ref(app), "FaultLog")); 2538fdd26906SClaire Weinan 2539253f11b8SEd Tanous BMCWEB_ROUTE( 2540253f11b8SEd Tanous app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/<str>/") 2541fdd26906SClaire Weinan .privileges(redfish::privileges::deleteLogEntry) 2542fdd26906SClaire Weinan .methods(boost::beast::http::verb::delete_)(std::bind_front( 2543fdd26906SClaire Weinan handleLogServicesDumpEntryDelete, std::ref(app), "FaultLog")); 2544fdd26906SClaire Weinan } 2545fdd26906SClaire Weinan 2546fdd26906SClaire Weinan inline void requestRoutesFaultLogDumpClear(App& app) 2547fdd26906SClaire Weinan { 2548fdd26906SClaire Weinan BMCWEB_ROUTE( 2549fdd26906SClaire Weinan app, 2550253f11b8SEd Tanous "/redfish/v1/Managers/<str>/LogServices/FaultLog/Actions/LogService.ClearLog/") 2551fdd26906SClaire Weinan .privileges(redfish::privileges::postLogService) 2552fdd26906SClaire Weinan .methods(boost::beast::http::verb::post)(std::bind_front( 2553fdd26906SClaire Weinan handleLogServicesDumpClearLogPost, std::ref(app), "FaultLog")); 25545cb1dd27SAsmitha Karunanithi } 25555cb1dd27SAsmitha Karunanithi 25567e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpService(App& app) 25575cb1dd27SAsmitha Karunanithi { 255822d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Dump/") 2559ed398213SEd Tanous .privileges(redfish::privileges::getLogService) 25606ab9ad54SClaire Weinan .methods(boost::beast::http::verb::get)(std::bind_front( 256122d268cbSEd Tanous handleLogServicesDumpServiceComputerSystemGet, std::ref(app))); 25625cb1dd27SAsmitha Karunanithi } 25635cb1dd27SAsmitha Karunanithi 25647e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpEntryCollection(App& app) 25657e860f15SJohn Edward Broadbent { 256622d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/") 2567ed398213SEd Tanous .privileges(redfish::privileges::getLogEntryCollection) 256822d268cbSEd Tanous .methods(boost::beast::http::verb::get)(std::bind_front( 256922d268cbSEd Tanous handleLogServicesDumpEntriesCollectionComputerSystemGet, 257022d268cbSEd Tanous std::ref(app))); 25715cb1dd27SAsmitha Karunanithi } 25725cb1dd27SAsmitha Karunanithi 25737e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpEntry(App& app) 25745cb1dd27SAsmitha Karunanithi { 25757e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 257622d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/<str>/") 2577ed398213SEd Tanous .privileges(redfish::privileges::getLogEntry) 25786ab9ad54SClaire Weinan .methods(boost::beast::http::verb::get)(std::bind_front( 257922d268cbSEd Tanous handleLogServicesDumpEntryComputerSystemGet, std::ref(app))); 25808d1b46d7Szhanghch05 25817e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 258222d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/<str>/") 2583ed398213SEd Tanous .privileges(redfish::privileges::deleteLogEntry) 25846ab9ad54SClaire Weinan .methods(boost::beast::http::verb::delete_)(std::bind_front( 258522d268cbSEd Tanous handleLogServicesDumpEntryComputerSystemDelete, std::ref(app))); 25865cb1dd27SAsmitha Karunanithi } 2587c9bb6861Sraviteja-b 25887e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpCreate(App& app) 2589c9bb6861Sraviteja-b { 25900fda0f12SGeorge Liu BMCWEB_ROUTE( 25910fda0f12SGeorge Liu app, 259222d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Dump/Actions/LogService.CollectDiagnosticData/") 2593ed398213SEd Tanous .privileges(redfish::privileges::postLogService) 259422d268cbSEd Tanous .methods(boost::beast::http::verb::post)(std::bind_front( 259522d268cbSEd Tanous handleLogServicesDumpCollectDiagnosticDataComputerSystemPost, 259622d268cbSEd Tanous std::ref(app))); 2597a43be80fSAsmitha Karunanithi } 2598a43be80fSAsmitha Karunanithi 25997e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpClear(App& app) 2600a43be80fSAsmitha Karunanithi { 26010fda0f12SGeorge Liu BMCWEB_ROUTE( 26020fda0f12SGeorge Liu app, 260322d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Dump/Actions/LogService.ClearLog/") 2604ed398213SEd Tanous .privileges(redfish::privileges::postLogService) 26056ab9ad54SClaire Weinan .methods(boost::beast::http::verb::post)(std::bind_front( 260622d268cbSEd Tanous handleLogServicesDumpClearLogComputerSystemPost, std::ref(app))); 2607013487e5Sraviteja-b } 2608013487e5Sraviteja-b 26097e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpService(App& app) 26101da66f75SEd Tanous { 26113946028dSAppaRao Puli // Note: Deviated from redfish privilege registry for GET & HEAD 26123946028dSAppaRao Puli // method for security reasons. 26131da66f75SEd Tanous /** 26141da66f75SEd Tanous * Functions triggers appropriate requests on DBus 26151da66f75SEd Tanous */ 261622d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Crashdump/") 2617ed398213SEd Tanous // This is incorrect, should be: 2618ed398213SEd Tanous //.privileges(redfish::privileges::getLogService) 2619432a890cSEd Tanous .privileges({{"ConfigureManager"}}) 2620bd79bce8SPatrick Williams .methods( 2621bd79bce8SPatrick Williams boost::beast::http::verb:: 2622bd79bce8SPatrick Williams get)([&app](const crow::Request& req, 262322d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 262422d268cbSEd Tanous const std::string& systemName) { 26253ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 262645ca1b86SEd Tanous { 262745ca1b86SEd Tanous return; 262845ca1b86SEd Tanous } 262925b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 26307f3e84a1SEd Tanous { 26317f3e84a1SEd Tanous // Option currently returns no systems. TBD 26327f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 26337f3e84a1SEd Tanous systemName); 26347f3e84a1SEd Tanous return; 26357f3e84a1SEd Tanous } 2636253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 263722d268cbSEd Tanous { 263822d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 263922d268cbSEd Tanous systemName); 264022d268cbSEd Tanous return; 264122d268cbSEd Tanous } 264222d268cbSEd Tanous 26437e860f15SJohn Edward Broadbent // Copy over the static data to include the entries added by 26447e860f15SJohn Edward Broadbent // SubRoute 26450f74e643SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 2646253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/Crashdump", 2647253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 2648e1f26343SJason M. Bills asyncResp->res.jsonValue["@odata.type"] = 26498e6c099aSJason M. Bills "#LogService.v1_2_0.LogService"; 26504f50ae4bSGunnar Mills asyncResp->res.jsonValue["Name"] = "Open BMC Oem Crashdump Service"; 26514f50ae4bSGunnar Mills asyncResp->res.jsonValue["Description"] = "Oem Crashdump Service"; 265215b89725SV-Sanjana asyncResp->res.jsonValue["Id"] = "Crashdump"; 2653539d8c6bSEd Tanous asyncResp->res.jsonValue["OverWritePolicy"] = 2654539d8c6bSEd Tanous log_service::OverWritePolicy::WrapsWhenFull; 2655e1f26343SJason M. Bills asyncResp->res.jsonValue["MaxNumberOfRecords"] = 3; 26567c8c4058STejas Patil 26577c8c4058STejas Patil std::pair<std::string, std::string> redfishDateTimeOffset = 26582b82937eSEd Tanous redfish::time_utils::getDateTimeOffsetNow(); 26597c8c4058STejas Patil asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first; 26607c8c4058STejas Patil asyncResp->res.jsonValue["DateTimeLocalOffset"] = 26617c8c4058STejas Patil redfishDateTimeOffset.second; 26627c8c4058STejas Patil 2663bd79bce8SPatrick Williams asyncResp->res.jsonValue["Entries"]["@odata.id"] = std::format( 2664bd79bce8SPatrick Williams "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries", 2665253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 2666253f11b8SEd Tanous asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"] 2667253f11b8SEd Tanous ["target"] = std::format( 2668253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/Crashdump/Actions/LogService.ClearLog", 2669253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 2670bd79bce8SPatrick Williams asyncResp->res 2671bd79bce8SPatrick Williams .jsonValue["Actions"]["#LogService.CollectDiagnosticData"] 2672253f11b8SEd Tanous ["target"] = std::format( 2673253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/Crashdump/Actions/LogService.CollectDiagnosticData", 2674253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 26757e860f15SJohn Edward Broadbent }); 26761da66f75SEd Tanous } 26771da66f75SEd Tanous 26787e860f15SJohn Edward Broadbent void inline requestRoutesCrashdumpClear(App& app) 26795b61b5e8SJason M. Bills { 26800fda0f12SGeorge Liu BMCWEB_ROUTE( 26810fda0f12SGeorge Liu app, 268222d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Crashdump/Actions/LogService.ClearLog/") 2683ed398213SEd Tanous // This is incorrect, should be: 2684ed398213SEd Tanous //.privileges(redfish::privileges::postLogService) 2685432a890cSEd Tanous .privileges({{"ConfigureComponents"}}) 26867e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 268745ca1b86SEd Tanous [&app](const crow::Request& req, 268822d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 268922d268cbSEd Tanous const std::string& systemName) { 26903ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 269145ca1b86SEd Tanous { 269245ca1b86SEd Tanous return; 269345ca1b86SEd Tanous } 269425b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 26957f3e84a1SEd Tanous { 26967f3e84a1SEd Tanous // Option currently returns no systems. TBD 26977f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 26987f3e84a1SEd Tanous systemName); 26997f3e84a1SEd Tanous return; 27007f3e84a1SEd Tanous } 2701253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 270222d268cbSEd Tanous { 270322d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 270422d268cbSEd Tanous systemName); 270522d268cbSEd Tanous return; 270622d268cbSEd Tanous } 27075b61b5e8SJason M. Bills crow::connections::systemBus->async_method_call( 27085e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec, 2709cb13a392SEd Tanous const std::string&) { 27105b61b5e8SJason M. Bills if (ec) 27115b61b5e8SJason M. Bills { 27125b61b5e8SJason M. Bills messages::internalError(asyncResp->res); 27135b61b5e8SJason M. Bills return; 27145b61b5e8SJason M. Bills } 27155b61b5e8SJason M. Bills messages::success(asyncResp->res); 27165b61b5e8SJason M. Bills }, 2717bd79bce8SPatrick Williams crashdumpObject, crashdumpPath, deleteAllInterface, 2718bd79bce8SPatrick Williams "DeleteAll"); 27197e860f15SJohn Edward Broadbent }); 27205b61b5e8SJason M. Bills } 27215b61b5e8SJason M. Bills 27224ff0f1f4SEd Tanous inline void 27238d1b46d7Szhanghch05 logCrashdumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 27248d1b46d7Szhanghch05 const std::string& logID, nlohmann::json& logEntryJson) 2725e855dd28SJason M. Bills { 2726043a0536SJohnathan Mantey auto getStoredLogCallback = 2727b9d36b47SEd Tanous [asyncResp, logID, 27285e7e2dc5SEd Tanous &logEntryJson](const boost::system::error_code& ec, 2729b9d36b47SEd Tanous const dbus::utility::DBusPropertiesMap& params) { 2730e855dd28SJason M. Bills if (ec) 2731e855dd28SJason M. Bills { 273262598e31SEd Tanous BMCWEB_LOG_DEBUG("failed to get log ec: {}", ec.message()); 27331ddcf01aSJason M. Bills if (ec.value() == 27341ddcf01aSJason M. Bills boost::system::linux_error::bad_request_descriptor) 27351ddcf01aSJason M. Bills { 2736bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "LogEntry", 2737bd79bce8SPatrick Williams logID); 27381ddcf01aSJason M. Bills } 27391ddcf01aSJason M. Bills else 27401ddcf01aSJason M. Bills { 2741e855dd28SJason M. Bills messages::internalError(asyncResp->res); 27421ddcf01aSJason M. Bills } 2743e855dd28SJason M. Bills return; 2744e855dd28SJason M. Bills } 2745043a0536SJohnathan Mantey 2746043a0536SJohnathan Mantey std::string timestamp{}; 2747043a0536SJohnathan Mantey std::string filename{}; 2748043a0536SJohnathan Mantey std::string logfile{}; 27492c70f800SEd Tanous parseCrashdumpParameters(params, filename, timestamp, logfile); 2750043a0536SJohnathan Mantey 2751043a0536SJohnathan Mantey if (filename.empty() || timestamp.empty()) 2752e855dd28SJason M. Bills { 27539db4ba25SJiaqing Zhao messages::resourceNotFound(asyncResp->res, "LogEntry", logID); 2754e855dd28SJason M. Bills return; 2755e855dd28SJason M. Bills } 2756e855dd28SJason M. Bills 2757043a0536SJohnathan Mantey std::string crashdumpURI = 2758bd79bce8SPatrick Williams std::format( 2759bd79bce8SPatrick Williams "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries/", 2760253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME) + 2761043a0536SJohnathan Mantey logID + "/" + filename; 276284afc48bSJason M. Bills nlohmann::json::object_t logEntry; 27639c11a172SVijay Lobo logEntry["@odata.type"] = "#LogEntry.v1_9_0.LogEntry"; 2764ef4c65b7SEd Tanous logEntry["@odata.id"] = boost::urls::format( 2765253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries/{}", 2766253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, logID); 276784afc48bSJason M. Bills logEntry["Name"] = "CPU Crashdump"; 276884afc48bSJason M. Bills logEntry["Id"] = logID; 2769539d8c6bSEd Tanous logEntry["EntryType"] = log_entry::LogEntryType::Oem; 277084afc48bSJason M. Bills logEntry["AdditionalDataURI"] = std::move(crashdumpURI); 277184afc48bSJason M. Bills logEntry["DiagnosticDataType"] = "OEM"; 277284afc48bSJason M. Bills logEntry["OEMDiagnosticDataType"] = "PECICrashdump"; 277384afc48bSJason M. Bills logEntry["Created"] = std::move(timestamp); 27742b20ef6eSJason M. Bills 27752b20ef6eSJason M. Bills // If logEntryJson references an array of LogEntry resources 27762b20ef6eSJason M. Bills // ('Members' list), then push this as a new entry, otherwise set it 27772b20ef6eSJason M. Bills // directly 27782b20ef6eSJason M. Bills if (logEntryJson.is_array()) 27792b20ef6eSJason M. Bills { 27802b20ef6eSJason M. Bills logEntryJson.push_back(logEntry); 27812b20ef6eSJason M. Bills asyncResp->res.jsonValue["Members@odata.count"] = 27822b20ef6eSJason M. Bills logEntryJson.size(); 27832b20ef6eSJason M. Bills } 27842b20ef6eSJason M. Bills else 27852b20ef6eSJason M. Bills { 2786d405bb51SJason M. Bills logEntryJson.update(logEntry); 27872b20ef6eSJason M. Bills } 2788e855dd28SJason M. Bills }; 2789d1bde9e5SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 2790d1bde9e5SKrzysztof Grobelny *crow::connections::systemBus, crashdumpObject, 2791d1bde9e5SKrzysztof Grobelny crashdumpPath + std::string("/") + logID, crashdumpInterface, 2792d1bde9e5SKrzysztof Grobelny std::move(getStoredLogCallback)); 2793e855dd28SJason M. Bills } 2794e855dd28SJason M. Bills 27957e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpEntryCollection(App& app) 27961da66f75SEd Tanous { 27973946028dSAppaRao Puli // Note: Deviated from redfish privilege registry for GET & HEAD 27983946028dSAppaRao Puli // method for security reasons. 27991da66f75SEd Tanous /** 28001da66f75SEd Tanous * Functions triggers appropriate requests on DBus 28011da66f75SEd Tanous */ 28027e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 280322d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/") 2804ed398213SEd Tanous // This is incorrect, should be. 2805ed398213SEd Tanous //.privileges(redfish::privileges::postLogEntryCollection) 2806432a890cSEd Tanous .privileges({{"ConfigureComponents"}}) 2807bd79bce8SPatrick Williams .methods( 2808bd79bce8SPatrick Williams boost::beast::http::verb:: 2809bd79bce8SPatrick Williams get)([&app](const crow::Request& req, 281022d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 281122d268cbSEd Tanous const std::string& systemName) { 28123ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 281345ca1b86SEd Tanous { 281445ca1b86SEd Tanous return; 281545ca1b86SEd Tanous } 281625b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 28177f3e84a1SEd Tanous { 28187f3e84a1SEd Tanous // Option currently returns no systems. TBD 28197f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 28207f3e84a1SEd Tanous systemName); 28217f3e84a1SEd Tanous return; 28227f3e84a1SEd Tanous } 2823253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 282422d268cbSEd Tanous { 282522d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 282622d268cbSEd Tanous systemName); 282722d268cbSEd Tanous return; 282822d268cbSEd Tanous } 282922d268cbSEd Tanous 28307a1dbc48SGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 28317a1dbc48SGeorge Liu crashdumpInterface}; 28327a1dbc48SGeorge Liu dbus::utility::getSubTreePaths( 28337a1dbc48SGeorge Liu "/", 0, interfaces, 28347a1dbc48SGeorge Liu [asyncResp](const boost::system::error_code& ec, 28352b20ef6eSJason M. Bills const std::vector<std::string>& resp) { 28361da66f75SEd Tanous if (ec) 28371da66f75SEd Tanous { 28381da66f75SEd Tanous if (ec.value() != 28391da66f75SEd Tanous boost::system::errc::no_such_file_or_directory) 28401da66f75SEd Tanous { 284162598e31SEd Tanous BMCWEB_LOG_DEBUG("failed to get entries ec: {}", 284262598e31SEd Tanous ec.message()); 2843f12894f8SJason M. Bills messages::internalError(asyncResp->res); 28441da66f75SEd Tanous return; 28451da66f75SEd Tanous } 28461da66f75SEd Tanous } 2847e1f26343SJason M. Bills asyncResp->res.jsonValue["@odata.type"] = 28481da66f75SEd Tanous "#LogEntryCollection.LogEntryCollection"; 2849253f11b8SEd Tanous asyncResp->res.jsonValue["@odata.id"] = std::format( 2850253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries", 2851253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 2852bd79bce8SPatrick Williams asyncResp->res.jsonValue["Name"] = 2853bd79bce8SPatrick Williams "Open BMC Crashdump Entries"; 2854e1f26343SJason M. Bills asyncResp->res.jsonValue["Description"] = 2855424c4176SJason M. Bills "Collection of Crashdump Entries"; 2856bd79bce8SPatrick Williams asyncResp->res.jsonValue["Members"] = 2857bd79bce8SPatrick Williams nlohmann::json::array(); 2858a2dd60a6SBrandon Kim asyncResp->res.jsonValue["Members@odata.count"] = 0; 28592b20ef6eSJason M. Bills 28602b20ef6eSJason M. Bills for (const std::string& path : resp) 28611da66f75SEd Tanous { 28622b20ef6eSJason M. Bills const sdbusplus::message::object_path objPath(path); 2863e855dd28SJason M. Bills // Get the log ID 28642b20ef6eSJason M. Bills std::string logID = objPath.filename(); 28652b20ef6eSJason M. Bills if (logID.empty()) 28661da66f75SEd Tanous { 2867e855dd28SJason M. Bills continue; 28681da66f75SEd Tanous } 2869e855dd28SJason M. Bills // Add the log entry to the array 28702b20ef6eSJason M. Bills logCrashdumpEntry(asyncResp, logID, 28712b20ef6eSJason M. Bills asyncResp->res.jsonValue["Members"]); 28721da66f75SEd Tanous } 28737a1dbc48SGeorge Liu }); 28747e860f15SJohn Edward Broadbent }); 28751da66f75SEd Tanous } 28761da66f75SEd Tanous 28777e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpEntry(App& app) 28781da66f75SEd Tanous { 28793946028dSAppaRao Puli // Note: Deviated from redfish privilege registry for GET & HEAD 28803946028dSAppaRao Puli // method for security reasons. 28811da66f75SEd Tanous 28827e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 288322d268cbSEd Tanous app, "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/<str>/") 2884ed398213SEd Tanous // this is incorrect, should be 2885ed398213SEd Tanous // .privileges(redfish::privileges::getLogEntry) 2886432a890cSEd Tanous .privileges({{"ConfigureComponents"}}) 28877e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 288845ca1b86SEd Tanous [&app](const crow::Request& req, 28897e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 289022d268cbSEd Tanous const std::string& systemName, const std::string& param) { 28913ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 289245ca1b86SEd Tanous { 289345ca1b86SEd Tanous return; 289445ca1b86SEd Tanous } 289525b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 28967f3e84a1SEd Tanous { 28977f3e84a1SEd Tanous // Option currently returns no systems. TBD 28987f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 28997f3e84a1SEd Tanous systemName); 29007f3e84a1SEd Tanous return; 29017f3e84a1SEd Tanous } 2902253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 290322d268cbSEd Tanous { 290422d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 290522d268cbSEd Tanous systemName); 290622d268cbSEd Tanous return; 290722d268cbSEd Tanous } 29087e860f15SJohn Edward Broadbent const std::string& logID = param; 2909e855dd28SJason M. Bills logCrashdumpEntry(asyncResp, logID, asyncResp->res.jsonValue); 29107e860f15SJohn Edward Broadbent }); 2911e855dd28SJason M. Bills } 2912e855dd28SJason M. Bills 29137e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpFile(App& app) 2914e855dd28SJason M. Bills { 29153946028dSAppaRao Puli // Note: Deviated from redfish privilege registry for GET & HEAD 29163946028dSAppaRao Puli // method for security reasons. 29177e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 29187e860f15SJohn Edward Broadbent app, 291922d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/<str>/<str>/") 2920ed398213SEd Tanous .privileges(redfish::privileges::getLogEntry) 29217e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 2922a4ce114aSNan Zhou [](const crow::Request& req, 29237e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 292422d268cbSEd Tanous const std::string& systemName, const std::string& logID, 292522d268cbSEd Tanous const std::string& fileName) { 2926bd79bce8SPatrick Williams // Do not call getRedfishRoute here since the crashdump file is 2927bd79bce8SPatrick Williams // not a Redfish resource. 292822d268cbSEd Tanous 292925b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 29307f3e84a1SEd Tanous { 29317f3e84a1SEd Tanous // Option currently returns no systems. TBD 29327f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 29337f3e84a1SEd Tanous systemName); 29347f3e84a1SEd Tanous return; 29357f3e84a1SEd Tanous } 2936253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 293722d268cbSEd Tanous { 293822d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 293922d268cbSEd Tanous systemName); 294022d268cbSEd Tanous return; 294122d268cbSEd Tanous } 294222d268cbSEd Tanous 2943043a0536SJohnathan Mantey auto getStoredLogCallback = 2944bd79bce8SPatrick Williams [asyncResp, logID, fileName, 2945bd79bce8SPatrick Williams url(boost::urls::url(req.url()))]( 29465e7e2dc5SEd Tanous const boost::system::error_code& ec, 2947bd79bce8SPatrick Williams const std::vector<std::pair< 2948bd79bce8SPatrick Williams std::string, dbus::utility::DbusVariantType>>& 29497e860f15SJohn Edward Broadbent resp) { 29501da66f75SEd Tanous if (ec) 29511da66f75SEd Tanous { 2952bd79bce8SPatrick Williams BMCWEB_LOG_DEBUG("failed to get log ec: {}", 2953bd79bce8SPatrick Williams ec.message()); 2954f12894f8SJason M. Bills messages::internalError(asyncResp->res); 29551da66f75SEd Tanous return; 29561da66f75SEd Tanous } 2957e855dd28SJason M. Bills 2958043a0536SJohnathan Mantey std::string dbusFilename{}; 2959043a0536SJohnathan Mantey std::string dbusTimestamp{}; 2960043a0536SJohnathan Mantey std::string dbusFilepath{}; 2961043a0536SJohnathan Mantey 2962bd79bce8SPatrick Williams parseCrashdumpParameters(resp, dbusFilename, 2963bd79bce8SPatrick Williams dbusTimestamp, dbusFilepath); 2964043a0536SJohnathan Mantey 2965043a0536SJohnathan Mantey if (dbusFilename.empty() || dbusTimestamp.empty() || 2966043a0536SJohnathan Mantey dbusFilepath.empty()) 29671da66f75SEd Tanous { 2968bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, 2969bd79bce8SPatrick Williams "LogEntry", logID); 29701da66f75SEd Tanous return; 29711da66f75SEd Tanous } 2972e855dd28SJason M. Bills 2973043a0536SJohnathan Mantey // Verify the file name parameter is correct 2974043a0536SJohnathan Mantey if (fileName != dbusFilename) 2975043a0536SJohnathan Mantey { 2976bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, 2977bd79bce8SPatrick Williams "LogEntry", logID); 2978043a0536SJohnathan Mantey return; 2979043a0536SJohnathan Mantey } 2980043a0536SJohnathan Mantey 2981d51c61b4SMyung Bae if (asyncResp->res.openFile(dbusFilepath) != 2982d51c61b4SMyung Bae crow::OpenCode::Success) 2983043a0536SJohnathan Mantey { 2984bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, 2985bd79bce8SPatrick Williams "LogEntry", logID); 2986043a0536SJohnathan Mantey return; 2987043a0536SJohnathan Mantey } 2988043a0536SJohnathan Mantey 29897e860f15SJohn Edward Broadbent // Configure this to be a file download when accessed 29907e860f15SJohn Edward Broadbent // from a browser 2991d9f6c621SEd Tanous asyncResp->res.addHeader( 2992bd79bce8SPatrick Williams boost::beast::http::field::content_disposition, 2993bd79bce8SPatrick Williams "attachment"); 29941da66f75SEd Tanous }; 2995d1bde9e5SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 2996d1bde9e5SKrzysztof Grobelny *crow::connections::systemBus, crashdumpObject, 2997bd79bce8SPatrick Williams crashdumpPath + std::string("/") + logID, 2998bd79bce8SPatrick Williams crashdumpInterface, std::move(getStoredLogCallback)); 29997e860f15SJohn Edward Broadbent }); 30001da66f75SEd Tanous } 30011da66f75SEd Tanous 3002c5a4c82aSJason M. Bills enum class OEMDiagnosticType 3003c5a4c82aSJason M. Bills { 3004c5a4c82aSJason M. Bills onDemand, 3005c5a4c82aSJason M. Bills telemetry, 3006c5a4c82aSJason M. Bills invalid, 3007c5a4c82aSJason M. Bills }; 3008c5a4c82aSJason M. Bills 300926ccae32SEd Tanous inline OEMDiagnosticType getOEMDiagnosticType(std::string_view oemDiagStr) 3010c5a4c82aSJason M. Bills { 3011c5a4c82aSJason M. Bills if (oemDiagStr == "OnDemand") 3012c5a4c82aSJason M. Bills { 3013c5a4c82aSJason M. Bills return OEMDiagnosticType::onDemand; 3014c5a4c82aSJason M. Bills } 3015c5a4c82aSJason M. Bills if (oemDiagStr == "Telemetry") 3016c5a4c82aSJason M. Bills { 3017c5a4c82aSJason M. Bills return OEMDiagnosticType::telemetry; 3018c5a4c82aSJason M. Bills } 3019c5a4c82aSJason M. Bills 3020c5a4c82aSJason M. Bills return OEMDiagnosticType::invalid; 3021c5a4c82aSJason M. Bills } 3022c5a4c82aSJason M. Bills 30237e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpCollect(App& app) 30241da66f75SEd Tanous { 30253946028dSAppaRao Puli // Note: Deviated from redfish privilege registry for GET & HEAD 30263946028dSAppaRao Puli // method for security reasons. 30270fda0f12SGeorge Liu BMCWEB_ROUTE( 30280fda0f12SGeorge Liu app, 302922d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Crashdump/Actions/LogService.CollectDiagnosticData/") 3030ed398213SEd Tanous // The below is incorrect; Should be ConfigureManager 3031ed398213SEd Tanous //.privileges(redfish::privileges::postLogService) 3032432a890cSEd Tanous .privileges({{"ConfigureComponents"}}) 3033002d39b4SEd Tanous .methods(boost::beast::http::verb::post)( 3034002d39b4SEd Tanous [&app](const crow::Request& req, 303522d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 303622d268cbSEd Tanous const std::string& systemName) { 30373ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 303845ca1b86SEd Tanous { 303945ca1b86SEd Tanous return; 304045ca1b86SEd Tanous } 304122d268cbSEd Tanous 304225b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 30437f3e84a1SEd Tanous { 30447f3e84a1SEd Tanous // Option currently returns no systems. TBD 30457f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 30467f3e84a1SEd Tanous systemName); 30477f3e84a1SEd Tanous return; 30487f3e84a1SEd Tanous } 3049253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 305022d268cbSEd Tanous { 305122d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 305222d268cbSEd Tanous systemName); 305322d268cbSEd Tanous return; 305422d268cbSEd Tanous } 305522d268cbSEd Tanous 30568e6c099aSJason M. Bills std::string diagnosticDataType; 30578e6c099aSJason M. Bills std::string oemDiagnosticDataType; 305815ed6780SWilly Tu if (!redfish::json_util::readJsonAction( 3059bd79bce8SPatrick Williams req, asyncResp->res, "DiagnosticDataType", 3060bd79bce8SPatrick Williams diagnosticDataType, "OEMDiagnosticDataType", 3061bd79bce8SPatrick Williams oemDiagnosticDataType)) 30628e6c099aSJason M. Bills { 30638e6c099aSJason M. Bills return; 30648e6c099aSJason M. Bills } 30658e6c099aSJason M. Bills 30668e6c099aSJason M. Bills if (diagnosticDataType != "OEM") 30678e6c099aSJason M. Bills { 306862598e31SEd Tanous BMCWEB_LOG_ERROR( 306962598e31SEd Tanous "Only OEM DiagnosticDataType supported for Crashdump"); 30708e6c099aSJason M. Bills messages::actionParameterValueFormatError( 3071bd79bce8SPatrick Williams asyncResp->res, diagnosticDataType, 3072bd79bce8SPatrick Williams "DiagnosticDataType", "CollectDiagnosticData"); 30738e6c099aSJason M. Bills return; 30748e6c099aSJason M. Bills } 30758e6c099aSJason M. Bills 3076c5a4c82aSJason M. Bills OEMDiagnosticType oemDiagType = 3077c5a4c82aSJason M. Bills getOEMDiagnosticType(oemDiagnosticDataType); 3078c5a4c82aSJason M. Bills 3079c5a4c82aSJason M. Bills std::string iface; 3080c5a4c82aSJason M. Bills std::string method; 3081c5a4c82aSJason M. Bills std::string taskMatchStr; 3082c5a4c82aSJason M. Bills if (oemDiagType == OEMDiagnosticType::onDemand) 3083c5a4c82aSJason M. Bills { 3084c5a4c82aSJason M. Bills iface = crashdumpOnDemandInterface; 3085c5a4c82aSJason M. Bills method = "GenerateOnDemandLog"; 3086bd79bce8SPatrick Williams taskMatchStr = 3087bd79bce8SPatrick Williams "type='signal'," 3088c5a4c82aSJason M. Bills "interface='org.freedesktop.DBus.Properties'," 3089c5a4c82aSJason M. Bills "member='PropertiesChanged'," 3090c5a4c82aSJason M. Bills "arg0namespace='com.intel.crashdump'"; 3091c5a4c82aSJason M. Bills } 3092c5a4c82aSJason M. Bills else if (oemDiagType == OEMDiagnosticType::telemetry) 3093c5a4c82aSJason M. Bills { 3094c5a4c82aSJason M. Bills iface = crashdumpTelemetryInterface; 3095c5a4c82aSJason M. Bills method = "GenerateTelemetryLog"; 3096bd79bce8SPatrick Williams taskMatchStr = 3097bd79bce8SPatrick Williams "type='signal'," 3098c5a4c82aSJason M. Bills "interface='org.freedesktop.DBus.Properties'," 3099c5a4c82aSJason M. Bills "member='PropertiesChanged'," 3100c5a4c82aSJason M. Bills "arg0namespace='com.intel.crashdump'"; 3101c5a4c82aSJason M. Bills } 3102c5a4c82aSJason M. Bills else 3103c5a4c82aSJason M. Bills { 310462598e31SEd Tanous BMCWEB_LOG_ERROR("Unsupported OEMDiagnosticDataType: {}", 310562598e31SEd Tanous oemDiagnosticDataType); 3106c5a4c82aSJason M. Bills messages::actionParameterValueFormatError( 3107bd79bce8SPatrick Williams asyncResp->res, oemDiagnosticDataType, 3108bd79bce8SPatrick Williams "OEMDiagnosticDataType", "CollectDiagnosticData"); 3109c5a4c82aSJason M. Bills return; 3110c5a4c82aSJason M. Bills } 3111c5a4c82aSJason M. Bills 3112c5a4c82aSJason M. Bills auto collectCrashdumpCallback = 3113c5a4c82aSJason M. Bills [asyncResp, payload(task::Payload(req)), 31145e7e2dc5SEd Tanous taskMatchStr](const boost::system::error_code& ec, 311598be3e39SEd Tanous const std::string&) mutable { 31161da66f75SEd Tanous if (ec) 31171da66f75SEd Tanous { 3118bd79bce8SPatrick Williams if (ec.value() == 3119bd79bce8SPatrick Williams boost::system::errc::operation_not_supported) 31201da66f75SEd Tanous { 3121f12894f8SJason M. Bills messages::resourceInStandby(asyncResp->res); 31221da66f75SEd Tanous } 3123bd79bce8SPatrick Williams else if (ec.value() == boost::system::errc:: 3124bd79bce8SPatrick Williams device_or_resource_busy) 31254363d3b2SJason M. Bills { 3126bd79bce8SPatrick Williams messages::serviceTemporarilyUnavailable( 3127bd79bce8SPatrick Williams asyncResp->res, "60"); 31284363d3b2SJason M. Bills } 31291da66f75SEd Tanous else 31301da66f75SEd Tanous { 3131f12894f8SJason M. Bills messages::internalError(asyncResp->res); 31321da66f75SEd Tanous } 31331da66f75SEd Tanous return; 31341da66f75SEd Tanous } 3135bd79bce8SPatrick Williams std::shared_ptr<task::TaskData> task = 3136bd79bce8SPatrick Williams task::TaskData::createTask( 3137bd79bce8SPatrick Williams [](const boost::system::error_code& ec2, 3138bd79bce8SPatrick Williams sdbusplus::message_t&, 3139bd79bce8SPatrick Williams const std::shared_ptr<task::TaskData>& 3140bd79bce8SPatrick Williams taskData) { 31418b24275dSEd Tanous if (!ec2) 314266afe4faSJames Feist { 3143bd79bce8SPatrick Williams taskData->messages.emplace_back( 3144bd79bce8SPatrick Williams messages::taskCompletedOK( 3145bd79bce8SPatrick Williams std::to_string( 3146bd79bce8SPatrick Williams taskData->index))); 3147831d6b09SJames Feist taskData->state = "Completed"; 314866afe4faSJames Feist } 314932898ceaSJames Feist return task::completed; 315066afe4faSJames Feist }, 3151c5a4c82aSJason M. Bills taskMatchStr); 3152c5a4c82aSJason M. Bills 315346229577SJames Feist task->startTimer(std::chrono::minutes(5)); 315446229577SJames Feist task->populateResp(asyncResp->res); 315598be3e39SEd Tanous task->payload.emplace(std::move(payload)); 31561da66f75SEd Tanous }; 31578e6c099aSJason M. Bills 31581da66f75SEd Tanous crow::connections::systemBus->async_method_call( 3159bd79bce8SPatrick Williams std::move(collectCrashdumpCallback), crashdumpObject, 3160bd79bce8SPatrick Williams crashdumpPath, iface, method); 31617e860f15SJohn Edward Broadbent }); 31626eda7685SKenny L. Ku } 31636eda7685SKenny L. Ku 3164599b9af3SAlexander Hansen inline void dBusLogServiceActionsClear( 3165599b9af3SAlexander Hansen const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 3166599b9af3SAlexander Hansen { 3167599b9af3SAlexander Hansen BMCWEB_LOG_DEBUG("Do delete all entries."); 3168599b9af3SAlexander Hansen 3169599b9af3SAlexander Hansen // Process response from Logging service. 3170599b9af3SAlexander Hansen auto respHandler = [asyncResp](const boost::system::error_code& ec) { 3171599b9af3SAlexander Hansen BMCWEB_LOG_DEBUG("doClearLog resp_handler callback: Done"); 3172599b9af3SAlexander Hansen if (ec) 3173599b9af3SAlexander Hansen { 3174599b9af3SAlexander Hansen // TODO Handle for specific error code 3175599b9af3SAlexander Hansen BMCWEB_LOG_ERROR("doClearLog resp_handler got error {}", ec); 3176599b9af3SAlexander Hansen asyncResp->res.result( 3177599b9af3SAlexander Hansen boost::beast::http::status::internal_server_error); 3178599b9af3SAlexander Hansen return; 3179599b9af3SAlexander Hansen } 3180599b9af3SAlexander Hansen 3181599b9af3SAlexander Hansen asyncResp->res.result(boost::beast::http::status::no_content); 3182599b9af3SAlexander Hansen }; 3183599b9af3SAlexander Hansen 3184599b9af3SAlexander Hansen // Make call to Logging service to request Clear Log 3185599b9af3SAlexander Hansen crow::connections::systemBus->async_method_call( 3186599b9af3SAlexander Hansen respHandler, "xyz.openbmc_project.Logging", 3187599b9af3SAlexander Hansen "/xyz/openbmc_project/logging", 3188599b9af3SAlexander Hansen "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll"); 3189599b9af3SAlexander Hansen } 3190599b9af3SAlexander Hansen 3191cb92c03bSAndrew Geissler /** 3192cb92c03bSAndrew Geissler * DBusLogServiceActionsClear class supports POST method for ClearLog action. 3193cb92c03bSAndrew Geissler */ 31947e860f15SJohn Edward Broadbent inline void requestRoutesDBusLogServiceActionsClear(App& app) 3195cb92c03bSAndrew Geissler { 3196cb92c03bSAndrew Geissler /** 3197cb92c03bSAndrew Geissler * Function handles POST method request. 3198cb92c03bSAndrew Geissler * The Clear Log actions does not require any parameter.The action deletes 3199cb92c03bSAndrew Geissler * all entries found in the Entries collection for this Log Service. 3200cb92c03bSAndrew Geissler */ 32017e860f15SJohn Edward Broadbent 32020fda0f12SGeorge Liu BMCWEB_ROUTE( 32030fda0f12SGeorge Liu app, 320422d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/EventLog/Actions/LogService.ClearLog/") 3205ed398213SEd Tanous .privileges(redfish::privileges::postLogService) 32067e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 320745ca1b86SEd Tanous [&app](const crow::Request& req, 320822d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 320922d268cbSEd Tanous const std::string& systemName) { 32103ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 321145ca1b86SEd Tanous { 321245ca1b86SEd Tanous return; 321345ca1b86SEd Tanous } 321425b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 32157f3e84a1SEd Tanous { 32167f3e84a1SEd Tanous // Option currently returns no systems. TBD 32177f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 32187f3e84a1SEd Tanous systemName); 32197f3e84a1SEd Tanous return; 32207f3e84a1SEd Tanous } 3221253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 322222d268cbSEd Tanous { 322322d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 322422d268cbSEd Tanous systemName); 322522d268cbSEd Tanous return; 322622d268cbSEd Tanous } 3227599b9af3SAlexander Hansen dBusLogServiceActionsClear(asyncResp); 32287e860f15SJohn Edward Broadbent }); 3229cb92c03bSAndrew Geissler } 3230a3316fc6SZhikuiRen 32311da66f75SEd Tanous } // namespace redfish 3232