11da66f75SEd Tanous /* 21da66f75SEd Tanous // Copyright (c) 2018 Intel Corporation 31da66f75SEd Tanous // 41da66f75SEd Tanous // Licensed under the Apache License, Version 2.0 (the "License"); 51da66f75SEd Tanous // you may not use this file except in compliance with the License. 61da66f75SEd Tanous // You may obtain a copy of the License at 71da66f75SEd Tanous // 81da66f75SEd Tanous // http://www.apache.org/licenses/LICENSE-2.0 91da66f75SEd Tanous // 101da66f75SEd Tanous // Unless required by applicable law or agreed to in writing, software 111da66f75SEd Tanous // distributed under the License is distributed on an "AS IS" BASIS, 121da66f75SEd Tanous // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131da66f75SEd Tanous // See the License for the specific language governing permissions and 141da66f75SEd 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" 333ccb3adbSEd Tanous #include "utils/dbus_utils.hpp" 345b90429aSEd Tanous #include "utils/json_utils.hpp" 353ccb3adbSEd Tanous #include "utils/time_utils.hpp" 361da66f75SEd Tanous 3775e8e218SMyung Bae #include <systemd/sd-id128.h> 388e31778eSAsmitha Karunanithi #include <tinyxml2.h> 39400fd1fbSAdriana Kobylak #include <unistd.h> 40e1f26343SJason M. Bills 4107c8c20dSEd Tanous #include <boost/beast/http/verb.hpp> 421da66f75SEd Tanous #include <boost/container/flat_map.hpp> 431ddcf01aSJason M. Bills #include <boost/system/linux_error.hpp> 44ef4c65b7SEd Tanous #include <boost/url/format.hpp> 45d1bde9e5SKrzysztof Grobelny #include <sdbusplus/asio/property.hpp> 46d1bde9e5SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp> 471214b7e7SGunnar Mills 487a1dbc48SGeorge Liu #include <array> 49647b3cdcSGeorge Liu #include <charconv> 50b5f288d2SAbhilash Raju #include <cstddef> 514418c7f0SJames Feist #include <filesystem> 5218f8f608SEd Tanous #include <iterator> 5375710de2SXiaochao Ma #include <optional> 543544d2a7SEd Tanous #include <ranges> 5526702d01SEd Tanous #include <span> 5618f8f608SEd Tanous #include <string> 57cd225da8SJason M. Bills #include <string_view> 58abf2add6SEd Tanous #include <variant> 591da66f75SEd Tanous 601da66f75SEd Tanous namespace redfish 611da66f75SEd Tanous { 621da66f75SEd Tanous 6389492a15SPatrick Williams constexpr const char* crashdumpObject = "com.intel.crashdump"; 6489492a15SPatrick Williams constexpr const char* crashdumpPath = "/com/intel/crashdump"; 6589492a15SPatrick Williams constexpr const char* crashdumpInterface = "com.intel.crashdump"; 6689492a15SPatrick Williams constexpr const char* deleteAllInterface = 675b61b5e8SJason M. Bills "xyz.openbmc_project.Collection.DeleteAll"; 6889492a15SPatrick Williams constexpr const char* crashdumpOnDemandInterface = 69424c4176SJason M. Bills "com.intel.crashdump.OnDemand"; 7089492a15SPatrick Williams constexpr const char* crashdumpTelemetryInterface = 716eda7685SKenny L. Ku "com.intel.crashdump.Telemetry"; 721da66f75SEd Tanous 738e31778eSAsmitha Karunanithi enum class DumpCreationProgress 748e31778eSAsmitha Karunanithi { 758e31778eSAsmitha Karunanithi DUMP_CREATE_SUCCESS, 768e31778eSAsmitha Karunanithi DUMP_CREATE_FAILED, 778e31778eSAsmitha Karunanithi DUMP_CREATE_INPROGRESS 788e31778eSAsmitha Karunanithi }; 798e31778eSAsmitha Karunanithi 80f6150403SJames Feist namespace fs = std::filesystem; 811da66f75SEd Tanous 82cb92c03bSAndrew Geissler inline std::string translateSeverityDbusToRedfish(const std::string& s) 83cb92c03bSAndrew Geissler { 84d4d25793SEd Tanous if ((s == "xyz.openbmc_project.Logging.Entry.Level.Alert") || 85d4d25793SEd Tanous (s == "xyz.openbmc_project.Logging.Entry.Level.Critical") || 86d4d25793SEd Tanous (s == "xyz.openbmc_project.Logging.Entry.Level.Emergency") || 87d4d25793SEd Tanous (s == "xyz.openbmc_project.Logging.Entry.Level.Error")) 88cb92c03bSAndrew Geissler { 89cb92c03bSAndrew Geissler return "Critical"; 90cb92c03bSAndrew Geissler } 913174e4dfSEd Tanous if ((s == "xyz.openbmc_project.Logging.Entry.Level.Debug") || 92d4d25793SEd Tanous (s == "xyz.openbmc_project.Logging.Entry.Level.Informational") || 93d4d25793SEd Tanous (s == "xyz.openbmc_project.Logging.Entry.Level.Notice")) 94cb92c03bSAndrew Geissler { 95cb92c03bSAndrew Geissler return "OK"; 96cb92c03bSAndrew Geissler } 973174e4dfSEd Tanous if (s == "xyz.openbmc_project.Logging.Entry.Level.Warning") 98cb92c03bSAndrew Geissler { 99cb92c03bSAndrew Geissler return "Warning"; 100cb92c03bSAndrew Geissler } 101cb92c03bSAndrew Geissler return ""; 102cb92c03bSAndrew Geissler } 103cb92c03bSAndrew Geissler 1049017faf2SAbhishek Patel inline std::optional<bool> getProviderNotifyAction(const std::string& notify) 1059017faf2SAbhishek Patel { 1069017faf2SAbhishek Patel std::optional<bool> notifyAction; 1079017faf2SAbhishek Patel if (notify == "xyz.openbmc_project.Logging.Entry.Notify.Notify") 1089017faf2SAbhishek Patel { 1099017faf2SAbhishek Patel notifyAction = true; 1109017faf2SAbhishek Patel } 1119017faf2SAbhishek Patel else if (notify == "xyz.openbmc_project.Logging.Entry.Notify.Inhibit") 1129017faf2SAbhishek Patel { 1139017faf2SAbhishek Patel notifyAction = false; 1149017faf2SAbhishek Patel } 1159017faf2SAbhishek Patel 1169017faf2SAbhishek Patel return notifyAction; 1179017faf2SAbhishek Patel } 1189017faf2SAbhishek Patel 11918f8f608SEd Tanous inline std::string getDumpPath(std::string_view dumpType) 12018f8f608SEd Tanous { 12118f8f608SEd Tanous std::string dbusDumpPath = "/xyz/openbmc_project/dump/"; 12218f8f608SEd Tanous std::ranges::transform(dumpType, std::back_inserter(dbusDumpPath), 12318f8f608SEd Tanous bmcweb::asciiToLower); 12418f8f608SEd Tanous 12518f8f608SEd Tanous return dbusDumpPath; 12618f8f608SEd Tanous } 12718f8f608SEd Tanous 128055713e4SEd Tanous inline bool getUniqueEntryID(const std::string& logEntry, std::string& entryID, 129e85d6b16SJason M. Bills const bool firstEntry = true) 13095820184SJason M. Bills { 131271584abSEd Tanous static time_t prevTs = 0; 13295820184SJason M. Bills static int index = 0; 133e85d6b16SJason M. Bills if (firstEntry) 134e85d6b16SJason M. Bills { 135e85d6b16SJason M. Bills prevTs = 0; 136e85d6b16SJason M. Bills } 137e85d6b16SJason M. Bills 13895820184SJason M. Bills // Get the entry timestamp 139271584abSEd Tanous std::time_t curTs = 0; 14095820184SJason M. Bills std::tm timeStruct = {}; 14195820184SJason M. Bills std::istringstream entryStream(logEntry); 14295820184SJason M. Bills if (entryStream >> std::get_time(&timeStruct, "%Y-%m-%dT%H:%M:%S")) 14395820184SJason M. Bills { 14495820184SJason M. Bills curTs = std::mktime(&timeStruct); 14595820184SJason M. Bills } 14695820184SJason M. Bills // If the timestamp isn't unique, increment the index 14795820184SJason M. Bills if (curTs == prevTs) 14895820184SJason M. Bills { 14995820184SJason M. Bills index++; 15095820184SJason M. Bills } 15195820184SJason M. Bills else 15295820184SJason M. Bills { 15395820184SJason M. Bills // Otherwise, reset it 15495820184SJason M. Bills index = 0; 15595820184SJason M. Bills } 15695820184SJason M. Bills // Save the timestamp 15795820184SJason M. Bills prevTs = curTs; 15895820184SJason M. Bills 15995820184SJason M. Bills entryID = std::to_string(curTs); 16095820184SJason M. Bills if (index > 0) 16195820184SJason M. Bills { 16295820184SJason M. Bills entryID += "_" + std::to_string(index); 16395820184SJason M. Bills } 16495820184SJason M. Bills return true; 16595820184SJason M. Bills } 16695820184SJason M. Bills 167*4ff0f1f4SEd Tanous inline bool 16895820184SJason M. Bills getRedfishLogFiles(std::vector<std::filesystem::path>& redfishLogFiles) 16995820184SJason M. Bills { 17095820184SJason M. Bills static const std::filesystem::path redfishLogDir = "/var/log"; 17195820184SJason M. Bills static const std::string redfishLogFilename = "redfish"; 17295820184SJason M. Bills 17395820184SJason M. Bills // Loop through the directory looking for redfish log files 17495820184SJason M. Bills for (const std::filesystem::directory_entry& dirEnt : 17595820184SJason M. Bills std::filesystem::directory_iterator(redfishLogDir)) 17695820184SJason M. Bills { 17795820184SJason M. Bills // If we find a redfish log file, save the path 17895820184SJason M. Bills std::string filename = dirEnt.path().filename(); 17911ba3979SEd Tanous if (filename.starts_with(redfishLogFilename)) 18095820184SJason M. Bills { 18195820184SJason M. Bills redfishLogFiles.emplace_back(redfishLogDir / filename); 18295820184SJason M. Bills } 18395820184SJason M. Bills } 18495820184SJason M. Bills // As the log files rotate, they are appended with a ".#" that is higher for 18595820184SJason M. Bills // the older logs. Since we don't expect more than 10 log files, we 18695820184SJason M. Bills // can just sort the list to get them in order from newest to oldest 1873544d2a7SEd Tanous std::ranges::sort(redfishLogFiles); 18895820184SJason M. Bills 18995820184SJason M. Bills return !redfishLogFiles.empty(); 19095820184SJason M. Bills } 19195820184SJason M. Bills 19268dd075aSAsmitha Karunanithi inline log_entry::OriginatorTypes 19368dd075aSAsmitha Karunanithi mapDbusOriginatorTypeToRedfish(const std::string& originatorType) 19468dd075aSAsmitha Karunanithi { 19568dd075aSAsmitha Karunanithi if (originatorType == 19668dd075aSAsmitha Karunanithi "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Client") 19768dd075aSAsmitha Karunanithi { 19868dd075aSAsmitha Karunanithi return log_entry::OriginatorTypes::Client; 19968dd075aSAsmitha Karunanithi } 20068dd075aSAsmitha Karunanithi if (originatorType == 20168dd075aSAsmitha Karunanithi "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Internal") 20268dd075aSAsmitha Karunanithi { 20368dd075aSAsmitha Karunanithi return log_entry::OriginatorTypes::Internal; 20468dd075aSAsmitha Karunanithi } 20568dd075aSAsmitha Karunanithi if (originatorType == 20668dd075aSAsmitha Karunanithi "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.SupportingService") 20768dd075aSAsmitha Karunanithi { 20868dd075aSAsmitha Karunanithi return log_entry::OriginatorTypes::SupportingService; 20968dd075aSAsmitha Karunanithi } 21068dd075aSAsmitha Karunanithi return log_entry::OriginatorTypes::Invalid; 21168dd075aSAsmitha Karunanithi } 21268dd075aSAsmitha Karunanithi 213aefe3786SClaire Weinan inline void parseDumpEntryFromDbusObject( 2142d613eb6SJiaqing Zhao const dbus::utility::ManagedObjectType::value_type& object, 215c6fecdabSClaire Weinan std::string& dumpStatus, uint64_t& size, uint64_t& timestampUs, 21668dd075aSAsmitha Karunanithi std::string& originatorId, log_entry::OriginatorTypes& originatorType, 217aefe3786SClaire Weinan const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 218aefe3786SClaire Weinan { 219aefe3786SClaire Weinan for (const auto& interfaceMap : object.second) 220aefe3786SClaire Weinan { 221aefe3786SClaire Weinan if (interfaceMap.first == "xyz.openbmc_project.Common.Progress") 222aefe3786SClaire Weinan { 223aefe3786SClaire Weinan for (const auto& propertyMap : interfaceMap.second) 224aefe3786SClaire Weinan { 225aefe3786SClaire Weinan if (propertyMap.first == "Status") 226aefe3786SClaire Weinan { 227aefe3786SClaire Weinan const auto* status = 228aefe3786SClaire Weinan std::get_if<std::string>(&propertyMap.second); 229aefe3786SClaire Weinan if (status == nullptr) 230aefe3786SClaire Weinan { 231aefe3786SClaire Weinan messages::internalError(asyncResp->res); 232aefe3786SClaire Weinan break; 233aefe3786SClaire Weinan } 234aefe3786SClaire Weinan dumpStatus = *status; 235aefe3786SClaire Weinan } 236aefe3786SClaire Weinan } 237aefe3786SClaire Weinan } 238aefe3786SClaire Weinan else if (interfaceMap.first == "xyz.openbmc_project.Dump.Entry") 239aefe3786SClaire Weinan { 240aefe3786SClaire Weinan for (const auto& propertyMap : interfaceMap.second) 241aefe3786SClaire Weinan { 242aefe3786SClaire Weinan if (propertyMap.first == "Size") 243aefe3786SClaire Weinan { 244aefe3786SClaire Weinan const auto* sizePtr = 245aefe3786SClaire Weinan std::get_if<uint64_t>(&propertyMap.second); 246aefe3786SClaire Weinan if (sizePtr == nullptr) 247aefe3786SClaire Weinan { 248aefe3786SClaire Weinan messages::internalError(asyncResp->res); 249aefe3786SClaire Weinan break; 250aefe3786SClaire Weinan } 251aefe3786SClaire Weinan size = *sizePtr; 252aefe3786SClaire Weinan break; 253aefe3786SClaire Weinan } 254aefe3786SClaire Weinan } 255aefe3786SClaire Weinan } 256aefe3786SClaire Weinan else if (interfaceMap.first == "xyz.openbmc_project.Time.EpochTime") 257aefe3786SClaire Weinan { 258aefe3786SClaire Weinan for (const auto& propertyMap : interfaceMap.second) 259aefe3786SClaire Weinan { 260aefe3786SClaire Weinan if (propertyMap.first == "Elapsed") 261aefe3786SClaire Weinan { 262aefe3786SClaire Weinan const uint64_t* usecsTimeStamp = 263aefe3786SClaire Weinan std::get_if<uint64_t>(&propertyMap.second); 264aefe3786SClaire Weinan if (usecsTimeStamp == nullptr) 265aefe3786SClaire Weinan { 266aefe3786SClaire Weinan messages::internalError(asyncResp->res); 267aefe3786SClaire Weinan break; 268aefe3786SClaire Weinan } 269c6fecdabSClaire Weinan timestampUs = *usecsTimeStamp; 270aefe3786SClaire Weinan break; 271aefe3786SClaire Weinan } 272aefe3786SClaire Weinan } 273aefe3786SClaire Weinan } 27468dd075aSAsmitha Karunanithi else if (interfaceMap.first == 27568dd075aSAsmitha Karunanithi "xyz.openbmc_project.Common.OriginatedBy") 27668dd075aSAsmitha Karunanithi { 27768dd075aSAsmitha Karunanithi for (const auto& propertyMap : interfaceMap.second) 27868dd075aSAsmitha Karunanithi { 27968dd075aSAsmitha Karunanithi if (propertyMap.first == "OriginatorId") 28068dd075aSAsmitha Karunanithi { 28168dd075aSAsmitha Karunanithi const std::string* id = 28268dd075aSAsmitha Karunanithi std::get_if<std::string>(&propertyMap.second); 28368dd075aSAsmitha Karunanithi if (id == nullptr) 28468dd075aSAsmitha Karunanithi { 28568dd075aSAsmitha Karunanithi messages::internalError(asyncResp->res); 28668dd075aSAsmitha Karunanithi break; 28768dd075aSAsmitha Karunanithi } 28868dd075aSAsmitha Karunanithi originatorId = *id; 28968dd075aSAsmitha Karunanithi } 29068dd075aSAsmitha Karunanithi 29168dd075aSAsmitha Karunanithi if (propertyMap.first == "OriginatorType") 29268dd075aSAsmitha Karunanithi { 29368dd075aSAsmitha Karunanithi const std::string* type = 29468dd075aSAsmitha Karunanithi std::get_if<std::string>(&propertyMap.second); 29568dd075aSAsmitha Karunanithi if (type == nullptr) 29668dd075aSAsmitha Karunanithi { 29768dd075aSAsmitha Karunanithi messages::internalError(asyncResp->res); 29868dd075aSAsmitha Karunanithi break; 29968dd075aSAsmitha Karunanithi } 30068dd075aSAsmitha Karunanithi 30168dd075aSAsmitha Karunanithi originatorType = mapDbusOriginatorTypeToRedfish(*type); 30268dd075aSAsmitha Karunanithi if (originatorType == log_entry::OriginatorTypes::Invalid) 30368dd075aSAsmitha Karunanithi { 30468dd075aSAsmitha Karunanithi messages::internalError(asyncResp->res); 30568dd075aSAsmitha Karunanithi break; 30668dd075aSAsmitha Karunanithi } 30768dd075aSAsmitha Karunanithi } 30868dd075aSAsmitha Karunanithi } 30968dd075aSAsmitha Karunanithi } 310aefe3786SClaire Weinan } 311aefe3786SClaire Weinan } 312aefe3786SClaire Weinan 31321ab404cSNan Zhou static std::string getDumpEntriesPath(const std::string& dumpType) 314fdd26906SClaire Weinan { 315fdd26906SClaire Weinan std::string entriesPath; 316fdd26906SClaire Weinan 317fdd26906SClaire Weinan if (dumpType == "BMC") 318fdd26906SClaire Weinan { 319253f11b8SEd Tanous entriesPath = 320253f11b8SEd Tanous std::format("/redfish/v1/Managers/{}/LogServices/Dump/Entries/", 321253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 322fdd26906SClaire Weinan } 323fdd26906SClaire Weinan else if (dumpType == "FaultLog") 324fdd26906SClaire Weinan { 325253f11b8SEd Tanous entriesPath = 326253f11b8SEd Tanous std::format("/redfish/v1/Managers/{}/LogServices/FaultLog/Entries/", 327253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 328fdd26906SClaire Weinan } 329fdd26906SClaire Weinan else if (dumpType == "System") 330fdd26906SClaire Weinan { 331253f11b8SEd Tanous entriesPath = 332253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/Dump/Entries/", 333253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 334fdd26906SClaire Weinan } 335fdd26906SClaire Weinan else 336fdd26906SClaire Weinan { 33762598e31SEd Tanous BMCWEB_LOG_ERROR("getDumpEntriesPath() invalid dump type: {}", 33862598e31SEd Tanous dumpType); 339fdd26906SClaire Weinan } 340fdd26906SClaire Weinan 341fdd26906SClaire Weinan // Returns empty string on error 342fdd26906SClaire Weinan return entriesPath; 343fdd26906SClaire Weinan } 344fdd26906SClaire Weinan 3458d1b46d7Szhanghch05 inline void 3468d1b46d7Szhanghch05 getDumpEntryCollection(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 3475cb1dd27SAsmitha Karunanithi const std::string& dumpType) 3485cb1dd27SAsmitha Karunanithi { 349fdd26906SClaire Weinan std::string entriesPath = getDumpEntriesPath(dumpType); 350fdd26906SClaire Weinan if (entriesPath.empty()) 3515cb1dd27SAsmitha Karunanithi { 3525cb1dd27SAsmitha Karunanithi messages::internalError(asyncResp->res); 3535cb1dd27SAsmitha Karunanithi return; 3545cb1dd27SAsmitha Karunanithi } 3555cb1dd27SAsmitha Karunanithi 3565eb468daSGeorge Liu sdbusplus::message::object_path path("/xyz/openbmc_project/dump"); 3575eb468daSGeorge Liu dbus::utility::getManagedObjects( 3585eb468daSGeorge Liu "xyz.openbmc_project.Dump.Manager", path, 359fdd26906SClaire Weinan [asyncResp, entriesPath, 3605e7e2dc5SEd Tanous dumpType](const boost::system::error_code& ec, 3615eb468daSGeorge Liu const dbus::utility::ManagedObjectType& objects) { 3625cb1dd27SAsmitha Karunanithi if (ec) 3635cb1dd27SAsmitha Karunanithi { 36462598e31SEd Tanous BMCWEB_LOG_ERROR("DumpEntry resp_handler got error {}", ec); 3655cb1dd27SAsmitha Karunanithi messages::internalError(asyncResp->res); 3665cb1dd27SAsmitha Karunanithi return; 3675cb1dd27SAsmitha Karunanithi } 3685cb1dd27SAsmitha Karunanithi 369fdd26906SClaire Weinan // Remove ending slash 370fdd26906SClaire Weinan std::string odataIdStr = entriesPath; 371fdd26906SClaire Weinan if (!odataIdStr.empty()) 372fdd26906SClaire Weinan { 373fdd26906SClaire Weinan odataIdStr.pop_back(); 374fdd26906SClaire Weinan } 375fdd26906SClaire Weinan 376fdd26906SClaire Weinan asyncResp->res.jsonValue["@odata.type"] = 377fdd26906SClaire Weinan "#LogEntryCollection.LogEntryCollection"; 378fdd26906SClaire Weinan asyncResp->res.jsonValue["@odata.id"] = std::move(odataIdStr); 379fdd26906SClaire Weinan asyncResp->res.jsonValue["Name"] = dumpType + " Dump Entries"; 380bd79bce8SPatrick Williams asyncResp->res.jsonValue["Description"] = 381bd79bce8SPatrick Williams "Collection of " + dumpType + " Dump Entries"; 382fdd26906SClaire Weinan 3833544d2a7SEd Tanous nlohmann::json::array_t entriesArray; 38418f8f608SEd Tanous std::string dumpEntryPath = getDumpPath(dumpType) + "/entry/"; 3855cb1dd27SAsmitha Karunanithi 3865eb468daSGeorge Liu dbus::utility::ManagedObjectType resp(objects); 3873544d2a7SEd Tanous std::ranges::sort(resp, [](const auto& l, const auto& r) { 388002d39b4SEd Tanous return AlphanumLess<std::string>()(l.first.filename(), 389002d39b4SEd Tanous r.first.filename()); 390565dfb6fSClaire Weinan }); 391565dfb6fSClaire Weinan 3925cb1dd27SAsmitha Karunanithi for (auto& object : resp) 3935cb1dd27SAsmitha Karunanithi { 394b47452b2SAsmitha Karunanithi if (object.first.str.find(dumpEntryPath) == std::string::npos) 3955cb1dd27SAsmitha Karunanithi { 3965cb1dd27SAsmitha Karunanithi continue; 3975cb1dd27SAsmitha Karunanithi } 398c6fecdabSClaire Weinan uint64_t timestampUs = 0; 3995cb1dd27SAsmitha Karunanithi uint64_t size = 0; 40035440d18SAsmitha Karunanithi std::string dumpStatus; 40168dd075aSAsmitha Karunanithi std::string originatorId; 40268dd075aSAsmitha Karunanithi log_entry::OriginatorTypes originatorType = 40368dd075aSAsmitha Karunanithi log_entry::OriginatorTypes::Internal; 404433b68b4SJason M. Bills nlohmann::json::object_t thisEntry; 4052dfd18efSEd Tanous 4062dfd18efSEd Tanous std::string entryID = object.first.filename(); 4072dfd18efSEd Tanous if (entryID.empty()) 4085cb1dd27SAsmitha Karunanithi { 4095cb1dd27SAsmitha Karunanithi continue; 4105cb1dd27SAsmitha Karunanithi } 4115cb1dd27SAsmitha Karunanithi 412bd79bce8SPatrick Williams parseDumpEntryFromDbusObject(object, dumpStatus, size, 413bd79bce8SPatrick Williams timestampUs, originatorId, 414bd79bce8SPatrick Williams originatorType, asyncResp); 4155cb1dd27SAsmitha Karunanithi 4160fda0f12SGeorge Liu if (dumpStatus != 4170fda0f12SGeorge Liu "xyz.openbmc_project.Common.Progress.OperationStatus.Completed" && 41835440d18SAsmitha Karunanithi !dumpStatus.empty()) 41935440d18SAsmitha Karunanithi { 42035440d18SAsmitha Karunanithi // Dump status is not Complete, no need to enumerate 42135440d18SAsmitha Karunanithi continue; 42235440d18SAsmitha Karunanithi } 42335440d18SAsmitha Karunanithi 42468dd075aSAsmitha Karunanithi thisEntry["@odata.type"] = "#LogEntry.v1_11_0.LogEntry"; 425fdd26906SClaire Weinan thisEntry["@odata.id"] = entriesPath + entryID; 4265cb1dd27SAsmitha Karunanithi thisEntry["Id"] = entryID; 4275cb1dd27SAsmitha Karunanithi thisEntry["EntryType"] = "Event"; 4285cb1dd27SAsmitha Karunanithi thisEntry["Name"] = dumpType + " Dump Entry"; 429bbd80db8SClaire Weinan thisEntry["Created"] = 430bbd80db8SClaire Weinan redfish::time_utils::getDateTimeUintUs(timestampUs); 4315cb1dd27SAsmitha Karunanithi 43268dd075aSAsmitha Karunanithi if (!originatorId.empty()) 43368dd075aSAsmitha Karunanithi { 43468dd075aSAsmitha Karunanithi thisEntry["Originator"] = originatorId; 43568dd075aSAsmitha Karunanithi thisEntry["OriginatorType"] = originatorType; 43668dd075aSAsmitha Karunanithi } 43768dd075aSAsmitha Karunanithi 4385cb1dd27SAsmitha Karunanithi if (dumpType == "BMC") 4395cb1dd27SAsmitha Karunanithi { 440d337bb72SAsmitha Karunanithi thisEntry["DiagnosticDataType"] = "Manager"; 441bd79bce8SPatrick Williams thisEntry["AdditionalDataURI"] = 442bd79bce8SPatrick Williams entriesPath + entryID + "/attachment"; 443fdd26906SClaire Weinan thisEntry["AdditionalDataSizeBytes"] = size; 4445cb1dd27SAsmitha Karunanithi } 4455cb1dd27SAsmitha Karunanithi else if (dumpType == "System") 4465cb1dd27SAsmitha Karunanithi { 447d337bb72SAsmitha Karunanithi thisEntry["DiagnosticDataType"] = "OEM"; 448d337bb72SAsmitha Karunanithi thisEntry["OEMDiagnosticDataType"] = "System"; 449bd79bce8SPatrick Williams thisEntry["AdditionalDataURI"] = 450bd79bce8SPatrick Williams entriesPath + entryID + "/attachment"; 451fdd26906SClaire Weinan thisEntry["AdditionalDataSizeBytes"] = size; 4525cb1dd27SAsmitha Karunanithi } 453b2ba3072SPatrick Williams entriesArray.emplace_back(std::move(thisEntry)); 4545cb1dd27SAsmitha Karunanithi } 455bd79bce8SPatrick Williams asyncResp->res.jsonValue["Members@odata.count"] = 456bd79bce8SPatrick Williams entriesArray.size(); 4573544d2a7SEd Tanous asyncResp->res.jsonValue["Members"] = std::move(entriesArray); 4585eb468daSGeorge Liu }); 4595cb1dd27SAsmitha Karunanithi } 4605cb1dd27SAsmitha Karunanithi 4618d1b46d7Szhanghch05 inline void 462c7a6d660SClaire Weinan getDumpEntryById(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 4638d1b46d7Szhanghch05 const std::string& entryID, const std::string& dumpType) 4645cb1dd27SAsmitha Karunanithi { 465fdd26906SClaire Weinan std::string entriesPath = getDumpEntriesPath(dumpType); 466fdd26906SClaire Weinan if (entriesPath.empty()) 4675cb1dd27SAsmitha Karunanithi { 4685cb1dd27SAsmitha Karunanithi messages::internalError(asyncResp->res); 4695cb1dd27SAsmitha Karunanithi return; 4705cb1dd27SAsmitha Karunanithi } 4715cb1dd27SAsmitha Karunanithi 4725eb468daSGeorge Liu sdbusplus::message::object_path path("/xyz/openbmc_project/dump"); 4735eb468daSGeorge Liu dbus::utility::getManagedObjects( 4745eb468daSGeorge Liu "xyz.openbmc_project.Dump.Manager", path, 475fdd26906SClaire Weinan [asyncResp, entryID, dumpType, 4765e7e2dc5SEd Tanous entriesPath](const boost::system::error_code& ec, 47702cad96eSEd Tanous const dbus::utility::ManagedObjectType& resp) { 4785cb1dd27SAsmitha Karunanithi if (ec) 4795cb1dd27SAsmitha Karunanithi { 48062598e31SEd Tanous BMCWEB_LOG_ERROR("DumpEntry resp_handler got error {}", ec); 4815cb1dd27SAsmitha Karunanithi messages::internalError(asyncResp->res); 4825cb1dd27SAsmitha Karunanithi return; 4835cb1dd27SAsmitha Karunanithi } 4845cb1dd27SAsmitha Karunanithi 485b47452b2SAsmitha Karunanithi bool foundDumpEntry = false; 48618f8f608SEd Tanous std::string dumpEntryPath = getDumpPath(dumpType) + "/entry/"; 487b47452b2SAsmitha Karunanithi 4889eb808c1SEd Tanous for (const auto& objectPath : resp) 4895cb1dd27SAsmitha Karunanithi { 490b47452b2SAsmitha Karunanithi if (objectPath.first.str != dumpEntryPath + entryID) 4915cb1dd27SAsmitha Karunanithi { 4925cb1dd27SAsmitha Karunanithi continue; 4935cb1dd27SAsmitha Karunanithi } 4945cb1dd27SAsmitha Karunanithi 4955cb1dd27SAsmitha Karunanithi foundDumpEntry = true; 496c6fecdabSClaire Weinan uint64_t timestampUs = 0; 4975cb1dd27SAsmitha Karunanithi uint64_t size = 0; 49835440d18SAsmitha Karunanithi std::string dumpStatus; 49968dd075aSAsmitha Karunanithi std::string originatorId; 50068dd075aSAsmitha Karunanithi log_entry::OriginatorTypes originatorType = 50168dd075aSAsmitha Karunanithi log_entry::OriginatorTypes::Internal; 5025cb1dd27SAsmitha Karunanithi 503aefe3786SClaire Weinan parseDumpEntryFromDbusObject(objectPath, dumpStatus, size, 50468dd075aSAsmitha Karunanithi timestampUs, originatorId, 50568dd075aSAsmitha Karunanithi originatorType, asyncResp); 5065cb1dd27SAsmitha Karunanithi 5070fda0f12SGeorge Liu if (dumpStatus != 5080fda0f12SGeorge Liu "xyz.openbmc_project.Common.Progress.OperationStatus.Completed" && 50935440d18SAsmitha Karunanithi !dumpStatus.empty()) 51035440d18SAsmitha Karunanithi { 51135440d18SAsmitha Karunanithi // Dump status is not Complete 51235440d18SAsmitha Karunanithi // return not found until status is changed to Completed 513bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, 514bd79bce8SPatrick Williams dumpType + " dump", entryID); 51535440d18SAsmitha Karunanithi return; 51635440d18SAsmitha Karunanithi } 51735440d18SAsmitha Karunanithi 5185cb1dd27SAsmitha Karunanithi asyncResp->res.jsonValue["@odata.type"] = 51968dd075aSAsmitha Karunanithi "#LogEntry.v1_11_0.LogEntry"; 520fdd26906SClaire Weinan asyncResp->res.jsonValue["@odata.id"] = entriesPath + entryID; 5215cb1dd27SAsmitha Karunanithi asyncResp->res.jsonValue["Id"] = entryID; 5225cb1dd27SAsmitha Karunanithi asyncResp->res.jsonValue["EntryType"] = "Event"; 5235cb1dd27SAsmitha Karunanithi asyncResp->res.jsonValue["Name"] = dumpType + " Dump Entry"; 524bbd80db8SClaire Weinan asyncResp->res.jsonValue["Created"] = 525bbd80db8SClaire Weinan redfish::time_utils::getDateTimeUintUs(timestampUs); 5265cb1dd27SAsmitha Karunanithi 52768dd075aSAsmitha Karunanithi if (!originatorId.empty()) 52868dd075aSAsmitha Karunanithi { 52968dd075aSAsmitha Karunanithi asyncResp->res.jsonValue["Originator"] = originatorId; 53068dd075aSAsmitha Karunanithi asyncResp->res.jsonValue["OriginatorType"] = originatorType; 53168dd075aSAsmitha Karunanithi } 53268dd075aSAsmitha Karunanithi 5335cb1dd27SAsmitha Karunanithi if (dumpType == "BMC") 5345cb1dd27SAsmitha Karunanithi { 535d337bb72SAsmitha Karunanithi asyncResp->res.jsonValue["DiagnosticDataType"] = "Manager"; 536d337bb72SAsmitha Karunanithi asyncResp->res.jsonValue["AdditionalDataURI"] = 537fdd26906SClaire Weinan entriesPath + entryID + "/attachment"; 538fdd26906SClaire Weinan asyncResp->res.jsonValue["AdditionalDataSizeBytes"] = size; 5395cb1dd27SAsmitha Karunanithi } 5405cb1dd27SAsmitha Karunanithi else if (dumpType == "System") 5415cb1dd27SAsmitha Karunanithi { 542d337bb72SAsmitha Karunanithi asyncResp->res.jsonValue["DiagnosticDataType"] = "OEM"; 543bd79bce8SPatrick Williams asyncResp->res.jsonValue["OEMDiagnosticDataType"] = 544bd79bce8SPatrick Williams "System"; 545d337bb72SAsmitha Karunanithi asyncResp->res.jsonValue["AdditionalDataURI"] = 546fdd26906SClaire Weinan entriesPath + entryID + "/attachment"; 547fdd26906SClaire Weinan asyncResp->res.jsonValue["AdditionalDataSizeBytes"] = size; 5485cb1dd27SAsmitha Karunanithi } 5495cb1dd27SAsmitha Karunanithi } 550e05aec50SEd Tanous if (!foundDumpEntry) 551b47452b2SAsmitha Karunanithi { 55262598e31SEd Tanous BMCWEB_LOG_WARNING("Can't find Dump Entry {}", entryID); 553b90d14f2SMyung Bae messages::resourceNotFound(asyncResp->res, dumpType + " dump", 554b90d14f2SMyung Bae entryID); 555b47452b2SAsmitha Karunanithi return; 556b47452b2SAsmitha Karunanithi } 5575eb468daSGeorge Liu }); 5585cb1dd27SAsmitha Karunanithi } 5595cb1dd27SAsmitha Karunanithi 5608d1b46d7Szhanghch05 inline void deleteDumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 5619878256fSStanley Chu const std::string& entryID, 562b47452b2SAsmitha Karunanithi const std::string& dumpType) 5635cb1dd27SAsmitha Karunanithi { 5645a39f77aSPatrick Williams auto respHandler = [asyncResp, 5655a39f77aSPatrick Williams entryID](const boost::system::error_code& ec) { 56662598e31SEd Tanous BMCWEB_LOG_DEBUG("Dump Entry doDelete callback: Done"); 5675cb1dd27SAsmitha Karunanithi if (ec) 5685cb1dd27SAsmitha Karunanithi { 5693de8d8baSGeorge Liu if (ec.value() == EBADR) 5703de8d8baSGeorge Liu { 5713de8d8baSGeorge Liu messages::resourceNotFound(asyncResp->res, "LogEntry", entryID); 5723de8d8baSGeorge Liu return; 5733de8d8baSGeorge Liu } 57462598e31SEd Tanous BMCWEB_LOG_ERROR( 57562598e31SEd Tanous "Dump (DBus) doDelete respHandler got error {} entryID={}", ec, 57662598e31SEd Tanous entryID); 5775cb1dd27SAsmitha Karunanithi messages::internalError(asyncResp->res); 5785cb1dd27SAsmitha Karunanithi return; 5795cb1dd27SAsmitha Karunanithi } 5805cb1dd27SAsmitha Karunanithi }; 58118f8f608SEd Tanous 5825cb1dd27SAsmitha Karunanithi crow::connections::systemBus->async_method_call( 5835cb1dd27SAsmitha Karunanithi respHandler, "xyz.openbmc_project.Dump.Manager", 58418f8f608SEd Tanous std::format("{}/entry/{}", getDumpPath(dumpType), entryID), 5855cb1dd27SAsmitha Karunanithi "xyz.openbmc_project.Object.Delete", "Delete"); 5865cb1dd27SAsmitha Karunanithi } 587b5f288d2SAbhilash Raju inline bool checkSizeLimit(int fd, crow::Response& res) 588b5f288d2SAbhilash Raju { 589b5f288d2SAbhilash Raju long long int size = lseek(fd, 0, SEEK_END); 590b5f288d2SAbhilash Raju if (size <= 0) 591b5f288d2SAbhilash Raju { 592b5f288d2SAbhilash Raju BMCWEB_LOG_ERROR("Failed to get size of file, lseek() returned {}", 593b5f288d2SAbhilash Raju size); 594b5f288d2SAbhilash Raju messages::internalError(res); 595b5f288d2SAbhilash Raju return false; 596b5f288d2SAbhilash Raju } 5975cb1dd27SAsmitha Karunanithi 598b5f288d2SAbhilash Raju // Arbitrary max size of 20MB to accommodate BMC dumps 599b5f288d2SAbhilash Raju constexpr long long int maxFileSize = 20LL * 1024LL * 1024LL; 600b5f288d2SAbhilash Raju if (size > maxFileSize) 601b5f288d2SAbhilash Raju { 602b5f288d2SAbhilash Raju BMCWEB_LOG_ERROR("File size {} exceeds maximum allowed size of {}", 603b5f288d2SAbhilash Raju size, maxFileSize); 604b5f288d2SAbhilash Raju messages::internalError(res); 605b5f288d2SAbhilash Raju return false; 606b5f288d2SAbhilash Raju } 607b5f288d2SAbhilash Raju off_t rc = lseek(fd, 0, SEEK_SET); 608b5f288d2SAbhilash Raju if (rc < 0) 609b5f288d2SAbhilash Raju { 610b5f288d2SAbhilash Raju BMCWEB_LOG_ERROR("Failed to reset file offset to 0"); 611b5f288d2SAbhilash Raju messages::internalError(res); 612b5f288d2SAbhilash Raju return false; 613b5f288d2SAbhilash Raju } 614b5f288d2SAbhilash Raju return true; 615b5f288d2SAbhilash Raju } 616bd79bce8SPatrick Williams inline void downloadEntryCallback( 617bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 618bd79bce8SPatrick Williams const std::string& entryID, const std::string& downloadEntryType, 619168d1b1aSCarson Labrado const boost::system::error_code& ec, 620168d1b1aSCarson Labrado const sdbusplus::message::unix_fd& unixfd) 621168d1b1aSCarson Labrado { 622168d1b1aSCarson Labrado if (ec.value() == EBADR) 623168d1b1aSCarson Labrado { 624168d1b1aSCarson Labrado messages::resourceNotFound(asyncResp->res, "EntryAttachment", entryID); 625168d1b1aSCarson Labrado return; 626168d1b1aSCarson Labrado } 627168d1b1aSCarson Labrado if (ec) 628168d1b1aSCarson Labrado { 629168d1b1aSCarson Labrado BMCWEB_LOG_ERROR("DBUS response error: {}", ec); 630168d1b1aSCarson Labrado messages::internalError(asyncResp->res); 631168d1b1aSCarson Labrado return; 632168d1b1aSCarson Labrado } 633168d1b1aSCarson Labrado 634168d1b1aSCarson Labrado // Make sure we know how to process the retrieved entry attachment 635168d1b1aSCarson Labrado if ((downloadEntryType != "BMC") && (downloadEntryType != "System")) 636168d1b1aSCarson Labrado { 637168d1b1aSCarson Labrado BMCWEB_LOG_ERROR("downloadEntryCallback() invalid entry type: {}", 638168d1b1aSCarson Labrado downloadEntryType); 639168d1b1aSCarson Labrado messages::internalError(asyncResp->res); 640168d1b1aSCarson Labrado } 641168d1b1aSCarson Labrado 642168d1b1aSCarson Labrado int fd = -1; 643168d1b1aSCarson Labrado fd = dup(unixfd); 644168d1b1aSCarson Labrado if (fd < 0) 645168d1b1aSCarson Labrado { 646168d1b1aSCarson Labrado BMCWEB_LOG_ERROR("Failed to open file"); 647168d1b1aSCarson Labrado messages::internalError(asyncResp->res); 648168d1b1aSCarson Labrado return; 649168d1b1aSCarson Labrado } 650b5f288d2SAbhilash Raju if (!checkSizeLimit(fd, asyncResp->res)) 651168d1b1aSCarson Labrado { 652168d1b1aSCarson Labrado close(fd); 653168d1b1aSCarson Labrado return; 654168d1b1aSCarson Labrado } 655168d1b1aSCarson Labrado if (downloadEntryType == "System") 656168d1b1aSCarson Labrado { 657b5f288d2SAbhilash Raju if (!asyncResp->res.openFd(fd, bmcweb::EncodingType::Base64)) 658b5f288d2SAbhilash Raju { 659b5f288d2SAbhilash Raju messages::internalError(asyncResp->res); 660b5f288d2SAbhilash Raju close(fd); 661b5f288d2SAbhilash Raju return; 662b5f288d2SAbhilash Raju } 663168d1b1aSCarson Labrado asyncResp->res.addHeader( 664168d1b1aSCarson Labrado boost::beast::http::field::content_transfer_encoding, "Base64"); 665b5f288d2SAbhilash Raju return; 666168d1b1aSCarson Labrado } 667b5f288d2SAbhilash Raju if (!asyncResp->res.openFd(fd)) 66827b0cf90SEd Tanous { 669b5f288d2SAbhilash Raju messages::internalError(asyncResp->res); 670b5f288d2SAbhilash Raju close(fd); 671b5f288d2SAbhilash Raju return; 67227b0cf90SEd Tanous } 673168d1b1aSCarson Labrado asyncResp->res.addHeader(boost::beast::http::field::content_type, 674168d1b1aSCarson Labrado "application/octet-stream"); 675168d1b1aSCarson Labrado } 676168d1b1aSCarson Labrado 677168d1b1aSCarson Labrado inline void 678168d1b1aSCarson Labrado downloadDumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 679168d1b1aSCarson Labrado const std::string& entryID, const std::string& dumpType) 680168d1b1aSCarson Labrado { 681168d1b1aSCarson Labrado if (dumpType != "BMC") 682168d1b1aSCarson Labrado { 683168d1b1aSCarson Labrado BMCWEB_LOG_WARNING("Can't find Dump Entry {}", entryID); 684168d1b1aSCarson Labrado messages::resourceNotFound(asyncResp->res, dumpType + " dump", entryID); 685168d1b1aSCarson Labrado return; 686168d1b1aSCarson Labrado } 687168d1b1aSCarson Labrado 688bd79bce8SPatrick Williams std::string dumpEntryPath = 689bd79bce8SPatrick Williams std::format("{}/entry/{}", getDumpPath(dumpType), entryID); 690168d1b1aSCarson Labrado 691168d1b1aSCarson Labrado auto downloadDumpEntryHandler = 692168d1b1aSCarson Labrado [asyncResp, entryID, 693168d1b1aSCarson Labrado dumpType](const boost::system::error_code& ec, 694168d1b1aSCarson Labrado const sdbusplus::message::unix_fd& unixfd) { 695168d1b1aSCarson Labrado downloadEntryCallback(asyncResp, entryID, dumpType, ec, unixfd); 696168d1b1aSCarson Labrado }; 697168d1b1aSCarson Labrado 698168d1b1aSCarson Labrado crow::connections::systemBus->async_method_call( 699168d1b1aSCarson Labrado std::move(downloadDumpEntryHandler), "xyz.openbmc_project.Dump.Manager", 700168d1b1aSCarson Labrado dumpEntryPath, "xyz.openbmc_project.Dump.Entry", "GetFileHandle"); 701168d1b1aSCarson Labrado } 702168d1b1aSCarson Labrado 703bd79bce8SPatrick Williams inline void downloadEventLogEntry( 704bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 705bd79bce8SPatrick Williams const std::string& systemName, const std::string& entryID, 706168d1b1aSCarson Labrado const std::string& dumpType) 707168d1b1aSCarson Labrado { 70825b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 709168d1b1aSCarson Labrado { 710168d1b1aSCarson Labrado // Option currently returns no systems. TBD 711168d1b1aSCarson Labrado messages::resourceNotFound(asyncResp->res, "ComputerSystem", 712168d1b1aSCarson Labrado systemName); 713168d1b1aSCarson Labrado return; 714168d1b1aSCarson Labrado } 715253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 716168d1b1aSCarson Labrado { 717168d1b1aSCarson Labrado messages::resourceNotFound(asyncResp->res, "ComputerSystem", 718168d1b1aSCarson Labrado systemName); 719168d1b1aSCarson Labrado return; 720168d1b1aSCarson Labrado } 721168d1b1aSCarson Labrado 722168d1b1aSCarson Labrado std::string entryPath = 723168d1b1aSCarson Labrado sdbusplus::message::object_path("/xyz/openbmc_project/logging/entry") / 724168d1b1aSCarson Labrado entryID; 725168d1b1aSCarson Labrado 726168d1b1aSCarson Labrado auto downloadEventLogEntryHandler = 727168d1b1aSCarson Labrado [asyncResp, entryID, 728168d1b1aSCarson Labrado dumpType](const boost::system::error_code& ec, 729168d1b1aSCarson Labrado const sdbusplus::message::unix_fd& unixfd) { 730168d1b1aSCarson Labrado downloadEntryCallback(asyncResp, entryID, dumpType, ec, unixfd); 731168d1b1aSCarson Labrado }; 732168d1b1aSCarson Labrado 733168d1b1aSCarson Labrado crow::connections::systemBus->async_method_call( 734168d1b1aSCarson Labrado std::move(downloadEventLogEntryHandler), "xyz.openbmc_project.Logging", 735168d1b1aSCarson Labrado entryPath, "xyz.openbmc_project.Logging.Entry", "GetEntry"); 736168d1b1aSCarson Labrado } 737168d1b1aSCarson Labrado 7388e31778eSAsmitha Karunanithi inline DumpCreationProgress 7398e31778eSAsmitha Karunanithi mapDbusStatusToDumpProgress(const std::string& status) 740a43be80fSAsmitha Karunanithi { 7418e31778eSAsmitha Karunanithi if (status == 7428e31778eSAsmitha Karunanithi "xyz.openbmc_project.Common.Progress.OperationStatus.Failed" || 7438e31778eSAsmitha Karunanithi status == "xyz.openbmc_project.Common.Progress.OperationStatus.Aborted") 7448e31778eSAsmitha Karunanithi { 7458e31778eSAsmitha Karunanithi return DumpCreationProgress::DUMP_CREATE_FAILED; 7468e31778eSAsmitha Karunanithi } 7478e31778eSAsmitha Karunanithi if (status == 7488e31778eSAsmitha Karunanithi "xyz.openbmc_project.Common.Progress.OperationStatus.Completed") 7498e31778eSAsmitha Karunanithi { 7508e31778eSAsmitha Karunanithi return DumpCreationProgress::DUMP_CREATE_SUCCESS; 7518e31778eSAsmitha Karunanithi } 7528e31778eSAsmitha Karunanithi return DumpCreationProgress::DUMP_CREATE_INPROGRESS; 7538e31778eSAsmitha Karunanithi } 7548e31778eSAsmitha Karunanithi 7558e31778eSAsmitha Karunanithi inline DumpCreationProgress 7568e31778eSAsmitha Karunanithi getDumpCompletionStatus(const dbus::utility::DBusPropertiesMap& values) 7578e31778eSAsmitha Karunanithi { 7588e31778eSAsmitha Karunanithi for (const auto& [key, val] : values) 7598e31778eSAsmitha Karunanithi { 7608e31778eSAsmitha Karunanithi if (key == "Status") 7618e31778eSAsmitha Karunanithi { 7628e31778eSAsmitha Karunanithi const std::string* value = std::get_if<std::string>(&val); 7638e31778eSAsmitha Karunanithi if (value == nullptr) 7648e31778eSAsmitha Karunanithi { 76562598e31SEd Tanous BMCWEB_LOG_ERROR("Status property value is null"); 7668e31778eSAsmitha Karunanithi return DumpCreationProgress::DUMP_CREATE_FAILED; 7678e31778eSAsmitha Karunanithi } 7688e31778eSAsmitha Karunanithi return mapDbusStatusToDumpProgress(*value); 7698e31778eSAsmitha Karunanithi } 7708e31778eSAsmitha Karunanithi } 7718e31778eSAsmitha Karunanithi return DumpCreationProgress::DUMP_CREATE_INPROGRESS; 7728e31778eSAsmitha Karunanithi } 7738e31778eSAsmitha Karunanithi 7748e31778eSAsmitha Karunanithi inline std::string getDumpEntryPath(const std::string& dumpPath) 7758e31778eSAsmitha Karunanithi { 7768e31778eSAsmitha Karunanithi if (dumpPath == "/xyz/openbmc_project/dump/bmc/entry") 7778e31778eSAsmitha Karunanithi { 778253f11b8SEd Tanous return std::format("/redfish/v1/Managers/{}/LogServices/Dump/Entries/", 7799f565090SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 7808e31778eSAsmitha Karunanithi } 7818e31778eSAsmitha Karunanithi if (dumpPath == "/xyz/openbmc_project/dump/system/entry") 7828e31778eSAsmitha Karunanithi { 783253f11b8SEd Tanous return std::format("/redfish/v1/Systems/{}/LogServices/Dump/Entries/", 784253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 7858e31778eSAsmitha Karunanithi } 7868e31778eSAsmitha Karunanithi return ""; 7878e31778eSAsmitha Karunanithi } 7888e31778eSAsmitha Karunanithi 7898e31778eSAsmitha Karunanithi inline void createDumpTaskCallback( 7908e31778eSAsmitha Karunanithi task::Payload&& payload, 7918e31778eSAsmitha Karunanithi const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 7928e31778eSAsmitha Karunanithi const sdbusplus::message::object_path& createdObjPath) 7938e31778eSAsmitha Karunanithi { 7948e31778eSAsmitha Karunanithi const std::string dumpPath = createdObjPath.parent_path().str; 7958e31778eSAsmitha Karunanithi const std::string dumpId = createdObjPath.filename(); 7968e31778eSAsmitha Karunanithi 7978e31778eSAsmitha Karunanithi std::string dumpEntryPath = getDumpEntryPath(dumpPath); 7988e31778eSAsmitha Karunanithi 7998e31778eSAsmitha Karunanithi if (dumpEntryPath.empty()) 8008e31778eSAsmitha Karunanithi { 80162598e31SEd Tanous BMCWEB_LOG_ERROR("Invalid dump type received"); 8028e31778eSAsmitha Karunanithi messages::internalError(asyncResp->res); 8038e31778eSAsmitha Karunanithi return; 8048e31778eSAsmitha Karunanithi } 8058e31778eSAsmitha Karunanithi 8068e31778eSAsmitha Karunanithi crow::connections::systemBus->async_method_call( 8078cb2c024SEd Tanous [asyncResp, payload = std::move(payload), createdObjPath, 8088e31778eSAsmitha Karunanithi dumpEntryPath{std::move(dumpEntryPath)}, 8095e7e2dc5SEd Tanous dumpId](const boost::system::error_code& ec, 8108e31778eSAsmitha Karunanithi const std::string& introspectXml) { 8118e31778eSAsmitha Karunanithi if (ec) 8128e31778eSAsmitha Karunanithi { 81362598e31SEd Tanous BMCWEB_LOG_ERROR("Introspect call failed with error: {}", 81462598e31SEd Tanous ec.message()); 8158e31778eSAsmitha Karunanithi messages::internalError(asyncResp->res); 8168e31778eSAsmitha Karunanithi return; 8178e31778eSAsmitha Karunanithi } 8188e31778eSAsmitha Karunanithi 8198e31778eSAsmitha Karunanithi // Check if the created dump object has implemented Progress 8208e31778eSAsmitha Karunanithi // interface to track dump completion. If yes, fetch the "Status" 8218e31778eSAsmitha Karunanithi // property of the interface, modify the task state accordingly. 8228e31778eSAsmitha Karunanithi // Else, return task completed. 8238e31778eSAsmitha Karunanithi tinyxml2::XMLDocument doc; 8248e31778eSAsmitha Karunanithi 8258e31778eSAsmitha Karunanithi doc.Parse(introspectXml.data(), introspectXml.size()); 8268e31778eSAsmitha Karunanithi tinyxml2::XMLNode* pRoot = doc.FirstChildElement("node"); 8278e31778eSAsmitha Karunanithi if (pRoot == nullptr) 8288e31778eSAsmitha Karunanithi { 82962598e31SEd Tanous BMCWEB_LOG_ERROR("XML document failed to parse"); 8308e31778eSAsmitha Karunanithi messages::internalError(asyncResp->res); 8318e31778eSAsmitha Karunanithi return; 8328e31778eSAsmitha Karunanithi } 8338e31778eSAsmitha Karunanithi tinyxml2::XMLElement* interfaceNode = 8348e31778eSAsmitha Karunanithi pRoot->FirstChildElement("interface"); 8358e31778eSAsmitha Karunanithi 8368e31778eSAsmitha Karunanithi bool isProgressIntfPresent = false; 8378e31778eSAsmitha Karunanithi while (interfaceNode != nullptr) 8388e31778eSAsmitha Karunanithi { 839bd79bce8SPatrick Williams const char* thisInterfaceName = 840bd79bce8SPatrick Williams interfaceNode->Attribute("name"); 8418e31778eSAsmitha Karunanithi if (thisInterfaceName != nullptr) 8428e31778eSAsmitha Karunanithi { 8438e31778eSAsmitha Karunanithi if (thisInterfaceName == 8448e31778eSAsmitha Karunanithi std::string_view("xyz.openbmc_project.Common.Progress")) 8458e31778eSAsmitha Karunanithi { 8468e31778eSAsmitha Karunanithi interfaceNode = 8478e31778eSAsmitha Karunanithi interfaceNode->NextSiblingElement("interface"); 8488e31778eSAsmitha Karunanithi continue; 8498e31778eSAsmitha Karunanithi } 8508e31778eSAsmitha Karunanithi isProgressIntfPresent = true; 8518e31778eSAsmitha Karunanithi break; 8528e31778eSAsmitha Karunanithi } 8538e31778eSAsmitha Karunanithi interfaceNode = interfaceNode->NextSiblingElement("interface"); 8548e31778eSAsmitha Karunanithi } 8558e31778eSAsmitha Karunanithi 856a43be80fSAsmitha Karunanithi std::shared_ptr<task::TaskData> task = task::TaskData::createTask( 8578e31778eSAsmitha Karunanithi [createdObjPath, dumpEntryPath, dumpId, isProgressIntfPresent]( 858bd79bce8SPatrick Williams const boost::system::error_code& ec2, 859bd79bce8SPatrick Williams sdbusplus::message_t& msg, 860a43be80fSAsmitha Karunanithi const std::shared_ptr<task::TaskData>& taskData) { 8618b24275dSEd Tanous if (ec2) 862cb13a392SEd Tanous { 86362598e31SEd Tanous BMCWEB_LOG_ERROR("{}: Error in creating dump", 86462598e31SEd Tanous createdObjPath.str); 865bd79bce8SPatrick Williams taskData->messages.emplace_back( 866bd79bce8SPatrick Williams messages::internalError()); 8676145ed6fSAsmitha Karunanithi taskData->state = "Cancelled"; 8686145ed6fSAsmitha Karunanithi return task::completed; 869cb13a392SEd Tanous } 870b9d36b47SEd Tanous 8718e31778eSAsmitha Karunanithi if (isProgressIntfPresent) 872a43be80fSAsmitha Karunanithi { 8738e31778eSAsmitha Karunanithi dbus::utility::DBusPropertiesMap values; 8748e31778eSAsmitha Karunanithi std::string prop; 8758e31778eSAsmitha Karunanithi msg.read(prop, values); 8768e31778eSAsmitha Karunanithi 8778e31778eSAsmitha Karunanithi DumpCreationProgress dumpStatus = 8788e31778eSAsmitha Karunanithi getDumpCompletionStatus(values); 879bd79bce8SPatrick Williams if (dumpStatus == 880bd79bce8SPatrick Williams DumpCreationProgress::DUMP_CREATE_FAILED) 8818e31778eSAsmitha Karunanithi { 88262598e31SEd Tanous BMCWEB_LOG_ERROR("{}: Error in creating dump", 88362598e31SEd Tanous createdObjPath.str); 8848e31778eSAsmitha Karunanithi taskData->state = "Cancelled"; 8858e31778eSAsmitha Karunanithi return task::completed; 8868e31778eSAsmitha Karunanithi } 8878e31778eSAsmitha Karunanithi 888bd79bce8SPatrick Williams if (dumpStatus == 889bd79bce8SPatrick Williams DumpCreationProgress::DUMP_CREATE_INPROGRESS) 8908e31778eSAsmitha Karunanithi { 891bd79bce8SPatrick Williams BMCWEB_LOG_DEBUG( 892bd79bce8SPatrick Williams "{}: Dump creation task is in progress", 89362598e31SEd Tanous createdObjPath.str); 8948e31778eSAsmitha Karunanithi return !task::completed; 8958e31778eSAsmitha Karunanithi } 8968e31778eSAsmitha Karunanithi } 8978e31778eSAsmitha Karunanithi 898a43be80fSAsmitha Karunanithi nlohmann::json retMessage = messages::success(); 899a43be80fSAsmitha Karunanithi taskData->messages.emplace_back(retMessage); 900a43be80fSAsmitha Karunanithi 901c51a58eeSEd Tanous boost::urls::url url = boost::urls::format( 902253f11b8SEd Tanous "/redfish/v1/Managers/{}/LogServices/Dump/Entries/{}", 903253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME, dumpId); 904c51a58eeSEd Tanous 905c51a58eeSEd Tanous std::string headerLoc = "Location: "; 906c51a58eeSEd Tanous headerLoc += url.buffer(); 907c51a58eeSEd Tanous 908bd79bce8SPatrick Williams taskData->payload->httpHeaders.emplace_back( 909bd79bce8SPatrick Williams std::move(headerLoc)); 910a43be80fSAsmitha Karunanithi 91162598e31SEd Tanous BMCWEB_LOG_DEBUG("{}: Dump creation task completed", 91262598e31SEd Tanous createdObjPath.str); 913a43be80fSAsmitha Karunanithi taskData->state = "Completed"; 914b47452b2SAsmitha Karunanithi return task::completed; 915a43be80fSAsmitha Karunanithi }, 9168e31778eSAsmitha Karunanithi "type='signal',interface='org.freedesktop.DBus.Properties'," 9178e31778eSAsmitha Karunanithi "member='PropertiesChanged',path='" + 9188e31778eSAsmitha Karunanithi createdObjPath.str + "'"); 919a43be80fSAsmitha Karunanithi 9208e31778eSAsmitha Karunanithi // The task timer is set to max time limit within which the 9218e31778eSAsmitha Karunanithi // requested dump will be collected. 9228e31778eSAsmitha Karunanithi task->startTimer(std::chrono::minutes(6)); 923a43be80fSAsmitha Karunanithi task->populateResp(asyncResp->res); 9248e31778eSAsmitha Karunanithi task->payload.emplace(payload); 9258e31778eSAsmitha Karunanithi }, 9268e31778eSAsmitha Karunanithi "xyz.openbmc_project.Dump.Manager", createdObjPath, 9278e31778eSAsmitha Karunanithi "org.freedesktop.DBus.Introspectable", "Introspect"); 928a43be80fSAsmitha Karunanithi } 929a43be80fSAsmitha Karunanithi 9308d1b46d7Szhanghch05 inline void createDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 9318d1b46d7Szhanghch05 const crow::Request& req, const std::string& dumpType) 932a43be80fSAsmitha Karunanithi { 933fdd26906SClaire Weinan std::string dumpPath = getDumpEntriesPath(dumpType); 934fdd26906SClaire Weinan if (dumpPath.empty()) 935a43be80fSAsmitha Karunanithi { 936a43be80fSAsmitha Karunanithi messages::internalError(asyncResp->res); 937a43be80fSAsmitha Karunanithi return; 938a43be80fSAsmitha Karunanithi } 939a43be80fSAsmitha Karunanithi 940a43be80fSAsmitha Karunanithi std::optional<std::string> diagnosticDataType; 941a43be80fSAsmitha Karunanithi std::optional<std::string> oemDiagnosticDataType; 942a43be80fSAsmitha Karunanithi 94315ed6780SWilly Tu if (!redfish::json_util::readJsonAction( 944a43be80fSAsmitha Karunanithi req, asyncResp->res, "DiagnosticDataType", diagnosticDataType, 945a43be80fSAsmitha Karunanithi "OEMDiagnosticDataType", oemDiagnosticDataType)) 946a43be80fSAsmitha Karunanithi { 947a43be80fSAsmitha Karunanithi return; 948a43be80fSAsmitha Karunanithi } 949a43be80fSAsmitha Karunanithi 950a43be80fSAsmitha Karunanithi if (dumpType == "System") 951a43be80fSAsmitha Karunanithi { 952a43be80fSAsmitha Karunanithi if (!oemDiagnosticDataType || !diagnosticDataType) 953a43be80fSAsmitha Karunanithi { 95462598e31SEd Tanous BMCWEB_LOG_ERROR( 95562598e31SEd Tanous "CreateDump action parameter 'DiagnosticDataType'/'OEMDiagnosticDataType' value not found!"); 956a43be80fSAsmitha Karunanithi messages::actionParameterMissing( 957a43be80fSAsmitha Karunanithi asyncResp->res, "CollectDiagnosticData", 958a43be80fSAsmitha Karunanithi "DiagnosticDataType & OEMDiagnosticDataType"); 959a43be80fSAsmitha Karunanithi return; 960a43be80fSAsmitha Karunanithi } 9613174e4dfSEd Tanous if ((*oemDiagnosticDataType != "System") || 962a43be80fSAsmitha Karunanithi (*diagnosticDataType != "OEM")) 963a43be80fSAsmitha Karunanithi { 96462598e31SEd Tanous BMCWEB_LOG_ERROR("Wrong parameter values passed"); 965ace85d60SEd Tanous messages::internalError(asyncResp->res); 966a43be80fSAsmitha Karunanithi return; 967a43be80fSAsmitha Karunanithi } 968253f11b8SEd Tanous dumpPath = std::format("/redfish/v1/Systems/{}/LogServices/Dump/", 969253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 970a43be80fSAsmitha Karunanithi } 971a43be80fSAsmitha Karunanithi else if (dumpType == "BMC") 972a43be80fSAsmitha Karunanithi { 973a43be80fSAsmitha Karunanithi if (!diagnosticDataType) 974a43be80fSAsmitha Karunanithi { 97562598e31SEd Tanous BMCWEB_LOG_ERROR( 97662598e31SEd Tanous "CreateDump action parameter 'DiagnosticDataType' not found!"); 977a43be80fSAsmitha Karunanithi messages::actionParameterMissing( 978a43be80fSAsmitha Karunanithi asyncResp->res, "CollectDiagnosticData", "DiagnosticDataType"); 979a43be80fSAsmitha Karunanithi return; 980a43be80fSAsmitha Karunanithi } 9813174e4dfSEd Tanous if (*diagnosticDataType != "Manager") 982a43be80fSAsmitha Karunanithi { 98362598e31SEd Tanous BMCWEB_LOG_ERROR( 98462598e31SEd Tanous "Wrong parameter value passed for 'DiagnosticDataType'"); 985ace85d60SEd Tanous messages::internalError(asyncResp->res); 986a43be80fSAsmitha Karunanithi return; 987a43be80fSAsmitha Karunanithi } 988253f11b8SEd Tanous dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/Dump/", 989253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 9905907571dSAsmitha Karunanithi } 9915907571dSAsmitha Karunanithi else 9925907571dSAsmitha Karunanithi { 99362598e31SEd Tanous BMCWEB_LOG_ERROR("CreateDump failed. Unknown dump type"); 9945907571dSAsmitha Karunanithi messages::internalError(asyncResp->res); 9955907571dSAsmitha Karunanithi return; 996a43be80fSAsmitha Karunanithi } 997a43be80fSAsmitha Karunanithi 9988e31778eSAsmitha Karunanithi std::vector<std::pair<std::string, std::variant<std::string, uint64_t>>> 9998e31778eSAsmitha Karunanithi createDumpParamVec; 10008e31778eSAsmitha Karunanithi 1001f574a8e1SCarson Labrado if (req.session != nullptr) 1002f574a8e1SCarson Labrado { 100368dd075aSAsmitha Karunanithi createDumpParamVec.emplace_back( 100468dd075aSAsmitha Karunanithi "xyz.openbmc_project.Dump.Create.CreateParameters.OriginatorId", 100568dd075aSAsmitha Karunanithi req.session->clientIp); 100668dd075aSAsmitha Karunanithi createDumpParamVec.emplace_back( 100768dd075aSAsmitha Karunanithi "xyz.openbmc_project.Dump.Create.CreateParameters.OriginatorType", 100868dd075aSAsmitha Karunanithi "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Client"); 1009f574a8e1SCarson Labrado } 101068dd075aSAsmitha Karunanithi 1011a43be80fSAsmitha Karunanithi crow::connections::systemBus->async_method_call( 10125e7e2dc5SEd Tanous [asyncResp, payload(task::Payload(req)), 10135e7e2dc5SEd Tanous dumpPath](const boost::system::error_code& ec, 10145e7e2dc5SEd Tanous const sdbusplus::message_t& msg, 10158e31778eSAsmitha Karunanithi const sdbusplus::message::object_path& objPath) mutable { 1016a43be80fSAsmitha Karunanithi if (ec) 1017a43be80fSAsmitha Karunanithi { 101862598e31SEd Tanous BMCWEB_LOG_ERROR("CreateDump resp_handler got error {}", ec); 10195907571dSAsmitha Karunanithi const sd_bus_error* dbusError = msg.get_error(); 10205907571dSAsmitha Karunanithi if (dbusError == nullptr) 10215907571dSAsmitha Karunanithi { 10225907571dSAsmitha Karunanithi messages::internalError(asyncResp->res); 10235907571dSAsmitha Karunanithi return; 10245907571dSAsmitha Karunanithi } 10255907571dSAsmitha Karunanithi 102662598e31SEd Tanous BMCWEB_LOG_ERROR("CreateDump DBus error: {} and error msg: {}", 102762598e31SEd Tanous dbusError->name, dbusError->message); 10285907571dSAsmitha Karunanithi if (std::string_view( 10295907571dSAsmitha Karunanithi "xyz.openbmc_project.Common.Error.NotAllowed") == 10305907571dSAsmitha Karunanithi dbusError->name) 10315907571dSAsmitha Karunanithi { 10325907571dSAsmitha Karunanithi messages::resourceInStandby(asyncResp->res); 10335907571dSAsmitha Karunanithi return; 10345907571dSAsmitha Karunanithi } 10355907571dSAsmitha Karunanithi if (std::string_view( 10365907571dSAsmitha Karunanithi "xyz.openbmc_project.Dump.Create.Error.Disabled") == 10375907571dSAsmitha Karunanithi dbusError->name) 10385907571dSAsmitha Karunanithi { 10395907571dSAsmitha Karunanithi messages::serviceDisabled(asyncResp->res, dumpPath); 10405907571dSAsmitha Karunanithi return; 10415907571dSAsmitha Karunanithi } 10425907571dSAsmitha Karunanithi if (std::string_view( 10435907571dSAsmitha Karunanithi "xyz.openbmc_project.Common.Error.Unavailable") == 10445907571dSAsmitha Karunanithi dbusError->name) 10455907571dSAsmitha Karunanithi { 10465907571dSAsmitha Karunanithi messages::resourceInUse(asyncResp->res); 10475907571dSAsmitha Karunanithi return; 10485907571dSAsmitha Karunanithi } 10495907571dSAsmitha Karunanithi // Other Dbus errors such as: 10505907571dSAsmitha Karunanithi // xyz.openbmc_project.Common.Error.InvalidArgument & 10515907571dSAsmitha Karunanithi // org.freedesktop.DBus.Error.InvalidArgs are all related to 10525907571dSAsmitha Karunanithi // the dbus call that is made here in the bmcweb 10535907571dSAsmitha Karunanithi // implementation and has nothing to do with the client's 10545907571dSAsmitha Karunanithi // input in the request. Hence, returning internal error 10555907571dSAsmitha Karunanithi // back to the client. 1056a43be80fSAsmitha Karunanithi messages::internalError(asyncResp->res); 1057a43be80fSAsmitha Karunanithi return; 1058a43be80fSAsmitha Karunanithi } 105962598e31SEd Tanous BMCWEB_LOG_DEBUG("Dump Created. Path: {}", objPath.str); 10608e31778eSAsmitha Karunanithi createDumpTaskCallback(std::move(payload), asyncResp, objPath); 1061a43be80fSAsmitha Karunanithi }, 106218f8f608SEd Tanous "xyz.openbmc_project.Dump.Manager", getDumpPath(dumpType), 10638e31778eSAsmitha Karunanithi "xyz.openbmc_project.Dump.Create", "CreateDump", createDumpParamVec); 1064a43be80fSAsmitha Karunanithi } 1065a43be80fSAsmitha Karunanithi 10668d1b46d7Szhanghch05 inline void clearDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 10678d1b46d7Szhanghch05 const std::string& dumpType) 106880319af1SAsmitha Karunanithi { 10690d946211SClaire Weinan crow::connections::systemBus->async_method_call( 10700d946211SClaire Weinan [asyncResp](const boost::system::error_code& ec) { 107180319af1SAsmitha Karunanithi if (ec) 107280319af1SAsmitha Karunanithi { 107362598e31SEd Tanous BMCWEB_LOG_ERROR("clearDump resp_handler got error {}", ec); 107480319af1SAsmitha Karunanithi messages::internalError(asyncResp->res); 107580319af1SAsmitha Karunanithi return; 107680319af1SAsmitha Karunanithi } 10770d946211SClaire Weinan }, 107818f8f608SEd Tanous "xyz.openbmc_project.Dump.Manager", getDumpPath(dumpType), 10790d946211SClaire Weinan "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll"); 108080319af1SAsmitha Karunanithi } 108180319af1SAsmitha Karunanithi 1082bd79bce8SPatrick Williams inline void parseCrashdumpParameters( 1083bd79bce8SPatrick Williams const dbus::utility::DBusPropertiesMap& params, std::string& filename, 1084bd79bce8SPatrick Williams std::string& timestamp, std::string& logfile) 1085043a0536SJohnathan Mantey { 1086d1bde9e5SKrzysztof Grobelny const std::string* filenamePtr = nullptr; 1087d1bde9e5SKrzysztof Grobelny const std::string* timestampPtr = nullptr; 1088d1bde9e5SKrzysztof Grobelny const std::string* logfilePtr = nullptr; 1089d1bde9e5SKrzysztof Grobelny 1090d1bde9e5SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 1091d1bde9e5SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), params, "Timestamp", timestampPtr, 1092d1bde9e5SKrzysztof Grobelny "Filename", filenamePtr, "Log", logfilePtr); 1093d1bde9e5SKrzysztof Grobelny 1094d1bde9e5SKrzysztof Grobelny if (!success) 1095043a0536SJohnathan Mantey { 1096d1bde9e5SKrzysztof Grobelny return; 1097043a0536SJohnathan Mantey } 1098d1bde9e5SKrzysztof Grobelny 1099d1bde9e5SKrzysztof Grobelny if (filenamePtr != nullptr) 1100043a0536SJohnathan Mantey { 1101d1bde9e5SKrzysztof Grobelny filename = *filenamePtr; 1102d1bde9e5SKrzysztof Grobelny } 1103d1bde9e5SKrzysztof Grobelny 1104d1bde9e5SKrzysztof Grobelny if (timestampPtr != nullptr) 1105043a0536SJohnathan Mantey { 1106d1bde9e5SKrzysztof Grobelny timestamp = *timestampPtr; 1107043a0536SJohnathan Mantey } 1108d1bde9e5SKrzysztof Grobelny 1109d1bde9e5SKrzysztof Grobelny if (logfilePtr != nullptr) 1110043a0536SJohnathan Mantey { 1111d1bde9e5SKrzysztof Grobelny logfile = *logfilePtr; 1112043a0536SJohnathan Mantey } 1113043a0536SJohnathan Mantey } 1114043a0536SJohnathan Mantey 11157e860f15SJohn Edward Broadbent inline void requestRoutesSystemLogServiceCollection(App& app) 11161da66f75SEd Tanous { 1117c4bf6374SJason M. Bills /** 1118c4bf6374SJason M. Bills * Functions triggers appropriate requests on DBus 1119c4bf6374SJason M. Bills */ 112022d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/") 1121ed398213SEd Tanous .privileges(redfish::privileges::getLogServiceCollection) 1122bd79bce8SPatrick Williams .methods( 1123bd79bce8SPatrick Williams boost::beast::http::verb:: 1124bd79bce8SPatrick Williams get)([&app](const crow::Request& req, 112522d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 112622d268cbSEd Tanous const std::string& systemName) { 11273ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 1128c4bf6374SJason M. Bills { 112945ca1b86SEd Tanous return; 113045ca1b86SEd Tanous } 113125b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 11327f3e84a1SEd Tanous { 11337f3e84a1SEd Tanous // Option currently returns no systems. TBD 11347f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 11357f3e84a1SEd Tanous systemName); 11367f3e84a1SEd Tanous return; 11377f3e84a1SEd Tanous } 1138253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 113922d268cbSEd Tanous { 114022d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 114122d268cbSEd Tanous systemName); 114222d268cbSEd Tanous return; 114322d268cbSEd Tanous } 114422d268cbSEd Tanous 11457e860f15SJohn Edward Broadbent // Collections don't include the static data added by SubRoute 11467e860f15SJohn Edward Broadbent // because it has a duplicate entry for members 1147c4bf6374SJason M. Bills asyncResp->res.jsonValue["@odata.type"] = 1148c4bf6374SJason M. Bills "#LogServiceCollection.LogServiceCollection"; 1149c4bf6374SJason M. Bills asyncResp->res.jsonValue["@odata.id"] = 1150253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices", 1151253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 115245ca1b86SEd Tanous asyncResp->res.jsonValue["Name"] = "System Log Services Collection"; 1153c4bf6374SJason M. Bills asyncResp->res.jsonValue["Description"] = 1154c4bf6374SJason M. Bills "Collection of LogServices for this Computer System"; 1155bd79bce8SPatrick Williams nlohmann::json& logServiceArray = 1156bd79bce8SPatrick Williams asyncResp->res.jsonValue["Members"]; 1157c4bf6374SJason M. Bills logServiceArray = nlohmann::json::array(); 11581476687dSEd Tanous nlohmann::json::object_t eventLog; 11591476687dSEd Tanous eventLog["@odata.id"] = 1160253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/EventLog", 1161253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1162b2ba3072SPatrick Williams logServiceArray.emplace_back(std::move(eventLog)); 116325b54dbaSEd Tanous if constexpr (BMCWEB_REDFISH_DUMP_LOG) 116425b54dbaSEd Tanous { 11651476687dSEd Tanous nlohmann::json::object_t dumpLog; 116625b54dbaSEd Tanous dumpLog["@odata.id"] = 1167253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/Dump", 1168253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1169b2ba3072SPatrick Williams logServiceArray.emplace_back(std::move(dumpLog)); 117025b54dbaSEd Tanous } 1171c9bb6861Sraviteja-b 11725ffd11f2SGunnar Mills if constexpr (BMCWEB_REDFISH_CPU_LOG) 117325b54dbaSEd Tanous { 11741476687dSEd Tanous nlohmann::json::object_t crashdump; 11751476687dSEd Tanous crashdump["@odata.id"] = 1176253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/Crashdump", 1177253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1178b2ba3072SPatrick Williams logServiceArray.emplace_back(std::move(crashdump)); 117925b54dbaSEd Tanous } 1180b7028ebfSSpencer Ku 118125b54dbaSEd Tanous if constexpr (BMCWEB_REDFISH_HOST_LOGGER) 118225b54dbaSEd Tanous { 11831476687dSEd Tanous nlohmann::json::object_t hostlogger; 11841476687dSEd Tanous hostlogger["@odata.id"] = 1185253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/HostLogger", 1186253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1187b2ba3072SPatrick Williams logServiceArray.emplace_back(std::move(hostlogger)); 118825b54dbaSEd Tanous } 1189c4bf6374SJason M. Bills asyncResp->res.jsonValue["Members@odata.count"] = 1190c4bf6374SJason M. Bills logServiceArray.size(); 1191a3316fc6SZhikuiRen 11927a1dbc48SGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 11937a1dbc48SGeorge Liu "xyz.openbmc_project.State.Boot.PostCode"}; 11947a1dbc48SGeorge Liu dbus::utility::getSubTreePaths( 11957a1dbc48SGeorge Liu "/", 0, interfaces, 11967a1dbc48SGeorge Liu [asyncResp](const boost::system::error_code& ec, 1197b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreePathsResponse& 1198b9d36b47SEd Tanous subtreePath) { 1199a3316fc6SZhikuiRen if (ec) 1200a3316fc6SZhikuiRen { 120162598e31SEd Tanous BMCWEB_LOG_ERROR("{}", ec); 1202a3316fc6SZhikuiRen return; 1203a3316fc6SZhikuiRen } 1204a3316fc6SZhikuiRen 120555f79e6fSEd Tanous for (const auto& pathStr : subtreePath) 1206a3316fc6SZhikuiRen { 1207a3316fc6SZhikuiRen if (pathStr.find("PostCode") != std::string::npos) 1208a3316fc6SZhikuiRen { 120923a21a1cSEd Tanous nlohmann::json& logServiceArrayLocal = 1210a3316fc6SZhikuiRen asyncResp->res.jsonValue["Members"]; 1211613dabeaSEd Tanous nlohmann::json::object_t member; 1212253f11b8SEd Tanous member["@odata.id"] = std::format( 1213253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/PostCodes", 1214253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1215613dabeaSEd Tanous 1216bd79bce8SPatrick Williams logServiceArrayLocal.emplace_back( 1217bd79bce8SPatrick Williams std::move(member)); 1218613dabeaSEd Tanous 121945ca1b86SEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = 122023a21a1cSEd Tanous logServiceArrayLocal.size(); 1221a3316fc6SZhikuiRen return; 1222a3316fc6SZhikuiRen } 1223a3316fc6SZhikuiRen } 12247a1dbc48SGeorge Liu }); 12257e860f15SJohn Edward Broadbent }); 1226c4bf6374SJason M. Bills } 1227c4bf6374SJason M. Bills 12287e860f15SJohn Edward Broadbent inline void requestRoutesEventLogService(App& app) 1229c4bf6374SJason M. Bills { 123022d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/") 1231ed398213SEd Tanous .privileges(redfish::privileges::getLogService) 1232bd79bce8SPatrick Williams .methods( 1233bd79bce8SPatrick Williams boost::beast::http::verb:: 1234bd79bce8SPatrick Williams get)([&app](const crow::Request& req, 123522d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 123622d268cbSEd Tanous const std::string& systemName) { 12373ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 123845ca1b86SEd Tanous { 123945ca1b86SEd Tanous return; 124045ca1b86SEd Tanous } 1241253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 124222d268cbSEd Tanous { 124322d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 124422d268cbSEd Tanous systemName); 124522d268cbSEd Tanous return; 124622d268cbSEd Tanous } 1247c4bf6374SJason M. Bills asyncResp->res.jsonValue["@odata.id"] = 1248253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/EventLog", 1249253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1250c4bf6374SJason M. Bills asyncResp->res.jsonValue["@odata.type"] = 1251b25644a1SJanet Adkins "#LogService.v1_2_0.LogService"; 1252c4bf6374SJason M. Bills asyncResp->res.jsonValue["Name"] = "Event Log Service"; 1253bd79bce8SPatrick Williams asyncResp->res.jsonValue["Description"] = 1254bd79bce8SPatrick Williams "System Event Log Service"; 1255c4bf6374SJason M. Bills asyncResp->res.jsonValue["Id"] = "EventLog"; 1256539d8c6bSEd Tanous asyncResp->res.jsonValue["OverWritePolicy"] = 1257539d8c6bSEd Tanous log_service::OverWritePolicy::WrapsWhenFull; 12587c8c4058STejas Patil 12597c8c4058STejas Patil std::pair<std::string, std::string> redfishDateTimeOffset = 12602b82937eSEd Tanous redfish::time_utils::getDateTimeOffsetNow(); 12617c8c4058STejas Patil 12627c8c4058STejas Patil asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first; 12637c8c4058STejas Patil asyncResp->res.jsonValue["DateTimeLocalOffset"] = 12647c8c4058STejas Patil redfishDateTimeOffset.second; 12657c8c4058STejas Patil 1266bd79bce8SPatrick Williams asyncResp->res.jsonValue["Entries"]["@odata.id"] = std::format( 1267bd79bce8SPatrick Williams "/redfish/v1/Systems/{}/LogServices/EventLog/Entries", 1268253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1269bd79bce8SPatrick Williams asyncResp->res 1270bd79bce8SPatrick Williams .jsonValue["Actions"]["#LogService.ClearLog"]["target"] 1271e7d6c8b2SGunnar Mills 127220fa6a2cSEd Tanous = std::format( 1273253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/EventLog/Actions/LogService.ClearLog", 127420fa6a2cSEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 12757e860f15SJohn Edward Broadbent }); 1276489640c6SJason M. Bills } 1277489640c6SJason M. Bills 1278599b9af3SAlexander Hansen inline void handleSystemsLogServicesEventLogActionsClearPost( 1279599b9af3SAlexander Hansen App& app, const crow::Request& req, 128022d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1281599b9af3SAlexander Hansen const std::string& systemName) 1282599b9af3SAlexander Hansen { 12833ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 128445ca1b86SEd Tanous { 128545ca1b86SEd Tanous return; 128645ca1b86SEd Tanous } 1287253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 128822d268cbSEd Tanous { 128922d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 129022d268cbSEd Tanous systemName); 129122d268cbSEd Tanous return; 129222d268cbSEd Tanous } 1293599b9af3SAlexander Hansen 1294489640c6SJason M. Bills // Clear the EventLog by deleting the log files 1295489640c6SJason M. Bills std::vector<std::filesystem::path> redfishLogFiles; 1296489640c6SJason M. Bills if (getRedfishLogFiles(redfishLogFiles)) 1297489640c6SJason M. Bills { 1298489640c6SJason M. Bills for (const std::filesystem::path& file : redfishLogFiles) 1299489640c6SJason M. Bills { 1300489640c6SJason M. Bills std::error_code ec; 1301489640c6SJason M. Bills std::filesystem::remove(file, ec); 1302489640c6SJason M. Bills } 1303489640c6SJason M. Bills } 1304489640c6SJason M. Bills 1305489640c6SJason M. Bills // Reload rsyslog so it knows to start new log files 1306489640c6SJason M. Bills crow::connections::systemBus->async_method_call( 13075e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 1308489640c6SJason M. Bills if (ec) 1309489640c6SJason M. Bills { 131062598e31SEd Tanous BMCWEB_LOG_ERROR("Failed to reload rsyslog: {}", ec); 1311489640c6SJason M. Bills messages::internalError(asyncResp->res); 1312489640c6SJason M. Bills return; 1313489640c6SJason M. Bills } 1314489640c6SJason M. Bills 1315489640c6SJason M. Bills messages::success(asyncResp->res); 1316489640c6SJason M. Bills }, 1317489640c6SJason M. Bills "org.freedesktop.systemd1", "/org/freedesktop/systemd1", 1318002d39b4SEd Tanous "org.freedesktop.systemd1.Manager", "ReloadUnit", "rsyslog.service", 1319002d39b4SEd Tanous "replace"); 1320599b9af3SAlexander Hansen } 1321599b9af3SAlexander Hansen 1322599b9af3SAlexander Hansen inline void requestRoutesJournalEventLogClear(App& app) 1323599b9af3SAlexander Hansen { 1324599b9af3SAlexander Hansen BMCWEB_ROUTE( 1325599b9af3SAlexander Hansen app, 1326599b9af3SAlexander Hansen "/redfish/v1/Systems/<str>/LogServices/EventLog/Actions/LogService.ClearLog/") 1327599b9af3SAlexander Hansen .privileges({{"ConfigureComponents"}}) 1328599b9af3SAlexander Hansen .methods(boost::beast::http::verb::post)(std::bind_front( 1329599b9af3SAlexander Hansen handleSystemsLogServicesEventLogActionsClearPost, std::ref(app))); 1330c4bf6374SJason M. Bills } 1331c4bf6374SJason M. Bills 1332ac992cdeSJason M. Bills enum class LogParseError 1333ac992cdeSJason M. Bills { 1334ac992cdeSJason M. Bills success, 1335ac992cdeSJason M. Bills parseFailed, 1336ac992cdeSJason M. Bills messageIdNotInRegistry, 1337ac992cdeSJason M. Bills }; 1338ac992cdeSJason M. Bills 1339bd79bce8SPatrick Williams static LogParseError fillEventLogEntryJson( 1340bd79bce8SPatrick Williams const std::string& logEntryID, const std::string& logEntry, 1341de703c5dSJason M. Bills nlohmann::json::object_t& logEntryJson) 1342c4bf6374SJason M. Bills { 134395820184SJason M. Bills // The redfish log format is "<Timestamp> <MessageId>,<MessageArgs>" 1344cd225da8SJason M. Bills // First get the Timestamp 1345f23b7296SEd Tanous size_t space = logEntry.find_first_of(' '); 1346cd225da8SJason M. Bills if (space == std::string::npos) 134795820184SJason M. Bills { 1348ac992cdeSJason M. Bills return LogParseError::parseFailed; 134995820184SJason M. Bills } 1350cd225da8SJason M. Bills std::string timestamp = logEntry.substr(0, space); 1351cd225da8SJason M. Bills // Then get the log contents 1352f23b7296SEd Tanous size_t entryStart = logEntry.find_first_not_of(' ', space); 1353cd225da8SJason M. Bills if (entryStart == std::string::npos) 1354cd225da8SJason M. Bills { 1355ac992cdeSJason M. Bills return LogParseError::parseFailed; 1356cd225da8SJason M. Bills } 1357cd225da8SJason M. Bills std::string_view entry(logEntry); 1358cd225da8SJason M. Bills entry.remove_prefix(entryStart); 1359cd225da8SJason M. Bills // Use split to separate the entry into its fields 1360cd225da8SJason M. Bills std::vector<std::string> logEntryFields; 136150ebd4afSEd Tanous bmcweb::split(logEntryFields, entry, ','); 1362cd225da8SJason M. Bills // We need at least a MessageId to be valid 13631e6deaf6SEd Tanous auto logEntryIter = logEntryFields.begin(); 13641e6deaf6SEd Tanous if (logEntryIter == logEntryFields.end()) 1365cd225da8SJason M. Bills { 1366ac992cdeSJason M. Bills return LogParseError::parseFailed; 1367cd225da8SJason M. Bills } 13681e6deaf6SEd Tanous std::string& messageID = *logEntryIter; 13694851d45dSJason M. Bills // Get the Message from the MessageRegistry 1370fffb8c1fSEd Tanous const registries::Message* message = registries::getMessage(messageID); 1371c4bf6374SJason M. Bills 13721e6deaf6SEd Tanous logEntryIter++; 137354417b02SSui Chen if (message == nullptr) 1374c4bf6374SJason M. Bills { 137562598e31SEd Tanous BMCWEB_LOG_WARNING("Log entry not found in registry: {}", logEntry); 1376ac992cdeSJason M. Bills return LogParseError::messageIdNotInRegistry; 1377c4bf6374SJason M. Bills } 1378c4bf6374SJason M. Bills 13791e6deaf6SEd Tanous std::vector<std::string_view> messageArgs(logEntryIter, 13801e6deaf6SEd Tanous logEntryFields.end()); 1381c05bba45SEd Tanous messageArgs.resize(message->numberOfArgs); 1382c05bba45SEd Tanous 1383bd79bce8SPatrick Williams std::string msg = 1384bd79bce8SPatrick Williams redfish::registries::fillMessageArgs(messageArgs, message->message); 13851e6deaf6SEd Tanous if (msg.empty()) 138615a86ff6SJason M. Bills { 13871e6deaf6SEd Tanous return LogParseError::parseFailed; 138815a86ff6SJason M. Bills } 13894851d45dSJason M. Bills 139095820184SJason M. Bills // Get the Created time from the timestamp. The log timestamp is in RFC3339 139195820184SJason M. Bills // format which matches the Redfish format except for the fractional seconds 139295820184SJason M. Bills // between the '.' and the '+', so just remove them. 1393f23b7296SEd Tanous std::size_t dot = timestamp.find_first_of('.'); 1394f23b7296SEd Tanous std::size_t plus = timestamp.find_first_of('+'); 139595820184SJason M. Bills if (dot != std::string::npos && plus != std::string::npos) 1396c4bf6374SJason M. Bills { 139795820184SJason M. Bills timestamp.erase(dot, plus - dot); 1398c4bf6374SJason M. Bills } 1399c4bf6374SJason M. Bills 1400c4bf6374SJason M. Bills // Fill in the log entry with the gathered data 14019c11a172SVijay Lobo logEntryJson["@odata.type"] = "#LogEntry.v1_9_0.LogEntry"; 1402ef4c65b7SEd Tanous logEntryJson["@odata.id"] = boost::urls::format( 1403253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}", 1404253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, logEntryID); 140584afc48bSJason M. Bills logEntryJson["Name"] = "System Event Log Entry"; 140684afc48bSJason M. Bills logEntryJson["Id"] = logEntryID; 140784afc48bSJason M. Bills logEntryJson["Message"] = std::move(msg); 140884afc48bSJason M. Bills logEntryJson["MessageId"] = std::move(messageID); 140984afc48bSJason M. Bills logEntryJson["MessageArgs"] = messageArgs; 141084afc48bSJason M. Bills logEntryJson["EntryType"] = "Event"; 141184afc48bSJason M. Bills logEntryJson["Severity"] = message->messageSeverity; 141284afc48bSJason M. Bills logEntryJson["Created"] = std::move(timestamp); 1413ac992cdeSJason M. Bills return LogParseError::success; 1414c4bf6374SJason M. Bills } 1415c4bf6374SJason M. Bills 1416898f2aa2SEd Tanous inline void fillEventLogLogEntryFromPropertyMap( 1417898f2aa2SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1418898f2aa2SEd Tanous const dbus::utility::DBusPropertiesMap& resp, 1419898f2aa2SEd Tanous nlohmann::json& objectToFillOut) 1420898f2aa2SEd Tanous { 1421898f2aa2SEd Tanous uint32_t id = 0; 1422898f2aa2SEd Tanous uint64_t timestamp = 0; 1423898f2aa2SEd Tanous uint64_t updateTimestamp = 0; 1424898f2aa2SEd Tanous std::string severity; 1425898f2aa2SEd Tanous std::string message; 1426898f2aa2SEd Tanous const std::string* filePath = nullptr; 1427898f2aa2SEd Tanous const std::string* resolution = nullptr; 1428898f2aa2SEd Tanous bool resolved = false; 1429898f2aa2SEd Tanous std::string notify; 1430898f2aa2SEd Tanous // clang-format off 1431898f2aa2SEd Tanous bool success = sdbusplus::unpackPropertiesNoThrow( 1432898f2aa2SEd Tanous dbus_utils::UnpackErrorPrinter(), resp, 1433898f2aa2SEd Tanous "Id", id, 1434898f2aa2SEd Tanous "Message", message, 1435898f2aa2SEd Tanous "Path", filePath, 1436898f2aa2SEd Tanous "Resolution", resolution, 1437898f2aa2SEd Tanous "Resolved", resolved, 1438898f2aa2SEd Tanous "ServiceProviderNotify", notify, 1439898f2aa2SEd Tanous "Severity", severity, 1440898f2aa2SEd Tanous "Timestamp", timestamp, 1441898f2aa2SEd Tanous "UpdateTimestamp", updateTimestamp 1442898f2aa2SEd Tanous ); 1443898f2aa2SEd Tanous // clang-format on 1444898f2aa2SEd Tanous 1445898f2aa2SEd Tanous if (!success) 1446898f2aa2SEd Tanous { 1447898f2aa2SEd Tanous messages::internalError(asyncResp->res); 1448898f2aa2SEd Tanous return; 1449898f2aa2SEd Tanous } 1450898f2aa2SEd Tanous 1451898f2aa2SEd Tanous objectToFillOut["@odata.type"] = "#LogEntry.v1_9_0.LogEntry"; 1452898f2aa2SEd Tanous objectToFillOut["@odata.id"] = boost::urls::format( 1453898f2aa2SEd Tanous "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}", 1454898f2aa2SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(id)); 1455898f2aa2SEd Tanous objectToFillOut["Name"] = "System Event Log Entry"; 1456898f2aa2SEd Tanous objectToFillOut["Id"] = std::to_string(id); 1457898f2aa2SEd Tanous objectToFillOut["Message"] = message; 1458898f2aa2SEd Tanous objectToFillOut["Resolved"] = resolved; 1459898f2aa2SEd Tanous std::optional<bool> notifyAction = getProviderNotifyAction(notify); 1460898f2aa2SEd Tanous if (notifyAction) 1461898f2aa2SEd Tanous { 1462898f2aa2SEd Tanous objectToFillOut["ServiceProviderNotified"] = *notifyAction; 1463898f2aa2SEd Tanous } 1464898f2aa2SEd Tanous if ((resolution != nullptr) && !resolution->empty()) 1465898f2aa2SEd Tanous { 1466898f2aa2SEd Tanous objectToFillOut["Resolution"] = *resolution; 1467898f2aa2SEd Tanous } 1468898f2aa2SEd Tanous objectToFillOut["EntryType"] = "Event"; 1469898f2aa2SEd Tanous objectToFillOut["Severity"] = translateSeverityDbusToRedfish(severity); 1470898f2aa2SEd Tanous objectToFillOut["Created"] = 1471898f2aa2SEd Tanous redfish::time_utils::getDateTimeUintMs(timestamp); 1472898f2aa2SEd Tanous objectToFillOut["Modified"] = 1473898f2aa2SEd Tanous redfish::time_utils::getDateTimeUintMs(updateTimestamp); 1474898f2aa2SEd Tanous if (filePath != nullptr) 1475898f2aa2SEd Tanous { 1476898f2aa2SEd Tanous objectToFillOut["AdditionalDataURI"] = boost::urls::format( 1477898f2aa2SEd Tanous "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}/attachment", 1478898f2aa2SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(id)); 1479898f2aa2SEd Tanous } 1480898f2aa2SEd Tanous } 1481898f2aa2SEd Tanous 1482b729096dSEd Tanous inline void afterLogEntriesGetManagedObjects( 1483b729096dSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1484b729096dSEd Tanous const boost::system::error_code& ec, 1485b729096dSEd Tanous const dbus::utility::ManagedObjectType& resp) 1486b729096dSEd Tanous { 1487b729096dSEd Tanous if (ec) 1488b729096dSEd Tanous { 1489b729096dSEd Tanous // TODO Handle for specific error code 1490b729096dSEd Tanous BMCWEB_LOG_ERROR("getLogEntriesIfaceData resp_handler got error {}", 1491b729096dSEd Tanous ec); 1492b729096dSEd Tanous messages::internalError(asyncResp->res); 1493b729096dSEd Tanous return; 1494b729096dSEd Tanous } 1495b729096dSEd Tanous nlohmann::json::array_t entriesArray; 1496b729096dSEd Tanous for (const auto& objectPath : resp) 1497b729096dSEd Tanous { 1498898f2aa2SEd Tanous dbus::utility::DBusPropertiesMap propsFlattened; 1499bd79bce8SPatrick Williams auto isEntry = 1500bd79bce8SPatrick Williams std::ranges::find_if(objectPath.second, [](const auto& object) { 1501898f2aa2SEd Tanous return object.first == "xyz.openbmc_project.Logging.Entry"; 1502898f2aa2SEd Tanous }); 1503898f2aa2SEd Tanous if (isEntry == objectPath.second.end()) 1504b729096dSEd Tanous { 1505b729096dSEd Tanous continue; 1506b729096dSEd Tanous } 1507898f2aa2SEd Tanous for (const auto& interfaceMap : objectPath.second) 1508b729096dSEd Tanous { 1509898f2aa2SEd Tanous for (const auto& propertyMap : interfaceMap.second) 1510b729096dSEd Tanous { 1511898f2aa2SEd Tanous propsFlattened.emplace_back(propertyMap.first, 1512898f2aa2SEd Tanous propertyMap.second); 1513b729096dSEd Tanous } 1514b729096dSEd Tanous } 1515898f2aa2SEd Tanous fillEventLogLogEntryFromPropertyMap(asyncResp, propsFlattened, 1516898f2aa2SEd Tanous entriesArray.emplace_back()); 1517b729096dSEd Tanous } 1518898f2aa2SEd Tanous 1519b729096dSEd Tanous std::ranges::sort(entriesArray, [](const nlohmann::json& left, 1520b729096dSEd Tanous const nlohmann::json& right) { 1521b729096dSEd Tanous return (left["Id"] <= right["Id"]); 1522b729096dSEd Tanous }); 1523b729096dSEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = entriesArray.size(); 1524b729096dSEd Tanous asyncResp->res.jsonValue["Members"] = std::move(entriesArray); 1525b729096dSEd Tanous } 1526b729096dSEd Tanous 1527599b9af3SAlexander Hansen inline void handleSystemsLogServiceEventLogLogEntryCollection( 1528599b9af3SAlexander Hansen App& app, const crow::Request& req, 152922d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1530599b9af3SAlexander Hansen const std::string& systemName) 1531599b9af3SAlexander Hansen { 1532c937d2bfSEd Tanous query_param::QueryCapabilities capabilities = { 1533c937d2bfSEd Tanous .canDelegateTop = true, 1534c937d2bfSEd Tanous .canDelegateSkip = true, 1535c937d2bfSEd Tanous }; 1536c937d2bfSEd Tanous query_param::Query delegatedQuery; 1537599b9af3SAlexander Hansen if (!redfish::setUpRedfishRouteWithDelegation(app, req, asyncResp, 1538599b9af3SAlexander Hansen delegatedQuery, capabilities)) 1539c4bf6374SJason M. Bills { 1540c4bf6374SJason M. Bills return; 1541c4bf6374SJason M. Bills } 154225b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 15437f3e84a1SEd Tanous { 15447f3e84a1SEd Tanous // Option currently returns no systems. TBD 15457f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 15467f3e84a1SEd Tanous systemName); 15477f3e84a1SEd Tanous return; 15487f3e84a1SEd Tanous } 1549253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 155022d268cbSEd Tanous { 155122d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 155222d268cbSEd Tanous systemName); 155322d268cbSEd Tanous return; 155422d268cbSEd Tanous } 155522d268cbSEd Tanous 15565143f7a5SJiaqing Zhao size_t top = delegatedQuery.top.value_or(query_param::Query::maxTop); 15573648c8beSEd Tanous size_t skip = delegatedQuery.skip.value_or(0); 15583648c8beSEd Tanous 15597e860f15SJohn Edward Broadbent // Collections don't include the static data added by SubRoute 15607e860f15SJohn Edward Broadbent // because it has a duplicate entry for members 1561c4bf6374SJason M. Bills asyncResp->res.jsonValue["@odata.type"] = 1562c4bf6374SJason M. Bills "#LogEntryCollection.LogEntryCollection"; 1563c4bf6374SJason M. Bills asyncResp->res.jsonValue["@odata.id"] = 1564253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries", 1565253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 1566c4bf6374SJason M. Bills asyncResp->res.jsonValue["Name"] = "System Event Log Entries"; 1567c4bf6374SJason M. Bills asyncResp->res.jsonValue["Description"] = 1568c4bf6374SJason M. Bills "Collection of System Event Log Entries"; 1569cb92c03bSAndrew Geissler 15704978b63fSJason M. Bills nlohmann::json& logEntryArray = asyncResp->res.jsonValue["Members"]; 1571c4bf6374SJason M. Bills logEntryArray = nlohmann::json::array(); 15727e860f15SJohn Edward Broadbent // Go through the log files and create a unique ID for each 15737e860f15SJohn Edward Broadbent // entry 157495820184SJason M. Bills std::vector<std::filesystem::path> redfishLogFiles; 157595820184SJason M. Bills getRedfishLogFiles(redfishLogFiles); 1576b01bf299SEd Tanous uint64_t entryCount = 0; 1577cd225da8SJason M. Bills std::string logEntry; 157895820184SJason M. Bills 15797e860f15SJohn Edward Broadbent // Oldest logs are in the last file, so start there and loop 15807e860f15SJohn Edward Broadbent // backwards 1581599b9af3SAlexander Hansen for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend(); it++) 1582c4bf6374SJason M. Bills { 1583cd225da8SJason M. Bills std::ifstream logStream(*it); 158495820184SJason M. Bills if (!logStream.is_open()) 1585c4bf6374SJason M. Bills { 1586c4bf6374SJason M. Bills continue; 1587c4bf6374SJason M. Bills } 1588c4bf6374SJason M. Bills 1589e85d6b16SJason M. Bills // Reset the unique ID on the first entry 1590e85d6b16SJason M. Bills bool firstEntry = true; 159195820184SJason M. Bills while (std::getline(logStream, logEntry)) 159295820184SJason M. Bills { 1593c4bf6374SJason M. Bills std::string idStr; 1594e85d6b16SJason M. Bills if (!getUniqueEntryID(logEntry, idStr, firstEntry)) 1595c4bf6374SJason M. Bills { 1596c4bf6374SJason M. Bills continue; 1597c4bf6374SJason M. Bills } 1598e85d6b16SJason M. Bills firstEntry = false; 1599e85d6b16SJason M. Bills 1600de703c5dSJason M. Bills nlohmann::json::object_t bmcLogEntry; 1601bd79bce8SPatrick Williams LogParseError status = 1602bd79bce8SPatrick Williams fillEventLogEntryJson(idStr, logEntry, bmcLogEntry); 1603ac992cdeSJason M. Bills if (status == LogParseError::messageIdNotInRegistry) 1604ac992cdeSJason M. Bills { 1605ac992cdeSJason M. Bills continue; 1606ac992cdeSJason M. Bills } 1607ac992cdeSJason M. Bills if (status != LogParseError::success) 1608c4bf6374SJason M. Bills { 1609c4bf6374SJason M. Bills messages::internalError(asyncResp->res); 1610c4bf6374SJason M. Bills return; 1611c4bf6374SJason M. Bills } 1612de703c5dSJason M. Bills 1613de703c5dSJason M. Bills entryCount++; 1614de703c5dSJason M. Bills // Handle paging using skip (number of entries to skip from the 1615de703c5dSJason M. Bills // start) and top (number of entries to display) 16163648c8beSEd Tanous if (entryCount <= skip || entryCount > skip + top) 1617de703c5dSJason M. Bills { 1618de703c5dSJason M. Bills continue; 1619de703c5dSJason M. Bills } 1620de703c5dSJason M. Bills 1621b2ba3072SPatrick Williams logEntryArray.emplace_back(std::move(bmcLogEntry)); 1622c4bf6374SJason M. Bills } 162395820184SJason M. Bills } 1624c4bf6374SJason M. Bills asyncResp->res.jsonValue["Members@odata.count"] = entryCount; 16253648c8beSEd Tanous if (skip + top < entryCount) 1626c4bf6374SJason M. Bills { 1627599b9af3SAlexander Hansen asyncResp->res.jsonValue["Members@odata.nextLink"] = 1628599b9af3SAlexander Hansen boost::urls::format( 1629253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/EventLog/Entries?$skip={}", 1630253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(skip + top)); 1631c4bf6374SJason M. Bills } 1632897967deSJason M. Bills } 1633897967deSJason M. Bills 1634599b9af3SAlexander Hansen inline void requestRoutesJournalEventLogEntryCollection(App& app) 1635897967deSJason M. Bills { 1636599b9af3SAlexander Hansen BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/") 1637599b9af3SAlexander Hansen .privileges(redfish::privileges::getLogEntryCollection) 1638599b9af3SAlexander Hansen .methods(boost::beast::http::verb::get)(std::bind_front( 1639599b9af3SAlexander Hansen handleSystemsLogServiceEventLogLogEntryCollection, std::ref(app))); 1640599b9af3SAlexander Hansen } 1641599b9af3SAlexander Hansen 1642599b9af3SAlexander Hansen inline void handleSystemsLogServiceEventLogEntriesGet( 1643599b9af3SAlexander Hansen App& app, const crow::Request& req, 16447e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1645599b9af3SAlexander Hansen const std::string& systemName, const std::string& param) 1646599b9af3SAlexander Hansen { 16473ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 164845ca1b86SEd Tanous { 164945ca1b86SEd Tanous return; 165045ca1b86SEd Tanous } 165125b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 16527f3e84a1SEd Tanous { 16537f3e84a1SEd Tanous // Option currently returns no systems. TBD 16547f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 16557f3e84a1SEd Tanous systemName); 16567f3e84a1SEd Tanous return; 16577f3e84a1SEd Tanous } 165822d268cbSEd Tanous 1659253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 166022d268cbSEd Tanous { 166122d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 166222d268cbSEd Tanous systemName); 166322d268cbSEd Tanous return; 166422d268cbSEd Tanous } 166522d268cbSEd Tanous 16667e860f15SJohn Edward Broadbent const std::string& targetID = param; 16678d1b46d7Szhanghch05 16687e860f15SJohn Edward Broadbent // Go through the log files and check the unique ID for each 16697e860f15SJohn Edward Broadbent // entry to find the target entry 1670897967deSJason M. Bills std::vector<std::filesystem::path> redfishLogFiles; 1671897967deSJason M. Bills getRedfishLogFiles(redfishLogFiles); 1672897967deSJason M. Bills std::string logEntry; 1673897967deSJason M. Bills 16747e860f15SJohn Edward Broadbent // Oldest logs are in the last file, so start there and loop 16757e860f15SJohn Edward Broadbent // backwards 1676599b9af3SAlexander Hansen for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend(); it++) 1677897967deSJason M. Bills { 1678897967deSJason M. Bills std::ifstream logStream(*it); 1679897967deSJason M. Bills if (!logStream.is_open()) 1680897967deSJason M. Bills { 1681897967deSJason M. Bills continue; 1682897967deSJason M. Bills } 1683897967deSJason M. Bills 1684897967deSJason M. Bills // Reset the unique ID on the first entry 1685897967deSJason M. Bills bool firstEntry = true; 1686897967deSJason M. Bills while (std::getline(logStream, logEntry)) 1687897967deSJason M. Bills { 1688897967deSJason M. Bills std::string idStr; 1689897967deSJason M. Bills if (!getUniqueEntryID(logEntry, idStr, firstEntry)) 1690897967deSJason M. Bills { 1691897967deSJason M. Bills continue; 1692897967deSJason M. Bills } 1693897967deSJason M. Bills firstEntry = false; 1694897967deSJason M. Bills 1695897967deSJason M. Bills if (idStr == targetID) 1696897967deSJason M. Bills { 1697de703c5dSJason M. Bills nlohmann::json::object_t bmcLogEntry; 1698bd79bce8SPatrick Williams LogParseError status = 1699bd79bce8SPatrick Williams fillEventLogEntryJson(idStr, logEntry, bmcLogEntry); 1700ac992cdeSJason M. Bills if (status != LogParseError::success) 1701897967deSJason M. Bills { 1702897967deSJason M. Bills messages::internalError(asyncResp->res); 1703897967deSJason M. Bills return; 1704897967deSJason M. Bills } 1705d405bb51SJason M. Bills asyncResp->res.jsonValue.update(bmcLogEntry); 1706897967deSJason M. Bills return; 1707897967deSJason M. Bills } 1708897967deSJason M. Bills } 1709897967deSJason M. Bills } 1710897967deSJason M. Bills // Requested ID was not found 17119db4ba25SJiaqing Zhao messages::resourceNotFound(asyncResp->res, "LogEntry", targetID); 1712599b9af3SAlexander Hansen } 1713599b9af3SAlexander Hansen 1714599b9af3SAlexander Hansen inline void requestRoutesJournalEventLogEntry(App& app) 1715599b9af3SAlexander Hansen { 1716599b9af3SAlexander Hansen BMCWEB_ROUTE( 1717599b9af3SAlexander Hansen app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/") 1718599b9af3SAlexander Hansen .privileges(redfish::privileges::getLogEntry) 1719599b9af3SAlexander Hansen .methods(boost::beast::http::verb::get)(std::bind_front( 1720599b9af3SAlexander Hansen handleSystemsLogServiceEventLogEntriesGet, std::ref(app))); 1721599b9af3SAlexander Hansen } 1722599b9af3SAlexander Hansen 1723599b9af3SAlexander Hansen inline void dBusEventLogEntryCollection( 1724599b9af3SAlexander Hansen const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1725599b9af3SAlexander Hansen { 1726599b9af3SAlexander Hansen // Collections don't include the static data added by SubRoute 1727599b9af3SAlexander Hansen // because it has a duplicate entry for members 1728599b9af3SAlexander Hansen asyncResp->res.jsonValue["@odata.type"] = 1729599b9af3SAlexander Hansen "#LogEntryCollection.LogEntryCollection"; 1730599b9af3SAlexander Hansen asyncResp->res.jsonValue["@odata.id"] = 1731599b9af3SAlexander Hansen std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries", 1732599b9af3SAlexander Hansen BMCWEB_REDFISH_SYSTEM_URI_NAME); 1733599b9af3SAlexander Hansen asyncResp->res.jsonValue["Name"] = "System Event Log Entries"; 1734599b9af3SAlexander Hansen asyncResp->res.jsonValue["Description"] = 1735599b9af3SAlexander Hansen "Collection of System Event Log Entries"; 1736599b9af3SAlexander Hansen 1737599b9af3SAlexander Hansen // DBus implementation of EventLog/Entries 1738599b9af3SAlexander Hansen // Make call to Logging Service to find all log entry objects 1739599b9af3SAlexander Hansen sdbusplus::message::object_path path("/xyz/openbmc_project/logging"); 1740599b9af3SAlexander Hansen dbus::utility::getManagedObjects( 1741599b9af3SAlexander Hansen "xyz.openbmc_project.Logging", path, 1742599b9af3SAlexander Hansen [asyncResp](const boost::system::error_code& ec, 1743599b9af3SAlexander Hansen const dbus::utility::ManagedObjectType& resp) { 1744b729096dSEd Tanous afterLogEntriesGetManagedObjects(asyncResp, ec, resp); 17457e860f15SJohn Edward Broadbent }); 174608a4e4b5SAnthony Wilson } 174708a4e4b5SAnthony Wilson 17487e860f15SJohn Edward Broadbent inline void requestRoutesDBusEventLogEntryCollection(App& app) 174908a4e4b5SAnthony Wilson { 175022d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/") 1751ed398213SEd Tanous .privileges(redfish::privileges::getLogEntryCollection) 1752002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 1753002d39b4SEd Tanous [&app](const crow::Request& req, 175422d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 175522d268cbSEd Tanous const std::string& systemName) { 17563ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 175745ca1b86SEd Tanous { 175845ca1b86SEd Tanous return; 175945ca1b86SEd Tanous } 176025b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 17617f3e84a1SEd Tanous { 17627f3e84a1SEd Tanous // Option currently returns no systems. TBD 17637f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 17647f3e84a1SEd Tanous systemName); 17657f3e84a1SEd Tanous return; 17667f3e84a1SEd Tanous } 1767253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 176822d268cbSEd Tanous { 176922d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 177022d268cbSEd Tanous systemName); 177122d268cbSEd Tanous return; 177222d268cbSEd Tanous } 1773599b9af3SAlexander Hansen dBusEventLogEntryCollection(asyncResp); 1774599b9af3SAlexander Hansen }); 1775599b9af3SAlexander Hansen } 177622d268cbSEd Tanous 1777bd79bce8SPatrick Williams inline void dBusEventLogEntryGet( 1778bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID) 1779599b9af3SAlexander Hansen { 1780599b9af3SAlexander Hansen dbus::utility::escapePathForDbus(entryID); 178108a4e4b5SAnthony Wilson 1782cb92c03bSAndrew Geissler // DBus implementation of EventLog/Entries 1783cb92c03bSAndrew Geissler // Make call to Logging Service to find all log entry objects 1784599b9af3SAlexander Hansen sdbusplus::asio::getAllProperties( 1785599b9af3SAlexander Hansen *crow::connections::systemBus, "xyz.openbmc_project.Logging", 1786599b9af3SAlexander Hansen "/xyz/openbmc_project/logging/entry/" + entryID, "", 1787599b9af3SAlexander Hansen [asyncResp, entryID](const boost::system::error_code& ec, 1788599b9af3SAlexander Hansen const dbus::utility::DBusPropertiesMap& resp) { 1789599b9af3SAlexander Hansen if (ec.value() == EBADR) 1790599b9af3SAlexander Hansen { 1791599b9af3SAlexander Hansen messages::resourceNotFound(asyncResp->res, "EventLogEntry", 1792599b9af3SAlexander Hansen entryID); 1793599b9af3SAlexander Hansen return; 1794599b9af3SAlexander Hansen } 1795cb92c03bSAndrew Geissler if (ec) 1796cb92c03bSAndrew Geissler { 1797bd79bce8SPatrick Williams BMCWEB_LOG_ERROR( 1798bd79bce8SPatrick Williams "EventLogEntry (DBus) resp_handler got error {}", ec); 1799cb92c03bSAndrew Geissler messages::internalError(asyncResp->res); 1800cb92c03bSAndrew Geissler return; 1801cb92c03bSAndrew Geissler } 18029017faf2SAbhishek Patel 1803898f2aa2SEd Tanous fillEventLogLogEntryFromPropertyMap(asyncResp, resp, 1804898f2aa2SEd Tanous asyncResp->res.jsonValue); 1805599b9af3SAlexander Hansen }); 18067e860f15SJohn Edward Broadbent } 1807599b9af3SAlexander Hansen 1808599b9af3SAlexander Hansen inline void 1809599b9af3SAlexander Hansen dBusEventLogEntryPatch(const crow::Request& req, 1810599b9af3SAlexander Hansen const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1811599b9af3SAlexander Hansen const std::string& entryId) 1812599b9af3SAlexander Hansen { 1813599b9af3SAlexander Hansen std::optional<bool> resolved; 1814599b9af3SAlexander Hansen 1815599b9af3SAlexander Hansen if (!json_util::readJsonPatch(req, asyncResp->res, "Resolved", resolved)) 1816599b9af3SAlexander Hansen { 1817599b9af3SAlexander Hansen return; 1818599b9af3SAlexander Hansen } 1819599b9af3SAlexander Hansen BMCWEB_LOG_DEBUG("Set Resolved"); 1820599b9af3SAlexander Hansen 1821599b9af3SAlexander Hansen setDbusProperty(asyncResp, "Resolved", "xyz.openbmc_project.Logging", 1822599b9af3SAlexander Hansen "/xyz/openbmc_project/logging/entry/" + entryId, 1823599b9af3SAlexander Hansen "xyz.openbmc_project.Logging.Entry", "Resolved", 1824599b9af3SAlexander Hansen resolved.value_or(false)); 1825599b9af3SAlexander Hansen } 1826599b9af3SAlexander Hansen 1827bd79bce8SPatrick Williams inline void dBusEventLogEntryDelete( 1828bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID) 1829599b9af3SAlexander Hansen { 1830599b9af3SAlexander Hansen BMCWEB_LOG_DEBUG("Do delete single event entries."); 1831599b9af3SAlexander Hansen 1832599b9af3SAlexander Hansen dbus::utility::escapePathForDbus(entryID); 1833599b9af3SAlexander Hansen 1834599b9af3SAlexander Hansen // Process response from Logging service. 1835599b9af3SAlexander Hansen auto respHandler = [asyncResp, 1836599b9af3SAlexander Hansen entryID](const boost::system::error_code& ec) { 1837599b9af3SAlexander Hansen BMCWEB_LOG_DEBUG("EventLogEntry (DBus) doDelete callback: Done"); 1838599b9af3SAlexander Hansen if (ec) 1839599b9af3SAlexander Hansen { 1840599b9af3SAlexander Hansen if (ec.value() == EBADR) 1841599b9af3SAlexander Hansen { 1842599b9af3SAlexander Hansen messages::resourceNotFound(asyncResp->res, "LogEntry", entryID); 1843599b9af3SAlexander Hansen return; 1844599b9af3SAlexander Hansen } 1845599b9af3SAlexander Hansen // TODO Handle for specific error code 1846599b9af3SAlexander Hansen BMCWEB_LOG_ERROR( 1847599b9af3SAlexander Hansen "EventLogEntry (DBus) doDelete respHandler got error {}", ec); 1848599b9af3SAlexander Hansen asyncResp->res.result( 1849599b9af3SAlexander Hansen boost::beast::http::status::internal_server_error); 1850599b9af3SAlexander Hansen return; 1851599b9af3SAlexander Hansen } 1852599b9af3SAlexander Hansen 1853599b9af3SAlexander Hansen asyncResp->res.result(boost::beast::http::status::ok); 1854599b9af3SAlexander Hansen }; 1855599b9af3SAlexander Hansen 1856599b9af3SAlexander Hansen // Make call to Logging service to request Delete Log 1857599b9af3SAlexander Hansen crow::connections::systemBus->async_method_call( 1858599b9af3SAlexander Hansen respHandler, "xyz.openbmc_project.Logging", 1859599b9af3SAlexander Hansen "/xyz/openbmc_project/logging/entry/" + entryID, 1860599b9af3SAlexander Hansen "xyz.openbmc_project.Object.Delete", "Delete"); 18617e860f15SJohn Edward Broadbent } 18627e860f15SJohn Edward Broadbent 18637e860f15SJohn Edward Broadbent inline void requestRoutesDBusEventLogEntry(App& app) 18647e860f15SJohn Edward Broadbent { 18657e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 186622d268cbSEd Tanous app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/") 1867ed398213SEd Tanous .privileges(redfish::privileges::getLogEntry) 1868002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 1869002d39b4SEd Tanous [&app](const crow::Request& req, 18707e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1871898f2aa2SEd Tanous const std::string& systemName, const std::string& entryId) { 18723ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 18737e860f15SJohn Edward Broadbent { 187445ca1b86SEd Tanous return; 187545ca1b86SEd Tanous } 187625b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 18777f3e84a1SEd Tanous { 18787f3e84a1SEd Tanous // Option currently returns no systems. TBD 18797f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 18807f3e84a1SEd Tanous systemName); 18817f3e84a1SEd Tanous return; 18827f3e84a1SEd Tanous } 1883253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 188422d268cbSEd Tanous { 188522d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 188622d268cbSEd Tanous systemName); 188722d268cbSEd Tanous return; 188822d268cbSEd Tanous } 188922d268cbSEd Tanous 1890898f2aa2SEd Tanous dBusEventLogEntryGet(asyncResp, entryId); 18917e860f15SJohn Edward Broadbent }); 1892336e96c6SChicago Duan 18937e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 189422d268cbSEd Tanous app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/") 1895ed398213SEd Tanous .privileges(redfish::privileges::patchLogEntry) 18967e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::patch)( 189745ca1b86SEd Tanous [&app](const crow::Request& req, 18987e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 189922d268cbSEd Tanous const std::string& systemName, const std::string& entryId) { 19003ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 190145ca1b86SEd Tanous { 190245ca1b86SEd Tanous return; 190345ca1b86SEd Tanous } 190425b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 19057f3e84a1SEd Tanous { 19067f3e84a1SEd Tanous // Option currently returns no systems. TBD 19077f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 19087f3e84a1SEd Tanous systemName); 19097f3e84a1SEd Tanous return; 19107f3e84a1SEd Tanous } 1911253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 191222d268cbSEd Tanous { 191322d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 191422d268cbSEd Tanous systemName); 191522d268cbSEd Tanous return; 191622d268cbSEd Tanous } 191775710de2SXiaochao Ma 1918599b9af3SAlexander Hansen dBusEventLogEntryPatch(req, asyncResp, entryId); 19197e860f15SJohn Edward Broadbent }); 192075710de2SXiaochao Ma 19217e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 192222d268cbSEd Tanous app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/") 1923ed398213SEd Tanous .privileges(redfish::privileges::deleteLogEntry) 1924ed398213SEd Tanous 1925002d39b4SEd Tanous .methods(boost::beast::http::verb::delete_)( 1926002d39b4SEd Tanous [&app](const crow::Request& req, 1927002d39b4SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 192822d268cbSEd Tanous const std::string& systemName, const std::string& param) { 19293ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 1930336e96c6SChicago Duan { 193145ca1b86SEd Tanous return; 193245ca1b86SEd Tanous } 193325b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 19347f3e84a1SEd Tanous { 19357f3e84a1SEd Tanous // Option currently returns no systems. TBD 19367f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 19377f3e84a1SEd Tanous systemName); 19387f3e84a1SEd Tanous return; 19397f3e84a1SEd Tanous } 1940253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 194122d268cbSEd Tanous { 194222d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 194322d268cbSEd Tanous systemName); 194422d268cbSEd Tanous return; 194522d268cbSEd Tanous } 1946599b9af3SAlexander Hansen dBusEventLogEntryDelete(asyncResp, param); 19477e860f15SJohn Edward Broadbent }); 1948400fd1fbSAdriana Kobylak } 1949400fd1fbSAdriana Kobylak 1950b7028ebfSSpencer Ku constexpr const char* hostLoggerFolderPath = "/var/log/console"; 1951b7028ebfSSpencer Ku 1952b7028ebfSSpencer Ku inline bool 1953b7028ebfSSpencer Ku getHostLoggerFiles(const std::string& hostLoggerFilePath, 1954b7028ebfSSpencer Ku std::vector<std::filesystem::path>& hostLoggerFiles) 1955b7028ebfSSpencer Ku { 1956b7028ebfSSpencer Ku std::error_code ec; 1957b7028ebfSSpencer Ku std::filesystem::directory_iterator logPath(hostLoggerFilePath, ec); 1958b7028ebfSSpencer Ku if (ec) 1959b7028ebfSSpencer Ku { 1960bf2ddedeSCarson Labrado BMCWEB_LOG_WARNING("{}", ec.message()); 1961b7028ebfSSpencer Ku return false; 1962b7028ebfSSpencer Ku } 1963b7028ebfSSpencer Ku for (const std::filesystem::directory_entry& it : logPath) 1964b7028ebfSSpencer Ku { 1965b7028ebfSSpencer Ku std::string filename = it.path().filename(); 1966b7028ebfSSpencer Ku // Prefix of each log files is "log". Find the file and save the 1967b7028ebfSSpencer Ku // path 196811ba3979SEd Tanous if (filename.starts_with("log")) 1969b7028ebfSSpencer Ku { 1970b7028ebfSSpencer Ku hostLoggerFiles.emplace_back(it.path()); 1971b7028ebfSSpencer Ku } 1972b7028ebfSSpencer Ku } 1973b7028ebfSSpencer Ku // As the log files rotate, they are appended with a ".#" that is higher for 1974b7028ebfSSpencer Ku // the older logs. Since we start from oldest logs, sort the name in 1975b7028ebfSSpencer Ku // descending order. 1976b7028ebfSSpencer Ku std::sort(hostLoggerFiles.rbegin(), hostLoggerFiles.rend(), 1977b7028ebfSSpencer Ku AlphanumLess<std::string>()); 1978b7028ebfSSpencer Ku 1979b7028ebfSSpencer Ku return true; 1980b7028ebfSSpencer Ku } 1981b7028ebfSSpencer Ku 198202cad96eSEd Tanous inline bool getHostLoggerEntries( 198302cad96eSEd Tanous const std::vector<std::filesystem::path>& hostLoggerFiles, uint64_t skip, 198402cad96eSEd Tanous uint64_t top, std::vector<std::string>& logEntries, size_t& logCount) 1985b7028ebfSSpencer Ku { 1986b7028ebfSSpencer Ku GzFileReader logFile; 1987b7028ebfSSpencer Ku 1988b7028ebfSSpencer Ku // Go though all log files and expose host logs. 1989b7028ebfSSpencer Ku for (const std::filesystem::path& it : hostLoggerFiles) 1990b7028ebfSSpencer Ku { 1991b7028ebfSSpencer Ku if (!logFile.gzGetLines(it.string(), skip, top, logEntries, logCount)) 1992b7028ebfSSpencer Ku { 199362598e31SEd Tanous BMCWEB_LOG_ERROR("fail to expose host logs"); 1994b7028ebfSSpencer Ku return false; 1995b7028ebfSSpencer Ku } 1996b7028ebfSSpencer Ku } 1997b7028ebfSSpencer Ku // Get lastMessage from constructor by getter 1998b7028ebfSSpencer Ku std::string lastMessage = logFile.getLastMessage(); 1999b7028ebfSSpencer Ku if (!lastMessage.empty()) 2000b7028ebfSSpencer Ku { 2001b7028ebfSSpencer Ku logCount++; 2002b7028ebfSSpencer Ku if (logCount > skip && logCount <= (skip + top)) 2003b7028ebfSSpencer Ku { 2004b7028ebfSSpencer Ku logEntries.push_back(lastMessage); 2005b7028ebfSSpencer Ku } 2006b7028ebfSSpencer Ku } 2007b7028ebfSSpencer Ku return true; 2008b7028ebfSSpencer Ku } 2009b7028ebfSSpencer Ku 2010dd72e87bSClaire Weinan inline void handleBMCLogServicesCollectionGet( 2011fdd26906SClaire Weinan crow::App& app, const crow::Request& req, 2012253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2013253f11b8SEd Tanous const std::string& managerId) 20141da66f75SEd Tanous { 20153ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 201645ca1b86SEd Tanous { 201745ca1b86SEd Tanous return; 201845ca1b86SEd Tanous } 2019253f11b8SEd Tanous 2020253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2021253f11b8SEd Tanous { 2022253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2023253f11b8SEd Tanous return; 2024253f11b8SEd Tanous } 2025253f11b8SEd Tanous 20267e860f15SJohn Edward Broadbent // Collections don't include the static data added by SubRoute 20277e860f15SJohn Edward Broadbent // because it has a duplicate entry for members 2028e1f26343SJason M. Bills asyncResp->res.jsonValue["@odata.type"] = 20291da66f75SEd Tanous "#LogServiceCollection.LogServiceCollection"; 2030253f11b8SEd Tanous asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 2031253f11b8SEd Tanous "/redfish/v1/Managers/{}/LogServices", BMCWEB_REDFISH_MANAGER_URI_NAME); 2032002d39b4SEd Tanous asyncResp->res.jsonValue["Name"] = "Open BMC Log Services Collection"; 2033e1f26343SJason M. Bills asyncResp->res.jsonValue["Description"] = 20341da66f75SEd Tanous "Collection of LogServices for this Manager"; 2035002d39b4SEd Tanous nlohmann::json& logServiceArray = asyncResp->res.jsonValue["Members"]; 2036c4bf6374SJason M. Bills logServiceArray = nlohmann::json::array(); 2037fdd26906SClaire Weinan 203825b54dbaSEd Tanous if constexpr (BMCWEB_REDFISH_BMC_JOURNAL) 203925b54dbaSEd Tanous { 2040613dabeaSEd Tanous nlohmann::json::object_t journal; 2041253f11b8SEd Tanous journal["@odata.id"] = 2042253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}/LogServices/Journal", 2043253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 2044b2ba3072SPatrick Williams logServiceArray.emplace_back(std::move(journal)); 204525b54dbaSEd Tanous } 2046fdd26906SClaire Weinan 2047fdd26906SClaire Weinan asyncResp->res.jsonValue["Members@odata.count"] = logServiceArray.size(); 2048fdd26906SClaire Weinan 204925b54dbaSEd Tanous if constexpr (BMCWEB_REDFISH_DUMP_LOG) 205025b54dbaSEd Tanous { 205115912159SGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 20527a1dbc48SGeorge Liu "xyz.openbmc_project.Collection.DeleteAll"}; 20537a1dbc48SGeorge Liu dbus::utility::getSubTreePaths( 20547a1dbc48SGeorge Liu "/xyz/openbmc_project/dump", 0, interfaces, 205525b54dbaSEd Tanous [asyncResp](const boost::system::error_code& ec, 205625b54dbaSEd Tanous const dbus::utility::MapperGetSubTreePathsResponse& 205725b54dbaSEd Tanous subTreePaths) { 2058fdd26906SClaire Weinan if (ec) 2059fdd26906SClaire Weinan { 206062598e31SEd Tanous BMCWEB_LOG_ERROR( 206162598e31SEd Tanous "handleBMCLogServicesCollectionGet respHandler got error {}", 206262598e31SEd Tanous ec); 2063bd79bce8SPatrick Williams // Assume that getting an error simply means there are no 2064bd79bce8SPatrick Williams // dump LogServices. Return without adding any error 2065bd79bce8SPatrick Williams // response. 2066fdd26906SClaire Weinan return; 2067fdd26906SClaire Weinan } 2068fdd26906SClaire Weinan 2069fdd26906SClaire Weinan nlohmann::json& logServiceArrayLocal = 2070fdd26906SClaire Weinan asyncResp->res.jsonValue["Members"]; 2071fdd26906SClaire Weinan 2072fdd26906SClaire Weinan for (const std::string& path : subTreePaths) 2073fdd26906SClaire Weinan { 2074fdd26906SClaire Weinan if (path == "/xyz/openbmc_project/dump/bmc") 2075fdd26906SClaire Weinan { 2076613dabeaSEd Tanous nlohmann::json::object_t member; 2077253f11b8SEd Tanous member["@odata.id"] = boost::urls::format( 2078253f11b8SEd Tanous "/redfish/v1/Managers/{}/LogServices/Dump", 2079253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 2080b2ba3072SPatrick Williams logServiceArrayLocal.emplace_back(std::move(member)); 2081fdd26906SClaire Weinan } 2082fdd26906SClaire Weinan else if (path == "/xyz/openbmc_project/dump/faultlog") 2083fdd26906SClaire Weinan { 2084613dabeaSEd Tanous nlohmann::json::object_t member; 2085253f11b8SEd Tanous member["@odata.id"] = boost::urls::format( 2086253f11b8SEd Tanous "/redfish/v1/Managers/{}/LogServices/FaultLog", 2087253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 2088b2ba3072SPatrick Williams logServiceArrayLocal.emplace_back(std::move(member)); 2089fdd26906SClaire Weinan } 2090fdd26906SClaire Weinan } 2091fdd26906SClaire Weinan 2092e1f26343SJason M. Bills asyncResp->res.jsonValue["Members@odata.count"] = 2093fdd26906SClaire Weinan logServiceArrayLocal.size(); 20947a1dbc48SGeorge Liu }); 209525b54dbaSEd Tanous } 2096fdd26906SClaire Weinan } 2097fdd26906SClaire Weinan 2098fdd26906SClaire Weinan inline void requestRoutesBMCLogServiceCollection(App& app) 2099fdd26906SClaire Weinan { 2100253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/") 2101fdd26906SClaire Weinan .privileges(redfish::privileges::getLogServiceCollection) 2102fdd26906SClaire Weinan .methods(boost::beast::http::verb::get)( 2103dd72e87bSClaire Weinan std::bind_front(handleBMCLogServicesCollectionGet, std::ref(app))); 2104e1f26343SJason M. Bills } 2105e1f26343SJason M. Bills 2106fdd26906SClaire Weinan inline void 2107fdd26906SClaire Weinan getDumpServiceInfo(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2108fdd26906SClaire Weinan const std::string& dumpType) 2109c9bb6861Sraviteja-b { 2110fdd26906SClaire Weinan std::string dumpPath; 2111539d8c6bSEd Tanous log_service::OverWritePolicy overWritePolicy = 2112539d8c6bSEd Tanous log_service::OverWritePolicy::Invalid; 2113fdd26906SClaire Weinan bool collectDiagnosticDataSupported = false; 2114fdd26906SClaire Weinan 2115fdd26906SClaire Weinan if (dumpType == "BMC") 211645ca1b86SEd Tanous { 2117253f11b8SEd Tanous dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/Dump", 2118253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 2119539d8c6bSEd Tanous overWritePolicy = log_service::OverWritePolicy::WrapsWhenFull; 2120fdd26906SClaire Weinan collectDiagnosticDataSupported = true; 2121fdd26906SClaire Weinan } 2122fdd26906SClaire Weinan else if (dumpType == "FaultLog") 2123fdd26906SClaire Weinan { 2124253f11b8SEd Tanous dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/FaultLog", 2125253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 2126539d8c6bSEd Tanous overWritePolicy = log_service::OverWritePolicy::Unknown; 2127fdd26906SClaire Weinan collectDiagnosticDataSupported = false; 2128fdd26906SClaire Weinan } 2129fdd26906SClaire Weinan else if (dumpType == "System") 2130fdd26906SClaire Weinan { 2131253f11b8SEd Tanous dumpPath = std::format("/redfish/v1/Systems/{}/LogServices/Dump", 2132253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 2133539d8c6bSEd Tanous overWritePolicy = log_service::OverWritePolicy::WrapsWhenFull; 2134fdd26906SClaire Weinan collectDiagnosticDataSupported = true; 2135fdd26906SClaire Weinan } 2136fdd26906SClaire Weinan else 2137fdd26906SClaire Weinan { 213862598e31SEd Tanous BMCWEB_LOG_ERROR("getDumpServiceInfo() invalid dump type: {}", 213962598e31SEd Tanous dumpType); 2140fdd26906SClaire Weinan messages::internalError(asyncResp->res); 214145ca1b86SEd Tanous return; 214245ca1b86SEd Tanous } 2143fdd26906SClaire Weinan 2144fdd26906SClaire Weinan asyncResp->res.jsonValue["@odata.id"] = dumpPath; 2145fdd26906SClaire Weinan asyncResp->res.jsonValue["@odata.type"] = "#LogService.v1_2_0.LogService"; 2146c9bb6861Sraviteja-b asyncResp->res.jsonValue["Name"] = "Dump LogService"; 2147fdd26906SClaire Weinan asyncResp->res.jsonValue["Description"] = dumpType + " Dump LogService"; 2148fdd26906SClaire Weinan asyncResp->res.jsonValue["Id"] = std::filesystem::path(dumpPath).filename(); 2149539d8c6bSEd Tanous asyncResp->res.jsonValue["OverWritePolicy"] = overWritePolicy; 21507c8c4058STejas Patil 21517c8c4058STejas Patil std::pair<std::string, std::string> redfishDateTimeOffset = 21522b82937eSEd Tanous redfish::time_utils::getDateTimeOffsetNow(); 21530fda0f12SGeorge Liu asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first; 21547c8c4058STejas Patil asyncResp->res.jsonValue["DateTimeLocalOffset"] = 21557c8c4058STejas Patil redfishDateTimeOffset.second; 21567c8c4058STejas Patil 2157fdd26906SClaire Weinan asyncResp->res.jsonValue["Entries"]["@odata.id"] = dumpPath + "/Entries"; 2158fdd26906SClaire Weinan 2159fdd26906SClaire Weinan if (collectDiagnosticDataSupported) 2160fdd26906SClaire Weinan { 2161002d39b4SEd Tanous asyncResp->res.jsonValue["Actions"]["#LogService.CollectDiagnosticData"] 21621476687dSEd Tanous ["target"] = 2163fdd26906SClaire Weinan dumpPath + "/Actions/LogService.CollectDiagnosticData"; 2164fdd26906SClaire Weinan } 21650d946211SClaire Weinan 21660d946211SClaire Weinan constexpr std::array<std::string_view, 1> interfaces = {deleteAllInterface}; 21670d946211SClaire Weinan dbus::utility::getSubTreePaths( 21680d946211SClaire Weinan "/xyz/openbmc_project/dump", 0, interfaces, 21690d946211SClaire Weinan [asyncResp, dumpType, dumpPath]( 21700d946211SClaire Weinan const boost::system::error_code& ec, 21710d946211SClaire Weinan const dbus::utility::MapperGetSubTreePathsResponse& subTreePaths) { 21720d946211SClaire Weinan if (ec) 21730d946211SClaire Weinan { 2174bd79bce8SPatrick Williams BMCWEB_LOG_ERROR("getDumpServiceInfo respHandler got error {}", 2175bd79bce8SPatrick Williams ec); 21760d946211SClaire Weinan // Assume that getting an error simply means there are no dump 21770d946211SClaire Weinan // LogServices. Return without adding any error response. 21780d946211SClaire Weinan return; 21790d946211SClaire Weinan } 218018f8f608SEd Tanous std::string dbusDumpPath = getDumpPath(dumpType); 21810d946211SClaire Weinan for (const std::string& path : subTreePaths) 21820d946211SClaire Weinan { 21830d946211SClaire Weinan if (path == dbusDumpPath) 21840d946211SClaire Weinan { 2185bd79bce8SPatrick Williams asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"] 2186bd79bce8SPatrick Williams ["target"] = 21870d946211SClaire Weinan dumpPath + "/Actions/LogService.ClearLog"; 21880d946211SClaire Weinan break; 21890d946211SClaire Weinan } 21900d946211SClaire Weinan } 21910d946211SClaire Weinan }); 2192c9bb6861Sraviteja-b } 2193c9bb6861Sraviteja-b 2194fdd26906SClaire Weinan inline void handleLogServicesDumpServiceGet( 2195fdd26906SClaire Weinan crow::App& app, const std::string& dumpType, const crow::Request& req, 2196253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2197253f11b8SEd Tanous const std::string& managerId) 21987e860f15SJohn Edward Broadbent { 21993ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 220045ca1b86SEd Tanous { 220145ca1b86SEd Tanous return; 220245ca1b86SEd Tanous } 2203253f11b8SEd Tanous 2204253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2205253f11b8SEd Tanous { 2206253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2207253f11b8SEd Tanous return; 2208253f11b8SEd Tanous } 2209253f11b8SEd Tanous 2210fdd26906SClaire Weinan getDumpServiceInfo(asyncResp, dumpType); 2211fdd26906SClaire Weinan } 2212c9bb6861Sraviteja-b 221322d268cbSEd Tanous inline void handleLogServicesDumpServiceComputerSystemGet( 221422d268cbSEd Tanous crow::App& app, const crow::Request& req, 221522d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 221622d268cbSEd Tanous const std::string& chassisId) 221722d268cbSEd Tanous { 221822d268cbSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 221922d268cbSEd Tanous { 222022d268cbSEd Tanous return; 222122d268cbSEd Tanous } 2222253f11b8SEd Tanous if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME) 222322d268cbSEd Tanous { 222422d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId); 222522d268cbSEd Tanous return; 222622d268cbSEd Tanous } 222722d268cbSEd Tanous getDumpServiceInfo(asyncResp, "System"); 222822d268cbSEd Tanous } 222922d268cbSEd Tanous 2230fdd26906SClaire Weinan inline void handleLogServicesDumpEntriesCollectionGet( 2231fdd26906SClaire Weinan crow::App& app, const std::string& dumpType, const crow::Request& req, 2232253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2233253f11b8SEd Tanous const std::string& managerId) 2234fdd26906SClaire Weinan { 2235fdd26906SClaire Weinan if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2236fdd26906SClaire Weinan { 2237fdd26906SClaire Weinan return; 2238fdd26906SClaire Weinan } 2239253f11b8SEd Tanous 2240253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2241253f11b8SEd Tanous { 2242253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2243253f11b8SEd Tanous return; 2244253f11b8SEd Tanous } 2245fdd26906SClaire Weinan getDumpEntryCollection(asyncResp, dumpType); 2246fdd26906SClaire Weinan } 2247fdd26906SClaire Weinan 224822d268cbSEd Tanous inline void handleLogServicesDumpEntriesCollectionComputerSystemGet( 224922d268cbSEd Tanous crow::App& app, const crow::Request& req, 225022d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 225122d268cbSEd Tanous const std::string& chassisId) 225222d268cbSEd Tanous { 225322d268cbSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 225422d268cbSEd Tanous { 225522d268cbSEd Tanous return; 225622d268cbSEd Tanous } 2257253f11b8SEd Tanous if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME) 225822d268cbSEd Tanous { 225922d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId); 226022d268cbSEd Tanous return; 226122d268cbSEd Tanous } 226222d268cbSEd Tanous getDumpEntryCollection(asyncResp, "System"); 226322d268cbSEd Tanous } 226422d268cbSEd Tanous 2265fdd26906SClaire Weinan inline void handleLogServicesDumpEntryGet( 2266fdd26906SClaire Weinan crow::App& app, const std::string& dumpType, const crow::Request& req, 2267fdd26906SClaire Weinan const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2268253f11b8SEd Tanous const std::string& managerId, const std::string& dumpId) 2269fdd26906SClaire Weinan { 2270fdd26906SClaire Weinan if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2271fdd26906SClaire Weinan { 2272fdd26906SClaire Weinan return; 2273fdd26906SClaire Weinan } 2274253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2275253f11b8SEd Tanous { 2276253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2277253f11b8SEd Tanous return; 2278253f11b8SEd Tanous } 2279fdd26906SClaire Weinan getDumpEntryById(asyncResp, dumpId, dumpType); 2280fdd26906SClaire Weinan } 2281168d1b1aSCarson Labrado 228222d268cbSEd Tanous inline void handleLogServicesDumpEntryComputerSystemGet( 228322d268cbSEd Tanous crow::App& app, const crow::Request& req, 228422d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 228522d268cbSEd Tanous const std::string& chassisId, const std::string& dumpId) 228622d268cbSEd Tanous { 228722d268cbSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 228822d268cbSEd Tanous { 228922d268cbSEd Tanous return; 229022d268cbSEd Tanous } 2291253f11b8SEd Tanous if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME) 229222d268cbSEd Tanous { 229322d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId); 229422d268cbSEd Tanous return; 229522d268cbSEd Tanous } 229622d268cbSEd Tanous getDumpEntryById(asyncResp, dumpId, "System"); 229722d268cbSEd Tanous } 2298fdd26906SClaire Weinan 2299fdd26906SClaire Weinan inline void handleLogServicesDumpEntryDelete( 2300fdd26906SClaire Weinan crow::App& app, const std::string& dumpType, const crow::Request& req, 2301fdd26906SClaire Weinan const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2302253f11b8SEd Tanous const std::string& managerId, const std::string& dumpId) 2303fdd26906SClaire Weinan { 2304fdd26906SClaire Weinan if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2305fdd26906SClaire Weinan { 2306fdd26906SClaire Weinan return; 2307fdd26906SClaire Weinan } 2308253f11b8SEd Tanous 2309253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2310253f11b8SEd Tanous { 2311253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2312253f11b8SEd Tanous return; 2313253f11b8SEd Tanous } 2314fdd26906SClaire Weinan deleteDumpEntry(asyncResp, dumpId, dumpType); 2315fdd26906SClaire Weinan } 2316fdd26906SClaire Weinan 231722d268cbSEd Tanous inline void handleLogServicesDumpEntryComputerSystemDelete( 231822d268cbSEd Tanous crow::App& app, const crow::Request& req, 231922d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 232022d268cbSEd Tanous const std::string& chassisId, const std::string& dumpId) 232122d268cbSEd Tanous { 232222d268cbSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 232322d268cbSEd Tanous { 232422d268cbSEd Tanous return; 232522d268cbSEd Tanous } 2326253f11b8SEd Tanous if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME) 232722d268cbSEd Tanous { 232822d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId); 232922d268cbSEd Tanous return; 233022d268cbSEd Tanous } 233122d268cbSEd Tanous deleteDumpEntry(asyncResp, dumpId, "System"); 233222d268cbSEd Tanous } 233322d268cbSEd Tanous 2334168d1b1aSCarson Labrado inline void handleLogServicesDumpEntryDownloadGet( 2335168d1b1aSCarson Labrado crow::App& app, const std::string& dumpType, const crow::Request& req, 2336168d1b1aSCarson Labrado const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2337253f11b8SEd Tanous const std::string& managerId, const std::string& dumpId) 2338168d1b1aSCarson Labrado { 2339168d1b1aSCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2340168d1b1aSCarson Labrado { 2341168d1b1aSCarson Labrado return; 2342168d1b1aSCarson Labrado } 2343253f11b8SEd Tanous 2344253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2345253f11b8SEd Tanous { 2346253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2347253f11b8SEd Tanous return; 2348253f11b8SEd Tanous } 2349168d1b1aSCarson Labrado downloadDumpEntry(asyncResp, dumpId, dumpType); 2350168d1b1aSCarson Labrado } 2351168d1b1aSCarson Labrado 2352168d1b1aSCarson Labrado inline void handleDBusEventLogEntryDownloadGet( 2353168d1b1aSCarson Labrado crow::App& app, const std::string& dumpType, const crow::Request& req, 2354168d1b1aSCarson Labrado const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2355168d1b1aSCarson Labrado const std::string& systemName, const std::string& entryID) 2356168d1b1aSCarson Labrado { 2357168d1b1aSCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2358168d1b1aSCarson Labrado { 2359168d1b1aSCarson Labrado return; 2360168d1b1aSCarson Labrado } 2361168d1b1aSCarson Labrado if (!http_helpers::isContentTypeAllowed( 2362168d1b1aSCarson Labrado req.getHeaderValue("Accept"), 2363168d1b1aSCarson Labrado http_helpers::ContentType::OctetStream, true)) 2364168d1b1aSCarson Labrado { 2365168d1b1aSCarson Labrado asyncResp->res.result(boost::beast::http::status::bad_request); 2366168d1b1aSCarson Labrado return; 2367168d1b1aSCarson Labrado } 2368168d1b1aSCarson Labrado downloadEventLogEntry(asyncResp, systemName, entryID, dumpType); 2369168d1b1aSCarson Labrado } 2370168d1b1aSCarson Labrado 2371fdd26906SClaire Weinan inline void handleLogServicesDumpCollectDiagnosticDataPost( 2372fdd26906SClaire Weinan crow::App& app, const std::string& dumpType, const crow::Request& req, 2373253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2374253f11b8SEd Tanous const std::string& managerId) 2375fdd26906SClaire Weinan { 2376fdd26906SClaire Weinan if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2377fdd26906SClaire Weinan { 2378fdd26906SClaire Weinan return; 2379fdd26906SClaire Weinan } 2380253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2381253f11b8SEd Tanous { 2382253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2383253f11b8SEd Tanous return; 2384253f11b8SEd Tanous } 2385253f11b8SEd Tanous 2386fdd26906SClaire Weinan createDump(asyncResp, req, dumpType); 2387fdd26906SClaire Weinan } 2388fdd26906SClaire Weinan 238922d268cbSEd Tanous inline void handleLogServicesDumpCollectDiagnosticDataComputerSystemPost( 239022d268cbSEd Tanous crow::App& app, const crow::Request& req, 239122d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 23927f3e84a1SEd Tanous const std::string& systemName) 239322d268cbSEd Tanous { 239422d268cbSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 239522d268cbSEd Tanous { 239622d268cbSEd Tanous return; 239722d268cbSEd Tanous } 23987f3e84a1SEd Tanous 239925b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 240022d268cbSEd Tanous { 24017f3e84a1SEd Tanous // Option currently returns no systems. TBD 24027f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 24037f3e84a1SEd Tanous systemName); 24047f3e84a1SEd Tanous return; 24057f3e84a1SEd Tanous } 2406253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 24077f3e84a1SEd Tanous { 24087f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 24097f3e84a1SEd Tanous systemName); 241022d268cbSEd Tanous return; 241122d268cbSEd Tanous } 241222d268cbSEd Tanous createDump(asyncResp, req, "System"); 241322d268cbSEd Tanous } 241422d268cbSEd Tanous 2415fdd26906SClaire Weinan inline void handleLogServicesDumpClearLogPost( 2416fdd26906SClaire Weinan crow::App& app, const std::string& dumpType, const crow::Request& req, 2417253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2418253f11b8SEd Tanous const std::string& managerId) 2419fdd26906SClaire Weinan { 2420fdd26906SClaire Weinan if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2421fdd26906SClaire Weinan { 2422fdd26906SClaire Weinan return; 2423fdd26906SClaire Weinan } 2424253f11b8SEd Tanous 2425253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2426253f11b8SEd Tanous { 2427253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2428253f11b8SEd Tanous return; 2429253f11b8SEd Tanous } 2430fdd26906SClaire Weinan clearDump(asyncResp, dumpType); 2431fdd26906SClaire Weinan } 2432fdd26906SClaire Weinan 243322d268cbSEd Tanous inline void handleLogServicesDumpClearLogComputerSystemPost( 243422d268cbSEd Tanous crow::App& app, const crow::Request& req, 243522d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 24367f3e84a1SEd Tanous const std::string& systemName) 243722d268cbSEd Tanous { 243822d268cbSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 243922d268cbSEd Tanous { 244022d268cbSEd Tanous return; 244122d268cbSEd Tanous } 244225b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 244322d268cbSEd Tanous { 24447f3e84a1SEd Tanous // Option currently returns no systems. TBD 24457f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 24467f3e84a1SEd Tanous systemName); 24477f3e84a1SEd Tanous return; 24487f3e84a1SEd Tanous } 2449253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 24507f3e84a1SEd Tanous { 24517f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 24527f3e84a1SEd Tanous systemName); 245322d268cbSEd Tanous return; 245422d268cbSEd Tanous } 245522d268cbSEd Tanous clearDump(asyncResp, "System"); 245622d268cbSEd Tanous } 245722d268cbSEd Tanous 2458fdd26906SClaire Weinan inline void requestRoutesBMCDumpService(App& app) 2459fdd26906SClaire Weinan { 2460253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/Dump/") 2461fdd26906SClaire Weinan .privileges(redfish::privileges::getLogService) 2462fdd26906SClaire Weinan .methods(boost::beast::http::verb::get)(std::bind_front( 2463fdd26906SClaire Weinan handleLogServicesDumpServiceGet, std::ref(app), "BMC")); 2464fdd26906SClaire Weinan } 2465fdd26906SClaire Weinan 2466fdd26906SClaire Weinan inline void requestRoutesBMCDumpEntryCollection(App& app) 2467fdd26906SClaire Weinan { 2468253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/") 2469fdd26906SClaire Weinan .privileges(redfish::privileges::getLogEntryCollection) 2470fdd26906SClaire Weinan .methods(boost::beast::http::verb::get)(std::bind_front( 2471fdd26906SClaire Weinan handleLogServicesDumpEntriesCollectionGet, std::ref(app), "BMC")); 2472c9bb6861Sraviteja-b } 2473c9bb6861Sraviteja-b 24747e860f15SJohn Edward Broadbent inline void requestRoutesBMCDumpEntry(App& app) 2475c9bb6861Sraviteja-b { 24767e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 2477253f11b8SEd Tanous "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/") 2478ed398213SEd Tanous .privileges(redfish::privileges::getLogEntry) 2479fdd26906SClaire Weinan .methods(boost::beast::http::verb::get)(std::bind_front( 2480fdd26906SClaire Weinan handleLogServicesDumpEntryGet, std::ref(app), "BMC")); 2481fdd26906SClaire Weinan 24827e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 2483253f11b8SEd Tanous "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/") 2484ed398213SEd Tanous .privileges(redfish::privileges::deleteLogEntry) 2485fdd26906SClaire Weinan .methods(boost::beast::http::verb::delete_)(std::bind_front( 2486fdd26906SClaire Weinan handleLogServicesDumpEntryDelete, std::ref(app), "BMC")); 2487c9bb6861Sraviteja-b } 2488c9bb6861Sraviteja-b 2489168d1b1aSCarson Labrado inline void requestRoutesBMCDumpEntryDownload(App& app) 2490168d1b1aSCarson Labrado { 2491168d1b1aSCarson Labrado BMCWEB_ROUTE( 2492168d1b1aSCarson Labrado app, 2493253f11b8SEd Tanous "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/attachment/") 2494168d1b1aSCarson Labrado .privileges(redfish::privileges::getLogEntry) 2495168d1b1aSCarson Labrado .methods(boost::beast::http::verb::get)(std::bind_front( 2496168d1b1aSCarson Labrado handleLogServicesDumpEntryDownloadGet, std::ref(app), "BMC")); 2497168d1b1aSCarson Labrado } 2498168d1b1aSCarson Labrado 24997e860f15SJohn Edward Broadbent inline void requestRoutesBMCDumpCreate(App& app) 2500c9bb6861Sraviteja-b { 25010fda0f12SGeorge Liu BMCWEB_ROUTE( 25020fda0f12SGeorge Liu app, 2503253f11b8SEd Tanous "/redfish/v1/Managers/<str>/LogServices/Dump/Actions/LogService.CollectDiagnosticData/") 2504ed398213SEd Tanous .privileges(redfish::privileges::postLogService) 25057e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 2506fdd26906SClaire Weinan std::bind_front(handleLogServicesDumpCollectDiagnosticDataPost, 2507fdd26906SClaire Weinan std::ref(app), "BMC")); 2508a43be80fSAsmitha Karunanithi } 2509a43be80fSAsmitha Karunanithi 25107e860f15SJohn Edward Broadbent inline void requestRoutesBMCDumpClear(App& app) 251180319af1SAsmitha Karunanithi { 25120fda0f12SGeorge Liu BMCWEB_ROUTE( 25130fda0f12SGeorge Liu app, 2514253f11b8SEd Tanous "/redfish/v1/Managers/<str>/LogServices/Dump/Actions/LogService.ClearLog/") 2515ed398213SEd Tanous .privileges(redfish::privileges::postLogService) 2516fdd26906SClaire Weinan .methods(boost::beast::http::verb::post)(std::bind_front( 2517fdd26906SClaire Weinan handleLogServicesDumpClearLogPost, std::ref(app), "BMC")); 251845ca1b86SEd Tanous } 2519fdd26906SClaire Weinan 2520168d1b1aSCarson Labrado inline void requestRoutesDBusEventLogEntryDownload(App& app) 2521168d1b1aSCarson Labrado { 2522168d1b1aSCarson Labrado BMCWEB_ROUTE( 2523168d1b1aSCarson Labrado app, 25249e9d99daSRavi Teja "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/attachment/") 2525168d1b1aSCarson Labrado .privileges(redfish::privileges::getLogEntry) 2526168d1b1aSCarson Labrado .methods(boost::beast::http::verb::get)(std::bind_front( 2527168d1b1aSCarson Labrado handleDBusEventLogEntryDownloadGet, std::ref(app), "System")); 2528168d1b1aSCarson Labrado } 2529168d1b1aSCarson Labrado 2530fdd26906SClaire Weinan inline void requestRoutesFaultLogDumpService(App& app) 2531fdd26906SClaire Weinan { 2532253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/") 2533fdd26906SClaire Weinan .privileges(redfish::privileges::getLogService) 2534fdd26906SClaire Weinan .methods(boost::beast::http::verb::get)(std::bind_front( 2535fdd26906SClaire Weinan handleLogServicesDumpServiceGet, std::ref(app), "FaultLog")); 2536fdd26906SClaire Weinan } 2537fdd26906SClaire Weinan 2538fdd26906SClaire Weinan inline void requestRoutesFaultLogDumpEntryCollection(App& app) 2539fdd26906SClaire Weinan { 2540253f11b8SEd Tanous BMCWEB_ROUTE(app, 2541253f11b8SEd Tanous "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/") 2542fdd26906SClaire Weinan .privileges(redfish::privileges::getLogEntryCollection) 2543fdd26906SClaire Weinan .methods(boost::beast::http::verb::get)( 2544fdd26906SClaire Weinan std::bind_front(handleLogServicesDumpEntriesCollectionGet, 2545fdd26906SClaire Weinan std::ref(app), "FaultLog")); 2546fdd26906SClaire Weinan } 2547fdd26906SClaire Weinan 2548fdd26906SClaire Weinan inline void requestRoutesFaultLogDumpEntry(App& app) 2549fdd26906SClaire Weinan { 2550253f11b8SEd Tanous BMCWEB_ROUTE( 2551253f11b8SEd Tanous app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/<str>/") 2552fdd26906SClaire Weinan .privileges(redfish::privileges::getLogEntry) 2553fdd26906SClaire Weinan .methods(boost::beast::http::verb::get)(std::bind_front( 2554fdd26906SClaire Weinan handleLogServicesDumpEntryGet, std::ref(app), "FaultLog")); 2555fdd26906SClaire Weinan 2556253f11b8SEd Tanous BMCWEB_ROUTE( 2557253f11b8SEd Tanous app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/<str>/") 2558fdd26906SClaire Weinan .privileges(redfish::privileges::deleteLogEntry) 2559fdd26906SClaire Weinan .methods(boost::beast::http::verb::delete_)(std::bind_front( 2560fdd26906SClaire Weinan handleLogServicesDumpEntryDelete, std::ref(app), "FaultLog")); 2561fdd26906SClaire Weinan } 2562fdd26906SClaire Weinan 2563fdd26906SClaire Weinan inline void requestRoutesFaultLogDumpClear(App& app) 2564fdd26906SClaire Weinan { 2565fdd26906SClaire Weinan BMCWEB_ROUTE( 2566fdd26906SClaire Weinan app, 2567253f11b8SEd Tanous "/redfish/v1/Managers/<str>/LogServices/FaultLog/Actions/LogService.ClearLog/") 2568fdd26906SClaire Weinan .privileges(redfish::privileges::postLogService) 2569fdd26906SClaire Weinan .methods(boost::beast::http::verb::post)(std::bind_front( 2570fdd26906SClaire Weinan handleLogServicesDumpClearLogPost, std::ref(app), "FaultLog")); 25715cb1dd27SAsmitha Karunanithi } 25725cb1dd27SAsmitha Karunanithi 25737e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpService(App& app) 25745cb1dd27SAsmitha Karunanithi { 257522d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Dump/") 2576ed398213SEd Tanous .privileges(redfish::privileges::getLogService) 25776ab9ad54SClaire Weinan .methods(boost::beast::http::verb::get)(std::bind_front( 257822d268cbSEd Tanous handleLogServicesDumpServiceComputerSystemGet, std::ref(app))); 25795cb1dd27SAsmitha Karunanithi } 25805cb1dd27SAsmitha Karunanithi 25817e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpEntryCollection(App& app) 25827e860f15SJohn Edward Broadbent { 258322d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/") 2584ed398213SEd Tanous .privileges(redfish::privileges::getLogEntryCollection) 258522d268cbSEd Tanous .methods(boost::beast::http::verb::get)(std::bind_front( 258622d268cbSEd Tanous handleLogServicesDumpEntriesCollectionComputerSystemGet, 258722d268cbSEd Tanous std::ref(app))); 25885cb1dd27SAsmitha Karunanithi } 25895cb1dd27SAsmitha Karunanithi 25907e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpEntry(App& app) 25915cb1dd27SAsmitha Karunanithi { 25927e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 259322d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/<str>/") 2594ed398213SEd Tanous .privileges(redfish::privileges::getLogEntry) 25956ab9ad54SClaire Weinan .methods(boost::beast::http::verb::get)(std::bind_front( 259622d268cbSEd Tanous handleLogServicesDumpEntryComputerSystemGet, std::ref(app))); 25978d1b46d7Szhanghch05 25987e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 259922d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/<str>/") 2600ed398213SEd Tanous .privileges(redfish::privileges::deleteLogEntry) 26016ab9ad54SClaire Weinan .methods(boost::beast::http::verb::delete_)(std::bind_front( 260222d268cbSEd Tanous handleLogServicesDumpEntryComputerSystemDelete, std::ref(app))); 26035cb1dd27SAsmitha Karunanithi } 2604c9bb6861Sraviteja-b 26057e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpCreate(App& app) 2606c9bb6861Sraviteja-b { 26070fda0f12SGeorge Liu BMCWEB_ROUTE( 26080fda0f12SGeorge Liu app, 260922d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Dump/Actions/LogService.CollectDiagnosticData/") 2610ed398213SEd Tanous .privileges(redfish::privileges::postLogService) 261122d268cbSEd Tanous .methods(boost::beast::http::verb::post)(std::bind_front( 261222d268cbSEd Tanous handleLogServicesDumpCollectDiagnosticDataComputerSystemPost, 261322d268cbSEd Tanous std::ref(app))); 2614a43be80fSAsmitha Karunanithi } 2615a43be80fSAsmitha Karunanithi 26167e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpClear(App& app) 2617a43be80fSAsmitha Karunanithi { 26180fda0f12SGeorge Liu BMCWEB_ROUTE( 26190fda0f12SGeorge Liu app, 262022d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Dump/Actions/LogService.ClearLog/") 2621ed398213SEd Tanous .privileges(redfish::privileges::postLogService) 26226ab9ad54SClaire Weinan .methods(boost::beast::http::verb::post)(std::bind_front( 262322d268cbSEd Tanous handleLogServicesDumpClearLogComputerSystemPost, std::ref(app))); 2624013487e5Sraviteja-b } 2625013487e5Sraviteja-b 26267e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpService(App& app) 26271da66f75SEd Tanous { 26283946028dSAppaRao Puli // Note: Deviated from redfish privilege registry for GET & HEAD 26293946028dSAppaRao Puli // method for security reasons. 26301da66f75SEd Tanous /** 26311da66f75SEd Tanous * Functions triggers appropriate requests on DBus 26321da66f75SEd Tanous */ 263322d268cbSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Crashdump/") 2634ed398213SEd Tanous // This is incorrect, should be: 2635ed398213SEd Tanous //.privileges(redfish::privileges::getLogService) 2636432a890cSEd Tanous .privileges({{"ConfigureManager"}}) 2637bd79bce8SPatrick Williams .methods( 2638bd79bce8SPatrick Williams boost::beast::http::verb:: 2639bd79bce8SPatrick Williams get)([&app](const crow::Request& req, 264022d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 264122d268cbSEd Tanous const std::string& systemName) { 26423ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 264345ca1b86SEd Tanous { 264445ca1b86SEd Tanous return; 264545ca1b86SEd Tanous } 264625b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 26477f3e84a1SEd Tanous { 26487f3e84a1SEd Tanous // Option currently returns no systems. TBD 26497f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 26507f3e84a1SEd Tanous systemName); 26517f3e84a1SEd Tanous return; 26527f3e84a1SEd Tanous } 2653253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 265422d268cbSEd Tanous { 265522d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 265622d268cbSEd Tanous systemName); 265722d268cbSEd Tanous return; 265822d268cbSEd Tanous } 265922d268cbSEd Tanous 26607e860f15SJohn Edward Broadbent // Copy over the static data to include the entries added by 26617e860f15SJohn Edward Broadbent // SubRoute 26620f74e643SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 2663253f11b8SEd Tanous std::format("/redfish/v1/Systems/{}/LogServices/Crashdump", 2664253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 2665e1f26343SJason M. Bills asyncResp->res.jsonValue["@odata.type"] = 26668e6c099aSJason M. Bills "#LogService.v1_2_0.LogService"; 26674f50ae4bSGunnar Mills asyncResp->res.jsonValue["Name"] = "Open BMC Oem Crashdump Service"; 26684f50ae4bSGunnar Mills asyncResp->res.jsonValue["Description"] = "Oem Crashdump Service"; 266915b89725SV-Sanjana asyncResp->res.jsonValue["Id"] = "Crashdump"; 2670539d8c6bSEd Tanous asyncResp->res.jsonValue["OverWritePolicy"] = 2671539d8c6bSEd Tanous log_service::OverWritePolicy::WrapsWhenFull; 2672e1f26343SJason M. Bills asyncResp->res.jsonValue["MaxNumberOfRecords"] = 3; 26737c8c4058STejas Patil 26747c8c4058STejas Patil std::pair<std::string, std::string> redfishDateTimeOffset = 26752b82937eSEd Tanous redfish::time_utils::getDateTimeOffsetNow(); 26767c8c4058STejas Patil asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first; 26777c8c4058STejas Patil asyncResp->res.jsonValue["DateTimeLocalOffset"] = 26787c8c4058STejas Patil redfishDateTimeOffset.second; 26797c8c4058STejas Patil 2680bd79bce8SPatrick Williams asyncResp->res.jsonValue["Entries"]["@odata.id"] = std::format( 2681bd79bce8SPatrick Williams "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries", 2682253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 2683253f11b8SEd Tanous asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"] 2684253f11b8SEd Tanous ["target"] = std::format( 2685253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/Crashdump/Actions/LogService.ClearLog", 2686253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 2687bd79bce8SPatrick Williams asyncResp->res 2688bd79bce8SPatrick Williams .jsonValue["Actions"]["#LogService.CollectDiagnosticData"] 2689253f11b8SEd Tanous ["target"] = std::format( 2690253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/Crashdump/Actions/LogService.CollectDiagnosticData", 2691253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 26927e860f15SJohn Edward Broadbent }); 26931da66f75SEd Tanous } 26941da66f75SEd Tanous 26957e860f15SJohn Edward Broadbent void inline requestRoutesCrashdumpClear(App& app) 26965b61b5e8SJason M. Bills { 26970fda0f12SGeorge Liu BMCWEB_ROUTE( 26980fda0f12SGeorge Liu app, 269922d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Crashdump/Actions/LogService.ClearLog/") 2700ed398213SEd Tanous // This is incorrect, should be: 2701ed398213SEd Tanous //.privileges(redfish::privileges::postLogService) 2702432a890cSEd Tanous .privileges({{"ConfigureComponents"}}) 27037e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 270445ca1b86SEd Tanous [&app](const crow::Request& req, 270522d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 270622d268cbSEd Tanous const std::string& systemName) { 27073ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 270845ca1b86SEd Tanous { 270945ca1b86SEd Tanous return; 271045ca1b86SEd Tanous } 271125b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 27127f3e84a1SEd Tanous { 27137f3e84a1SEd Tanous // Option currently returns no systems. TBD 27147f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 27157f3e84a1SEd Tanous systemName); 27167f3e84a1SEd Tanous return; 27177f3e84a1SEd Tanous } 2718253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 271922d268cbSEd Tanous { 272022d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 272122d268cbSEd Tanous systemName); 272222d268cbSEd Tanous return; 272322d268cbSEd Tanous } 27245b61b5e8SJason M. Bills crow::connections::systemBus->async_method_call( 27255e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec, 2726cb13a392SEd Tanous const std::string&) { 27275b61b5e8SJason M. Bills if (ec) 27285b61b5e8SJason M. Bills { 27295b61b5e8SJason M. Bills messages::internalError(asyncResp->res); 27305b61b5e8SJason M. Bills return; 27315b61b5e8SJason M. Bills } 27325b61b5e8SJason M. Bills messages::success(asyncResp->res); 27335b61b5e8SJason M. Bills }, 2734bd79bce8SPatrick Williams crashdumpObject, crashdumpPath, deleteAllInterface, 2735bd79bce8SPatrick Williams "DeleteAll"); 27367e860f15SJohn Edward Broadbent }); 27375b61b5e8SJason M. Bills } 27385b61b5e8SJason M. Bills 2739*4ff0f1f4SEd Tanous inline void 27408d1b46d7Szhanghch05 logCrashdumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 27418d1b46d7Szhanghch05 const std::string& logID, nlohmann::json& logEntryJson) 2742e855dd28SJason M. Bills { 2743043a0536SJohnathan Mantey auto getStoredLogCallback = 2744b9d36b47SEd Tanous [asyncResp, logID, 27455e7e2dc5SEd Tanous &logEntryJson](const boost::system::error_code& ec, 2746b9d36b47SEd Tanous const dbus::utility::DBusPropertiesMap& params) { 2747e855dd28SJason M. Bills if (ec) 2748e855dd28SJason M. Bills { 274962598e31SEd Tanous BMCWEB_LOG_DEBUG("failed to get log ec: {}", ec.message()); 27501ddcf01aSJason M. Bills if (ec.value() == 27511ddcf01aSJason M. Bills boost::system::linux_error::bad_request_descriptor) 27521ddcf01aSJason M. Bills { 2753bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "LogEntry", 2754bd79bce8SPatrick Williams logID); 27551ddcf01aSJason M. Bills } 27561ddcf01aSJason M. Bills else 27571ddcf01aSJason M. Bills { 2758e855dd28SJason M. Bills messages::internalError(asyncResp->res); 27591ddcf01aSJason M. Bills } 2760e855dd28SJason M. Bills return; 2761e855dd28SJason M. Bills } 2762043a0536SJohnathan Mantey 2763043a0536SJohnathan Mantey std::string timestamp{}; 2764043a0536SJohnathan Mantey std::string filename{}; 2765043a0536SJohnathan Mantey std::string logfile{}; 27662c70f800SEd Tanous parseCrashdumpParameters(params, filename, timestamp, logfile); 2767043a0536SJohnathan Mantey 2768043a0536SJohnathan Mantey if (filename.empty() || timestamp.empty()) 2769e855dd28SJason M. Bills { 27709db4ba25SJiaqing Zhao messages::resourceNotFound(asyncResp->res, "LogEntry", logID); 2771e855dd28SJason M. Bills return; 2772e855dd28SJason M. Bills } 2773e855dd28SJason M. Bills 2774043a0536SJohnathan Mantey std::string crashdumpURI = 2775bd79bce8SPatrick Williams std::format( 2776bd79bce8SPatrick Williams "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries/", 2777253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME) + 2778043a0536SJohnathan Mantey logID + "/" + filename; 277984afc48bSJason M. Bills nlohmann::json::object_t logEntry; 27809c11a172SVijay Lobo logEntry["@odata.type"] = "#LogEntry.v1_9_0.LogEntry"; 2781ef4c65b7SEd Tanous logEntry["@odata.id"] = boost::urls::format( 2782253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries/{}", 2783253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, logID); 278484afc48bSJason M. Bills logEntry["Name"] = "CPU Crashdump"; 278584afc48bSJason M. Bills logEntry["Id"] = logID; 2786539d8c6bSEd Tanous logEntry["EntryType"] = log_entry::LogEntryType::Oem; 278784afc48bSJason M. Bills logEntry["AdditionalDataURI"] = std::move(crashdumpURI); 278884afc48bSJason M. Bills logEntry["DiagnosticDataType"] = "OEM"; 278984afc48bSJason M. Bills logEntry["OEMDiagnosticDataType"] = "PECICrashdump"; 279084afc48bSJason M. Bills logEntry["Created"] = std::move(timestamp); 27912b20ef6eSJason M. Bills 27922b20ef6eSJason M. Bills // If logEntryJson references an array of LogEntry resources 27932b20ef6eSJason M. Bills // ('Members' list), then push this as a new entry, otherwise set it 27942b20ef6eSJason M. Bills // directly 27952b20ef6eSJason M. Bills if (logEntryJson.is_array()) 27962b20ef6eSJason M. Bills { 27972b20ef6eSJason M. Bills logEntryJson.push_back(logEntry); 27982b20ef6eSJason M. Bills asyncResp->res.jsonValue["Members@odata.count"] = 27992b20ef6eSJason M. Bills logEntryJson.size(); 28002b20ef6eSJason M. Bills } 28012b20ef6eSJason M. Bills else 28022b20ef6eSJason M. Bills { 2803d405bb51SJason M. Bills logEntryJson.update(logEntry); 28042b20ef6eSJason M. Bills } 2805e855dd28SJason M. Bills }; 2806d1bde9e5SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 2807d1bde9e5SKrzysztof Grobelny *crow::connections::systemBus, crashdumpObject, 2808d1bde9e5SKrzysztof Grobelny crashdumpPath + std::string("/") + logID, crashdumpInterface, 2809d1bde9e5SKrzysztof Grobelny std::move(getStoredLogCallback)); 2810e855dd28SJason M. Bills } 2811e855dd28SJason M. Bills 28127e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpEntryCollection(App& app) 28131da66f75SEd Tanous { 28143946028dSAppaRao Puli // Note: Deviated from redfish privilege registry for GET & HEAD 28153946028dSAppaRao Puli // method for security reasons. 28161da66f75SEd Tanous /** 28171da66f75SEd Tanous * Functions triggers appropriate requests on DBus 28181da66f75SEd Tanous */ 28197e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 282022d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/") 2821ed398213SEd Tanous // This is incorrect, should be. 2822ed398213SEd Tanous //.privileges(redfish::privileges::postLogEntryCollection) 2823432a890cSEd Tanous .privileges({{"ConfigureComponents"}}) 2824bd79bce8SPatrick Williams .methods( 2825bd79bce8SPatrick Williams boost::beast::http::verb:: 2826bd79bce8SPatrick Williams get)([&app](const crow::Request& req, 282722d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 282822d268cbSEd Tanous const std::string& systemName) { 28293ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 283045ca1b86SEd Tanous { 283145ca1b86SEd Tanous return; 283245ca1b86SEd Tanous } 283325b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 28347f3e84a1SEd Tanous { 28357f3e84a1SEd Tanous // Option currently returns no systems. TBD 28367f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 28377f3e84a1SEd Tanous systemName); 28387f3e84a1SEd Tanous return; 28397f3e84a1SEd Tanous } 2840253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 284122d268cbSEd Tanous { 284222d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 284322d268cbSEd Tanous systemName); 284422d268cbSEd Tanous return; 284522d268cbSEd Tanous } 284622d268cbSEd Tanous 28477a1dbc48SGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 28487a1dbc48SGeorge Liu crashdumpInterface}; 28497a1dbc48SGeorge Liu dbus::utility::getSubTreePaths( 28507a1dbc48SGeorge Liu "/", 0, interfaces, 28517a1dbc48SGeorge Liu [asyncResp](const boost::system::error_code& ec, 28522b20ef6eSJason M. Bills const std::vector<std::string>& resp) { 28531da66f75SEd Tanous if (ec) 28541da66f75SEd Tanous { 28551da66f75SEd Tanous if (ec.value() != 28561da66f75SEd Tanous boost::system::errc::no_such_file_or_directory) 28571da66f75SEd Tanous { 285862598e31SEd Tanous BMCWEB_LOG_DEBUG("failed to get entries ec: {}", 285962598e31SEd Tanous ec.message()); 2860f12894f8SJason M. Bills messages::internalError(asyncResp->res); 28611da66f75SEd Tanous return; 28621da66f75SEd Tanous } 28631da66f75SEd Tanous } 2864e1f26343SJason M. Bills asyncResp->res.jsonValue["@odata.type"] = 28651da66f75SEd Tanous "#LogEntryCollection.LogEntryCollection"; 2866253f11b8SEd Tanous asyncResp->res.jsonValue["@odata.id"] = std::format( 2867253f11b8SEd Tanous "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries", 2868253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME); 2869bd79bce8SPatrick Williams asyncResp->res.jsonValue["Name"] = 2870bd79bce8SPatrick Williams "Open BMC Crashdump Entries"; 2871e1f26343SJason M. Bills asyncResp->res.jsonValue["Description"] = 2872424c4176SJason M. Bills "Collection of Crashdump Entries"; 2873bd79bce8SPatrick Williams asyncResp->res.jsonValue["Members"] = 2874bd79bce8SPatrick Williams nlohmann::json::array(); 2875a2dd60a6SBrandon Kim asyncResp->res.jsonValue["Members@odata.count"] = 0; 28762b20ef6eSJason M. Bills 28772b20ef6eSJason M. Bills for (const std::string& path : resp) 28781da66f75SEd Tanous { 28792b20ef6eSJason M. Bills const sdbusplus::message::object_path objPath(path); 2880e855dd28SJason M. Bills // Get the log ID 28812b20ef6eSJason M. Bills std::string logID = objPath.filename(); 28822b20ef6eSJason M. Bills if (logID.empty()) 28831da66f75SEd Tanous { 2884e855dd28SJason M. Bills continue; 28851da66f75SEd Tanous } 2886e855dd28SJason M. Bills // Add the log entry to the array 28872b20ef6eSJason M. Bills logCrashdumpEntry(asyncResp, logID, 28882b20ef6eSJason M. Bills asyncResp->res.jsonValue["Members"]); 28891da66f75SEd Tanous } 28907a1dbc48SGeorge Liu }); 28917e860f15SJohn Edward Broadbent }); 28921da66f75SEd Tanous } 28931da66f75SEd Tanous 28947e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpEntry(App& app) 28951da66f75SEd Tanous { 28963946028dSAppaRao Puli // Note: Deviated from redfish privilege registry for GET & HEAD 28973946028dSAppaRao Puli // method for security reasons. 28981da66f75SEd Tanous 28997e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 290022d268cbSEd Tanous app, "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/<str>/") 2901ed398213SEd Tanous // this is incorrect, should be 2902ed398213SEd Tanous // .privileges(redfish::privileges::getLogEntry) 2903432a890cSEd Tanous .privileges({{"ConfigureComponents"}}) 29047e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 290545ca1b86SEd Tanous [&app](const crow::Request& req, 29067e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 290722d268cbSEd Tanous const std::string& systemName, const std::string& param) { 29083ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 290945ca1b86SEd Tanous { 291045ca1b86SEd Tanous return; 291145ca1b86SEd Tanous } 291225b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 29137f3e84a1SEd Tanous { 29147f3e84a1SEd Tanous // Option currently returns no systems. TBD 29157f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 29167f3e84a1SEd Tanous systemName); 29177f3e84a1SEd Tanous return; 29187f3e84a1SEd Tanous } 2919253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 292022d268cbSEd Tanous { 292122d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 292222d268cbSEd Tanous systemName); 292322d268cbSEd Tanous return; 292422d268cbSEd Tanous } 29257e860f15SJohn Edward Broadbent const std::string& logID = param; 2926e855dd28SJason M. Bills logCrashdumpEntry(asyncResp, logID, asyncResp->res.jsonValue); 29277e860f15SJohn Edward Broadbent }); 2928e855dd28SJason M. Bills } 2929e855dd28SJason M. Bills 29307e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpFile(App& app) 2931e855dd28SJason M. Bills { 29323946028dSAppaRao Puli // Note: Deviated from redfish privilege registry for GET & HEAD 29333946028dSAppaRao Puli // method for security reasons. 29347e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 29357e860f15SJohn Edward Broadbent app, 293622d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/<str>/<str>/") 2937ed398213SEd Tanous .privileges(redfish::privileges::getLogEntry) 29387e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 2939a4ce114aSNan Zhou [](const crow::Request& req, 29407e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 294122d268cbSEd Tanous const std::string& systemName, const std::string& logID, 294222d268cbSEd Tanous const std::string& fileName) { 2943bd79bce8SPatrick Williams // Do not call getRedfishRoute here since the crashdump file is 2944bd79bce8SPatrick Williams // not a Redfish resource. 294522d268cbSEd Tanous 294625b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 29477f3e84a1SEd Tanous { 29487f3e84a1SEd Tanous // Option currently returns no systems. TBD 29497f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 29507f3e84a1SEd Tanous systemName); 29517f3e84a1SEd Tanous return; 29527f3e84a1SEd Tanous } 2953253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 295422d268cbSEd Tanous { 295522d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 295622d268cbSEd Tanous systemName); 295722d268cbSEd Tanous return; 295822d268cbSEd Tanous } 295922d268cbSEd Tanous 2960043a0536SJohnathan Mantey auto getStoredLogCallback = 2961bd79bce8SPatrick Williams [asyncResp, logID, fileName, 2962bd79bce8SPatrick Williams url(boost::urls::url(req.url()))]( 29635e7e2dc5SEd Tanous const boost::system::error_code& ec, 2964bd79bce8SPatrick Williams const std::vector<std::pair< 2965bd79bce8SPatrick Williams std::string, dbus::utility::DbusVariantType>>& 29667e860f15SJohn Edward Broadbent resp) { 29671da66f75SEd Tanous if (ec) 29681da66f75SEd Tanous { 2969bd79bce8SPatrick Williams BMCWEB_LOG_DEBUG("failed to get log ec: {}", 2970bd79bce8SPatrick Williams ec.message()); 2971f12894f8SJason M. Bills messages::internalError(asyncResp->res); 29721da66f75SEd Tanous return; 29731da66f75SEd Tanous } 2974e855dd28SJason M. Bills 2975043a0536SJohnathan Mantey std::string dbusFilename{}; 2976043a0536SJohnathan Mantey std::string dbusTimestamp{}; 2977043a0536SJohnathan Mantey std::string dbusFilepath{}; 2978043a0536SJohnathan Mantey 2979bd79bce8SPatrick Williams parseCrashdumpParameters(resp, dbusFilename, 2980bd79bce8SPatrick Williams dbusTimestamp, dbusFilepath); 2981043a0536SJohnathan Mantey 2982043a0536SJohnathan Mantey if (dbusFilename.empty() || dbusTimestamp.empty() || 2983043a0536SJohnathan Mantey dbusFilepath.empty()) 29841da66f75SEd Tanous { 2985bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, 2986bd79bce8SPatrick Williams "LogEntry", logID); 29871da66f75SEd Tanous return; 29881da66f75SEd Tanous } 2989e855dd28SJason M. Bills 2990043a0536SJohnathan Mantey // Verify the file name parameter is correct 2991043a0536SJohnathan Mantey if (fileName != dbusFilename) 2992043a0536SJohnathan Mantey { 2993bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, 2994bd79bce8SPatrick Williams "LogEntry", logID); 2995043a0536SJohnathan Mantey return; 2996043a0536SJohnathan Mantey } 2997043a0536SJohnathan Mantey 299827b0cf90SEd Tanous if (!asyncResp->res.openFile(dbusFilepath)) 2999043a0536SJohnathan Mantey { 3000bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, 3001bd79bce8SPatrick Williams "LogEntry", logID); 3002043a0536SJohnathan Mantey return; 3003043a0536SJohnathan Mantey } 3004043a0536SJohnathan Mantey 30057e860f15SJohn Edward Broadbent // Configure this to be a file download when accessed 30067e860f15SJohn Edward Broadbent // from a browser 3007d9f6c621SEd Tanous asyncResp->res.addHeader( 3008bd79bce8SPatrick Williams boost::beast::http::field::content_disposition, 3009bd79bce8SPatrick Williams "attachment"); 30101da66f75SEd Tanous }; 3011d1bde9e5SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 3012d1bde9e5SKrzysztof Grobelny *crow::connections::systemBus, crashdumpObject, 3013bd79bce8SPatrick Williams crashdumpPath + std::string("/") + logID, 3014bd79bce8SPatrick Williams crashdumpInterface, std::move(getStoredLogCallback)); 30157e860f15SJohn Edward Broadbent }); 30161da66f75SEd Tanous } 30171da66f75SEd Tanous 3018c5a4c82aSJason M. Bills enum class OEMDiagnosticType 3019c5a4c82aSJason M. Bills { 3020c5a4c82aSJason M. Bills onDemand, 3021c5a4c82aSJason M. Bills telemetry, 3022c5a4c82aSJason M. Bills invalid, 3023c5a4c82aSJason M. Bills }; 3024c5a4c82aSJason M. Bills 302526ccae32SEd Tanous inline OEMDiagnosticType getOEMDiagnosticType(std::string_view oemDiagStr) 3026c5a4c82aSJason M. Bills { 3027c5a4c82aSJason M. Bills if (oemDiagStr == "OnDemand") 3028c5a4c82aSJason M. Bills { 3029c5a4c82aSJason M. Bills return OEMDiagnosticType::onDemand; 3030c5a4c82aSJason M. Bills } 3031c5a4c82aSJason M. Bills if (oemDiagStr == "Telemetry") 3032c5a4c82aSJason M. Bills { 3033c5a4c82aSJason M. Bills return OEMDiagnosticType::telemetry; 3034c5a4c82aSJason M. Bills } 3035c5a4c82aSJason M. Bills 3036c5a4c82aSJason M. Bills return OEMDiagnosticType::invalid; 3037c5a4c82aSJason M. Bills } 3038c5a4c82aSJason M. Bills 30397e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpCollect(App& app) 30401da66f75SEd Tanous { 30413946028dSAppaRao Puli // Note: Deviated from redfish privilege registry for GET & HEAD 30423946028dSAppaRao Puli // method for security reasons. 30430fda0f12SGeorge Liu BMCWEB_ROUTE( 30440fda0f12SGeorge Liu app, 304522d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/Crashdump/Actions/LogService.CollectDiagnosticData/") 3046ed398213SEd Tanous // The below is incorrect; Should be ConfigureManager 3047ed398213SEd Tanous //.privileges(redfish::privileges::postLogService) 3048432a890cSEd Tanous .privileges({{"ConfigureComponents"}}) 3049002d39b4SEd Tanous .methods(boost::beast::http::verb::post)( 3050002d39b4SEd Tanous [&app](const crow::Request& req, 305122d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 305222d268cbSEd Tanous const std::string& systemName) { 30533ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 305445ca1b86SEd Tanous { 305545ca1b86SEd Tanous return; 305645ca1b86SEd Tanous } 305722d268cbSEd Tanous 305825b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 30597f3e84a1SEd Tanous { 30607f3e84a1SEd Tanous // Option currently returns no systems. TBD 30617f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 30627f3e84a1SEd Tanous systemName); 30637f3e84a1SEd Tanous return; 30647f3e84a1SEd Tanous } 3065253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 306622d268cbSEd Tanous { 306722d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 306822d268cbSEd Tanous systemName); 306922d268cbSEd Tanous return; 307022d268cbSEd Tanous } 307122d268cbSEd Tanous 30728e6c099aSJason M. Bills std::string diagnosticDataType; 30738e6c099aSJason M. Bills std::string oemDiagnosticDataType; 307415ed6780SWilly Tu if (!redfish::json_util::readJsonAction( 3075bd79bce8SPatrick Williams req, asyncResp->res, "DiagnosticDataType", 3076bd79bce8SPatrick Williams diagnosticDataType, "OEMDiagnosticDataType", 3077bd79bce8SPatrick Williams oemDiagnosticDataType)) 30788e6c099aSJason M. Bills { 30798e6c099aSJason M. Bills return; 30808e6c099aSJason M. Bills } 30818e6c099aSJason M. Bills 30828e6c099aSJason M. Bills if (diagnosticDataType != "OEM") 30838e6c099aSJason M. Bills { 308462598e31SEd Tanous BMCWEB_LOG_ERROR( 308562598e31SEd Tanous "Only OEM DiagnosticDataType supported for Crashdump"); 30868e6c099aSJason M. Bills messages::actionParameterValueFormatError( 3087bd79bce8SPatrick Williams asyncResp->res, diagnosticDataType, 3088bd79bce8SPatrick Williams "DiagnosticDataType", "CollectDiagnosticData"); 30898e6c099aSJason M. Bills return; 30908e6c099aSJason M. Bills } 30918e6c099aSJason M. Bills 3092c5a4c82aSJason M. Bills OEMDiagnosticType oemDiagType = 3093c5a4c82aSJason M. Bills getOEMDiagnosticType(oemDiagnosticDataType); 3094c5a4c82aSJason M. Bills 3095c5a4c82aSJason M. Bills std::string iface; 3096c5a4c82aSJason M. Bills std::string method; 3097c5a4c82aSJason M. Bills std::string taskMatchStr; 3098c5a4c82aSJason M. Bills if (oemDiagType == OEMDiagnosticType::onDemand) 3099c5a4c82aSJason M. Bills { 3100c5a4c82aSJason M. Bills iface = crashdumpOnDemandInterface; 3101c5a4c82aSJason M. Bills method = "GenerateOnDemandLog"; 3102bd79bce8SPatrick Williams taskMatchStr = 3103bd79bce8SPatrick Williams "type='signal'," 3104c5a4c82aSJason M. Bills "interface='org.freedesktop.DBus.Properties'," 3105c5a4c82aSJason M. Bills "member='PropertiesChanged'," 3106c5a4c82aSJason M. Bills "arg0namespace='com.intel.crashdump'"; 3107c5a4c82aSJason M. Bills } 3108c5a4c82aSJason M. Bills else if (oemDiagType == OEMDiagnosticType::telemetry) 3109c5a4c82aSJason M. Bills { 3110c5a4c82aSJason M. Bills iface = crashdumpTelemetryInterface; 3111c5a4c82aSJason M. Bills method = "GenerateTelemetryLog"; 3112bd79bce8SPatrick Williams taskMatchStr = 3113bd79bce8SPatrick Williams "type='signal'," 3114c5a4c82aSJason M. Bills "interface='org.freedesktop.DBus.Properties'," 3115c5a4c82aSJason M. Bills "member='PropertiesChanged'," 3116c5a4c82aSJason M. Bills "arg0namespace='com.intel.crashdump'"; 3117c5a4c82aSJason M. Bills } 3118c5a4c82aSJason M. Bills else 3119c5a4c82aSJason M. Bills { 312062598e31SEd Tanous BMCWEB_LOG_ERROR("Unsupported OEMDiagnosticDataType: {}", 312162598e31SEd Tanous oemDiagnosticDataType); 3122c5a4c82aSJason M. Bills messages::actionParameterValueFormatError( 3123bd79bce8SPatrick Williams asyncResp->res, oemDiagnosticDataType, 3124bd79bce8SPatrick Williams "OEMDiagnosticDataType", "CollectDiagnosticData"); 3125c5a4c82aSJason M. Bills return; 3126c5a4c82aSJason M. Bills } 3127c5a4c82aSJason M. Bills 3128c5a4c82aSJason M. Bills auto collectCrashdumpCallback = 3129c5a4c82aSJason M. Bills [asyncResp, payload(task::Payload(req)), 31305e7e2dc5SEd Tanous taskMatchStr](const boost::system::error_code& ec, 313198be3e39SEd Tanous const std::string&) mutable { 31321da66f75SEd Tanous if (ec) 31331da66f75SEd Tanous { 3134bd79bce8SPatrick Williams if (ec.value() == 3135bd79bce8SPatrick Williams boost::system::errc::operation_not_supported) 31361da66f75SEd Tanous { 3137f12894f8SJason M. Bills messages::resourceInStandby(asyncResp->res); 31381da66f75SEd Tanous } 3139bd79bce8SPatrick Williams else if (ec.value() == boost::system::errc:: 3140bd79bce8SPatrick Williams device_or_resource_busy) 31414363d3b2SJason M. Bills { 3142bd79bce8SPatrick Williams messages::serviceTemporarilyUnavailable( 3143bd79bce8SPatrick Williams asyncResp->res, "60"); 31444363d3b2SJason M. Bills } 31451da66f75SEd Tanous else 31461da66f75SEd Tanous { 3147f12894f8SJason M. Bills messages::internalError(asyncResp->res); 31481da66f75SEd Tanous } 31491da66f75SEd Tanous return; 31501da66f75SEd Tanous } 3151bd79bce8SPatrick Williams std::shared_ptr<task::TaskData> task = 3152bd79bce8SPatrick Williams task::TaskData::createTask( 3153bd79bce8SPatrick Williams [](const boost::system::error_code& ec2, 3154bd79bce8SPatrick Williams sdbusplus::message_t&, 3155bd79bce8SPatrick Williams const std::shared_ptr<task::TaskData>& 3156bd79bce8SPatrick Williams taskData) { 31578b24275dSEd Tanous if (!ec2) 315866afe4faSJames Feist { 3159bd79bce8SPatrick Williams taskData->messages.emplace_back( 3160bd79bce8SPatrick Williams messages::taskCompletedOK( 3161bd79bce8SPatrick Williams std::to_string( 3162bd79bce8SPatrick Williams taskData->index))); 3163831d6b09SJames Feist taskData->state = "Completed"; 316466afe4faSJames Feist } 316532898ceaSJames Feist return task::completed; 316666afe4faSJames Feist }, 3167c5a4c82aSJason M. Bills taskMatchStr); 3168c5a4c82aSJason M. Bills 316946229577SJames Feist task->startTimer(std::chrono::minutes(5)); 317046229577SJames Feist task->populateResp(asyncResp->res); 317198be3e39SEd Tanous task->payload.emplace(std::move(payload)); 31721da66f75SEd Tanous }; 31738e6c099aSJason M. Bills 31741da66f75SEd Tanous crow::connections::systemBus->async_method_call( 3175bd79bce8SPatrick Williams std::move(collectCrashdumpCallback), crashdumpObject, 3176bd79bce8SPatrick Williams crashdumpPath, iface, method); 31777e860f15SJohn Edward Broadbent }); 31786eda7685SKenny L. Ku } 31796eda7685SKenny L. Ku 3180599b9af3SAlexander Hansen inline void dBusLogServiceActionsClear( 3181599b9af3SAlexander Hansen const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 3182599b9af3SAlexander Hansen { 3183599b9af3SAlexander Hansen BMCWEB_LOG_DEBUG("Do delete all entries."); 3184599b9af3SAlexander Hansen 3185599b9af3SAlexander Hansen // Process response from Logging service. 3186599b9af3SAlexander Hansen auto respHandler = [asyncResp](const boost::system::error_code& ec) { 3187599b9af3SAlexander Hansen BMCWEB_LOG_DEBUG("doClearLog resp_handler callback: Done"); 3188599b9af3SAlexander Hansen if (ec) 3189599b9af3SAlexander Hansen { 3190599b9af3SAlexander Hansen // TODO Handle for specific error code 3191599b9af3SAlexander Hansen BMCWEB_LOG_ERROR("doClearLog resp_handler got error {}", ec); 3192599b9af3SAlexander Hansen asyncResp->res.result( 3193599b9af3SAlexander Hansen boost::beast::http::status::internal_server_error); 3194599b9af3SAlexander Hansen return; 3195599b9af3SAlexander Hansen } 3196599b9af3SAlexander Hansen 3197599b9af3SAlexander Hansen asyncResp->res.result(boost::beast::http::status::no_content); 3198599b9af3SAlexander Hansen }; 3199599b9af3SAlexander Hansen 3200599b9af3SAlexander Hansen // Make call to Logging service to request Clear Log 3201599b9af3SAlexander Hansen crow::connections::systemBus->async_method_call( 3202599b9af3SAlexander Hansen respHandler, "xyz.openbmc_project.Logging", 3203599b9af3SAlexander Hansen "/xyz/openbmc_project/logging", 3204599b9af3SAlexander Hansen "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll"); 3205599b9af3SAlexander Hansen } 3206599b9af3SAlexander Hansen 3207cb92c03bSAndrew Geissler /** 3208cb92c03bSAndrew Geissler * DBusLogServiceActionsClear class supports POST method for ClearLog action. 3209cb92c03bSAndrew Geissler */ 32107e860f15SJohn Edward Broadbent inline void requestRoutesDBusLogServiceActionsClear(App& app) 3211cb92c03bSAndrew Geissler { 3212cb92c03bSAndrew Geissler /** 3213cb92c03bSAndrew Geissler * Function handles POST method request. 3214cb92c03bSAndrew Geissler * The Clear Log actions does not require any parameter.The action deletes 3215cb92c03bSAndrew Geissler * all entries found in the Entries collection for this Log Service. 3216cb92c03bSAndrew Geissler */ 32177e860f15SJohn Edward Broadbent 32180fda0f12SGeorge Liu BMCWEB_ROUTE( 32190fda0f12SGeorge Liu app, 322022d268cbSEd Tanous "/redfish/v1/Systems/<str>/LogServices/EventLog/Actions/LogService.ClearLog/") 3221ed398213SEd Tanous .privileges(redfish::privileges::postLogService) 32227e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 322345ca1b86SEd Tanous [&app](const crow::Request& req, 322422d268cbSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 322522d268cbSEd Tanous const std::string& systemName) { 32263ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 322745ca1b86SEd Tanous { 322845ca1b86SEd Tanous return; 322945ca1b86SEd Tanous } 323025b54dbaSEd Tanous if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 32317f3e84a1SEd Tanous { 32327f3e84a1SEd Tanous // Option currently returns no systems. TBD 32337f3e84a1SEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 32347f3e84a1SEd Tanous systemName); 32357f3e84a1SEd Tanous return; 32367f3e84a1SEd Tanous } 3237253f11b8SEd Tanous if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 323822d268cbSEd Tanous { 323922d268cbSEd Tanous messages::resourceNotFound(asyncResp->res, "ComputerSystem", 324022d268cbSEd Tanous systemName); 324122d268cbSEd Tanous return; 324222d268cbSEd Tanous } 3243599b9af3SAlexander Hansen dBusLogServiceActionsClear(asyncResp); 32447e860f15SJohn Edward Broadbent }); 3245cb92c03bSAndrew Geissler } 3246a3316fc6SZhikuiRen 32471da66f75SEd Tanous } // namespace redfish 3248