xref: /openbmc/bmcweb/features/redfish/lib/log_services.hpp (revision 40e9b92ec19acffb46f83a6e55b18974da5d708e)
1*40e9b92eSEd Tanous // SPDX-License-Identifier: Apache-2.0
2*40e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright OpenBMC Authors
3*40e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright 2018 Intel Corporation
41da66f75SEd Tanous #pragma once
51da66f75SEd Tanous 
63ccb3adbSEd Tanous #include "app.hpp"
77a1dbc48SGeorge Liu #include "dbus_utility.hpp"
83ccb3adbSEd Tanous #include "error_messages.hpp"
968dd075aSAsmitha Karunanithi #include "generated/enums/log_entry.hpp"
10539d8c6bSEd Tanous #include "generated/enums/log_service.hpp"
11b7028ebfSSpencer Ku #include "gzfile.hpp"
12647b3cdcSGeorge Liu #include "http_utility.hpp"
13b7028ebfSSpencer Ku #include "human_sort.hpp"
143ccb3adbSEd Tanous #include "query.hpp"
154851d45dSJason M. Bills #include "registries.hpp"
164851d45dSJason M. Bills #include "registries/base_message_registry.hpp"
174851d45dSJason M. Bills #include "registries/openbmc_message_registry.hpp"
183ccb3adbSEd Tanous #include "registries/privilege_registry.hpp"
1946229577SJames Feist #include "task.hpp"
205b90429aSEd Tanous #include "task_messages.hpp"
21262dcc1cSAlexander Hansen #include "utils/dbus_event_log_entry.hpp"
223ccb3adbSEd Tanous #include "utils/dbus_utils.hpp"
235b90429aSEd Tanous #include "utils/json_utils.hpp"
243ccb3adbSEd Tanous #include "utils/time_utils.hpp"
251da66f75SEd Tanous 
2675e8e218SMyung Bae #include <systemd/sd-id128.h>
278e31778eSAsmitha Karunanithi #include <tinyxml2.h>
28400fd1fbSAdriana Kobylak #include <unistd.h>
29e1f26343SJason M. Bills 
3007c8c20dSEd Tanous #include <boost/beast/http/verb.hpp>
311da66f75SEd Tanous #include <boost/container/flat_map.hpp>
321ddcf01aSJason M. Bills #include <boost/system/linux_error.hpp>
33ef4c65b7SEd Tanous #include <boost/url/format.hpp>
34d1bde9e5SKrzysztof Grobelny #include <sdbusplus/asio/property.hpp>
35d1bde9e5SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp>
361214b7e7SGunnar Mills 
377a1dbc48SGeorge Liu #include <array>
38647b3cdcSGeorge Liu #include <charconv>
39b5f288d2SAbhilash Raju #include <cstddef>
404418c7f0SJames Feist #include <filesystem>
4118f8f608SEd Tanous #include <iterator>
4275710de2SXiaochao Ma #include <optional>
433544d2a7SEd Tanous #include <ranges>
4426702d01SEd Tanous #include <span>
4518f8f608SEd Tanous #include <string>
46cd225da8SJason M. Bills #include <string_view>
47abf2add6SEd Tanous #include <variant>
481da66f75SEd Tanous 
491da66f75SEd Tanous namespace redfish
501da66f75SEd Tanous {
511da66f75SEd Tanous 
5289492a15SPatrick Williams constexpr const char* crashdumpObject = "com.intel.crashdump";
5389492a15SPatrick Williams constexpr const char* crashdumpPath = "/com/intel/crashdump";
5489492a15SPatrick Williams constexpr const char* crashdumpInterface = "com.intel.crashdump";
5589492a15SPatrick Williams constexpr const char* deleteAllInterface =
565b61b5e8SJason M. Bills     "xyz.openbmc_project.Collection.DeleteAll";
5789492a15SPatrick Williams constexpr const char* crashdumpOnDemandInterface =
58424c4176SJason M. Bills     "com.intel.crashdump.OnDemand";
5989492a15SPatrick Williams constexpr const char* crashdumpTelemetryInterface =
606eda7685SKenny L. Ku     "com.intel.crashdump.Telemetry";
611da66f75SEd Tanous 
628e31778eSAsmitha Karunanithi enum class DumpCreationProgress
638e31778eSAsmitha Karunanithi {
648e31778eSAsmitha Karunanithi     DUMP_CREATE_SUCCESS,
658e31778eSAsmitha Karunanithi     DUMP_CREATE_FAILED,
668e31778eSAsmitha Karunanithi     DUMP_CREATE_INPROGRESS
678e31778eSAsmitha Karunanithi };
688e31778eSAsmitha Karunanithi 
69f6150403SJames Feist namespace fs = std::filesystem;
701da66f75SEd Tanous 
71cb92c03bSAndrew Geissler inline std::string translateSeverityDbusToRedfish(const std::string& s)
72cb92c03bSAndrew Geissler {
73d4d25793SEd Tanous     if ((s == "xyz.openbmc_project.Logging.Entry.Level.Alert") ||
74d4d25793SEd Tanous         (s == "xyz.openbmc_project.Logging.Entry.Level.Critical") ||
75d4d25793SEd Tanous         (s == "xyz.openbmc_project.Logging.Entry.Level.Emergency") ||
76d4d25793SEd Tanous         (s == "xyz.openbmc_project.Logging.Entry.Level.Error"))
77cb92c03bSAndrew Geissler     {
78cb92c03bSAndrew Geissler         return "Critical";
79cb92c03bSAndrew Geissler     }
803174e4dfSEd Tanous     if ((s == "xyz.openbmc_project.Logging.Entry.Level.Debug") ||
81d4d25793SEd Tanous         (s == "xyz.openbmc_project.Logging.Entry.Level.Informational") ||
82d4d25793SEd Tanous         (s == "xyz.openbmc_project.Logging.Entry.Level.Notice"))
83cb92c03bSAndrew Geissler     {
84cb92c03bSAndrew Geissler         return "OK";
85cb92c03bSAndrew Geissler     }
863174e4dfSEd Tanous     if (s == "xyz.openbmc_project.Logging.Entry.Level.Warning")
87cb92c03bSAndrew Geissler     {
88cb92c03bSAndrew Geissler         return "Warning";
89cb92c03bSAndrew Geissler     }
90cb92c03bSAndrew Geissler     return "";
91cb92c03bSAndrew Geissler }
92cb92c03bSAndrew Geissler 
939017faf2SAbhishek Patel inline std::optional<bool> getProviderNotifyAction(const std::string& notify)
949017faf2SAbhishek Patel {
959017faf2SAbhishek Patel     std::optional<bool> notifyAction;
969017faf2SAbhishek Patel     if (notify == "xyz.openbmc_project.Logging.Entry.Notify.Notify")
979017faf2SAbhishek Patel     {
989017faf2SAbhishek Patel         notifyAction = true;
999017faf2SAbhishek Patel     }
1009017faf2SAbhishek Patel     else if (notify == "xyz.openbmc_project.Logging.Entry.Notify.Inhibit")
1019017faf2SAbhishek Patel     {
1029017faf2SAbhishek Patel         notifyAction = false;
1039017faf2SAbhishek Patel     }
1049017faf2SAbhishek Patel 
1059017faf2SAbhishek Patel     return notifyAction;
1069017faf2SAbhishek Patel }
1079017faf2SAbhishek Patel 
10818f8f608SEd Tanous inline std::string getDumpPath(std::string_view dumpType)
10918f8f608SEd Tanous {
11018f8f608SEd Tanous     std::string dbusDumpPath = "/xyz/openbmc_project/dump/";
11118f8f608SEd Tanous     std::ranges::transform(dumpType, std::back_inserter(dbusDumpPath),
11218f8f608SEd Tanous                            bmcweb::asciiToLower);
11318f8f608SEd Tanous 
11418f8f608SEd Tanous     return dbusDumpPath;
11518f8f608SEd Tanous }
11618f8f608SEd Tanous 
117055713e4SEd Tanous inline bool getUniqueEntryID(const std::string& logEntry, std::string& entryID,
118e85d6b16SJason M. Bills                              const bool firstEntry = true)
11995820184SJason M. Bills {
120271584abSEd Tanous     static time_t prevTs = 0;
12195820184SJason M. Bills     static int index = 0;
122e85d6b16SJason M. Bills     if (firstEntry)
123e85d6b16SJason M. Bills     {
124e85d6b16SJason M. Bills         prevTs = 0;
125e85d6b16SJason M. Bills     }
126e85d6b16SJason M. Bills 
12795820184SJason M. Bills     // Get the entry timestamp
128271584abSEd Tanous     std::time_t curTs = 0;
12995820184SJason M. Bills     std::tm timeStruct = {};
13095820184SJason M. Bills     std::istringstream entryStream(logEntry);
13195820184SJason M. Bills     if (entryStream >> std::get_time(&timeStruct, "%Y-%m-%dT%H:%M:%S"))
13295820184SJason M. Bills     {
13395820184SJason M. Bills         curTs = std::mktime(&timeStruct);
13495820184SJason M. Bills     }
13595820184SJason M. Bills     // If the timestamp isn't unique, increment the index
13695820184SJason M. Bills     if (curTs == prevTs)
13795820184SJason M. Bills     {
13895820184SJason M. Bills         index++;
13995820184SJason M. Bills     }
14095820184SJason M. Bills     else
14195820184SJason M. Bills     {
14295820184SJason M. Bills         // Otherwise, reset it
14395820184SJason M. Bills         index = 0;
14495820184SJason M. Bills     }
14595820184SJason M. Bills     // Save the timestamp
14695820184SJason M. Bills     prevTs = curTs;
14795820184SJason M. Bills 
14895820184SJason M. Bills     entryID = std::to_string(curTs);
14995820184SJason M. Bills     if (index > 0)
15095820184SJason M. Bills     {
15195820184SJason M. Bills         entryID += "_" + std::to_string(index);
15295820184SJason M. Bills     }
15395820184SJason M. Bills     return true;
15495820184SJason M. Bills }
15595820184SJason M. Bills 
1564ff0f1f4SEd Tanous inline bool
15795820184SJason M. Bills     getRedfishLogFiles(std::vector<std::filesystem::path>& redfishLogFiles)
15895820184SJason M. Bills {
15995820184SJason M. Bills     static const std::filesystem::path redfishLogDir = "/var/log";
16095820184SJason M. Bills     static const std::string redfishLogFilename = "redfish";
16195820184SJason M. Bills 
16295820184SJason M. Bills     // Loop through the directory looking for redfish log files
16395820184SJason M. Bills     for (const std::filesystem::directory_entry& dirEnt :
16495820184SJason M. Bills          std::filesystem::directory_iterator(redfishLogDir))
16595820184SJason M. Bills     {
16695820184SJason M. Bills         // If we find a redfish log file, save the path
16795820184SJason M. Bills         std::string filename = dirEnt.path().filename();
16811ba3979SEd Tanous         if (filename.starts_with(redfishLogFilename))
16995820184SJason M. Bills         {
17095820184SJason M. Bills             redfishLogFiles.emplace_back(redfishLogDir / filename);
17195820184SJason M. Bills         }
17295820184SJason M. Bills     }
17395820184SJason M. Bills     // As the log files rotate, they are appended with a ".#" that is higher for
17495820184SJason M. Bills     // the older logs. Since we don't expect more than 10 log files, we
17595820184SJason M. Bills     // can just sort the list to get them in order from newest to oldest
1763544d2a7SEd Tanous     std::ranges::sort(redfishLogFiles);
17795820184SJason M. Bills 
17895820184SJason M. Bills     return !redfishLogFiles.empty();
17995820184SJason M. Bills }
18095820184SJason M. Bills 
18168dd075aSAsmitha Karunanithi inline log_entry::OriginatorTypes
18268dd075aSAsmitha Karunanithi     mapDbusOriginatorTypeToRedfish(const std::string& originatorType)
18368dd075aSAsmitha Karunanithi {
18468dd075aSAsmitha Karunanithi     if (originatorType ==
18568dd075aSAsmitha Karunanithi         "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Client")
18668dd075aSAsmitha Karunanithi     {
18768dd075aSAsmitha Karunanithi         return log_entry::OriginatorTypes::Client;
18868dd075aSAsmitha Karunanithi     }
18968dd075aSAsmitha Karunanithi     if (originatorType ==
19068dd075aSAsmitha Karunanithi         "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Internal")
19168dd075aSAsmitha Karunanithi     {
19268dd075aSAsmitha Karunanithi         return log_entry::OriginatorTypes::Internal;
19368dd075aSAsmitha Karunanithi     }
19468dd075aSAsmitha Karunanithi     if (originatorType ==
19568dd075aSAsmitha Karunanithi         "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.SupportingService")
19668dd075aSAsmitha Karunanithi     {
19768dd075aSAsmitha Karunanithi         return log_entry::OriginatorTypes::SupportingService;
19868dd075aSAsmitha Karunanithi     }
19968dd075aSAsmitha Karunanithi     return log_entry::OriginatorTypes::Invalid;
20068dd075aSAsmitha Karunanithi }
20168dd075aSAsmitha Karunanithi 
202aefe3786SClaire Weinan inline void parseDumpEntryFromDbusObject(
2032d613eb6SJiaqing Zhao     const dbus::utility::ManagedObjectType::value_type& object,
204c6fecdabSClaire Weinan     std::string& dumpStatus, uint64_t& size, uint64_t& timestampUs,
20568dd075aSAsmitha Karunanithi     std::string& originatorId, log_entry::OriginatorTypes& originatorType,
206aefe3786SClaire Weinan     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
207aefe3786SClaire Weinan {
208aefe3786SClaire Weinan     for (const auto& interfaceMap : object.second)
209aefe3786SClaire Weinan     {
210aefe3786SClaire Weinan         if (interfaceMap.first == "xyz.openbmc_project.Common.Progress")
211aefe3786SClaire Weinan         {
212aefe3786SClaire Weinan             for (const auto& propertyMap : interfaceMap.second)
213aefe3786SClaire Weinan             {
214aefe3786SClaire Weinan                 if (propertyMap.first == "Status")
215aefe3786SClaire Weinan                 {
216aefe3786SClaire Weinan                     const auto* status =
217aefe3786SClaire Weinan                         std::get_if<std::string>(&propertyMap.second);
218aefe3786SClaire Weinan                     if (status == nullptr)
219aefe3786SClaire Weinan                     {
220aefe3786SClaire Weinan                         messages::internalError(asyncResp->res);
221aefe3786SClaire Weinan                         break;
222aefe3786SClaire Weinan                     }
223aefe3786SClaire Weinan                     dumpStatus = *status;
224aefe3786SClaire Weinan                 }
225aefe3786SClaire Weinan             }
226aefe3786SClaire Weinan         }
227aefe3786SClaire Weinan         else if (interfaceMap.first == "xyz.openbmc_project.Dump.Entry")
228aefe3786SClaire Weinan         {
229aefe3786SClaire Weinan             for (const auto& propertyMap : interfaceMap.second)
230aefe3786SClaire Weinan             {
231aefe3786SClaire Weinan                 if (propertyMap.first == "Size")
232aefe3786SClaire Weinan                 {
233aefe3786SClaire Weinan                     const auto* sizePtr =
234aefe3786SClaire Weinan                         std::get_if<uint64_t>(&propertyMap.second);
235aefe3786SClaire Weinan                     if (sizePtr == nullptr)
236aefe3786SClaire Weinan                     {
237aefe3786SClaire Weinan                         messages::internalError(asyncResp->res);
238aefe3786SClaire Weinan                         break;
239aefe3786SClaire Weinan                     }
240aefe3786SClaire Weinan                     size = *sizePtr;
241aefe3786SClaire Weinan                     break;
242aefe3786SClaire Weinan                 }
243aefe3786SClaire Weinan             }
244aefe3786SClaire Weinan         }
245aefe3786SClaire Weinan         else if (interfaceMap.first == "xyz.openbmc_project.Time.EpochTime")
246aefe3786SClaire Weinan         {
247aefe3786SClaire Weinan             for (const auto& propertyMap : interfaceMap.second)
248aefe3786SClaire Weinan             {
249aefe3786SClaire Weinan                 if (propertyMap.first == "Elapsed")
250aefe3786SClaire Weinan                 {
251aefe3786SClaire Weinan                     const uint64_t* usecsTimeStamp =
252aefe3786SClaire Weinan                         std::get_if<uint64_t>(&propertyMap.second);
253aefe3786SClaire Weinan                     if (usecsTimeStamp == nullptr)
254aefe3786SClaire Weinan                     {
255aefe3786SClaire Weinan                         messages::internalError(asyncResp->res);
256aefe3786SClaire Weinan                         break;
257aefe3786SClaire Weinan                     }
258c6fecdabSClaire Weinan                     timestampUs = *usecsTimeStamp;
259aefe3786SClaire Weinan                     break;
260aefe3786SClaire Weinan                 }
261aefe3786SClaire Weinan             }
262aefe3786SClaire Weinan         }
26368dd075aSAsmitha Karunanithi         else if (interfaceMap.first ==
26468dd075aSAsmitha Karunanithi                  "xyz.openbmc_project.Common.OriginatedBy")
26568dd075aSAsmitha Karunanithi         {
26668dd075aSAsmitha Karunanithi             for (const auto& propertyMap : interfaceMap.second)
26768dd075aSAsmitha Karunanithi             {
26868dd075aSAsmitha Karunanithi                 if (propertyMap.first == "OriginatorId")
26968dd075aSAsmitha Karunanithi                 {
27068dd075aSAsmitha Karunanithi                     const std::string* id =
27168dd075aSAsmitha Karunanithi                         std::get_if<std::string>(&propertyMap.second);
27268dd075aSAsmitha Karunanithi                     if (id == nullptr)
27368dd075aSAsmitha Karunanithi                     {
27468dd075aSAsmitha Karunanithi                         messages::internalError(asyncResp->res);
27568dd075aSAsmitha Karunanithi                         break;
27668dd075aSAsmitha Karunanithi                     }
27768dd075aSAsmitha Karunanithi                     originatorId = *id;
27868dd075aSAsmitha Karunanithi                 }
27968dd075aSAsmitha Karunanithi 
28068dd075aSAsmitha Karunanithi                 if (propertyMap.first == "OriginatorType")
28168dd075aSAsmitha Karunanithi                 {
28268dd075aSAsmitha Karunanithi                     const std::string* type =
28368dd075aSAsmitha Karunanithi                         std::get_if<std::string>(&propertyMap.second);
28468dd075aSAsmitha Karunanithi                     if (type == nullptr)
28568dd075aSAsmitha Karunanithi                     {
28668dd075aSAsmitha Karunanithi                         messages::internalError(asyncResp->res);
28768dd075aSAsmitha Karunanithi                         break;
28868dd075aSAsmitha Karunanithi                     }
28968dd075aSAsmitha Karunanithi 
29068dd075aSAsmitha Karunanithi                     originatorType = mapDbusOriginatorTypeToRedfish(*type);
29168dd075aSAsmitha Karunanithi                     if (originatorType == log_entry::OriginatorTypes::Invalid)
29268dd075aSAsmitha Karunanithi                     {
29368dd075aSAsmitha Karunanithi                         messages::internalError(asyncResp->res);
29468dd075aSAsmitha Karunanithi                         break;
29568dd075aSAsmitha Karunanithi                     }
29668dd075aSAsmitha Karunanithi                 }
29768dd075aSAsmitha Karunanithi             }
29868dd075aSAsmitha Karunanithi         }
299aefe3786SClaire Weinan     }
300aefe3786SClaire Weinan }
301aefe3786SClaire Weinan 
30221ab404cSNan Zhou static std::string getDumpEntriesPath(const std::string& dumpType)
303fdd26906SClaire Weinan {
304fdd26906SClaire Weinan     std::string entriesPath;
305fdd26906SClaire Weinan 
306fdd26906SClaire Weinan     if (dumpType == "BMC")
307fdd26906SClaire Weinan     {
308253f11b8SEd Tanous         entriesPath =
309253f11b8SEd Tanous             std::format("/redfish/v1/Managers/{}/LogServices/Dump/Entries/",
310253f11b8SEd Tanous                         BMCWEB_REDFISH_MANAGER_URI_NAME);
311fdd26906SClaire Weinan     }
312fdd26906SClaire Weinan     else if (dumpType == "FaultLog")
313fdd26906SClaire Weinan     {
314253f11b8SEd Tanous         entriesPath =
315253f11b8SEd Tanous             std::format("/redfish/v1/Managers/{}/LogServices/FaultLog/Entries/",
316253f11b8SEd Tanous                         BMCWEB_REDFISH_MANAGER_URI_NAME);
317fdd26906SClaire Weinan     }
318fdd26906SClaire Weinan     else if (dumpType == "System")
319fdd26906SClaire Weinan     {
320253f11b8SEd Tanous         entriesPath =
321253f11b8SEd Tanous             std::format("/redfish/v1/Systems/{}/LogServices/Dump/Entries/",
322253f11b8SEd Tanous                         BMCWEB_REDFISH_SYSTEM_URI_NAME);
323fdd26906SClaire Weinan     }
324fdd26906SClaire Weinan     else
325fdd26906SClaire Weinan     {
32662598e31SEd Tanous         BMCWEB_LOG_ERROR("getDumpEntriesPath() invalid dump type: {}",
32762598e31SEd Tanous                          dumpType);
328fdd26906SClaire Weinan     }
329fdd26906SClaire Weinan 
330fdd26906SClaire Weinan     // Returns empty string on error
331fdd26906SClaire Weinan     return entriesPath;
332fdd26906SClaire Weinan }
333fdd26906SClaire Weinan 
3348d1b46d7Szhanghch05 inline void
3358d1b46d7Szhanghch05     getDumpEntryCollection(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3365cb1dd27SAsmitha Karunanithi                            const std::string& dumpType)
3375cb1dd27SAsmitha Karunanithi {
338fdd26906SClaire Weinan     std::string entriesPath = getDumpEntriesPath(dumpType);
339fdd26906SClaire Weinan     if (entriesPath.empty())
3405cb1dd27SAsmitha Karunanithi     {
3415cb1dd27SAsmitha Karunanithi         messages::internalError(asyncResp->res);
3425cb1dd27SAsmitha Karunanithi         return;
3435cb1dd27SAsmitha Karunanithi     }
3445cb1dd27SAsmitha Karunanithi 
3455eb468daSGeorge Liu     sdbusplus::message::object_path path("/xyz/openbmc_project/dump");
3465eb468daSGeorge Liu     dbus::utility::getManagedObjects(
3475eb468daSGeorge Liu         "xyz.openbmc_project.Dump.Manager", path,
348fdd26906SClaire Weinan         [asyncResp, entriesPath,
3495e7e2dc5SEd Tanous          dumpType](const boost::system::error_code& ec,
3505eb468daSGeorge Liu                    const dbus::utility::ManagedObjectType& objects) {
3515cb1dd27SAsmitha Karunanithi             if (ec)
3525cb1dd27SAsmitha Karunanithi             {
35362598e31SEd Tanous                 BMCWEB_LOG_ERROR("DumpEntry resp_handler got error {}", ec);
3545cb1dd27SAsmitha Karunanithi                 messages::internalError(asyncResp->res);
3555cb1dd27SAsmitha Karunanithi                 return;
3565cb1dd27SAsmitha Karunanithi             }
3575cb1dd27SAsmitha Karunanithi 
358fdd26906SClaire Weinan             // Remove ending slash
359fdd26906SClaire Weinan             std::string odataIdStr = entriesPath;
360fdd26906SClaire Weinan             if (!odataIdStr.empty())
361fdd26906SClaire Weinan             {
362fdd26906SClaire Weinan                 odataIdStr.pop_back();
363fdd26906SClaire Weinan             }
364fdd26906SClaire Weinan 
365fdd26906SClaire Weinan             asyncResp->res.jsonValue["@odata.type"] =
366fdd26906SClaire Weinan                 "#LogEntryCollection.LogEntryCollection";
367fdd26906SClaire Weinan             asyncResp->res.jsonValue["@odata.id"] = std::move(odataIdStr);
368fdd26906SClaire Weinan             asyncResp->res.jsonValue["Name"] = dumpType + " Dump Entries";
369bd79bce8SPatrick Williams             asyncResp->res.jsonValue["Description"] =
370bd79bce8SPatrick Williams                 "Collection of " + dumpType + " Dump Entries";
371fdd26906SClaire Weinan 
3723544d2a7SEd Tanous             nlohmann::json::array_t entriesArray;
37318f8f608SEd Tanous             std::string dumpEntryPath = getDumpPath(dumpType) + "/entry/";
3745cb1dd27SAsmitha Karunanithi 
3755eb468daSGeorge Liu             dbus::utility::ManagedObjectType resp(objects);
3763544d2a7SEd Tanous             std::ranges::sort(resp, [](const auto& l, const auto& r) {
377002d39b4SEd Tanous                 return AlphanumLess<std::string>()(l.first.filename(),
378002d39b4SEd Tanous                                                    r.first.filename());
379565dfb6fSClaire Weinan             });
380565dfb6fSClaire Weinan 
3815cb1dd27SAsmitha Karunanithi             for (auto& object : resp)
3825cb1dd27SAsmitha Karunanithi             {
383b47452b2SAsmitha Karunanithi                 if (object.first.str.find(dumpEntryPath) == std::string::npos)
3845cb1dd27SAsmitha Karunanithi                 {
3855cb1dd27SAsmitha Karunanithi                     continue;
3865cb1dd27SAsmitha Karunanithi                 }
387c6fecdabSClaire Weinan                 uint64_t timestampUs = 0;
3885cb1dd27SAsmitha Karunanithi                 uint64_t size = 0;
38935440d18SAsmitha Karunanithi                 std::string dumpStatus;
39068dd075aSAsmitha Karunanithi                 std::string originatorId;
39168dd075aSAsmitha Karunanithi                 log_entry::OriginatorTypes originatorType =
39268dd075aSAsmitha Karunanithi                     log_entry::OriginatorTypes::Internal;
393433b68b4SJason M. Bills                 nlohmann::json::object_t thisEntry;
3942dfd18efSEd Tanous 
3952dfd18efSEd Tanous                 std::string entryID = object.first.filename();
3962dfd18efSEd Tanous                 if (entryID.empty())
3975cb1dd27SAsmitha Karunanithi                 {
3985cb1dd27SAsmitha Karunanithi                     continue;
3995cb1dd27SAsmitha Karunanithi                 }
4005cb1dd27SAsmitha Karunanithi 
401bd79bce8SPatrick Williams                 parseDumpEntryFromDbusObject(object, dumpStatus, size,
402bd79bce8SPatrick Williams                                              timestampUs, originatorId,
403bd79bce8SPatrick Williams                                              originatorType, asyncResp);
4045cb1dd27SAsmitha Karunanithi 
4050fda0f12SGeorge Liu                 if (dumpStatus !=
4060fda0f12SGeorge Liu                         "xyz.openbmc_project.Common.Progress.OperationStatus.Completed" &&
40735440d18SAsmitha Karunanithi                     !dumpStatus.empty())
40835440d18SAsmitha Karunanithi                 {
40935440d18SAsmitha Karunanithi                     // Dump status is not Complete, no need to enumerate
41035440d18SAsmitha Karunanithi                     continue;
41135440d18SAsmitha Karunanithi                 }
41235440d18SAsmitha Karunanithi 
41368dd075aSAsmitha Karunanithi                 thisEntry["@odata.type"] = "#LogEntry.v1_11_0.LogEntry";
414fdd26906SClaire Weinan                 thisEntry["@odata.id"] = entriesPath + entryID;
4155cb1dd27SAsmitha Karunanithi                 thisEntry["Id"] = entryID;
4165cb1dd27SAsmitha Karunanithi                 thisEntry["EntryType"] = "Event";
4175cb1dd27SAsmitha Karunanithi                 thisEntry["Name"] = dumpType + " Dump Entry";
418bbd80db8SClaire Weinan                 thisEntry["Created"] =
419bbd80db8SClaire Weinan                     redfish::time_utils::getDateTimeUintUs(timestampUs);
4205cb1dd27SAsmitha Karunanithi 
42168dd075aSAsmitha Karunanithi                 if (!originatorId.empty())
42268dd075aSAsmitha Karunanithi                 {
42368dd075aSAsmitha Karunanithi                     thisEntry["Originator"] = originatorId;
42468dd075aSAsmitha Karunanithi                     thisEntry["OriginatorType"] = originatorType;
42568dd075aSAsmitha Karunanithi                 }
42668dd075aSAsmitha Karunanithi 
4275cb1dd27SAsmitha Karunanithi                 if (dumpType == "BMC")
4285cb1dd27SAsmitha Karunanithi                 {
429d337bb72SAsmitha Karunanithi                     thisEntry["DiagnosticDataType"] = "Manager";
430bd79bce8SPatrick Williams                     thisEntry["AdditionalDataURI"] =
431bd79bce8SPatrick Williams                         entriesPath + entryID + "/attachment";
432fdd26906SClaire Weinan                     thisEntry["AdditionalDataSizeBytes"] = size;
4335cb1dd27SAsmitha Karunanithi                 }
4345cb1dd27SAsmitha Karunanithi                 else if (dumpType == "System")
4355cb1dd27SAsmitha Karunanithi                 {
436d337bb72SAsmitha Karunanithi                     thisEntry["DiagnosticDataType"] = "OEM";
437d337bb72SAsmitha Karunanithi                     thisEntry["OEMDiagnosticDataType"] = "System";
438bd79bce8SPatrick Williams                     thisEntry["AdditionalDataURI"] =
439bd79bce8SPatrick Williams                         entriesPath + entryID + "/attachment";
440fdd26906SClaire Weinan                     thisEntry["AdditionalDataSizeBytes"] = size;
4415cb1dd27SAsmitha Karunanithi                 }
442b2ba3072SPatrick Williams                 entriesArray.emplace_back(std::move(thisEntry));
4435cb1dd27SAsmitha Karunanithi             }
444bd79bce8SPatrick Williams             asyncResp->res.jsonValue["Members@odata.count"] =
445bd79bce8SPatrick Williams                 entriesArray.size();
4463544d2a7SEd Tanous             asyncResp->res.jsonValue["Members"] = std::move(entriesArray);
4475eb468daSGeorge Liu         });
4485cb1dd27SAsmitha Karunanithi }
4495cb1dd27SAsmitha Karunanithi 
4508d1b46d7Szhanghch05 inline void
451c7a6d660SClaire Weinan     getDumpEntryById(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
4528d1b46d7Szhanghch05                      const std::string& entryID, const std::string& dumpType)
4535cb1dd27SAsmitha Karunanithi {
454fdd26906SClaire Weinan     std::string entriesPath = getDumpEntriesPath(dumpType);
455fdd26906SClaire Weinan     if (entriesPath.empty())
4565cb1dd27SAsmitha Karunanithi     {
4575cb1dd27SAsmitha Karunanithi         messages::internalError(asyncResp->res);
4585cb1dd27SAsmitha Karunanithi         return;
4595cb1dd27SAsmitha Karunanithi     }
4605cb1dd27SAsmitha Karunanithi 
4615eb468daSGeorge Liu     sdbusplus::message::object_path path("/xyz/openbmc_project/dump");
4625eb468daSGeorge Liu     dbus::utility::getManagedObjects(
4635eb468daSGeorge Liu         "xyz.openbmc_project.Dump.Manager", path,
464fdd26906SClaire Weinan         [asyncResp, entryID, dumpType,
4655e7e2dc5SEd Tanous          entriesPath](const boost::system::error_code& ec,
46602cad96eSEd Tanous                       const dbus::utility::ManagedObjectType& resp) {
4675cb1dd27SAsmitha Karunanithi             if (ec)
4685cb1dd27SAsmitha Karunanithi             {
46962598e31SEd Tanous                 BMCWEB_LOG_ERROR("DumpEntry resp_handler got error {}", ec);
4705cb1dd27SAsmitha Karunanithi                 messages::internalError(asyncResp->res);
4715cb1dd27SAsmitha Karunanithi                 return;
4725cb1dd27SAsmitha Karunanithi             }
4735cb1dd27SAsmitha Karunanithi 
474b47452b2SAsmitha Karunanithi             bool foundDumpEntry = false;
47518f8f608SEd Tanous             std::string dumpEntryPath = getDumpPath(dumpType) + "/entry/";
476b47452b2SAsmitha Karunanithi 
4779eb808c1SEd Tanous             for (const auto& objectPath : resp)
4785cb1dd27SAsmitha Karunanithi             {
479b47452b2SAsmitha Karunanithi                 if (objectPath.first.str != dumpEntryPath + entryID)
4805cb1dd27SAsmitha Karunanithi                 {
4815cb1dd27SAsmitha Karunanithi                     continue;
4825cb1dd27SAsmitha Karunanithi                 }
4835cb1dd27SAsmitha Karunanithi 
4845cb1dd27SAsmitha Karunanithi                 foundDumpEntry = true;
485c6fecdabSClaire Weinan                 uint64_t timestampUs = 0;
4865cb1dd27SAsmitha Karunanithi                 uint64_t size = 0;
48735440d18SAsmitha Karunanithi                 std::string dumpStatus;
48868dd075aSAsmitha Karunanithi                 std::string originatorId;
48968dd075aSAsmitha Karunanithi                 log_entry::OriginatorTypes originatorType =
49068dd075aSAsmitha Karunanithi                     log_entry::OriginatorTypes::Internal;
4915cb1dd27SAsmitha Karunanithi 
492aefe3786SClaire Weinan                 parseDumpEntryFromDbusObject(objectPath, dumpStatus, size,
49368dd075aSAsmitha Karunanithi                                              timestampUs, originatorId,
49468dd075aSAsmitha Karunanithi                                              originatorType, asyncResp);
4955cb1dd27SAsmitha Karunanithi 
4960fda0f12SGeorge Liu                 if (dumpStatus !=
4970fda0f12SGeorge Liu                         "xyz.openbmc_project.Common.Progress.OperationStatus.Completed" &&
49835440d18SAsmitha Karunanithi                     !dumpStatus.empty())
49935440d18SAsmitha Karunanithi                 {
50035440d18SAsmitha Karunanithi                     // Dump status is not Complete
50135440d18SAsmitha Karunanithi                     // return not found until status is changed to Completed
502bd79bce8SPatrick Williams                     messages::resourceNotFound(asyncResp->res,
503bd79bce8SPatrick Williams                                                dumpType + " dump", entryID);
50435440d18SAsmitha Karunanithi                     return;
50535440d18SAsmitha Karunanithi                 }
50635440d18SAsmitha Karunanithi 
5075cb1dd27SAsmitha Karunanithi                 asyncResp->res.jsonValue["@odata.type"] =
50868dd075aSAsmitha Karunanithi                     "#LogEntry.v1_11_0.LogEntry";
509fdd26906SClaire Weinan                 asyncResp->res.jsonValue["@odata.id"] = entriesPath + entryID;
5105cb1dd27SAsmitha Karunanithi                 asyncResp->res.jsonValue["Id"] = entryID;
5115cb1dd27SAsmitha Karunanithi                 asyncResp->res.jsonValue["EntryType"] = "Event";
5125cb1dd27SAsmitha Karunanithi                 asyncResp->res.jsonValue["Name"] = dumpType + " Dump Entry";
513bbd80db8SClaire Weinan                 asyncResp->res.jsonValue["Created"] =
514bbd80db8SClaire Weinan                     redfish::time_utils::getDateTimeUintUs(timestampUs);
5155cb1dd27SAsmitha Karunanithi 
51668dd075aSAsmitha Karunanithi                 if (!originatorId.empty())
51768dd075aSAsmitha Karunanithi                 {
51868dd075aSAsmitha Karunanithi                     asyncResp->res.jsonValue["Originator"] = originatorId;
51968dd075aSAsmitha Karunanithi                     asyncResp->res.jsonValue["OriginatorType"] = originatorType;
52068dd075aSAsmitha Karunanithi                 }
52168dd075aSAsmitha Karunanithi 
5225cb1dd27SAsmitha Karunanithi                 if (dumpType == "BMC")
5235cb1dd27SAsmitha Karunanithi                 {
524d337bb72SAsmitha Karunanithi                     asyncResp->res.jsonValue["DiagnosticDataType"] = "Manager";
525d337bb72SAsmitha Karunanithi                     asyncResp->res.jsonValue["AdditionalDataURI"] =
526fdd26906SClaire Weinan                         entriesPath + entryID + "/attachment";
527fdd26906SClaire Weinan                     asyncResp->res.jsonValue["AdditionalDataSizeBytes"] = size;
5285cb1dd27SAsmitha Karunanithi                 }
5295cb1dd27SAsmitha Karunanithi                 else if (dumpType == "System")
5305cb1dd27SAsmitha Karunanithi                 {
531d337bb72SAsmitha Karunanithi                     asyncResp->res.jsonValue["DiagnosticDataType"] = "OEM";
532bd79bce8SPatrick Williams                     asyncResp->res.jsonValue["OEMDiagnosticDataType"] =
533bd79bce8SPatrick Williams                         "System";
534d337bb72SAsmitha Karunanithi                     asyncResp->res.jsonValue["AdditionalDataURI"] =
535fdd26906SClaire Weinan                         entriesPath + entryID + "/attachment";
536fdd26906SClaire Weinan                     asyncResp->res.jsonValue["AdditionalDataSizeBytes"] = size;
5375cb1dd27SAsmitha Karunanithi                 }
5385cb1dd27SAsmitha Karunanithi             }
539e05aec50SEd Tanous             if (!foundDumpEntry)
540b47452b2SAsmitha Karunanithi             {
54162598e31SEd Tanous                 BMCWEB_LOG_WARNING("Can't find Dump Entry {}", entryID);
542b90d14f2SMyung Bae                 messages::resourceNotFound(asyncResp->res, dumpType + " dump",
543b90d14f2SMyung Bae                                            entryID);
544b47452b2SAsmitha Karunanithi                 return;
545b47452b2SAsmitha Karunanithi             }
5465eb468daSGeorge Liu         });
5475cb1dd27SAsmitha Karunanithi }
5485cb1dd27SAsmitha Karunanithi 
5498d1b46d7Szhanghch05 inline void deleteDumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
5509878256fSStanley Chu                             const std::string& entryID,
551b47452b2SAsmitha Karunanithi                             const std::string& dumpType)
5525cb1dd27SAsmitha Karunanithi {
5535a39f77aSPatrick Williams     auto respHandler = [asyncResp,
5545a39f77aSPatrick Williams                         entryID](const boost::system::error_code& ec) {
55562598e31SEd Tanous         BMCWEB_LOG_DEBUG("Dump Entry doDelete callback: Done");
5565cb1dd27SAsmitha Karunanithi         if (ec)
5575cb1dd27SAsmitha Karunanithi         {
5583de8d8baSGeorge Liu             if (ec.value() == EBADR)
5593de8d8baSGeorge Liu             {
5603de8d8baSGeorge Liu                 messages::resourceNotFound(asyncResp->res, "LogEntry", entryID);
5613de8d8baSGeorge Liu                 return;
5623de8d8baSGeorge Liu             }
56362598e31SEd Tanous             BMCWEB_LOG_ERROR(
56462598e31SEd Tanous                 "Dump (DBus) doDelete respHandler got error {} entryID={}", ec,
56562598e31SEd Tanous                 entryID);
5665cb1dd27SAsmitha Karunanithi             messages::internalError(asyncResp->res);
5675cb1dd27SAsmitha Karunanithi             return;
5685cb1dd27SAsmitha Karunanithi         }
5695cb1dd27SAsmitha Karunanithi     };
57018f8f608SEd Tanous 
5715cb1dd27SAsmitha Karunanithi     crow::connections::systemBus->async_method_call(
5725cb1dd27SAsmitha Karunanithi         respHandler, "xyz.openbmc_project.Dump.Manager",
57318f8f608SEd Tanous         std::format("{}/entry/{}", getDumpPath(dumpType), entryID),
5745cb1dd27SAsmitha Karunanithi         "xyz.openbmc_project.Object.Delete", "Delete");
5755cb1dd27SAsmitha Karunanithi }
576b5f288d2SAbhilash Raju inline bool checkSizeLimit(int fd, crow::Response& res)
577b5f288d2SAbhilash Raju {
578b5f288d2SAbhilash Raju     long long int size = lseek(fd, 0, SEEK_END);
579b5f288d2SAbhilash Raju     if (size <= 0)
580b5f288d2SAbhilash Raju     {
581b5f288d2SAbhilash Raju         BMCWEB_LOG_ERROR("Failed to get size of file, lseek() returned {}",
582b5f288d2SAbhilash Raju                          size);
583b5f288d2SAbhilash Raju         messages::internalError(res);
584b5f288d2SAbhilash Raju         return false;
585b5f288d2SAbhilash Raju     }
5865cb1dd27SAsmitha Karunanithi 
587b5f288d2SAbhilash Raju     // Arbitrary max size of 20MB to accommodate BMC dumps
588b5f288d2SAbhilash Raju     constexpr long long int maxFileSize = 20LL * 1024LL * 1024LL;
589b5f288d2SAbhilash Raju     if (size > maxFileSize)
590b5f288d2SAbhilash Raju     {
591b5f288d2SAbhilash Raju         BMCWEB_LOG_ERROR("File size {} exceeds maximum allowed size of {}",
592b5f288d2SAbhilash Raju                          size, maxFileSize);
593b5f288d2SAbhilash Raju         messages::internalError(res);
594b5f288d2SAbhilash Raju         return false;
595b5f288d2SAbhilash Raju     }
596b5f288d2SAbhilash Raju     off_t rc = lseek(fd, 0, SEEK_SET);
597b5f288d2SAbhilash Raju     if (rc < 0)
598b5f288d2SAbhilash Raju     {
599b5f288d2SAbhilash Raju         BMCWEB_LOG_ERROR("Failed to reset file offset to 0");
600b5f288d2SAbhilash Raju         messages::internalError(res);
601b5f288d2SAbhilash Raju         return false;
602b5f288d2SAbhilash Raju     }
603b5f288d2SAbhilash Raju     return true;
604b5f288d2SAbhilash Raju }
605bd79bce8SPatrick Williams inline void downloadEntryCallback(
606bd79bce8SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
607bd79bce8SPatrick Williams     const std::string& entryID, const std::string& downloadEntryType,
608168d1b1aSCarson Labrado     const boost::system::error_code& ec,
609168d1b1aSCarson Labrado     const sdbusplus::message::unix_fd& unixfd)
610168d1b1aSCarson Labrado {
611168d1b1aSCarson Labrado     if (ec.value() == EBADR)
612168d1b1aSCarson Labrado     {
613168d1b1aSCarson Labrado         messages::resourceNotFound(asyncResp->res, "EntryAttachment", entryID);
614168d1b1aSCarson Labrado         return;
615168d1b1aSCarson Labrado     }
616168d1b1aSCarson Labrado     if (ec)
617168d1b1aSCarson Labrado     {
618168d1b1aSCarson Labrado         BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
619168d1b1aSCarson Labrado         messages::internalError(asyncResp->res);
620168d1b1aSCarson Labrado         return;
621168d1b1aSCarson Labrado     }
622168d1b1aSCarson Labrado 
623168d1b1aSCarson Labrado     // Make sure we know how to process the retrieved entry attachment
624168d1b1aSCarson Labrado     if ((downloadEntryType != "BMC") && (downloadEntryType != "System"))
625168d1b1aSCarson Labrado     {
626168d1b1aSCarson Labrado         BMCWEB_LOG_ERROR("downloadEntryCallback() invalid entry type: {}",
627168d1b1aSCarson Labrado                          downloadEntryType);
628168d1b1aSCarson Labrado         messages::internalError(asyncResp->res);
629168d1b1aSCarson Labrado     }
630168d1b1aSCarson Labrado 
631168d1b1aSCarson Labrado     int fd = -1;
632168d1b1aSCarson Labrado     fd = dup(unixfd);
633168d1b1aSCarson Labrado     if (fd < 0)
634168d1b1aSCarson Labrado     {
635168d1b1aSCarson Labrado         BMCWEB_LOG_ERROR("Failed to open file");
636168d1b1aSCarson Labrado         messages::internalError(asyncResp->res);
637168d1b1aSCarson Labrado         return;
638168d1b1aSCarson Labrado     }
639b5f288d2SAbhilash Raju     if (!checkSizeLimit(fd, asyncResp->res))
640168d1b1aSCarson Labrado     {
641168d1b1aSCarson Labrado         close(fd);
642168d1b1aSCarson Labrado         return;
643168d1b1aSCarson Labrado     }
644168d1b1aSCarson Labrado     if (downloadEntryType == "System")
645168d1b1aSCarson Labrado     {
646b5f288d2SAbhilash Raju         if (!asyncResp->res.openFd(fd, bmcweb::EncodingType::Base64))
647b5f288d2SAbhilash Raju         {
648b5f288d2SAbhilash Raju             messages::internalError(asyncResp->res);
649b5f288d2SAbhilash Raju             close(fd);
650b5f288d2SAbhilash Raju             return;
651b5f288d2SAbhilash Raju         }
652168d1b1aSCarson Labrado         asyncResp->res.addHeader(
653168d1b1aSCarson Labrado             boost::beast::http::field::content_transfer_encoding, "Base64");
654b5f288d2SAbhilash Raju         return;
655168d1b1aSCarson Labrado     }
656b5f288d2SAbhilash Raju     if (!asyncResp->res.openFd(fd))
65727b0cf90SEd Tanous     {
658b5f288d2SAbhilash Raju         messages::internalError(asyncResp->res);
659b5f288d2SAbhilash Raju         close(fd);
660b5f288d2SAbhilash Raju         return;
66127b0cf90SEd Tanous     }
662168d1b1aSCarson Labrado     asyncResp->res.addHeader(boost::beast::http::field::content_type,
663168d1b1aSCarson Labrado                              "application/octet-stream");
664168d1b1aSCarson Labrado }
665168d1b1aSCarson Labrado 
666168d1b1aSCarson Labrado inline void
667168d1b1aSCarson Labrado     downloadDumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
668168d1b1aSCarson Labrado                       const std::string& entryID, const std::string& dumpType)
669168d1b1aSCarson Labrado {
670168d1b1aSCarson Labrado     if (dumpType != "BMC")
671168d1b1aSCarson Labrado     {
672168d1b1aSCarson Labrado         BMCWEB_LOG_WARNING("Can't find Dump Entry {}", entryID);
673168d1b1aSCarson Labrado         messages::resourceNotFound(asyncResp->res, dumpType + " dump", entryID);
674168d1b1aSCarson Labrado         return;
675168d1b1aSCarson Labrado     }
676168d1b1aSCarson Labrado 
677bd79bce8SPatrick Williams     std::string dumpEntryPath =
678bd79bce8SPatrick Williams         std::format("{}/entry/{}", getDumpPath(dumpType), entryID);
679168d1b1aSCarson Labrado 
680168d1b1aSCarson Labrado     auto downloadDumpEntryHandler =
681168d1b1aSCarson Labrado         [asyncResp, entryID,
682168d1b1aSCarson Labrado          dumpType](const boost::system::error_code& ec,
683168d1b1aSCarson Labrado                    const sdbusplus::message::unix_fd& unixfd) {
684168d1b1aSCarson Labrado             downloadEntryCallback(asyncResp, entryID, dumpType, ec, unixfd);
685168d1b1aSCarson Labrado         };
686168d1b1aSCarson Labrado 
687168d1b1aSCarson Labrado     crow::connections::systemBus->async_method_call(
688168d1b1aSCarson Labrado         std::move(downloadDumpEntryHandler), "xyz.openbmc_project.Dump.Manager",
689168d1b1aSCarson Labrado         dumpEntryPath, "xyz.openbmc_project.Dump.Entry", "GetFileHandle");
690168d1b1aSCarson Labrado }
691168d1b1aSCarson Labrado 
692bd79bce8SPatrick Williams inline void downloadEventLogEntry(
693bd79bce8SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
694bd79bce8SPatrick Williams     const std::string& systemName, const std::string& entryID,
695168d1b1aSCarson Labrado     const std::string& dumpType)
696168d1b1aSCarson Labrado {
69725b54dbaSEd Tanous     if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
698168d1b1aSCarson Labrado     {
699168d1b1aSCarson Labrado         // Option currently returns no systems.  TBD
700168d1b1aSCarson Labrado         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
701168d1b1aSCarson Labrado                                    systemName);
702168d1b1aSCarson Labrado         return;
703168d1b1aSCarson Labrado     }
704253f11b8SEd Tanous     if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
705168d1b1aSCarson Labrado     {
706168d1b1aSCarson Labrado         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
707168d1b1aSCarson Labrado                                    systemName);
708168d1b1aSCarson Labrado         return;
709168d1b1aSCarson Labrado     }
710168d1b1aSCarson Labrado 
711168d1b1aSCarson Labrado     std::string entryPath =
712168d1b1aSCarson Labrado         sdbusplus::message::object_path("/xyz/openbmc_project/logging/entry") /
713168d1b1aSCarson Labrado         entryID;
714168d1b1aSCarson Labrado 
715168d1b1aSCarson Labrado     auto downloadEventLogEntryHandler =
716168d1b1aSCarson Labrado         [asyncResp, entryID,
717168d1b1aSCarson Labrado          dumpType](const boost::system::error_code& ec,
718168d1b1aSCarson Labrado                    const sdbusplus::message::unix_fd& unixfd) {
719168d1b1aSCarson Labrado             downloadEntryCallback(asyncResp, entryID, dumpType, ec, unixfd);
720168d1b1aSCarson Labrado         };
721168d1b1aSCarson Labrado 
722168d1b1aSCarson Labrado     crow::connections::systemBus->async_method_call(
723168d1b1aSCarson Labrado         std::move(downloadEventLogEntryHandler), "xyz.openbmc_project.Logging",
724168d1b1aSCarson Labrado         entryPath, "xyz.openbmc_project.Logging.Entry", "GetEntry");
725168d1b1aSCarson Labrado }
726168d1b1aSCarson Labrado 
7278e31778eSAsmitha Karunanithi inline DumpCreationProgress
7288e31778eSAsmitha Karunanithi     mapDbusStatusToDumpProgress(const std::string& status)
729a43be80fSAsmitha Karunanithi {
7308e31778eSAsmitha Karunanithi     if (status ==
7318e31778eSAsmitha Karunanithi             "xyz.openbmc_project.Common.Progress.OperationStatus.Failed" ||
7328e31778eSAsmitha Karunanithi         status == "xyz.openbmc_project.Common.Progress.OperationStatus.Aborted")
7338e31778eSAsmitha Karunanithi     {
7348e31778eSAsmitha Karunanithi         return DumpCreationProgress::DUMP_CREATE_FAILED;
7358e31778eSAsmitha Karunanithi     }
7368e31778eSAsmitha Karunanithi     if (status ==
7378e31778eSAsmitha Karunanithi         "xyz.openbmc_project.Common.Progress.OperationStatus.Completed")
7388e31778eSAsmitha Karunanithi     {
7398e31778eSAsmitha Karunanithi         return DumpCreationProgress::DUMP_CREATE_SUCCESS;
7408e31778eSAsmitha Karunanithi     }
7418e31778eSAsmitha Karunanithi     return DumpCreationProgress::DUMP_CREATE_INPROGRESS;
7428e31778eSAsmitha Karunanithi }
7438e31778eSAsmitha Karunanithi 
7448e31778eSAsmitha Karunanithi inline DumpCreationProgress
7458e31778eSAsmitha Karunanithi     getDumpCompletionStatus(const dbus::utility::DBusPropertiesMap& values)
7468e31778eSAsmitha Karunanithi {
7478e31778eSAsmitha Karunanithi     for (const auto& [key, val] : values)
7488e31778eSAsmitha Karunanithi     {
7498e31778eSAsmitha Karunanithi         if (key == "Status")
7508e31778eSAsmitha Karunanithi         {
7518e31778eSAsmitha Karunanithi             const std::string* value = std::get_if<std::string>(&val);
7528e31778eSAsmitha Karunanithi             if (value == nullptr)
7538e31778eSAsmitha Karunanithi             {
75462598e31SEd Tanous                 BMCWEB_LOG_ERROR("Status property value is null");
7558e31778eSAsmitha Karunanithi                 return DumpCreationProgress::DUMP_CREATE_FAILED;
7568e31778eSAsmitha Karunanithi             }
7578e31778eSAsmitha Karunanithi             return mapDbusStatusToDumpProgress(*value);
7588e31778eSAsmitha Karunanithi         }
7598e31778eSAsmitha Karunanithi     }
7608e31778eSAsmitha Karunanithi     return DumpCreationProgress::DUMP_CREATE_INPROGRESS;
7618e31778eSAsmitha Karunanithi }
7628e31778eSAsmitha Karunanithi 
7638e31778eSAsmitha Karunanithi inline std::string getDumpEntryPath(const std::string& dumpPath)
7648e31778eSAsmitha Karunanithi {
7658e31778eSAsmitha Karunanithi     if (dumpPath == "/xyz/openbmc_project/dump/bmc/entry")
7668e31778eSAsmitha Karunanithi     {
767253f11b8SEd Tanous         return std::format("/redfish/v1/Managers/{}/LogServices/Dump/Entries/",
7689f565090SEd Tanous                            BMCWEB_REDFISH_MANAGER_URI_NAME);
7698e31778eSAsmitha Karunanithi     }
7708e31778eSAsmitha Karunanithi     if (dumpPath == "/xyz/openbmc_project/dump/system/entry")
7718e31778eSAsmitha Karunanithi     {
772253f11b8SEd Tanous         return std::format("/redfish/v1/Systems/{}/LogServices/Dump/Entries/",
773253f11b8SEd Tanous                            BMCWEB_REDFISH_SYSTEM_URI_NAME);
7748e31778eSAsmitha Karunanithi     }
7758e31778eSAsmitha Karunanithi     return "";
7768e31778eSAsmitha Karunanithi }
7778e31778eSAsmitha Karunanithi 
7788e31778eSAsmitha Karunanithi inline void createDumpTaskCallback(
7798e31778eSAsmitha Karunanithi     task::Payload&& payload,
7808e31778eSAsmitha Karunanithi     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
7818e31778eSAsmitha Karunanithi     const sdbusplus::message::object_path& createdObjPath)
7828e31778eSAsmitha Karunanithi {
7838e31778eSAsmitha Karunanithi     const std::string dumpPath = createdObjPath.parent_path().str;
7848e31778eSAsmitha Karunanithi     const std::string dumpId = createdObjPath.filename();
7858e31778eSAsmitha Karunanithi 
7868e31778eSAsmitha Karunanithi     std::string dumpEntryPath = getDumpEntryPath(dumpPath);
7878e31778eSAsmitha Karunanithi 
7888e31778eSAsmitha Karunanithi     if (dumpEntryPath.empty())
7898e31778eSAsmitha Karunanithi     {
79062598e31SEd Tanous         BMCWEB_LOG_ERROR("Invalid dump type received");
7918e31778eSAsmitha Karunanithi         messages::internalError(asyncResp->res);
7928e31778eSAsmitha Karunanithi         return;
7938e31778eSAsmitha Karunanithi     }
7948e31778eSAsmitha Karunanithi 
7958e31778eSAsmitha Karunanithi     crow::connections::systemBus->async_method_call(
7968cb2c024SEd Tanous         [asyncResp, payload = std::move(payload), createdObjPath,
7978e31778eSAsmitha Karunanithi          dumpEntryPath{std::move(dumpEntryPath)},
7985e7e2dc5SEd Tanous          dumpId](const boost::system::error_code& ec,
7998e31778eSAsmitha Karunanithi                  const std::string& introspectXml) {
8008e31778eSAsmitha Karunanithi             if (ec)
8018e31778eSAsmitha Karunanithi             {
80262598e31SEd Tanous                 BMCWEB_LOG_ERROR("Introspect call failed with error: {}",
80362598e31SEd Tanous                                  ec.message());
8048e31778eSAsmitha Karunanithi                 messages::internalError(asyncResp->res);
8058e31778eSAsmitha Karunanithi                 return;
8068e31778eSAsmitha Karunanithi             }
8078e31778eSAsmitha Karunanithi 
8088e31778eSAsmitha Karunanithi             // Check if the created dump object has implemented Progress
8098e31778eSAsmitha Karunanithi             // interface to track dump completion. If yes, fetch the "Status"
8108e31778eSAsmitha Karunanithi             // property of the interface, modify the task state accordingly.
8118e31778eSAsmitha Karunanithi             // Else, return task completed.
8128e31778eSAsmitha Karunanithi             tinyxml2::XMLDocument doc;
8138e31778eSAsmitha Karunanithi 
8148e31778eSAsmitha Karunanithi             doc.Parse(introspectXml.data(), introspectXml.size());
8158e31778eSAsmitha Karunanithi             tinyxml2::XMLNode* pRoot = doc.FirstChildElement("node");
8168e31778eSAsmitha Karunanithi             if (pRoot == nullptr)
8178e31778eSAsmitha Karunanithi             {
81862598e31SEd Tanous                 BMCWEB_LOG_ERROR("XML document failed to parse");
8198e31778eSAsmitha Karunanithi                 messages::internalError(asyncResp->res);
8208e31778eSAsmitha Karunanithi                 return;
8218e31778eSAsmitha Karunanithi             }
8228e31778eSAsmitha Karunanithi             tinyxml2::XMLElement* interfaceNode =
8238e31778eSAsmitha Karunanithi                 pRoot->FirstChildElement("interface");
8248e31778eSAsmitha Karunanithi 
8258e31778eSAsmitha Karunanithi             bool isProgressIntfPresent = false;
8268e31778eSAsmitha Karunanithi             while (interfaceNode != nullptr)
8278e31778eSAsmitha Karunanithi             {
828bd79bce8SPatrick Williams                 const char* thisInterfaceName =
829bd79bce8SPatrick Williams                     interfaceNode->Attribute("name");
8308e31778eSAsmitha Karunanithi                 if (thisInterfaceName != nullptr)
8318e31778eSAsmitha Karunanithi                 {
8328e31778eSAsmitha Karunanithi                     if (thisInterfaceName ==
8338e31778eSAsmitha Karunanithi                         std::string_view("xyz.openbmc_project.Common.Progress"))
8348e31778eSAsmitha Karunanithi                     {
8358e31778eSAsmitha Karunanithi                         interfaceNode =
8368e31778eSAsmitha Karunanithi                             interfaceNode->NextSiblingElement("interface");
8378e31778eSAsmitha Karunanithi                         continue;
8388e31778eSAsmitha Karunanithi                     }
8398e31778eSAsmitha Karunanithi                     isProgressIntfPresent = true;
8408e31778eSAsmitha Karunanithi                     break;
8418e31778eSAsmitha Karunanithi                 }
8428e31778eSAsmitha Karunanithi                 interfaceNode = interfaceNode->NextSiblingElement("interface");
8438e31778eSAsmitha Karunanithi             }
8448e31778eSAsmitha Karunanithi 
845a43be80fSAsmitha Karunanithi             std::shared_ptr<task::TaskData> task = task::TaskData::createTask(
8468e31778eSAsmitha Karunanithi                 [createdObjPath, dumpEntryPath, dumpId, isProgressIntfPresent](
847bd79bce8SPatrick Williams                     const boost::system::error_code& ec2,
848bd79bce8SPatrick Williams                     sdbusplus::message_t& msg,
849a43be80fSAsmitha Karunanithi                     const std::shared_ptr<task::TaskData>& taskData) {
8508b24275dSEd Tanous                     if (ec2)
851cb13a392SEd Tanous                     {
85262598e31SEd Tanous                         BMCWEB_LOG_ERROR("{}: Error in creating dump",
85362598e31SEd Tanous                                          createdObjPath.str);
854bd79bce8SPatrick Williams                         taskData->messages.emplace_back(
855bd79bce8SPatrick Williams                             messages::internalError());
8566145ed6fSAsmitha Karunanithi                         taskData->state = "Cancelled";
8576145ed6fSAsmitha Karunanithi                         return task::completed;
858cb13a392SEd Tanous                     }
859b9d36b47SEd Tanous 
8608e31778eSAsmitha Karunanithi                     if (isProgressIntfPresent)
861a43be80fSAsmitha Karunanithi                     {
8628e31778eSAsmitha Karunanithi                         dbus::utility::DBusPropertiesMap values;
8638e31778eSAsmitha Karunanithi                         std::string prop;
8648e31778eSAsmitha Karunanithi                         msg.read(prop, values);
8658e31778eSAsmitha Karunanithi 
8668e31778eSAsmitha Karunanithi                         DumpCreationProgress dumpStatus =
8678e31778eSAsmitha Karunanithi                             getDumpCompletionStatus(values);
868bd79bce8SPatrick Williams                         if (dumpStatus ==
869bd79bce8SPatrick Williams                             DumpCreationProgress::DUMP_CREATE_FAILED)
8708e31778eSAsmitha Karunanithi                         {
87162598e31SEd Tanous                             BMCWEB_LOG_ERROR("{}: Error in creating dump",
87262598e31SEd Tanous                                              createdObjPath.str);
8738e31778eSAsmitha Karunanithi                             taskData->state = "Cancelled";
8748e31778eSAsmitha Karunanithi                             return task::completed;
8758e31778eSAsmitha Karunanithi                         }
8768e31778eSAsmitha Karunanithi 
877bd79bce8SPatrick Williams                         if (dumpStatus ==
878bd79bce8SPatrick Williams                             DumpCreationProgress::DUMP_CREATE_INPROGRESS)
8798e31778eSAsmitha Karunanithi                         {
880bd79bce8SPatrick Williams                             BMCWEB_LOG_DEBUG(
881bd79bce8SPatrick Williams                                 "{}: Dump creation task is in progress",
88262598e31SEd Tanous                                 createdObjPath.str);
8838e31778eSAsmitha Karunanithi                             return !task::completed;
8848e31778eSAsmitha Karunanithi                         }
8858e31778eSAsmitha Karunanithi                     }
8868e31778eSAsmitha Karunanithi 
887a43be80fSAsmitha Karunanithi                     nlohmann::json retMessage = messages::success();
888a43be80fSAsmitha Karunanithi                     taskData->messages.emplace_back(retMessage);
889a43be80fSAsmitha Karunanithi 
890c51a58eeSEd Tanous                     boost::urls::url url = boost::urls::format(
891253f11b8SEd Tanous                         "/redfish/v1/Managers/{}/LogServices/Dump/Entries/{}",
892253f11b8SEd Tanous                         BMCWEB_REDFISH_MANAGER_URI_NAME, dumpId);
893c51a58eeSEd Tanous 
894c51a58eeSEd Tanous                     std::string headerLoc = "Location: ";
895c51a58eeSEd Tanous                     headerLoc += url.buffer();
896c51a58eeSEd Tanous 
897bd79bce8SPatrick Williams                     taskData->payload->httpHeaders.emplace_back(
898bd79bce8SPatrick Williams                         std::move(headerLoc));
899a43be80fSAsmitha Karunanithi 
90062598e31SEd Tanous                     BMCWEB_LOG_DEBUG("{}: Dump creation task completed",
90162598e31SEd Tanous                                      createdObjPath.str);
902a43be80fSAsmitha Karunanithi                     taskData->state = "Completed";
903b47452b2SAsmitha Karunanithi                     return task::completed;
904a43be80fSAsmitha Karunanithi                 },
9058e31778eSAsmitha Karunanithi                 "type='signal',interface='org.freedesktop.DBus.Properties',"
9068e31778eSAsmitha Karunanithi                 "member='PropertiesChanged',path='" +
9078e31778eSAsmitha Karunanithi                     createdObjPath.str + "'");
908a43be80fSAsmitha Karunanithi 
9098e31778eSAsmitha Karunanithi             // The task timer is set to max time limit within which the
9108e31778eSAsmitha Karunanithi             // requested dump will be collected.
9118e31778eSAsmitha Karunanithi             task->startTimer(std::chrono::minutes(6));
912a43be80fSAsmitha Karunanithi             task->populateResp(asyncResp->res);
9138e31778eSAsmitha Karunanithi             task->payload.emplace(payload);
9148e31778eSAsmitha Karunanithi         },
9158e31778eSAsmitha Karunanithi         "xyz.openbmc_project.Dump.Manager", createdObjPath,
9168e31778eSAsmitha Karunanithi         "org.freedesktop.DBus.Introspectable", "Introspect");
917a43be80fSAsmitha Karunanithi }
918a43be80fSAsmitha Karunanithi 
9198d1b46d7Szhanghch05 inline void createDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
9208d1b46d7Szhanghch05                        const crow::Request& req, const std::string& dumpType)
921a43be80fSAsmitha Karunanithi {
922fdd26906SClaire Weinan     std::string dumpPath = getDumpEntriesPath(dumpType);
923fdd26906SClaire Weinan     if (dumpPath.empty())
924a43be80fSAsmitha Karunanithi     {
925a43be80fSAsmitha Karunanithi         messages::internalError(asyncResp->res);
926a43be80fSAsmitha Karunanithi         return;
927a43be80fSAsmitha Karunanithi     }
928a43be80fSAsmitha Karunanithi 
929a43be80fSAsmitha Karunanithi     std::optional<std::string> diagnosticDataType;
930a43be80fSAsmitha Karunanithi     std::optional<std::string> oemDiagnosticDataType;
931a43be80fSAsmitha Karunanithi 
932afc474aeSMyung Bae     if (!redfish::json_util::readJsonAction( //
933afc474aeSMyung Bae             req, asyncResp->res, //
934afc474aeSMyung Bae             "DiagnosticDataType", diagnosticDataType, //
935afc474aeSMyung Bae             "OEMDiagnosticDataType", oemDiagnosticDataType //
936afc474aeSMyung Bae             ))
937a43be80fSAsmitha Karunanithi     {
938a43be80fSAsmitha Karunanithi         return;
939a43be80fSAsmitha Karunanithi     }
940a43be80fSAsmitha Karunanithi 
941a43be80fSAsmitha Karunanithi     if (dumpType == "System")
942a43be80fSAsmitha Karunanithi     {
943a43be80fSAsmitha Karunanithi         if (!oemDiagnosticDataType || !diagnosticDataType)
944a43be80fSAsmitha Karunanithi         {
94562598e31SEd Tanous             BMCWEB_LOG_ERROR(
94662598e31SEd Tanous                 "CreateDump action parameter 'DiagnosticDataType'/'OEMDiagnosticDataType' value not found!");
947a43be80fSAsmitha Karunanithi             messages::actionParameterMissing(
948a43be80fSAsmitha Karunanithi                 asyncResp->res, "CollectDiagnosticData",
949a43be80fSAsmitha Karunanithi                 "DiagnosticDataType & OEMDiagnosticDataType");
950a43be80fSAsmitha Karunanithi             return;
951a43be80fSAsmitha Karunanithi         }
9523174e4dfSEd Tanous         if ((*oemDiagnosticDataType != "System") ||
953a43be80fSAsmitha Karunanithi             (*diagnosticDataType != "OEM"))
954a43be80fSAsmitha Karunanithi         {
95562598e31SEd Tanous             BMCWEB_LOG_ERROR("Wrong parameter values passed");
956ace85d60SEd Tanous             messages::internalError(asyncResp->res);
957a43be80fSAsmitha Karunanithi             return;
958a43be80fSAsmitha Karunanithi         }
959253f11b8SEd Tanous         dumpPath = std::format("/redfish/v1/Systems/{}/LogServices/Dump/",
960253f11b8SEd Tanous                                BMCWEB_REDFISH_SYSTEM_URI_NAME);
961a43be80fSAsmitha Karunanithi     }
962a43be80fSAsmitha Karunanithi     else if (dumpType == "BMC")
963a43be80fSAsmitha Karunanithi     {
964a43be80fSAsmitha Karunanithi         if (!diagnosticDataType)
965a43be80fSAsmitha Karunanithi         {
96662598e31SEd Tanous             BMCWEB_LOG_ERROR(
96762598e31SEd Tanous                 "CreateDump action parameter 'DiagnosticDataType' not found!");
968a43be80fSAsmitha Karunanithi             messages::actionParameterMissing(
969a43be80fSAsmitha Karunanithi                 asyncResp->res, "CollectDiagnosticData", "DiagnosticDataType");
970a43be80fSAsmitha Karunanithi             return;
971a43be80fSAsmitha Karunanithi         }
9723174e4dfSEd Tanous         if (*diagnosticDataType != "Manager")
973a43be80fSAsmitha Karunanithi         {
97462598e31SEd Tanous             BMCWEB_LOG_ERROR(
97562598e31SEd Tanous                 "Wrong parameter value passed for 'DiagnosticDataType'");
976ace85d60SEd Tanous             messages::internalError(asyncResp->res);
977a43be80fSAsmitha Karunanithi             return;
978a43be80fSAsmitha Karunanithi         }
979253f11b8SEd Tanous         dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/Dump/",
980253f11b8SEd Tanous                                BMCWEB_REDFISH_MANAGER_URI_NAME);
9815907571dSAsmitha Karunanithi     }
9825907571dSAsmitha Karunanithi     else
9835907571dSAsmitha Karunanithi     {
98462598e31SEd Tanous         BMCWEB_LOG_ERROR("CreateDump failed. Unknown dump type");
9855907571dSAsmitha Karunanithi         messages::internalError(asyncResp->res);
9865907571dSAsmitha Karunanithi         return;
987a43be80fSAsmitha Karunanithi     }
988a43be80fSAsmitha Karunanithi 
9898e31778eSAsmitha Karunanithi     std::vector<std::pair<std::string, std::variant<std::string, uint64_t>>>
9908e31778eSAsmitha Karunanithi         createDumpParamVec;
9918e31778eSAsmitha Karunanithi 
992f574a8e1SCarson Labrado     if (req.session != nullptr)
993f574a8e1SCarson Labrado     {
99468dd075aSAsmitha Karunanithi         createDumpParamVec.emplace_back(
99568dd075aSAsmitha Karunanithi             "xyz.openbmc_project.Dump.Create.CreateParameters.OriginatorId",
99668dd075aSAsmitha Karunanithi             req.session->clientIp);
99768dd075aSAsmitha Karunanithi         createDumpParamVec.emplace_back(
99868dd075aSAsmitha Karunanithi             "xyz.openbmc_project.Dump.Create.CreateParameters.OriginatorType",
99968dd075aSAsmitha Karunanithi             "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Client");
1000f574a8e1SCarson Labrado     }
100168dd075aSAsmitha Karunanithi 
1002a43be80fSAsmitha Karunanithi     crow::connections::systemBus->async_method_call(
10035e7e2dc5SEd Tanous         [asyncResp, payload(task::Payload(req)),
10045e7e2dc5SEd Tanous          dumpPath](const boost::system::error_code& ec,
10055e7e2dc5SEd Tanous                    const sdbusplus::message_t& msg,
10068e31778eSAsmitha Karunanithi                    const sdbusplus::message::object_path& objPath) mutable {
1007a43be80fSAsmitha Karunanithi             if (ec)
1008a43be80fSAsmitha Karunanithi             {
100962598e31SEd Tanous                 BMCWEB_LOG_ERROR("CreateDump resp_handler got error {}", ec);
10105907571dSAsmitha Karunanithi                 const sd_bus_error* dbusError = msg.get_error();
10115907571dSAsmitha Karunanithi                 if (dbusError == nullptr)
10125907571dSAsmitha Karunanithi                 {
10135907571dSAsmitha Karunanithi                     messages::internalError(asyncResp->res);
10145907571dSAsmitha Karunanithi                     return;
10155907571dSAsmitha Karunanithi                 }
10165907571dSAsmitha Karunanithi 
101762598e31SEd Tanous                 BMCWEB_LOG_ERROR("CreateDump DBus error: {} and error msg: {}",
101862598e31SEd Tanous                                  dbusError->name, dbusError->message);
10195907571dSAsmitha Karunanithi                 if (std::string_view(
10205907571dSAsmitha Karunanithi                         "xyz.openbmc_project.Common.Error.NotAllowed") ==
10215907571dSAsmitha Karunanithi                     dbusError->name)
10225907571dSAsmitha Karunanithi                 {
10235907571dSAsmitha Karunanithi                     messages::resourceInStandby(asyncResp->res);
10245907571dSAsmitha Karunanithi                     return;
10255907571dSAsmitha Karunanithi                 }
10265907571dSAsmitha Karunanithi                 if (std::string_view(
10275907571dSAsmitha Karunanithi                         "xyz.openbmc_project.Dump.Create.Error.Disabled") ==
10285907571dSAsmitha Karunanithi                     dbusError->name)
10295907571dSAsmitha Karunanithi                 {
10305907571dSAsmitha Karunanithi                     messages::serviceDisabled(asyncResp->res, dumpPath);
10315907571dSAsmitha Karunanithi                     return;
10325907571dSAsmitha Karunanithi                 }
10335907571dSAsmitha Karunanithi                 if (std::string_view(
10345907571dSAsmitha Karunanithi                         "xyz.openbmc_project.Common.Error.Unavailable") ==
10355907571dSAsmitha Karunanithi                     dbusError->name)
10365907571dSAsmitha Karunanithi                 {
10375907571dSAsmitha Karunanithi                     messages::resourceInUse(asyncResp->res);
10385907571dSAsmitha Karunanithi                     return;
10395907571dSAsmitha Karunanithi                 }
10405907571dSAsmitha Karunanithi                 // Other Dbus errors such as:
10415907571dSAsmitha Karunanithi                 // xyz.openbmc_project.Common.Error.InvalidArgument &
10425907571dSAsmitha Karunanithi                 // org.freedesktop.DBus.Error.InvalidArgs are all related to
10435907571dSAsmitha Karunanithi                 // the dbus call that is made here in the bmcweb
10445907571dSAsmitha Karunanithi                 // implementation and has nothing to do with the client's
10455907571dSAsmitha Karunanithi                 // input in the request. Hence, returning internal error
10465907571dSAsmitha Karunanithi                 // back to the client.
1047a43be80fSAsmitha Karunanithi                 messages::internalError(asyncResp->res);
1048a43be80fSAsmitha Karunanithi                 return;
1049a43be80fSAsmitha Karunanithi             }
105062598e31SEd Tanous             BMCWEB_LOG_DEBUG("Dump Created. Path: {}", objPath.str);
10518e31778eSAsmitha Karunanithi             createDumpTaskCallback(std::move(payload), asyncResp, objPath);
1052a43be80fSAsmitha Karunanithi         },
105318f8f608SEd Tanous         "xyz.openbmc_project.Dump.Manager", getDumpPath(dumpType),
10548e31778eSAsmitha Karunanithi         "xyz.openbmc_project.Dump.Create", "CreateDump", createDumpParamVec);
1055a43be80fSAsmitha Karunanithi }
1056a43be80fSAsmitha Karunanithi 
10578d1b46d7Szhanghch05 inline void clearDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
10588d1b46d7Szhanghch05                       const std::string& dumpType)
105980319af1SAsmitha Karunanithi {
10600d946211SClaire Weinan     crow::connections::systemBus->async_method_call(
10610d946211SClaire Weinan         [asyncResp](const boost::system::error_code& ec) {
106280319af1SAsmitha Karunanithi             if (ec)
106380319af1SAsmitha Karunanithi             {
106462598e31SEd Tanous                 BMCWEB_LOG_ERROR("clearDump resp_handler got error {}", ec);
106580319af1SAsmitha Karunanithi                 messages::internalError(asyncResp->res);
106680319af1SAsmitha Karunanithi                 return;
106780319af1SAsmitha Karunanithi             }
10680d946211SClaire Weinan         },
106918f8f608SEd Tanous         "xyz.openbmc_project.Dump.Manager", getDumpPath(dumpType),
10700d946211SClaire Weinan         "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
107180319af1SAsmitha Karunanithi }
107280319af1SAsmitha Karunanithi 
1073bd79bce8SPatrick Williams inline void parseCrashdumpParameters(
1074bd79bce8SPatrick Williams     const dbus::utility::DBusPropertiesMap& params, std::string& filename,
1075bd79bce8SPatrick Williams     std::string& timestamp, std::string& logfile)
1076043a0536SJohnathan Mantey {
1077d1bde9e5SKrzysztof Grobelny     const std::string* filenamePtr = nullptr;
1078d1bde9e5SKrzysztof Grobelny     const std::string* timestampPtr = nullptr;
1079d1bde9e5SKrzysztof Grobelny     const std::string* logfilePtr = nullptr;
1080d1bde9e5SKrzysztof Grobelny 
1081d1bde9e5SKrzysztof Grobelny     const bool success = sdbusplus::unpackPropertiesNoThrow(
1082d1bde9e5SKrzysztof Grobelny         dbus_utils::UnpackErrorPrinter(), params, "Timestamp", timestampPtr,
1083d1bde9e5SKrzysztof Grobelny         "Filename", filenamePtr, "Log", logfilePtr);
1084d1bde9e5SKrzysztof Grobelny 
1085d1bde9e5SKrzysztof Grobelny     if (!success)
1086043a0536SJohnathan Mantey     {
1087d1bde9e5SKrzysztof Grobelny         return;
1088043a0536SJohnathan Mantey     }
1089d1bde9e5SKrzysztof Grobelny 
1090d1bde9e5SKrzysztof Grobelny     if (filenamePtr != nullptr)
1091043a0536SJohnathan Mantey     {
1092d1bde9e5SKrzysztof Grobelny         filename = *filenamePtr;
1093d1bde9e5SKrzysztof Grobelny     }
1094d1bde9e5SKrzysztof Grobelny 
1095d1bde9e5SKrzysztof Grobelny     if (timestampPtr != nullptr)
1096043a0536SJohnathan Mantey     {
1097d1bde9e5SKrzysztof Grobelny         timestamp = *timestampPtr;
1098043a0536SJohnathan Mantey     }
1099d1bde9e5SKrzysztof Grobelny 
1100d1bde9e5SKrzysztof Grobelny     if (logfilePtr != nullptr)
1101043a0536SJohnathan Mantey     {
1102d1bde9e5SKrzysztof Grobelny         logfile = *logfilePtr;
1103043a0536SJohnathan Mantey     }
1104043a0536SJohnathan Mantey }
1105043a0536SJohnathan Mantey 
11067e860f15SJohn Edward Broadbent inline void requestRoutesSystemLogServiceCollection(App& app)
11071da66f75SEd Tanous {
1108c4bf6374SJason M. Bills     /**
1109c4bf6374SJason M. Bills      * Functions triggers appropriate requests on DBus
1110c4bf6374SJason M. Bills      */
111122d268cbSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/")
1112ed398213SEd Tanous         .privileges(redfish::privileges::getLogServiceCollection)
1113bd79bce8SPatrick Williams         .methods(
1114bd79bce8SPatrick Williams             boost::beast::http::verb::
1115bd79bce8SPatrick Williams                 get)([&app](const crow::Request& req,
111622d268cbSEd Tanous                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
111722d268cbSEd Tanous                             const std::string& systemName) {
11183ba00073SCarson Labrado             if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1119c4bf6374SJason M. Bills             {
112045ca1b86SEd Tanous                 return;
112145ca1b86SEd Tanous             }
112225b54dbaSEd Tanous             if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
11237f3e84a1SEd Tanous             {
11247f3e84a1SEd Tanous                 // Option currently returns no systems.  TBD
11257f3e84a1SEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
11267f3e84a1SEd Tanous                                            systemName);
11277f3e84a1SEd Tanous                 return;
11287f3e84a1SEd Tanous             }
1129253f11b8SEd Tanous             if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
113022d268cbSEd Tanous             {
113122d268cbSEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
113222d268cbSEd Tanous                                            systemName);
113322d268cbSEd Tanous                 return;
113422d268cbSEd Tanous             }
113522d268cbSEd Tanous 
11367e860f15SJohn Edward Broadbent             // Collections don't include the static data added by SubRoute
11377e860f15SJohn Edward Broadbent             // because it has a duplicate entry for members
1138c4bf6374SJason M. Bills             asyncResp->res.jsonValue["@odata.type"] =
1139c4bf6374SJason M. Bills                 "#LogServiceCollection.LogServiceCollection";
1140c4bf6374SJason M. Bills             asyncResp->res.jsonValue["@odata.id"] =
1141253f11b8SEd Tanous                 std::format("/redfish/v1/Systems/{}/LogServices",
1142253f11b8SEd Tanous                             BMCWEB_REDFISH_SYSTEM_URI_NAME);
114345ca1b86SEd Tanous             asyncResp->res.jsonValue["Name"] = "System Log Services Collection";
1144c4bf6374SJason M. Bills             asyncResp->res.jsonValue["Description"] =
1145c4bf6374SJason M. Bills                 "Collection of LogServices for this Computer System";
1146bd79bce8SPatrick Williams             nlohmann::json& logServiceArray =
1147bd79bce8SPatrick Williams                 asyncResp->res.jsonValue["Members"];
1148c4bf6374SJason M. Bills             logServiceArray = nlohmann::json::array();
11491476687dSEd Tanous             nlohmann::json::object_t eventLog;
11501476687dSEd Tanous             eventLog["@odata.id"] =
1151253f11b8SEd Tanous                 std::format("/redfish/v1/Systems/{}/LogServices/EventLog",
1152253f11b8SEd Tanous                             BMCWEB_REDFISH_SYSTEM_URI_NAME);
1153b2ba3072SPatrick Williams             logServiceArray.emplace_back(std::move(eventLog));
115425b54dbaSEd Tanous             if constexpr (BMCWEB_REDFISH_DUMP_LOG)
115525b54dbaSEd Tanous             {
11561476687dSEd Tanous                 nlohmann::json::object_t dumpLog;
115725b54dbaSEd Tanous                 dumpLog["@odata.id"] =
1158253f11b8SEd Tanous                     std::format("/redfish/v1/Systems/{}/LogServices/Dump",
1159253f11b8SEd Tanous                                 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1160b2ba3072SPatrick Williams                 logServiceArray.emplace_back(std::move(dumpLog));
116125b54dbaSEd Tanous             }
1162c9bb6861Sraviteja-b 
11635ffd11f2SGunnar Mills             if constexpr (BMCWEB_REDFISH_CPU_LOG)
116425b54dbaSEd Tanous             {
11651476687dSEd Tanous                 nlohmann::json::object_t crashdump;
11661476687dSEd Tanous                 crashdump["@odata.id"] =
1167253f11b8SEd Tanous                     std::format("/redfish/v1/Systems/{}/LogServices/Crashdump",
1168253f11b8SEd Tanous                                 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1169b2ba3072SPatrick Williams                 logServiceArray.emplace_back(std::move(crashdump));
117025b54dbaSEd Tanous             }
1171b7028ebfSSpencer Ku 
117225b54dbaSEd Tanous             if constexpr (BMCWEB_REDFISH_HOST_LOGGER)
117325b54dbaSEd Tanous             {
11741476687dSEd Tanous                 nlohmann::json::object_t hostlogger;
11751476687dSEd Tanous                 hostlogger["@odata.id"] =
1176253f11b8SEd Tanous                     std::format("/redfish/v1/Systems/{}/LogServices/HostLogger",
1177253f11b8SEd Tanous                                 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1178b2ba3072SPatrick Williams                 logServiceArray.emplace_back(std::move(hostlogger));
117925b54dbaSEd Tanous             }
1180c4bf6374SJason M. Bills             asyncResp->res.jsonValue["Members@odata.count"] =
1181c4bf6374SJason M. Bills                 logServiceArray.size();
1182a3316fc6SZhikuiRen 
11837a1dbc48SGeorge Liu             constexpr std::array<std::string_view, 1> interfaces = {
11847a1dbc48SGeorge Liu                 "xyz.openbmc_project.State.Boot.PostCode"};
11857a1dbc48SGeorge Liu             dbus::utility::getSubTreePaths(
11867a1dbc48SGeorge Liu                 "/", 0, interfaces,
11877a1dbc48SGeorge Liu                 [asyncResp](const boost::system::error_code& ec,
1188b9d36b47SEd Tanous                             const dbus::utility::MapperGetSubTreePathsResponse&
1189b9d36b47SEd Tanous                                 subtreePath) {
1190a3316fc6SZhikuiRen                     if (ec)
1191a3316fc6SZhikuiRen                     {
119262598e31SEd Tanous                         BMCWEB_LOG_ERROR("{}", ec);
1193a3316fc6SZhikuiRen                         return;
1194a3316fc6SZhikuiRen                     }
1195a3316fc6SZhikuiRen 
119655f79e6fSEd Tanous                     for (const auto& pathStr : subtreePath)
1197a3316fc6SZhikuiRen                     {
1198a3316fc6SZhikuiRen                         if (pathStr.find("PostCode") != std::string::npos)
1199a3316fc6SZhikuiRen                         {
120023a21a1cSEd Tanous                             nlohmann::json& logServiceArrayLocal =
1201a3316fc6SZhikuiRen                                 asyncResp->res.jsonValue["Members"];
1202613dabeaSEd Tanous                             nlohmann::json::object_t member;
1203253f11b8SEd Tanous                             member["@odata.id"] = std::format(
1204253f11b8SEd Tanous                                 "/redfish/v1/Systems/{}/LogServices/PostCodes",
1205253f11b8SEd Tanous                                 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1206613dabeaSEd Tanous 
1207bd79bce8SPatrick Williams                             logServiceArrayLocal.emplace_back(
1208bd79bce8SPatrick Williams                                 std::move(member));
1209613dabeaSEd Tanous 
121045ca1b86SEd Tanous                             asyncResp->res.jsonValue["Members@odata.count"] =
121123a21a1cSEd Tanous                                 logServiceArrayLocal.size();
1212a3316fc6SZhikuiRen                             return;
1213a3316fc6SZhikuiRen                         }
1214a3316fc6SZhikuiRen                     }
12157a1dbc48SGeorge Liu                 });
12167e860f15SJohn Edward Broadbent         });
1217c4bf6374SJason M. Bills }
1218c4bf6374SJason M. Bills 
12197e860f15SJohn Edward Broadbent inline void requestRoutesEventLogService(App& app)
1220c4bf6374SJason M. Bills {
122122d268cbSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/")
1222ed398213SEd Tanous         .privileges(redfish::privileges::getLogService)
1223bd79bce8SPatrick Williams         .methods(
1224bd79bce8SPatrick Williams             boost::beast::http::verb::
1225bd79bce8SPatrick Williams                 get)([&app](const crow::Request& req,
122622d268cbSEd Tanous                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
122722d268cbSEd Tanous                             const std::string& systemName) {
12283ba00073SCarson Labrado             if (!redfish::setUpRedfishRoute(app, req, asyncResp))
122945ca1b86SEd Tanous             {
123045ca1b86SEd Tanous                 return;
123145ca1b86SEd Tanous             }
1232253f11b8SEd Tanous             if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
123322d268cbSEd Tanous             {
123422d268cbSEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
123522d268cbSEd Tanous                                            systemName);
123622d268cbSEd Tanous                 return;
123722d268cbSEd Tanous             }
1238c4bf6374SJason M. Bills             asyncResp->res.jsonValue["@odata.id"] =
1239253f11b8SEd Tanous                 std::format("/redfish/v1/Systems/{}/LogServices/EventLog",
1240253f11b8SEd Tanous                             BMCWEB_REDFISH_SYSTEM_URI_NAME);
1241c4bf6374SJason M. Bills             asyncResp->res.jsonValue["@odata.type"] =
1242b25644a1SJanet Adkins                 "#LogService.v1_2_0.LogService";
1243c4bf6374SJason M. Bills             asyncResp->res.jsonValue["Name"] = "Event Log Service";
1244bd79bce8SPatrick Williams             asyncResp->res.jsonValue["Description"] =
1245bd79bce8SPatrick Williams                 "System Event Log Service";
1246c4bf6374SJason M. Bills             asyncResp->res.jsonValue["Id"] = "EventLog";
1247539d8c6bSEd Tanous             asyncResp->res.jsonValue["OverWritePolicy"] =
1248539d8c6bSEd Tanous                 log_service::OverWritePolicy::WrapsWhenFull;
12497c8c4058STejas Patil 
12507c8c4058STejas Patil             std::pair<std::string, std::string> redfishDateTimeOffset =
12512b82937eSEd Tanous                 redfish::time_utils::getDateTimeOffsetNow();
12527c8c4058STejas Patil 
12537c8c4058STejas Patil             asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
12547c8c4058STejas Patil             asyncResp->res.jsonValue["DateTimeLocalOffset"] =
12557c8c4058STejas Patil                 redfishDateTimeOffset.second;
12567c8c4058STejas Patil 
1257bd79bce8SPatrick Williams             asyncResp->res.jsonValue["Entries"]["@odata.id"] = std::format(
1258bd79bce8SPatrick Williams                 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
1259253f11b8SEd Tanous                 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1260bd79bce8SPatrick Williams             asyncResp->res
1261bd79bce8SPatrick Williams                 .jsonValue["Actions"]["#LogService.ClearLog"]["target"]
1262e7d6c8b2SGunnar Mills 
126320fa6a2cSEd Tanous                 = std::format(
1264253f11b8SEd Tanous                     "/redfish/v1/Systems/{}/LogServices/EventLog/Actions/LogService.ClearLog",
126520fa6a2cSEd Tanous                     BMCWEB_REDFISH_SYSTEM_URI_NAME);
12667e860f15SJohn Edward Broadbent         });
1267489640c6SJason M. Bills }
1268489640c6SJason M. Bills 
1269599b9af3SAlexander Hansen inline void handleSystemsLogServicesEventLogActionsClearPost(
1270599b9af3SAlexander Hansen     App& app, const crow::Request& req,
127122d268cbSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1272599b9af3SAlexander Hansen     const std::string& systemName)
1273599b9af3SAlexander Hansen {
12743ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
127545ca1b86SEd Tanous     {
127645ca1b86SEd Tanous         return;
127745ca1b86SEd Tanous     }
1278253f11b8SEd Tanous     if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
127922d268cbSEd Tanous     {
128022d268cbSEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
128122d268cbSEd Tanous                                    systemName);
128222d268cbSEd Tanous         return;
128322d268cbSEd Tanous     }
1284599b9af3SAlexander Hansen 
1285489640c6SJason M. Bills     // Clear the EventLog by deleting the log files
1286489640c6SJason M. Bills     std::vector<std::filesystem::path> redfishLogFiles;
1287489640c6SJason M. Bills     if (getRedfishLogFiles(redfishLogFiles))
1288489640c6SJason M. Bills     {
1289489640c6SJason M. Bills         for (const std::filesystem::path& file : redfishLogFiles)
1290489640c6SJason M. Bills         {
1291489640c6SJason M. Bills             std::error_code ec;
1292489640c6SJason M. Bills             std::filesystem::remove(file, ec);
1293489640c6SJason M. Bills         }
1294489640c6SJason M. Bills     }
1295489640c6SJason M. Bills 
1296489640c6SJason M. Bills     // Reload rsyslog so it knows to start new log files
1297489640c6SJason M. Bills     crow::connections::systemBus->async_method_call(
12985e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
1299489640c6SJason M. Bills             if (ec)
1300489640c6SJason M. Bills             {
130162598e31SEd Tanous                 BMCWEB_LOG_ERROR("Failed to reload rsyslog: {}", ec);
1302489640c6SJason M. Bills                 messages::internalError(asyncResp->res);
1303489640c6SJason M. Bills                 return;
1304489640c6SJason M. Bills             }
1305489640c6SJason M. Bills 
1306489640c6SJason M. Bills             messages::success(asyncResp->res);
1307489640c6SJason M. Bills         },
1308489640c6SJason M. Bills         "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
1309002d39b4SEd Tanous         "org.freedesktop.systemd1.Manager", "ReloadUnit", "rsyslog.service",
1310002d39b4SEd Tanous         "replace");
1311599b9af3SAlexander Hansen }
1312599b9af3SAlexander Hansen 
1313599b9af3SAlexander Hansen inline void requestRoutesJournalEventLogClear(App& app)
1314599b9af3SAlexander Hansen {
1315599b9af3SAlexander Hansen     BMCWEB_ROUTE(
1316599b9af3SAlexander Hansen         app,
1317599b9af3SAlexander Hansen         "/redfish/v1/Systems/<str>/LogServices/EventLog/Actions/LogService.ClearLog/")
1318599b9af3SAlexander Hansen         .privileges({{"ConfigureComponents"}})
1319599b9af3SAlexander Hansen         .methods(boost::beast::http::verb::post)(std::bind_front(
1320599b9af3SAlexander Hansen             handleSystemsLogServicesEventLogActionsClearPost, std::ref(app)));
1321c4bf6374SJason M. Bills }
1322c4bf6374SJason M. Bills 
1323ac992cdeSJason M. Bills enum class LogParseError
1324ac992cdeSJason M. Bills {
1325ac992cdeSJason M. Bills     success,
1326ac992cdeSJason M. Bills     parseFailed,
1327ac992cdeSJason M. Bills     messageIdNotInRegistry,
1328ac992cdeSJason M. Bills };
1329ac992cdeSJason M. Bills 
1330bd79bce8SPatrick Williams static LogParseError fillEventLogEntryJson(
1331bd79bce8SPatrick Williams     const std::string& logEntryID, const std::string& logEntry,
1332de703c5dSJason M. Bills     nlohmann::json::object_t& logEntryJson)
1333c4bf6374SJason M. Bills {
133495820184SJason M. Bills     // The redfish log format is "<Timestamp> <MessageId>,<MessageArgs>"
1335cd225da8SJason M. Bills     // First get the Timestamp
1336f23b7296SEd Tanous     size_t space = logEntry.find_first_of(' ');
1337cd225da8SJason M. Bills     if (space == std::string::npos)
133895820184SJason M. Bills     {
1339ac992cdeSJason M. Bills         return LogParseError::parseFailed;
134095820184SJason M. Bills     }
1341cd225da8SJason M. Bills     std::string timestamp = logEntry.substr(0, space);
1342cd225da8SJason M. Bills     // Then get the log contents
1343f23b7296SEd Tanous     size_t entryStart = logEntry.find_first_not_of(' ', space);
1344cd225da8SJason M. Bills     if (entryStart == std::string::npos)
1345cd225da8SJason M. Bills     {
1346ac992cdeSJason M. Bills         return LogParseError::parseFailed;
1347cd225da8SJason M. Bills     }
1348cd225da8SJason M. Bills     std::string_view entry(logEntry);
1349cd225da8SJason M. Bills     entry.remove_prefix(entryStart);
1350cd225da8SJason M. Bills     // Use split to separate the entry into its fields
1351cd225da8SJason M. Bills     std::vector<std::string> logEntryFields;
135250ebd4afSEd Tanous     bmcweb::split(logEntryFields, entry, ',');
1353cd225da8SJason M. Bills     // We need at least a MessageId to be valid
13541e6deaf6SEd Tanous     auto logEntryIter = logEntryFields.begin();
13551e6deaf6SEd Tanous     if (logEntryIter == logEntryFields.end())
1356cd225da8SJason M. Bills     {
1357ac992cdeSJason M. Bills         return LogParseError::parseFailed;
1358cd225da8SJason M. Bills     }
13591e6deaf6SEd Tanous     std::string& messageID = *logEntryIter;
13604851d45dSJason M. Bills     // Get the Message from the MessageRegistry
1361fffb8c1fSEd Tanous     const registries::Message* message = registries::getMessage(messageID);
1362c4bf6374SJason M. Bills 
13631e6deaf6SEd Tanous     logEntryIter++;
136454417b02SSui Chen     if (message == nullptr)
1365c4bf6374SJason M. Bills     {
136662598e31SEd Tanous         BMCWEB_LOG_WARNING("Log entry not found in registry: {}", logEntry);
1367ac992cdeSJason M. Bills         return LogParseError::messageIdNotInRegistry;
1368c4bf6374SJason M. Bills     }
1369c4bf6374SJason M. Bills 
13701e6deaf6SEd Tanous     std::vector<std::string_view> messageArgs(logEntryIter,
13711e6deaf6SEd Tanous                                               logEntryFields.end());
1372c05bba45SEd Tanous     messageArgs.resize(message->numberOfArgs);
1373c05bba45SEd Tanous 
1374bd79bce8SPatrick Williams     std::string msg =
1375bd79bce8SPatrick Williams         redfish::registries::fillMessageArgs(messageArgs, message->message);
13761e6deaf6SEd Tanous     if (msg.empty())
137715a86ff6SJason M. Bills     {
13781e6deaf6SEd Tanous         return LogParseError::parseFailed;
137915a86ff6SJason M. Bills     }
13804851d45dSJason M. Bills 
138195820184SJason M. Bills     // Get the Created time from the timestamp. The log timestamp is in RFC3339
138295820184SJason M. Bills     // format which matches the Redfish format except for the fractional seconds
138395820184SJason M. Bills     // between the '.' and the '+', so just remove them.
1384f23b7296SEd Tanous     std::size_t dot = timestamp.find_first_of('.');
1385f23b7296SEd Tanous     std::size_t plus = timestamp.find_first_of('+');
138695820184SJason M. Bills     if (dot != std::string::npos && plus != std::string::npos)
1387c4bf6374SJason M. Bills     {
138895820184SJason M. Bills         timestamp.erase(dot, plus - dot);
1389c4bf6374SJason M. Bills     }
1390c4bf6374SJason M. Bills 
1391c4bf6374SJason M. Bills     // Fill in the log entry with the gathered data
13929c11a172SVijay Lobo     logEntryJson["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
1393ef4c65b7SEd Tanous     logEntryJson["@odata.id"] = boost::urls::format(
1394253f11b8SEd Tanous         "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}",
1395253f11b8SEd Tanous         BMCWEB_REDFISH_SYSTEM_URI_NAME, logEntryID);
139684afc48bSJason M. Bills     logEntryJson["Name"] = "System Event Log Entry";
139784afc48bSJason M. Bills     logEntryJson["Id"] = logEntryID;
139884afc48bSJason M. Bills     logEntryJson["Message"] = std::move(msg);
139984afc48bSJason M. Bills     logEntryJson["MessageId"] = std::move(messageID);
140084afc48bSJason M. Bills     logEntryJson["MessageArgs"] = messageArgs;
140184afc48bSJason M. Bills     logEntryJson["EntryType"] = "Event";
140284afc48bSJason M. Bills     logEntryJson["Severity"] = message->messageSeverity;
140384afc48bSJason M. Bills     logEntryJson["Created"] = std::move(timestamp);
1404ac992cdeSJason M. Bills     return LogParseError::success;
1405c4bf6374SJason M. Bills }
1406c4bf6374SJason M. Bills 
1407898f2aa2SEd Tanous inline void fillEventLogLogEntryFromPropertyMap(
1408898f2aa2SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1409898f2aa2SEd Tanous     const dbus::utility::DBusPropertiesMap& resp,
1410898f2aa2SEd Tanous     nlohmann::json& objectToFillOut)
1411898f2aa2SEd Tanous {
1412262dcc1cSAlexander Hansen     std::optional<DbusEventLogEntry> optEntry =
1413262dcc1cSAlexander Hansen         fillDbusEventLogEntryFromPropertyMap(resp);
1414898f2aa2SEd Tanous 
1415262dcc1cSAlexander Hansen     if (!optEntry.has_value())
1416898f2aa2SEd Tanous     {
1417898f2aa2SEd Tanous         messages::internalError(asyncResp->res);
1418898f2aa2SEd Tanous         return;
1419898f2aa2SEd Tanous     }
1420262dcc1cSAlexander Hansen     DbusEventLogEntry entry = optEntry.value();
1421898f2aa2SEd Tanous 
1422898f2aa2SEd Tanous     objectToFillOut["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
1423898f2aa2SEd Tanous     objectToFillOut["@odata.id"] = boost::urls::format(
1424898f2aa2SEd Tanous         "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}",
1425262dcc1cSAlexander Hansen         BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(entry.Id));
1426898f2aa2SEd Tanous     objectToFillOut["Name"] = "System Event Log Entry";
1427262dcc1cSAlexander Hansen     objectToFillOut["Id"] = std::to_string(entry.Id);
1428262dcc1cSAlexander Hansen     objectToFillOut["Message"] = entry.Message;
1429262dcc1cSAlexander Hansen     objectToFillOut["Resolved"] = entry.Resolved;
1430262dcc1cSAlexander Hansen     std::optional<bool> notifyAction =
1431262dcc1cSAlexander Hansen         getProviderNotifyAction(entry.ServiceProviderNotify);
1432898f2aa2SEd Tanous     if (notifyAction)
1433898f2aa2SEd Tanous     {
1434898f2aa2SEd Tanous         objectToFillOut["ServiceProviderNotified"] = *notifyAction;
1435898f2aa2SEd Tanous     }
1436262dcc1cSAlexander Hansen     if ((entry.Resolution != nullptr) && !entry.Resolution->empty())
1437898f2aa2SEd Tanous     {
1438262dcc1cSAlexander Hansen         objectToFillOut["Resolution"] = *entry.Resolution;
1439898f2aa2SEd Tanous     }
1440898f2aa2SEd Tanous     objectToFillOut["EntryType"] = "Event";
1441262dcc1cSAlexander Hansen     objectToFillOut["Severity"] =
1442262dcc1cSAlexander Hansen         translateSeverityDbusToRedfish(entry.Severity);
1443898f2aa2SEd Tanous     objectToFillOut["Created"] =
1444262dcc1cSAlexander Hansen         redfish::time_utils::getDateTimeUintMs(entry.Timestamp);
1445898f2aa2SEd Tanous     objectToFillOut["Modified"] =
1446262dcc1cSAlexander Hansen         redfish::time_utils::getDateTimeUintMs(entry.UpdateTimestamp);
1447262dcc1cSAlexander Hansen     if (entry.Path != nullptr)
1448898f2aa2SEd Tanous     {
1449898f2aa2SEd Tanous         objectToFillOut["AdditionalDataURI"] = boost::urls::format(
1450898f2aa2SEd Tanous             "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}/attachment",
1451262dcc1cSAlexander Hansen             BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(entry.Id));
1452898f2aa2SEd Tanous     }
1453898f2aa2SEd Tanous }
1454898f2aa2SEd Tanous 
1455b729096dSEd Tanous inline void afterLogEntriesGetManagedObjects(
1456b729096dSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1457b729096dSEd Tanous     const boost::system::error_code& ec,
1458b729096dSEd Tanous     const dbus::utility::ManagedObjectType& resp)
1459b729096dSEd Tanous {
1460b729096dSEd Tanous     if (ec)
1461b729096dSEd Tanous     {
1462b729096dSEd Tanous         // TODO Handle for specific error code
1463b729096dSEd Tanous         BMCWEB_LOG_ERROR("getLogEntriesIfaceData resp_handler got error {}",
1464b729096dSEd Tanous                          ec);
1465b729096dSEd Tanous         messages::internalError(asyncResp->res);
1466b729096dSEd Tanous         return;
1467b729096dSEd Tanous     }
1468b729096dSEd Tanous     nlohmann::json::array_t entriesArray;
1469b729096dSEd Tanous     for (const auto& objectPath : resp)
1470b729096dSEd Tanous     {
1471898f2aa2SEd Tanous         dbus::utility::DBusPropertiesMap propsFlattened;
1472bd79bce8SPatrick Williams         auto isEntry =
1473bd79bce8SPatrick Williams             std::ranges::find_if(objectPath.second, [](const auto& object) {
1474898f2aa2SEd Tanous                 return object.first == "xyz.openbmc_project.Logging.Entry";
1475898f2aa2SEd Tanous             });
1476898f2aa2SEd Tanous         if (isEntry == objectPath.second.end())
1477b729096dSEd Tanous         {
1478b729096dSEd Tanous             continue;
1479b729096dSEd Tanous         }
1480898f2aa2SEd Tanous         for (const auto& interfaceMap : objectPath.second)
1481b729096dSEd Tanous         {
1482898f2aa2SEd Tanous             for (const auto& propertyMap : interfaceMap.second)
1483b729096dSEd Tanous             {
1484898f2aa2SEd Tanous                 propsFlattened.emplace_back(propertyMap.first,
1485898f2aa2SEd Tanous                                             propertyMap.second);
1486b729096dSEd Tanous             }
1487b729096dSEd Tanous         }
1488898f2aa2SEd Tanous         fillEventLogLogEntryFromPropertyMap(asyncResp, propsFlattened,
1489898f2aa2SEd Tanous                                             entriesArray.emplace_back());
1490b729096dSEd Tanous     }
1491898f2aa2SEd Tanous 
1492b729096dSEd Tanous     std::ranges::sort(entriesArray, [](const nlohmann::json& left,
1493b729096dSEd Tanous                                        const nlohmann::json& right) {
1494b729096dSEd Tanous         return (left["Id"] <= right["Id"]);
1495b729096dSEd Tanous     });
1496b729096dSEd Tanous     asyncResp->res.jsonValue["Members@odata.count"] = entriesArray.size();
1497b729096dSEd Tanous     asyncResp->res.jsonValue["Members"] = std::move(entriesArray);
1498b729096dSEd Tanous }
1499b729096dSEd Tanous 
1500599b9af3SAlexander Hansen inline void handleSystemsLogServiceEventLogLogEntryCollection(
1501599b9af3SAlexander Hansen     App& app, const crow::Request& req,
150222d268cbSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1503599b9af3SAlexander Hansen     const std::string& systemName)
1504599b9af3SAlexander Hansen {
1505c937d2bfSEd Tanous     query_param::QueryCapabilities capabilities = {
1506c937d2bfSEd Tanous         .canDelegateTop = true,
1507c937d2bfSEd Tanous         .canDelegateSkip = true,
1508c937d2bfSEd Tanous     };
1509c937d2bfSEd Tanous     query_param::Query delegatedQuery;
1510599b9af3SAlexander Hansen     if (!redfish::setUpRedfishRouteWithDelegation(app, req, asyncResp,
1511599b9af3SAlexander Hansen                                                   delegatedQuery, capabilities))
1512c4bf6374SJason M. Bills     {
1513c4bf6374SJason M. Bills         return;
1514c4bf6374SJason M. Bills     }
151525b54dbaSEd Tanous     if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
15167f3e84a1SEd Tanous     {
15177f3e84a1SEd Tanous         // Option currently returns no systems.  TBD
15187f3e84a1SEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
15197f3e84a1SEd Tanous                                    systemName);
15207f3e84a1SEd Tanous         return;
15217f3e84a1SEd Tanous     }
1522253f11b8SEd Tanous     if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
152322d268cbSEd Tanous     {
152422d268cbSEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
152522d268cbSEd Tanous                                    systemName);
152622d268cbSEd Tanous         return;
152722d268cbSEd Tanous     }
152822d268cbSEd Tanous 
15295143f7a5SJiaqing Zhao     size_t top = delegatedQuery.top.value_or(query_param::Query::maxTop);
15303648c8beSEd Tanous     size_t skip = delegatedQuery.skip.value_or(0);
15313648c8beSEd Tanous 
15327e860f15SJohn Edward Broadbent     // Collections don't include the static data added by SubRoute
15337e860f15SJohn Edward Broadbent     // because it has a duplicate entry for members
1534c4bf6374SJason M. Bills     asyncResp->res.jsonValue["@odata.type"] =
1535c4bf6374SJason M. Bills         "#LogEntryCollection.LogEntryCollection";
1536c4bf6374SJason M. Bills     asyncResp->res.jsonValue["@odata.id"] =
1537253f11b8SEd Tanous         std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
1538253f11b8SEd Tanous                     BMCWEB_REDFISH_SYSTEM_URI_NAME);
1539c4bf6374SJason M. Bills     asyncResp->res.jsonValue["Name"] = "System Event Log Entries";
1540c4bf6374SJason M. Bills     asyncResp->res.jsonValue["Description"] =
1541c4bf6374SJason M. Bills         "Collection of System Event Log Entries";
1542cb92c03bSAndrew Geissler 
15434978b63fSJason M. Bills     nlohmann::json& logEntryArray = asyncResp->res.jsonValue["Members"];
1544c4bf6374SJason M. Bills     logEntryArray = nlohmann::json::array();
15457e860f15SJohn Edward Broadbent     // Go through the log files and create a unique ID for each
15467e860f15SJohn Edward Broadbent     // entry
154795820184SJason M. Bills     std::vector<std::filesystem::path> redfishLogFiles;
154895820184SJason M. Bills     getRedfishLogFiles(redfishLogFiles);
1549b01bf299SEd Tanous     uint64_t entryCount = 0;
1550cd225da8SJason M. Bills     std::string logEntry;
155195820184SJason M. Bills 
15527e860f15SJohn Edward Broadbent     // Oldest logs are in the last file, so start there and loop
15537e860f15SJohn Edward Broadbent     // backwards
1554599b9af3SAlexander Hansen     for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend(); it++)
1555c4bf6374SJason M. Bills     {
1556cd225da8SJason M. Bills         std::ifstream logStream(*it);
155795820184SJason M. Bills         if (!logStream.is_open())
1558c4bf6374SJason M. Bills         {
1559c4bf6374SJason M. Bills             continue;
1560c4bf6374SJason M. Bills         }
1561c4bf6374SJason M. Bills 
1562e85d6b16SJason M. Bills         // Reset the unique ID on the first entry
1563e85d6b16SJason M. Bills         bool firstEntry = true;
156495820184SJason M. Bills         while (std::getline(logStream, logEntry))
156595820184SJason M. Bills         {
1566c4bf6374SJason M. Bills             std::string idStr;
1567e85d6b16SJason M. Bills             if (!getUniqueEntryID(logEntry, idStr, firstEntry))
1568c4bf6374SJason M. Bills             {
1569c4bf6374SJason M. Bills                 continue;
1570c4bf6374SJason M. Bills             }
1571e85d6b16SJason M. Bills             firstEntry = false;
1572e85d6b16SJason M. Bills 
1573de703c5dSJason M. Bills             nlohmann::json::object_t bmcLogEntry;
1574bd79bce8SPatrick Williams             LogParseError status =
1575bd79bce8SPatrick Williams                 fillEventLogEntryJson(idStr, logEntry, bmcLogEntry);
1576ac992cdeSJason M. Bills             if (status == LogParseError::messageIdNotInRegistry)
1577ac992cdeSJason M. Bills             {
1578ac992cdeSJason M. Bills                 continue;
1579ac992cdeSJason M. Bills             }
1580ac992cdeSJason M. Bills             if (status != LogParseError::success)
1581c4bf6374SJason M. Bills             {
1582c4bf6374SJason M. Bills                 messages::internalError(asyncResp->res);
1583c4bf6374SJason M. Bills                 return;
1584c4bf6374SJason M. Bills             }
1585de703c5dSJason M. Bills 
1586de703c5dSJason M. Bills             entryCount++;
1587de703c5dSJason M. Bills             // Handle paging using skip (number of entries to skip from the
1588de703c5dSJason M. Bills             // start) and top (number of entries to display)
15893648c8beSEd Tanous             if (entryCount <= skip || entryCount > skip + top)
1590de703c5dSJason M. Bills             {
1591de703c5dSJason M. Bills                 continue;
1592de703c5dSJason M. Bills             }
1593de703c5dSJason M. Bills 
1594b2ba3072SPatrick Williams             logEntryArray.emplace_back(std::move(bmcLogEntry));
1595c4bf6374SJason M. Bills         }
159695820184SJason M. Bills     }
1597c4bf6374SJason M. Bills     asyncResp->res.jsonValue["Members@odata.count"] = entryCount;
15983648c8beSEd Tanous     if (skip + top < entryCount)
1599c4bf6374SJason M. Bills     {
1600599b9af3SAlexander Hansen         asyncResp->res.jsonValue["Members@odata.nextLink"] =
1601599b9af3SAlexander Hansen             boost::urls::format(
1602253f11b8SEd Tanous                 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries?$skip={}",
1603253f11b8SEd Tanous                 BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(skip + top));
1604c4bf6374SJason M. Bills     }
1605897967deSJason M. Bills }
1606897967deSJason M. Bills 
1607599b9af3SAlexander Hansen inline void requestRoutesJournalEventLogEntryCollection(App& app)
1608897967deSJason M. Bills {
1609599b9af3SAlexander Hansen     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/")
1610599b9af3SAlexander Hansen         .privileges(redfish::privileges::getLogEntryCollection)
1611599b9af3SAlexander Hansen         .methods(boost::beast::http::verb::get)(std::bind_front(
1612599b9af3SAlexander Hansen             handleSystemsLogServiceEventLogLogEntryCollection, std::ref(app)));
1613599b9af3SAlexander Hansen }
1614599b9af3SAlexander Hansen 
1615599b9af3SAlexander Hansen inline void handleSystemsLogServiceEventLogEntriesGet(
1616599b9af3SAlexander Hansen     App& app, const crow::Request& req,
16177e860f15SJohn Edward Broadbent     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1618599b9af3SAlexander Hansen     const std::string& systemName, const std::string& param)
1619599b9af3SAlexander Hansen {
16203ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
162145ca1b86SEd Tanous     {
162245ca1b86SEd Tanous         return;
162345ca1b86SEd Tanous     }
162425b54dbaSEd Tanous     if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
16257f3e84a1SEd Tanous     {
16267f3e84a1SEd Tanous         // Option currently returns no systems.  TBD
16277f3e84a1SEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
16287f3e84a1SEd Tanous                                    systemName);
16297f3e84a1SEd Tanous         return;
16307f3e84a1SEd Tanous     }
163122d268cbSEd Tanous 
1632253f11b8SEd Tanous     if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
163322d268cbSEd Tanous     {
163422d268cbSEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
163522d268cbSEd Tanous                                    systemName);
163622d268cbSEd Tanous         return;
163722d268cbSEd Tanous     }
163822d268cbSEd Tanous 
16397e860f15SJohn Edward Broadbent     const std::string& targetID = param;
16408d1b46d7Szhanghch05 
16417e860f15SJohn Edward Broadbent     // Go through the log files and check the unique ID for each
16427e860f15SJohn Edward Broadbent     // entry to find the target entry
1643897967deSJason M. Bills     std::vector<std::filesystem::path> redfishLogFiles;
1644897967deSJason M. Bills     getRedfishLogFiles(redfishLogFiles);
1645897967deSJason M. Bills     std::string logEntry;
1646897967deSJason M. Bills 
16477e860f15SJohn Edward Broadbent     // Oldest logs are in the last file, so start there and loop
16487e860f15SJohn Edward Broadbent     // backwards
1649599b9af3SAlexander Hansen     for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend(); it++)
1650897967deSJason M. Bills     {
1651897967deSJason M. Bills         std::ifstream logStream(*it);
1652897967deSJason M. Bills         if (!logStream.is_open())
1653897967deSJason M. Bills         {
1654897967deSJason M. Bills             continue;
1655897967deSJason M. Bills         }
1656897967deSJason M. Bills 
1657897967deSJason M. Bills         // Reset the unique ID on the first entry
1658897967deSJason M. Bills         bool firstEntry = true;
1659897967deSJason M. Bills         while (std::getline(logStream, logEntry))
1660897967deSJason M. Bills         {
1661897967deSJason M. Bills             std::string idStr;
1662897967deSJason M. Bills             if (!getUniqueEntryID(logEntry, idStr, firstEntry))
1663897967deSJason M. Bills             {
1664897967deSJason M. Bills                 continue;
1665897967deSJason M. Bills             }
1666897967deSJason M. Bills             firstEntry = false;
1667897967deSJason M. Bills 
1668897967deSJason M. Bills             if (idStr == targetID)
1669897967deSJason M. Bills             {
1670de703c5dSJason M. Bills                 nlohmann::json::object_t bmcLogEntry;
1671bd79bce8SPatrick Williams                 LogParseError status =
1672bd79bce8SPatrick Williams                     fillEventLogEntryJson(idStr, logEntry, bmcLogEntry);
1673ac992cdeSJason M. Bills                 if (status != LogParseError::success)
1674897967deSJason M. Bills                 {
1675897967deSJason M. Bills                     messages::internalError(asyncResp->res);
1676897967deSJason M. Bills                     return;
1677897967deSJason M. Bills                 }
1678d405bb51SJason M. Bills                 asyncResp->res.jsonValue.update(bmcLogEntry);
1679897967deSJason M. Bills                 return;
1680897967deSJason M. Bills             }
1681897967deSJason M. Bills         }
1682897967deSJason M. Bills     }
1683897967deSJason M. Bills     // Requested ID was not found
16849db4ba25SJiaqing Zhao     messages::resourceNotFound(asyncResp->res, "LogEntry", targetID);
1685599b9af3SAlexander Hansen }
1686599b9af3SAlexander Hansen 
1687599b9af3SAlexander Hansen inline void requestRoutesJournalEventLogEntry(App& app)
1688599b9af3SAlexander Hansen {
1689599b9af3SAlexander Hansen     BMCWEB_ROUTE(
1690599b9af3SAlexander Hansen         app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
1691599b9af3SAlexander Hansen         .privileges(redfish::privileges::getLogEntry)
1692599b9af3SAlexander Hansen         .methods(boost::beast::http::verb::get)(std::bind_front(
1693599b9af3SAlexander Hansen             handleSystemsLogServiceEventLogEntriesGet, std::ref(app)));
1694599b9af3SAlexander Hansen }
1695599b9af3SAlexander Hansen 
1696599b9af3SAlexander Hansen inline void dBusEventLogEntryCollection(
1697599b9af3SAlexander Hansen     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1698599b9af3SAlexander Hansen {
1699599b9af3SAlexander Hansen     // Collections don't include the static data added by SubRoute
1700599b9af3SAlexander Hansen     // because it has a duplicate entry for members
1701599b9af3SAlexander Hansen     asyncResp->res.jsonValue["@odata.type"] =
1702599b9af3SAlexander Hansen         "#LogEntryCollection.LogEntryCollection";
1703599b9af3SAlexander Hansen     asyncResp->res.jsonValue["@odata.id"] =
1704599b9af3SAlexander Hansen         std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
1705599b9af3SAlexander Hansen                     BMCWEB_REDFISH_SYSTEM_URI_NAME);
1706599b9af3SAlexander Hansen     asyncResp->res.jsonValue["Name"] = "System Event Log Entries";
1707599b9af3SAlexander Hansen     asyncResp->res.jsonValue["Description"] =
1708599b9af3SAlexander Hansen         "Collection of System Event Log Entries";
1709599b9af3SAlexander Hansen 
1710599b9af3SAlexander Hansen     // DBus implementation of EventLog/Entries
1711599b9af3SAlexander Hansen     // Make call to Logging Service to find all log entry objects
1712599b9af3SAlexander Hansen     sdbusplus::message::object_path path("/xyz/openbmc_project/logging");
1713599b9af3SAlexander Hansen     dbus::utility::getManagedObjects(
1714599b9af3SAlexander Hansen         "xyz.openbmc_project.Logging", path,
1715599b9af3SAlexander Hansen         [asyncResp](const boost::system::error_code& ec,
1716599b9af3SAlexander Hansen                     const dbus::utility::ManagedObjectType& resp) {
1717b729096dSEd Tanous             afterLogEntriesGetManagedObjects(asyncResp, ec, resp);
17187e860f15SJohn Edward Broadbent         });
171908a4e4b5SAnthony Wilson }
172008a4e4b5SAnthony Wilson 
17217e860f15SJohn Edward Broadbent inline void requestRoutesDBusEventLogEntryCollection(App& app)
172208a4e4b5SAnthony Wilson {
172322d268cbSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/")
1724ed398213SEd Tanous         .privileges(redfish::privileges::getLogEntryCollection)
1725002d39b4SEd Tanous         .methods(boost::beast::http::verb::get)(
1726002d39b4SEd Tanous             [&app](const crow::Request& req,
172722d268cbSEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
172822d268cbSEd Tanous                    const std::string& systemName) {
17293ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
173045ca1b86SEd Tanous                 {
173145ca1b86SEd Tanous                     return;
173245ca1b86SEd Tanous                 }
173325b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
17347f3e84a1SEd Tanous                 {
17357f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
17367f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
17377f3e84a1SEd Tanous                                                systemName);
17387f3e84a1SEd Tanous                     return;
17397f3e84a1SEd Tanous                 }
1740253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
174122d268cbSEd Tanous                 {
174222d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
174322d268cbSEd Tanous                                                systemName);
174422d268cbSEd Tanous                     return;
174522d268cbSEd Tanous                 }
1746599b9af3SAlexander Hansen                 dBusEventLogEntryCollection(asyncResp);
1747599b9af3SAlexander Hansen             });
1748599b9af3SAlexander Hansen }
174922d268cbSEd Tanous 
1750bd79bce8SPatrick Williams inline void dBusEventLogEntryGet(
1751bd79bce8SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID)
1752599b9af3SAlexander Hansen {
1753599b9af3SAlexander Hansen     dbus::utility::escapePathForDbus(entryID);
175408a4e4b5SAnthony Wilson 
1755cb92c03bSAndrew Geissler     // DBus implementation of EventLog/Entries
1756cb92c03bSAndrew Geissler     // Make call to Logging Service to find all log entry objects
1757deae6a78SEd Tanous     dbus::utility::getAllProperties(
1758deae6a78SEd Tanous         "xyz.openbmc_project.Logging",
1759599b9af3SAlexander Hansen         "/xyz/openbmc_project/logging/entry/" + entryID, "",
1760599b9af3SAlexander Hansen         [asyncResp, entryID](const boost::system::error_code& ec,
1761599b9af3SAlexander Hansen                              const dbus::utility::DBusPropertiesMap& resp) {
1762599b9af3SAlexander Hansen             if (ec.value() == EBADR)
1763599b9af3SAlexander Hansen             {
1764599b9af3SAlexander Hansen                 messages::resourceNotFound(asyncResp->res, "EventLogEntry",
1765599b9af3SAlexander Hansen                                            entryID);
1766599b9af3SAlexander Hansen                 return;
1767599b9af3SAlexander Hansen             }
1768cb92c03bSAndrew Geissler             if (ec)
1769cb92c03bSAndrew Geissler             {
1770bd79bce8SPatrick Williams                 BMCWEB_LOG_ERROR(
1771bd79bce8SPatrick Williams                     "EventLogEntry (DBus) resp_handler got error {}", ec);
1772cb92c03bSAndrew Geissler                 messages::internalError(asyncResp->res);
1773cb92c03bSAndrew Geissler                 return;
1774cb92c03bSAndrew Geissler             }
17759017faf2SAbhishek Patel 
1776898f2aa2SEd Tanous             fillEventLogLogEntryFromPropertyMap(asyncResp, resp,
1777898f2aa2SEd Tanous                                                 asyncResp->res.jsonValue);
1778599b9af3SAlexander Hansen         });
17797e860f15SJohn Edward Broadbent }
1780599b9af3SAlexander Hansen 
1781599b9af3SAlexander Hansen inline void
1782599b9af3SAlexander Hansen     dBusEventLogEntryPatch(const crow::Request& req,
1783599b9af3SAlexander Hansen                            const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1784599b9af3SAlexander Hansen                            const std::string& entryId)
1785599b9af3SAlexander Hansen {
1786599b9af3SAlexander Hansen     std::optional<bool> resolved;
1787599b9af3SAlexander Hansen 
1788599b9af3SAlexander Hansen     if (!json_util::readJsonPatch(req, asyncResp->res, "Resolved", resolved))
1789599b9af3SAlexander Hansen     {
1790599b9af3SAlexander Hansen         return;
1791599b9af3SAlexander Hansen     }
1792599b9af3SAlexander Hansen     BMCWEB_LOG_DEBUG("Set Resolved");
1793599b9af3SAlexander Hansen 
1794599b9af3SAlexander Hansen     setDbusProperty(asyncResp, "Resolved", "xyz.openbmc_project.Logging",
1795599b9af3SAlexander Hansen                     "/xyz/openbmc_project/logging/entry/" + entryId,
1796599b9af3SAlexander Hansen                     "xyz.openbmc_project.Logging.Entry", "Resolved",
1797599b9af3SAlexander Hansen                     resolved.value_or(false));
1798599b9af3SAlexander Hansen }
1799599b9af3SAlexander Hansen 
1800bd79bce8SPatrick Williams inline void dBusEventLogEntryDelete(
1801bd79bce8SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID)
1802599b9af3SAlexander Hansen {
1803599b9af3SAlexander Hansen     BMCWEB_LOG_DEBUG("Do delete single event entries.");
1804599b9af3SAlexander Hansen 
1805599b9af3SAlexander Hansen     dbus::utility::escapePathForDbus(entryID);
1806599b9af3SAlexander Hansen 
1807599b9af3SAlexander Hansen     // Process response from Logging service.
1808599b9af3SAlexander Hansen     auto respHandler = [asyncResp,
1809599b9af3SAlexander Hansen                         entryID](const boost::system::error_code& ec) {
1810599b9af3SAlexander Hansen         BMCWEB_LOG_DEBUG("EventLogEntry (DBus) doDelete callback: Done");
1811599b9af3SAlexander Hansen         if (ec)
1812599b9af3SAlexander Hansen         {
1813599b9af3SAlexander Hansen             if (ec.value() == EBADR)
1814599b9af3SAlexander Hansen             {
1815599b9af3SAlexander Hansen                 messages::resourceNotFound(asyncResp->res, "LogEntry", entryID);
1816599b9af3SAlexander Hansen                 return;
1817599b9af3SAlexander Hansen             }
1818599b9af3SAlexander Hansen             // TODO Handle for specific error code
1819599b9af3SAlexander Hansen             BMCWEB_LOG_ERROR(
1820599b9af3SAlexander Hansen                 "EventLogEntry (DBus) doDelete respHandler got error {}", ec);
1821599b9af3SAlexander Hansen             asyncResp->res.result(
1822599b9af3SAlexander Hansen                 boost::beast::http::status::internal_server_error);
1823599b9af3SAlexander Hansen             return;
1824599b9af3SAlexander Hansen         }
1825599b9af3SAlexander Hansen 
1826599b9af3SAlexander Hansen         asyncResp->res.result(boost::beast::http::status::ok);
1827599b9af3SAlexander Hansen     };
1828599b9af3SAlexander Hansen 
1829599b9af3SAlexander Hansen     // Make call to Logging service to request Delete Log
1830599b9af3SAlexander Hansen     crow::connections::systemBus->async_method_call(
1831599b9af3SAlexander Hansen         respHandler, "xyz.openbmc_project.Logging",
1832599b9af3SAlexander Hansen         "/xyz/openbmc_project/logging/entry/" + entryID,
1833599b9af3SAlexander Hansen         "xyz.openbmc_project.Object.Delete", "Delete");
18347e860f15SJohn Edward Broadbent }
18357e860f15SJohn Edward Broadbent 
18367e860f15SJohn Edward Broadbent inline void requestRoutesDBusEventLogEntry(App& app)
18377e860f15SJohn Edward Broadbent {
18387e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
183922d268cbSEd Tanous         app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
1840ed398213SEd Tanous         .privileges(redfish::privileges::getLogEntry)
1841002d39b4SEd Tanous         .methods(boost::beast::http::verb::get)(
1842002d39b4SEd Tanous             [&app](const crow::Request& req,
18437e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1844898f2aa2SEd Tanous                    const std::string& systemName, const std::string& entryId) {
18453ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
18467e860f15SJohn Edward Broadbent                 {
184745ca1b86SEd Tanous                     return;
184845ca1b86SEd Tanous                 }
184925b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
18507f3e84a1SEd Tanous                 {
18517f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
18527f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
18537f3e84a1SEd Tanous                                                systemName);
18547f3e84a1SEd Tanous                     return;
18557f3e84a1SEd Tanous                 }
1856253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
185722d268cbSEd Tanous                 {
185822d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
185922d268cbSEd Tanous                                                systemName);
186022d268cbSEd Tanous                     return;
186122d268cbSEd Tanous                 }
186222d268cbSEd Tanous 
1863898f2aa2SEd Tanous                 dBusEventLogEntryGet(asyncResp, entryId);
18647e860f15SJohn Edward Broadbent             });
1865336e96c6SChicago Duan 
18667e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
186722d268cbSEd Tanous         app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
1868ed398213SEd Tanous         .privileges(redfish::privileges::patchLogEntry)
18697e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::patch)(
187045ca1b86SEd Tanous             [&app](const crow::Request& req,
18717e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
187222d268cbSEd Tanous                    const std::string& systemName, const std::string& entryId) {
18733ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
187445ca1b86SEd Tanous                 {
187545ca1b86SEd Tanous                     return;
187645ca1b86SEd Tanous                 }
187725b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
18787f3e84a1SEd Tanous                 {
18797f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
18807f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
18817f3e84a1SEd Tanous                                                systemName);
18827f3e84a1SEd Tanous                     return;
18837f3e84a1SEd Tanous                 }
1884253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
188522d268cbSEd Tanous                 {
188622d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
188722d268cbSEd Tanous                                                systemName);
188822d268cbSEd Tanous                     return;
188922d268cbSEd Tanous                 }
189075710de2SXiaochao Ma 
1891599b9af3SAlexander Hansen                 dBusEventLogEntryPatch(req, asyncResp, entryId);
18927e860f15SJohn Edward Broadbent             });
189375710de2SXiaochao Ma 
18947e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
189522d268cbSEd Tanous         app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
1896ed398213SEd Tanous         .privileges(redfish::privileges::deleteLogEntry)
1897ed398213SEd Tanous 
1898002d39b4SEd Tanous         .methods(boost::beast::http::verb::delete_)(
1899002d39b4SEd Tanous             [&app](const crow::Request& req,
1900002d39b4SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
190122d268cbSEd Tanous                    const std::string& systemName, const std::string& param) {
19023ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1903336e96c6SChicago Duan                 {
190445ca1b86SEd Tanous                     return;
190545ca1b86SEd Tanous                 }
190625b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
19077f3e84a1SEd Tanous                 {
19087f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
19097f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
19107f3e84a1SEd Tanous                                                systemName);
19117f3e84a1SEd Tanous                     return;
19127f3e84a1SEd Tanous                 }
1913253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
191422d268cbSEd Tanous                 {
191522d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
191622d268cbSEd Tanous                                                systemName);
191722d268cbSEd Tanous                     return;
191822d268cbSEd Tanous                 }
1919599b9af3SAlexander Hansen                 dBusEventLogEntryDelete(asyncResp, param);
19207e860f15SJohn Edward Broadbent             });
1921400fd1fbSAdriana Kobylak }
1922400fd1fbSAdriana Kobylak 
1923b7028ebfSSpencer Ku constexpr const char* hostLoggerFolderPath = "/var/log/console";
1924b7028ebfSSpencer Ku 
1925b7028ebfSSpencer Ku inline bool
1926b7028ebfSSpencer Ku     getHostLoggerFiles(const std::string& hostLoggerFilePath,
1927b7028ebfSSpencer Ku                        std::vector<std::filesystem::path>& hostLoggerFiles)
1928b7028ebfSSpencer Ku {
1929b7028ebfSSpencer Ku     std::error_code ec;
1930b7028ebfSSpencer Ku     std::filesystem::directory_iterator logPath(hostLoggerFilePath, ec);
1931b7028ebfSSpencer Ku     if (ec)
1932b7028ebfSSpencer Ku     {
1933bf2ddedeSCarson Labrado         BMCWEB_LOG_WARNING("{}", ec.message());
1934b7028ebfSSpencer Ku         return false;
1935b7028ebfSSpencer Ku     }
1936b7028ebfSSpencer Ku     for (const std::filesystem::directory_entry& it : logPath)
1937b7028ebfSSpencer Ku     {
1938b7028ebfSSpencer Ku         std::string filename = it.path().filename();
1939b7028ebfSSpencer Ku         // Prefix of each log files is "log". Find the file and save the
1940b7028ebfSSpencer Ku         // path
194111ba3979SEd Tanous         if (filename.starts_with("log"))
1942b7028ebfSSpencer Ku         {
1943b7028ebfSSpencer Ku             hostLoggerFiles.emplace_back(it.path());
1944b7028ebfSSpencer Ku         }
1945b7028ebfSSpencer Ku     }
1946b7028ebfSSpencer Ku     // As the log files rotate, they are appended with a ".#" that is higher for
1947b7028ebfSSpencer Ku     // the older logs. Since we start from oldest logs, sort the name in
1948b7028ebfSSpencer Ku     // descending order.
1949b7028ebfSSpencer Ku     std::sort(hostLoggerFiles.rbegin(), hostLoggerFiles.rend(),
1950b7028ebfSSpencer Ku               AlphanumLess<std::string>());
1951b7028ebfSSpencer Ku 
1952b7028ebfSSpencer Ku     return true;
1953b7028ebfSSpencer Ku }
1954b7028ebfSSpencer Ku 
195502cad96eSEd Tanous inline bool getHostLoggerEntries(
195602cad96eSEd Tanous     const std::vector<std::filesystem::path>& hostLoggerFiles, uint64_t skip,
195702cad96eSEd Tanous     uint64_t top, std::vector<std::string>& logEntries, size_t& logCount)
1958b7028ebfSSpencer Ku {
1959b7028ebfSSpencer Ku     GzFileReader logFile;
1960b7028ebfSSpencer Ku 
1961b7028ebfSSpencer Ku     // Go though all log files and expose host logs.
1962b7028ebfSSpencer Ku     for (const std::filesystem::path& it : hostLoggerFiles)
1963b7028ebfSSpencer Ku     {
1964b7028ebfSSpencer Ku         if (!logFile.gzGetLines(it.string(), skip, top, logEntries, logCount))
1965b7028ebfSSpencer Ku         {
196662598e31SEd Tanous             BMCWEB_LOG_ERROR("fail to expose host logs");
1967b7028ebfSSpencer Ku             return false;
1968b7028ebfSSpencer Ku         }
1969b7028ebfSSpencer Ku     }
1970b7028ebfSSpencer Ku     // Get lastMessage from constructor by getter
1971b7028ebfSSpencer Ku     std::string lastMessage = logFile.getLastMessage();
1972b7028ebfSSpencer Ku     if (!lastMessage.empty())
1973b7028ebfSSpencer Ku     {
1974b7028ebfSSpencer Ku         logCount++;
1975b7028ebfSSpencer Ku         if (logCount > skip && logCount <= (skip + top))
1976b7028ebfSSpencer Ku         {
1977b7028ebfSSpencer Ku             logEntries.push_back(lastMessage);
1978b7028ebfSSpencer Ku         }
1979b7028ebfSSpencer Ku     }
1980b7028ebfSSpencer Ku     return true;
1981b7028ebfSSpencer Ku }
1982b7028ebfSSpencer Ku 
1983dd72e87bSClaire Weinan inline void handleBMCLogServicesCollectionGet(
1984fdd26906SClaire Weinan     crow::App& app, const crow::Request& req,
1985253f11b8SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1986253f11b8SEd Tanous     const std::string& managerId)
19871da66f75SEd Tanous {
19883ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
198945ca1b86SEd Tanous     {
199045ca1b86SEd Tanous         return;
199145ca1b86SEd Tanous     }
1992253f11b8SEd Tanous 
1993253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
1994253f11b8SEd Tanous     {
1995253f11b8SEd Tanous         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
1996253f11b8SEd Tanous         return;
1997253f11b8SEd Tanous     }
1998253f11b8SEd Tanous 
19997e860f15SJohn Edward Broadbent     // Collections don't include the static data added by SubRoute
20007e860f15SJohn Edward Broadbent     // because it has a duplicate entry for members
2001e1f26343SJason M. Bills     asyncResp->res.jsonValue["@odata.type"] =
20021da66f75SEd Tanous         "#LogServiceCollection.LogServiceCollection";
2003253f11b8SEd Tanous     asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
2004253f11b8SEd Tanous         "/redfish/v1/Managers/{}/LogServices", BMCWEB_REDFISH_MANAGER_URI_NAME);
2005002d39b4SEd Tanous     asyncResp->res.jsonValue["Name"] = "Open BMC Log Services Collection";
2006e1f26343SJason M. Bills     asyncResp->res.jsonValue["Description"] =
20071da66f75SEd Tanous         "Collection of LogServices for this Manager";
2008002d39b4SEd Tanous     nlohmann::json& logServiceArray = asyncResp->res.jsonValue["Members"];
2009c4bf6374SJason M. Bills     logServiceArray = nlohmann::json::array();
2010fdd26906SClaire Weinan 
201125b54dbaSEd Tanous     if constexpr (BMCWEB_REDFISH_BMC_JOURNAL)
201225b54dbaSEd Tanous     {
2013613dabeaSEd Tanous         nlohmann::json::object_t journal;
2014253f11b8SEd Tanous         journal["@odata.id"] =
2015253f11b8SEd Tanous             boost::urls::format("/redfish/v1/Managers/{}/LogServices/Journal",
2016253f11b8SEd Tanous                                 BMCWEB_REDFISH_MANAGER_URI_NAME);
2017b2ba3072SPatrick Williams         logServiceArray.emplace_back(std::move(journal));
201825b54dbaSEd Tanous     }
2019fdd26906SClaire Weinan 
2020fdd26906SClaire Weinan     asyncResp->res.jsonValue["Members@odata.count"] = logServiceArray.size();
2021fdd26906SClaire Weinan 
202225b54dbaSEd Tanous     if constexpr (BMCWEB_REDFISH_DUMP_LOG)
202325b54dbaSEd Tanous     {
202415912159SGeorge Liu         constexpr std::array<std::string_view, 1> interfaces = {
20257a1dbc48SGeorge Liu             "xyz.openbmc_project.Collection.DeleteAll"};
20267a1dbc48SGeorge Liu         dbus::utility::getSubTreePaths(
20277a1dbc48SGeorge Liu             "/xyz/openbmc_project/dump", 0, interfaces,
202825b54dbaSEd Tanous             [asyncResp](const boost::system::error_code& ec,
202925b54dbaSEd Tanous                         const dbus::utility::MapperGetSubTreePathsResponse&
203025b54dbaSEd Tanous                             subTreePaths) {
2031fdd26906SClaire Weinan                 if (ec)
2032fdd26906SClaire Weinan                 {
203362598e31SEd Tanous                     BMCWEB_LOG_ERROR(
203462598e31SEd Tanous                         "handleBMCLogServicesCollectionGet respHandler got error {}",
203562598e31SEd Tanous                         ec);
2036bd79bce8SPatrick Williams                     // Assume that getting an error simply means there are no
2037bd79bce8SPatrick Williams                     // dump LogServices. Return without adding any error
2038bd79bce8SPatrick Williams                     // response.
2039fdd26906SClaire Weinan                     return;
2040fdd26906SClaire Weinan                 }
2041fdd26906SClaire Weinan 
2042fdd26906SClaire Weinan                 nlohmann::json& logServiceArrayLocal =
2043fdd26906SClaire Weinan                     asyncResp->res.jsonValue["Members"];
2044fdd26906SClaire Weinan 
2045fdd26906SClaire Weinan                 for (const std::string& path : subTreePaths)
2046fdd26906SClaire Weinan                 {
2047fdd26906SClaire Weinan                     if (path == "/xyz/openbmc_project/dump/bmc")
2048fdd26906SClaire Weinan                     {
2049613dabeaSEd Tanous                         nlohmann::json::object_t member;
2050253f11b8SEd Tanous                         member["@odata.id"] = boost::urls::format(
2051253f11b8SEd Tanous                             "/redfish/v1/Managers/{}/LogServices/Dump",
2052253f11b8SEd Tanous                             BMCWEB_REDFISH_MANAGER_URI_NAME);
2053b2ba3072SPatrick Williams                         logServiceArrayLocal.emplace_back(std::move(member));
2054fdd26906SClaire Weinan                     }
2055fdd26906SClaire Weinan                     else if (path == "/xyz/openbmc_project/dump/faultlog")
2056fdd26906SClaire Weinan                     {
2057613dabeaSEd Tanous                         nlohmann::json::object_t member;
2058253f11b8SEd Tanous                         member["@odata.id"] = boost::urls::format(
2059253f11b8SEd Tanous                             "/redfish/v1/Managers/{}/LogServices/FaultLog",
2060253f11b8SEd Tanous                             BMCWEB_REDFISH_MANAGER_URI_NAME);
2061b2ba3072SPatrick Williams                         logServiceArrayLocal.emplace_back(std::move(member));
2062fdd26906SClaire Weinan                     }
2063fdd26906SClaire Weinan                 }
2064fdd26906SClaire Weinan 
2065e1f26343SJason M. Bills                 asyncResp->res.jsonValue["Members@odata.count"] =
2066fdd26906SClaire Weinan                     logServiceArrayLocal.size();
20677a1dbc48SGeorge Liu             });
206825b54dbaSEd Tanous     }
2069fdd26906SClaire Weinan }
2070fdd26906SClaire Weinan 
2071fdd26906SClaire Weinan inline void requestRoutesBMCLogServiceCollection(App& app)
2072fdd26906SClaire Weinan {
2073253f11b8SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/")
2074fdd26906SClaire Weinan         .privileges(redfish::privileges::getLogServiceCollection)
2075fdd26906SClaire Weinan         .methods(boost::beast::http::verb::get)(
2076dd72e87bSClaire Weinan             std::bind_front(handleBMCLogServicesCollectionGet, std::ref(app)));
2077e1f26343SJason M. Bills }
2078e1f26343SJason M. Bills 
2079fdd26906SClaire Weinan inline void
2080fdd26906SClaire Weinan     getDumpServiceInfo(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2081fdd26906SClaire Weinan                        const std::string& dumpType)
2082c9bb6861Sraviteja-b {
2083fdd26906SClaire Weinan     std::string dumpPath;
2084539d8c6bSEd Tanous     log_service::OverWritePolicy overWritePolicy =
2085539d8c6bSEd Tanous         log_service::OverWritePolicy::Invalid;
2086fdd26906SClaire Weinan     bool collectDiagnosticDataSupported = false;
2087fdd26906SClaire Weinan 
2088fdd26906SClaire Weinan     if (dumpType == "BMC")
208945ca1b86SEd Tanous     {
2090253f11b8SEd Tanous         dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/Dump",
2091253f11b8SEd Tanous                                BMCWEB_REDFISH_MANAGER_URI_NAME);
2092539d8c6bSEd Tanous         overWritePolicy = log_service::OverWritePolicy::WrapsWhenFull;
2093fdd26906SClaire Weinan         collectDiagnosticDataSupported = true;
2094fdd26906SClaire Weinan     }
2095fdd26906SClaire Weinan     else if (dumpType == "FaultLog")
2096fdd26906SClaire Weinan     {
2097253f11b8SEd Tanous         dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/FaultLog",
2098253f11b8SEd Tanous                                BMCWEB_REDFISH_MANAGER_URI_NAME);
2099539d8c6bSEd Tanous         overWritePolicy = log_service::OverWritePolicy::Unknown;
2100fdd26906SClaire Weinan         collectDiagnosticDataSupported = false;
2101fdd26906SClaire Weinan     }
2102fdd26906SClaire Weinan     else if (dumpType == "System")
2103fdd26906SClaire Weinan     {
2104253f11b8SEd Tanous         dumpPath = std::format("/redfish/v1/Systems/{}/LogServices/Dump",
2105253f11b8SEd Tanous                                BMCWEB_REDFISH_SYSTEM_URI_NAME);
2106539d8c6bSEd Tanous         overWritePolicy = log_service::OverWritePolicy::WrapsWhenFull;
2107fdd26906SClaire Weinan         collectDiagnosticDataSupported = true;
2108fdd26906SClaire Weinan     }
2109fdd26906SClaire Weinan     else
2110fdd26906SClaire Weinan     {
211162598e31SEd Tanous         BMCWEB_LOG_ERROR("getDumpServiceInfo() invalid dump type: {}",
211262598e31SEd Tanous                          dumpType);
2113fdd26906SClaire Weinan         messages::internalError(asyncResp->res);
211445ca1b86SEd Tanous         return;
211545ca1b86SEd Tanous     }
2116fdd26906SClaire Weinan 
2117fdd26906SClaire Weinan     asyncResp->res.jsonValue["@odata.id"] = dumpPath;
2118fdd26906SClaire Weinan     asyncResp->res.jsonValue["@odata.type"] = "#LogService.v1_2_0.LogService";
2119c9bb6861Sraviteja-b     asyncResp->res.jsonValue["Name"] = "Dump LogService";
2120fdd26906SClaire Weinan     asyncResp->res.jsonValue["Description"] = dumpType + " Dump LogService";
2121fdd26906SClaire Weinan     asyncResp->res.jsonValue["Id"] = std::filesystem::path(dumpPath).filename();
2122539d8c6bSEd Tanous     asyncResp->res.jsonValue["OverWritePolicy"] = overWritePolicy;
21237c8c4058STejas Patil 
21247c8c4058STejas Patil     std::pair<std::string, std::string> redfishDateTimeOffset =
21252b82937eSEd Tanous         redfish::time_utils::getDateTimeOffsetNow();
21260fda0f12SGeorge Liu     asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
21277c8c4058STejas Patil     asyncResp->res.jsonValue["DateTimeLocalOffset"] =
21287c8c4058STejas Patil         redfishDateTimeOffset.second;
21297c8c4058STejas Patil 
2130fdd26906SClaire Weinan     asyncResp->res.jsonValue["Entries"]["@odata.id"] = dumpPath + "/Entries";
2131fdd26906SClaire Weinan 
2132fdd26906SClaire Weinan     if (collectDiagnosticDataSupported)
2133fdd26906SClaire Weinan     {
2134002d39b4SEd Tanous         asyncResp->res.jsonValue["Actions"]["#LogService.CollectDiagnosticData"]
21351476687dSEd Tanous                                 ["target"] =
2136fdd26906SClaire Weinan             dumpPath + "/Actions/LogService.CollectDiagnosticData";
2137fdd26906SClaire Weinan     }
21380d946211SClaire Weinan 
21390d946211SClaire Weinan     constexpr std::array<std::string_view, 1> interfaces = {deleteAllInterface};
21400d946211SClaire Weinan     dbus::utility::getSubTreePaths(
21410d946211SClaire Weinan         "/xyz/openbmc_project/dump", 0, interfaces,
21420d946211SClaire Weinan         [asyncResp, dumpType, dumpPath](
21430d946211SClaire Weinan             const boost::system::error_code& ec,
21440d946211SClaire Weinan             const dbus::utility::MapperGetSubTreePathsResponse& subTreePaths) {
21450d946211SClaire Weinan             if (ec)
21460d946211SClaire Weinan             {
2147bd79bce8SPatrick Williams                 BMCWEB_LOG_ERROR("getDumpServiceInfo respHandler got error {}",
2148bd79bce8SPatrick Williams                                  ec);
21490d946211SClaire Weinan                 // Assume that getting an error simply means there are no dump
21500d946211SClaire Weinan                 // LogServices. Return without adding any error response.
21510d946211SClaire Weinan                 return;
21520d946211SClaire Weinan             }
215318f8f608SEd Tanous             std::string dbusDumpPath = getDumpPath(dumpType);
21540d946211SClaire Weinan             for (const std::string& path : subTreePaths)
21550d946211SClaire Weinan             {
21560d946211SClaire Weinan                 if (path == dbusDumpPath)
21570d946211SClaire Weinan                 {
2158bd79bce8SPatrick Williams                     asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"]
2159bd79bce8SPatrick Williams                                             ["target"] =
21600d946211SClaire Weinan                         dumpPath + "/Actions/LogService.ClearLog";
21610d946211SClaire Weinan                     break;
21620d946211SClaire Weinan                 }
21630d946211SClaire Weinan             }
21640d946211SClaire Weinan         });
2165c9bb6861Sraviteja-b }
2166c9bb6861Sraviteja-b 
2167fdd26906SClaire Weinan inline void handleLogServicesDumpServiceGet(
2168fdd26906SClaire Weinan     crow::App& app, const std::string& dumpType, const crow::Request& req,
2169253f11b8SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2170253f11b8SEd Tanous     const std::string& managerId)
21717e860f15SJohn Edward Broadbent {
21723ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
217345ca1b86SEd Tanous     {
217445ca1b86SEd Tanous         return;
217545ca1b86SEd Tanous     }
2176253f11b8SEd Tanous 
2177253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2178253f11b8SEd Tanous     {
2179253f11b8SEd Tanous         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2180253f11b8SEd Tanous         return;
2181253f11b8SEd Tanous     }
2182253f11b8SEd Tanous 
2183fdd26906SClaire Weinan     getDumpServiceInfo(asyncResp, dumpType);
2184fdd26906SClaire Weinan }
2185c9bb6861Sraviteja-b 
218622d268cbSEd Tanous inline void handleLogServicesDumpServiceComputerSystemGet(
218722d268cbSEd Tanous     crow::App& app, const crow::Request& req,
218822d268cbSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
218922d268cbSEd Tanous     const std::string& chassisId)
219022d268cbSEd Tanous {
219122d268cbSEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
219222d268cbSEd Tanous     {
219322d268cbSEd Tanous         return;
219422d268cbSEd Tanous     }
2195253f11b8SEd Tanous     if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
219622d268cbSEd Tanous     {
219722d268cbSEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
219822d268cbSEd Tanous         return;
219922d268cbSEd Tanous     }
220022d268cbSEd Tanous     getDumpServiceInfo(asyncResp, "System");
220122d268cbSEd Tanous }
220222d268cbSEd Tanous 
2203fdd26906SClaire Weinan inline void handleLogServicesDumpEntriesCollectionGet(
2204fdd26906SClaire Weinan     crow::App& app, const std::string& dumpType, const crow::Request& req,
2205253f11b8SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2206253f11b8SEd Tanous     const std::string& managerId)
2207fdd26906SClaire Weinan {
2208fdd26906SClaire Weinan     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2209fdd26906SClaire Weinan     {
2210fdd26906SClaire Weinan         return;
2211fdd26906SClaire Weinan     }
2212253f11b8SEd Tanous 
2213253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2214253f11b8SEd Tanous     {
2215253f11b8SEd Tanous         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2216253f11b8SEd Tanous         return;
2217253f11b8SEd Tanous     }
2218fdd26906SClaire Weinan     getDumpEntryCollection(asyncResp, dumpType);
2219fdd26906SClaire Weinan }
2220fdd26906SClaire Weinan 
222122d268cbSEd Tanous inline void handleLogServicesDumpEntriesCollectionComputerSystemGet(
222222d268cbSEd Tanous     crow::App& app, const crow::Request& req,
222322d268cbSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
222422d268cbSEd Tanous     const std::string& chassisId)
222522d268cbSEd Tanous {
222622d268cbSEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
222722d268cbSEd Tanous     {
222822d268cbSEd Tanous         return;
222922d268cbSEd Tanous     }
2230253f11b8SEd Tanous     if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
223122d268cbSEd Tanous     {
223222d268cbSEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
223322d268cbSEd Tanous         return;
223422d268cbSEd Tanous     }
223522d268cbSEd Tanous     getDumpEntryCollection(asyncResp, "System");
223622d268cbSEd Tanous }
223722d268cbSEd Tanous 
2238fdd26906SClaire Weinan inline void handleLogServicesDumpEntryGet(
2239fdd26906SClaire Weinan     crow::App& app, const std::string& dumpType, const crow::Request& req,
2240fdd26906SClaire Weinan     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2241253f11b8SEd Tanous     const std::string& managerId, const std::string& dumpId)
2242fdd26906SClaire Weinan {
2243fdd26906SClaire Weinan     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2244fdd26906SClaire Weinan     {
2245fdd26906SClaire Weinan         return;
2246fdd26906SClaire Weinan     }
2247253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2248253f11b8SEd Tanous     {
2249253f11b8SEd Tanous         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2250253f11b8SEd Tanous         return;
2251253f11b8SEd Tanous     }
2252fdd26906SClaire Weinan     getDumpEntryById(asyncResp, dumpId, dumpType);
2253fdd26906SClaire Weinan }
2254168d1b1aSCarson Labrado 
225522d268cbSEd Tanous inline void handleLogServicesDumpEntryComputerSystemGet(
225622d268cbSEd Tanous     crow::App& app, const crow::Request& req,
225722d268cbSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
225822d268cbSEd Tanous     const std::string& chassisId, const std::string& dumpId)
225922d268cbSEd Tanous {
226022d268cbSEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
226122d268cbSEd Tanous     {
226222d268cbSEd Tanous         return;
226322d268cbSEd Tanous     }
2264253f11b8SEd Tanous     if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
226522d268cbSEd Tanous     {
226622d268cbSEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
226722d268cbSEd Tanous         return;
226822d268cbSEd Tanous     }
226922d268cbSEd Tanous     getDumpEntryById(asyncResp, dumpId, "System");
227022d268cbSEd Tanous }
2271fdd26906SClaire Weinan 
2272fdd26906SClaire Weinan inline void handleLogServicesDumpEntryDelete(
2273fdd26906SClaire Weinan     crow::App& app, const std::string& dumpType, const crow::Request& req,
2274fdd26906SClaire Weinan     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2275253f11b8SEd Tanous     const std::string& managerId, const std::string& dumpId)
2276fdd26906SClaire Weinan {
2277fdd26906SClaire Weinan     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2278fdd26906SClaire Weinan     {
2279fdd26906SClaire Weinan         return;
2280fdd26906SClaire Weinan     }
2281253f11b8SEd Tanous 
2282253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2283253f11b8SEd Tanous     {
2284253f11b8SEd Tanous         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2285253f11b8SEd Tanous         return;
2286253f11b8SEd Tanous     }
2287fdd26906SClaire Weinan     deleteDumpEntry(asyncResp, dumpId, dumpType);
2288fdd26906SClaire Weinan }
2289fdd26906SClaire Weinan 
229022d268cbSEd Tanous inline void handleLogServicesDumpEntryComputerSystemDelete(
229122d268cbSEd Tanous     crow::App& app, const crow::Request& req,
229222d268cbSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
229322d268cbSEd Tanous     const std::string& chassisId, const std::string& dumpId)
229422d268cbSEd Tanous {
229522d268cbSEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
229622d268cbSEd Tanous     {
229722d268cbSEd Tanous         return;
229822d268cbSEd Tanous     }
2299253f11b8SEd Tanous     if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
230022d268cbSEd Tanous     {
230122d268cbSEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
230222d268cbSEd Tanous         return;
230322d268cbSEd Tanous     }
230422d268cbSEd Tanous     deleteDumpEntry(asyncResp, dumpId, "System");
230522d268cbSEd Tanous }
230622d268cbSEd Tanous 
2307168d1b1aSCarson Labrado inline void handleLogServicesDumpEntryDownloadGet(
2308168d1b1aSCarson Labrado     crow::App& app, const std::string& dumpType, const crow::Request& req,
2309168d1b1aSCarson Labrado     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2310253f11b8SEd Tanous     const std::string& managerId, const std::string& dumpId)
2311168d1b1aSCarson Labrado {
2312168d1b1aSCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2313168d1b1aSCarson Labrado     {
2314168d1b1aSCarson Labrado         return;
2315168d1b1aSCarson Labrado     }
2316253f11b8SEd Tanous 
2317253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2318253f11b8SEd Tanous     {
2319253f11b8SEd Tanous         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2320253f11b8SEd Tanous         return;
2321253f11b8SEd Tanous     }
2322168d1b1aSCarson Labrado     downloadDumpEntry(asyncResp, dumpId, dumpType);
2323168d1b1aSCarson Labrado }
2324168d1b1aSCarson Labrado 
2325168d1b1aSCarson Labrado inline void handleDBusEventLogEntryDownloadGet(
2326168d1b1aSCarson Labrado     crow::App& app, const std::string& dumpType, const crow::Request& req,
2327168d1b1aSCarson Labrado     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2328168d1b1aSCarson Labrado     const std::string& systemName, const std::string& entryID)
2329168d1b1aSCarson Labrado {
2330168d1b1aSCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2331168d1b1aSCarson Labrado     {
2332168d1b1aSCarson Labrado         return;
2333168d1b1aSCarson Labrado     }
2334168d1b1aSCarson Labrado     if (!http_helpers::isContentTypeAllowed(
2335168d1b1aSCarson Labrado             req.getHeaderValue("Accept"),
2336168d1b1aSCarson Labrado             http_helpers::ContentType::OctetStream, true))
2337168d1b1aSCarson Labrado     {
2338168d1b1aSCarson Labrado         asyncResp->res.result(boost::beast::http::status::bad_request);
2339168d1b1aSCarson Labrado         return;
2340168d1b1aSCarson Labrado     }
2341168d1b1aSCarson Labrado     downloadEventLogEntry(asyncResp, systemName, entryID, dumpType);
2342168d1b1aSCarson Labrado }
2343168d1b1aSCarson Labrado 
2344fdd26906SClaire Weinan inline void handleLogServicesDumpCollectDiagnosticDataPost(
2345fdd26906SClaire Weinan     crow::App& app, const std::string& dumpType, const crow::Request& req,
2346253f11b8SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2347253f11b8SEd Tanous     const std::string& managerId)
2348fdd26906SClaire Weinan {
2349fdd26906SClaire Weinan     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2350fdd26906SClaire Weinan     {
2351fdd26906SClaire Weinan         return;
2352fdd26906SClaire Weinan     }
2353253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2354253f11b8SEd Tanous     {
2355253f11b8SEd Tanous         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2356253f11b8SEd Tanous         return;
2357253f11b8SEd Tanous     }
2358253f11b8SEd Tanous 
2359fdd26906SClaire Weinan     createDump(asyncResp, req, dumpType);
2360fdd26906SClaire Weinan }
2361fdd26906SClaire Weinan 
236222d268cbSEd Tanous inline void handleLogServicesDumpCollectDiagnosticDataComputerSystemPost(
236322d268cbSEd Tanous     crow::App& app, const crow::Request& req,
236422d268cbSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
23657f3e84a1SEd Tanous     const std::string& systemName)
236622d268cbSEd Tanous {
236722d268cbSEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
236822d268cbSEd Tanous     {
236922d268cbSEd Tanous         return;
237022d268cbSEd Tanous     }
23717f3e84a1SEd Tanous 
237225b54dbaSEd Tanous     if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
237322d268cbSEd Tanous     {
23747f3e84a1SEd Tanous         // Option currently returns no systems.  TBD
23757f3e84a1SEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
23767f3e84a1SEd Tanous                                    systemName);
23777f3e84a1SEd Tanous         return;
23787f3e84a1SEd Tanous     }
2379253f11b8SEd Tanous     if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
23807f3e84a1SEd Tanous     {
23817f3e84a1SEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
23827f3e84a1SEd Tanous                                    systemName);
238322d268cbSEd Tanous         return;
238422d268cbSEd Tanous     }
238522d268cbSEd Tanous     createDump(asyncResp, req, "System");
238622d268cbSEd Tanous }
238722d268cbSEd Tanous 
2388fdd26906SClaire Weinan inline void handleLogServicesDumpClearLogPost(
2389fdd26906SClaire Weinan     crow::App& app, const std::string& dumpType, const crow::Request& req,
2390253f11b8SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2391253f11b8SEd Tanous     const std::string& managerId)
2392fdd26906SClaire Weinan {
2393fdd26906SClaire Weinan     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2394fdd26906SClaire Weinan     {
2395fdd26906SClaire Weinan         return;
2396fdd26906SClaire Weinan     }
2397253f11b8SEd Tanous 
2398253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2399253f11b8SEd Tanous     {
2400253f11b8SEd Tanous         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2401253f11b8SEd Tanous         return;
2402253f11b8SEd Tanous     }
2403fdd26906SClaire Weinan     clearDump(asyncResp, dumpType);
2404fdd26906SClaire Weinan }
2405fdd26906SClaire Weinan 
240622d268cbSEd Tanous inline void handleLogServicesDumpClearLogComputerSystemPost(
240722d268cbSEd Tanous     crow::App& app, const crow::Request& req,
240822d268cbSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
24097f3e84a1SEd Tanous     const std::string& systemName)
241022d268cbSEd Tanous {
241122d268cbSEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
241222d268cbSEd Tanous     {
241322d268cbSEd Tanous         return;
241422d268cbSEd Tanous     }
241525b54dbaSEd Tanous     if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
241622d268cbSEd Tanous     {
24177f3e84a1SEd Tanous         // Option currently returns no systems.  TBD
24187f3e84a1SEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
24197f3e84a1SEd Tanous                                    systemName);
24207f3e84a1SEd Tanous         return;
24217f3e84a1SEd Tanous     }
2422253f11b8SEd Tanous     if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
24237f3e84a1SEd Tanous     {
24247f3e84a1SEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
24257f3e84a1SEd Tanous                                    systemName);
242622d268cbSEd Tanous         return;
242722d268cbSEd Tanous     }
242822d268cbSEd Tanous     clearDump(asyncResp, "System");
242922d268cbSEd Tanous }
243022d268cbSEd Tanous 
2431fdd26906SClaire Weinan inline void requestRoutesBMCDumpService(App& app)
2432fdd26906SClaire Weinan {
2433253f11b8SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/Dump/")
2434fdd26906SClaire Weinan         .privileges(redfish::privileges::getLogService)
2435fdd26906SClaire Weinan         .methods(boost::beast::http::verb::get)(std::bind_front(
2436fdd26906SClaire Weinan             handleLogServicesDumpServiceGet, std::ref(app), "BMC"));
2437fdd26906SClaire Weinan }
2438fdd26906SClaire Weinan 
2439fdd26906SClaire Weinan inline void requestRoutesBMCDumpEntryCollection(App& app)
2440fdd26906SClaire Weinan {
2441253f11b8SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/")
2442fdd26906SClaire Weinan         .privileges(redfish::privileges::getLogEntryCollection)
2443fdd26906SClaire Weinan         .methods(boost::beast::http::verb::get)(std::bind_front(
2444fdd26906SClaire Weinan             handleLogServicesDumpEntriesCollectionGet, std::ref(app), "BMC"));
2445c9bb6861Sraviteja-b }
2446c9bb6861Sraviteja-b 
24477e860f15SJohn Edward Broadbent inline void requestRoutesBMCDumpEntry(App& app)
2448c9bb6861Sraviteja-b {
24497e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
2450253f11b8SEd Tanous                  "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/")
2451ed398213SEd Tanous         .privileges(redfish::privileges::getLogEntry)
2452fdd26906SClaire Weinan         .methods(boost::beast::http::verb::get)(std::bind_front(
2453fdd26906SClaire Weinan             handleLogServicesDumpEntryGet, std::ref(app), "BMC"));
2454fdd26906SClaire Weinan 
24557e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
2456253f11b8SEd Tanous                  "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/")
2457ed398213SEd Tanous         .privileges(redfish::privileges::deleteLogEntry)
2458fdd26906SClaire Weinan         .methods(boost::beast::http::verb::delete_)(std::bind_front(
2459fdd26906SClaire Weinan             handleLogServicesDumpEntryDelete, std::ref(app), "BMC"));
2460c9bb6861Sraviteja-b }
2461c9bb6861Sraviteja-b 
2462168d1b1aSCarson Labrado inline void requestRoutesBMCDumpEntryDownload(App& app)
2463168d1b1aSCarson Labrado {
2464168d1b1aSCarson Labrado     BMCWEB_ROUTE(
2465168d1b1aSCarson Labrado         app,
2466253f11b8SEd Tanous         "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/attachment/")
2467168d1b1aSCarson Labrado         .privileges(redfish::privileges::getLogEntry)
2468168d1b1aSCarson Labrado         .methods(boost::beast::http::verb::get)(std::bind_front(
2469168d1b1aSCarson Labrado             handleLogServicesDumpEntryDownloadGet, std::ref(app), "BMC"));
2470168d1b1aSCarson Labrado }
2471168d1b1aSCarson Labrado 
24727e860f15SJohn Edward Broadbent inline void requestRoutesBMCDumpCreate(App& app)
2473c9bb6861Sraviteja-b {
24740fda0f12SGeorge Liu     BMCWEB_ROUTE(
24750fda0f12SGeorge Liu         app,
2476253f11b8SEd Tanous         "/redfish/v1/Managers/<str>/LogServices/Dump/Actions/LogService.CollectDiagnosticData/")
2477ed398213SEd Tanous         .privileges(redfish::privileges::postLogService)
24787e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
2479fdd26906SClaire Weinan             std::bind_front(handleLogServicesDumpCollectDiagnosticDataPost,
2480fdd26906SClaire Weinan                             std::ref(app), "BMC"));
2481a43be80fSAsmitha Karunanithi }
2482a43be80fSAsmitha Karunanithi 
24837e860f15SJohn Edward Broadbent inline void requestRoutesBMCDumpClear(App& app)
248480319af1SAsmitha Karunanithi {
24850fda0f12SGeorge Liu     BMCWEB_ROUTE(
24860fda0f12SGeorge Liu         app,
2487253f11b8SEd Tanous         "/redfish/v1/Managers/<str>/LogServices/Dump/Actions/LogService.ClearLog/")
2488ed398213SEd Tanous         .privileges(redfish::privileges::postLogService)
2489fdd26906SClaire Weinan         .methods(boost::beast::http::verb::post)(std::bind_front(
2490fdd26906SClaire Weinan             handleLogServicesDumpClearLogPost, std::ref(app), "BMC"));
249145ca1b86SEd Tanous }
2492fdd26906SClaire Weinan 
2493168d1b1aSCarson Labrado inline void requestRoutesDBusEventLogEntryDownload(App& app)
2494168d1b1aSCarson Labrado {
2495168d1b1aSCarson Labrado     BMCWEB_ROUTE(
2496168d1b1aSCarson Labrado         app,
24979e9d99daSRavi Teja         "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/attachment/")
2498168d1b1aSCarson Labrado         .privileges(redfish::privileges::getLogEntry)
2499168d1b1aSCarson Labrado         .methods(boost::beast::http::verb::get)(std::bind_front(
2500168d1b1aSCarson Labrado             handleDBusEventLogEntryDownloadGet, std::ref(app), "System"));
2501168d1b1aSCarson Labrado }
2502168d1b1aSCarson Labrado 
2503fdd26906SClaire Weinan inline void requestRoutesFaultLogDumpService(App& app)
2504fdd26906SClaire Weinan {
2505253f11b8SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/")
2506fdd26906SClaire Weinan         .privileges(redfish::privileges::getLogService)
2507fdd26906SClaire Weinan         .methods(boost::beast::http::verb::get)(std::bind_front(
2508fdd26906SClaire Weinan             handleLogServicesDumpServiceGet, std::ref(app), "FaultLog"));
2509fdd26906SClaire Weinan }
2510fdd26906SClaire Weinan 
2511fdd26906SClaire Weinan inline void requestRoutesFaultLogDumpEntryCollection(App& app)
2512fdd26906SClaire Weinan {
2513253f11b8SEd Tanous     BMCWEB_ROUTE(app,
2514253f11b8SEd Tanous                  "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/")
2515fdd26906SClaire Weinan         .privileges(redfish::privileges::getLogEntryCollection)
2516fdd26906SClaire Weinan         .methods(boost::beast::http::verb::get)(
2517fdd26906SClaire Weinan             std::bind_front(handleLogServicesDumpEntriesCollectionGet,
2518fdd26906SClaire Weinan                             std::ref(app), "FaultLog"));
2519fdd26906SClaire Weinan }
2520fdd26906SClaire Weinan 
2521fdd26906SClaire Weinan inline void requestRoutesFaultLogDumpEntry(App& app)
2522fdd26906SClaire Weinan {
2523253f11b8SEd Tanous     BMCWEB_ROUTE(
2524253f11b8SEd Tanous         app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/<str>/")
2525fdd26906SClaire Weinan         .privileges(redfish::privileges::getLogEntry)
2526fdd26906SClaire Weinan         .methods(boost::beast::http::verb::get)(std::bind_front(
2527fdd26906SClaire Weinan             handleLogServicesDumpEntryGet, std::ref(app), "FaultLog"));
2528fdd26906SClaire Weinan 
2529253f11b8SEd Tanous     BMCWEB_ROUTE(
2530253f11b8SEd Tanous         app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/<str>/")
2531fdd26906SClaire Weinan         .privileges(redfish::privileges::deleteLogEntry)
2532fdd26906SClaire Weinan         .methods(boost::beast::http::verb::delete_)(std::bind_front(
2533fdd26906SClaire Weinan             handleLogServicesDumpEntryDelete, std::ref(app), "FaultLog"));
2534fdd26906SClaire Weinan }
2535fdd26906SClaire Weinan 
2536fdd26906SClaire Weinan inline void requestRoutesFaultLogDumpClear(App& app)
2537fdd26906SClaire Weinan {
2538fdd26906SClaire Weinan     BMCWEB_ROUTE(
2539fdd26906SClaire Weinan         app,
2540253f11b8SEd Tanous         "/redfish/v1/Managers/<str>/LogServices/FaultLog/Actions/LogService.ClearLog/")
2541fdd26906SClaire Weinan         .privileges(redfish::privileges::postLogService)
2542fdd26906SClaire Weinan         .methods(boost::beast::http::verb::post)(std::bind_front(
2543fdd26906SClaire Weinan             handleLogServicesDumpClearLogPost, std::ref(app), "FaultLog"));
25445cb1dd27SAsmitha Karunanithi }
25455cb1dd27SAsmitha Karunanithi 
25467e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpService(App& app)
25475cb1dd27SAsmitha Karunanithi {
254822d268cbSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Dump/")
2549ed398213SEd Tanous         .privileges(redfish::privileges::getLogService)
25506ab9ad54SClaire Weinan         .methods(boost::beast::http::verb::get)(std::bind_front(
255122d268cbSEd Tanous             handleLogServicesDumpServiceComputerSystemGet, std::ref(app)));
25525cb1dd27SAsmitha Karunanithi }
25535cb1dd27SAsmitha Karunanithi 
25547e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpEntryCollection(App& app)
25557e860f15SJohn Edward Broadbent {
255622d268cbSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/")
2557ed398213SEd Tanous         .privileges(redfish::privileges::getLogEntryCollection)
255822d268cbSEd Tanous         .methods(boost::beast::http::verb::get)(std::bind_front(
255922d268cbSEd Tanous             handleLogServicesDumpEntriesCollectionComputerSystemGet,
256022d268cbSEd Tanous             std::ref(app)));
25615cb1dd27SAsmitha Karunanithi }
25625cb1dd27SAsmitha Karunanithi 
25637e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpEntry(App& app)
25645cb1dd27SAsmitha Karunanithi {
25657e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
256622d268cbSEd Tanous                  "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/<str>/")
2567ed398213SEd Tanous         .privileges(redfish::privileges::getLogEntry)
25686ab9ad54SClaire Weinan         .methods(boost::beast::http::verb::get)(std::bind_front(
256922d268cbSEd Tanous             handleLogServicesDumpEntryComputerSystemGet, std::ref(app)));
25708d1b46d7Szhanghch05 
25717e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
257222d268cbSEd Tanous                  "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/<str>/")
2573ed398213SEd Tanous         .privileges(redfish::privileges::deleteLogEntry)
25746ab9ad54SClaire Weinan         .methods(boost::beast::http::verb::delete_)(std::bind_front(
257522d268cbSEd Tanous             handleLogServicesDumpEntryComputerSystemDelete, std::ref(app)));
25765cb1dd27SAsmitha Karunanithi }
2577c9bb6861Sraviteja-b 
25787e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpCreate(App& app)
2579c9bb6861Sraviteja-b {
25800fda0f12SGeorge Liu     BMCWEB_ROUTE(
25810fda0f12SGeorge Liu         app,
258222d268cbSEd Tanous         "/redfish/v1/Systems/<str>/LogServices/Dump/Actions/LogService.CollectDiagnosticData/")
2583ed398213SEd Tanous         .privileges(redfish::privileges::postLogService)
258422d268cbSEd Tanous         .methods(boost::beast::http::verb::post)(std::bind_front(
258522d268cbSEd Tanous             handleLogServicesDumpCollectDiagnosticDataComputerSystemPost,
258622d268cbSEd Tanous             std::ref(app)));
2587a43be80fSAsmitha Karunanithi }
2588a43be80fSAsmitha Karunanithi 
25897e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpClear(App& app)
2590a43be80fSAsmitha Karunanithi {
25910fda0f12SGeorge Liu     BMCWEB_ROUTE(
25920fda0f12SGeorge Liu         app,
259322d268cbSEd Tanous         "/redfish/v1/Systems/<str>/LogServices/Dump/Actions/LogService.ClearLog/")
2594ed398213SEd Tanous         .privileges(redfish::privileges::postLogService)
25956ab9ad54SClaire Weinan         .methods(boost::beast::http::verb::post)(std::bind_front(
259622d268cbSEd Tanous             handleLogServicesDumpClearLogComputerSystemPost, std::ref(app)));
2597013487e5Sraviteja-b }
2598013487e5Sraviteja-b 
25997e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpService(App& app)
26001da66f75SEd Tanous {
26013946028dSAppaRao Puli     // Note: Deviated from redfish privilege registry for GET & HEAD
26023946028dSAppaRao Puli     // method for security reasons.
26031da66f75SEd Tanous     /**
26041da66f75SEd Tanous      * Functions triggers appropriate requests on DBus
26051da66f75SEd Tanous      */
260622d268cbSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Crashdump/")
2607ed398213SEd Tanous         // This is incorrect, should be:
2608ed398213SEd Tanous         //.privileges(redfish::privileges::getLogService)
2609432a890cSEd Tanous         .privileges({{"ConfigureManager"}})
2610bd79bce8SPatrick Williams         .methods(
2611bd79bce8SPatrick Williams             boost::beast::http::verb::
2612bd79bce8SPatrick Williams                 get)([&app](const crow::Request& req,
261322d268cbSEd Tanous                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
261422d268cbSEd Tanous                             const std::string& systemName) {
26153ba00073SCarson Labrado             if (!redfish::setUpRedfishRoute(app, req, asyncResp))
261645ca1b86SEd Tanous             {
261745ca1b86SEd Tanous                 return;
261845ca1b86SEd Tanous             }
261925b54dbaSEd Tanous             if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
26207f3e84a1SEd Tanous             {
26217f3e84a1SEd Tanous                 // Option currently returns no systems.  TBD
26227f3e84a1SEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
26237f3e84a1SEd Tanous                                            systemName);
26247f3e84a1SEd Tanous                 return;
26257f3e84a1SEd Tanous             }
2626253f11b8SEd Tanous             if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
262722d268cbSEd Tanous             {
262822d268cbSEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
262922d268cbSEd Tanous                                            systemName);
263022d268cbSEd Tanous                 return;
263122d268cbSEd Tanous             }
263222d268cbSEd Tanous 
26337e860f15SJohn Edward Broadbent             // Copy over the static data to include the entries added by
26347e860f15SJohn Edward Broadbent             // SubRoute
26350f74e643SEd Tanous             asyncResp->res.jsonValue["@odata.id"] =
2636253f11b8SEd Tanous                 std::format("/redfish/v1/Systems/{}/LogServices/Crashdump",
2637253f11b8SEd Tanous                             BMCWEB_REDFISH_SYSTEM_URI_NAME);
2638e1f26343SJason M. Bills             asyncResp->res.jsonValue["@odata.type"] =
26398e6c099aSJason M. Bills                 "#LogService.v1_2_0.LogService";
26404f50ae4bSGunnar Mills             asyncResp->res.jsonValue["Name"] = "Open BMC Oem Crashdump Service";
26414f50ae4bSGunnar Mills             asyncResp->res.jsonValue["Description"] = "Oem Crashdump Service";
264215b89725SV-Sanjana             asyncResp->res.jsonValue["Id"] = "Crashdump";
2643539d8c6bSEd Tanous             asyncResp->res.jsonValue["OverWritePolicy"] =
2644539d8c6bSEd Tanous                 log_service::OverWritePolicy::WrapsWhenFull;
2645e1f26343SJason M. Bills             asyncResp->res.jsonValue["MaxNumberOfRecords"] = 3;
26467c8c4058STejas Patil 
26477c8c4058STejas Patil             std::pair<std::string, std::string> redfishDateTimeOffset =
26482b82937eSEd Tanous                 redfish::time_utils::getDateTimeOffsetNow();
26497c8c4058STejas Patil             asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
26507c8c4058STejas Patil             asyncResp->res.jsonValue["DateTimeLocalOffset"] =
26517c8c4058STejas Patil                 redfishDateTimeOffset.second;
26527c8c4058STejas Patil 
2653bd79bce8SPatrick Williams             asyncResp->res.jsonValue["Entries"]["@odata.id"] = std::format(
2654bd79bce8SPatrick Williams                 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries",
2655253f11b8SEd Tanous                 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2656253f11b8SEd Tanous             asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"]
2657253f11b8SEd Tanous                                     ["target"] = std::format(
2658253f11b8SEd Tanous                 "/redfish/v1/Systems/{}/LogServices/Crashdump/Actions/LogService.ClearLog",
2659253f11b8SEd Tanous                 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2660bd79bce8SPatrick Williams             asyncResp->res
2661bd79bce8SPatrick Williams                 .jsonValue["Actions"]["#LogService.CollectDiagnosticData"]
2662253f11b8SEd Tanous                           ["target"] = std::format(
2663253f11b8SEd Tanous                 "/redfish/v1/Systems/{}/LogServices/Crashdump/Actions/LogService.CollectDiagnosticData",
2664253f11b8SEd Tanous                 BMCWEB_REDFISH_SYSTEM_URI_NAME);
26657e860f15SJohn Edward Broadbent         });
26661da66f75SEd Tanous }
26671da66f75SEd Tanous 
26687e860f15SJohn Edward Broadbent void inline requestRoutesCrashdumpClear(App& app)
26695b61b5e8SJason M. Bills {
26700fda0f12SGeorge Liu     BMCWEB_ROUTE(
26710fda0f12SGeorge Liu         app,
267222d268cbSEd Tanous         "/redfish/v1/Systems/<str>/LogServices/Crashdump/Actions/LogService.ClearLog/")
2673ed398213SEd Tanous         // This is incorrect, should be:
2674ed398213SEd Tanous         //.privileges(redfish::privileges::postLogService)
2675432a890cSEd Tanous         .privileges({{"ConfigureComponents"}})
26767e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
267745ca1b86SEd Tanous             [&app](const crow::Request& req,
267822d268cbSEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
267922d268cbSEd Tanous                    const std::string& systemName) {
26803ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
268145ca1b86SEd Tanous                 {
268245ca1b86SEd Tanous                     return;
268345ca1b86SEd Tanous                 }
268425b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
26857f3e84a1SEd Tanous                 {
26867f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
26877f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
26887f3e84a1SEd Tanous                                                systemName);
26897f3e84a1SEd Tanous                     return;
26907f3e84a1SEd Tanous                 }
2691253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
269222d268cbSEd Tanous                 {
269322d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
269422d268cbSEd Tanous                                                systemName);
269522d268cbSEd Tanous                     return;
269622d268cbSEd Tanous                 }
26975b61b5e8SJason M. Bills                 crow::connections::systemBus->async_method_call(
26985e7e2dc5SEd Tanous                     [asyncResp](const boost::system::error_code& ec,
2699cb13a392SEd Tanous                                 const std::string&) {
27005b61b5e8SJason M. Bills                         if (ec)
27015b61b5e8SJason M. Bills                         {
27025b61b5e8SJason M. Bills                             messages::internalError(asyncResp->res);
27035b61b5e8SJason M. Bills                             return;
27045b61b5e8SJason M. Bills                         }
27055b61b5e8SJason M. Bills                         messages::success(asyncResp->res);
27065b61b5e8SJason M. Bills                     },
2707bd79bce8SPatrick Williams                     crashdumpObject, crashdumpPath, deleteAllInterface,
2708bd79bce8SPatrick Williams                     "DeleteAll");
27097e860f15SJohn Edward Broadbent             });
27105b61b5e8SJason M. Bills }
27115b61b5e8SJason M. Bills 
27124ff0f1f4SEd Tanous inline void
27138d1b46d7Szhanghch05     logCrashdumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
27148d1b46d7Szhanghch05                       const std::string& logID, nlohmann::json& logEntryJson)
2715e855dd28SJason M. Bills {
2716043a0536SJohnathan Mantey     auto getStoredLogCallback =
2717b9d36b47SEd Tanous         [asyncResp, logID,
27185e7e2dc5SEd Tanous          &logEntryJson](const boost::system::error_code& ec,
2719b9d36b47SEd Tanous                         const dbus::utility::DBusPropertiesMap& params) {
2720e855dd28SJason M. Bills             if (ec)
2721e855dd28SJason M. Bills             {
272262598e31SEd Tanous                 BMCWEB_LOG_DEBUG("failed to get log ec: {}", ec.message());
27231ddcf01aSJason M. Bills                 if (ec.value() ==
27241ddcf01aSJason M. Bills                     boost::system::linux_error::bad_request_descriptor)
27251ddcf01aSJason M. Bills                 {
2726bd79bce8SPatrick Williams                     messages::resourceNotFound(asyncResp->res, "LogEntry",
2727bd79bce8SPatrick Williams                                                logID);
27281ddcf01aSJason M. Bills                 }
27291ddcf01aSJason M. Bills                 else
27301ddcf01aSJason M. Bills                 {
2731e855dd28SJason M. Bills                     messages::internalError(asyncResp->res);
27321ddcf01aSJason M. Bills                 }
2733e855dd28SJason M. Bills                 return;
2734e855dd28SJason M. Bills             }
2735043a0536SJohnathan Mantey 
2736043a0536SJohnathan Mantey             std::string timestamp{};
2737043a0536SJohnathan Mantey             std::string filename{};
2738043a0536SJohnathan Mantey             std::string logfile{};
27392c70f800SEd Tanous             parseCrashdumpParameters(params, filename, timestamp, logfile);
2740043a0536SJohnathan Mantey 
2741043a0536SJohnathan Mantey             if (filename.empty() || timestamp.empty())
2742e855dd28SJason M. Bills             {
27439db4ba25SJiaqing Zhao                 messages::resourceNotFound(asyncResp->res, "LogEntry", logID);
2744e855dd28SJason M. Bills                 return;
2745e855dd28SJason M. Bills             }
2746e855dd28SJason M. Bills 
2747043a0536SJohnathan Mantey             std::string crashdumpURI =
2748bd79bce8SPatrick Williams                 std::format(
2749bd79bce8SPatrick Williams                     "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries/",
2750253f11b8SEd Tanous                     BMCWEB_REDFISH_SYSTEM_URI_NAME) +
2751043a0536SJohnathan Mantey                 logID + "/" + filename;
275284afc48bSJason M. Bills             nlohmann::json::object_t logEntry;
27539c11a172SVijay Lobo             logEntry["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
2754ef4c65b7SEd Tanous             logEntry["@odata.id"] = boost::urls::format(
2755253f11b8SEd Tanous                 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries/{}",
2756253f11b8SEd Tanous                 BMCWEB_REDFISH_SYSTEM_URI_NAME, logID);
275784afc48bSJason M. Bills             logEntry["Name"] = "CPU Crashdump";
275884afc48bSJason M. Bills             logEntry["Id"] = logID;
2759539d8c6bSEd Tanous             logEntry["EntryType"] = log_entry::LogEntryType::Oem;
276084afc48bSJason M. Bills             logEntry["AdditionalDataURI"] = std::move(crashdumpURI);
276184afc48bSJason M. Bills             logEntry["DiagnosticDataType"] = "OEM";
276284afc48bSJason M. Bills             logEntry["OEMDiagnosticDataType"] = "PECICrashdump";
276384afc48bSJason M. Bills             logEntry["Created"] = std::move(timestamp);
27642b20ef6eSJason M. Bills 
27652b20ef6eSJason M. Bills             // If logEntryJson references an array of LogEntry resources
27662b20ef6eSJason M. Bills             // ('Members' list), then push this as a new entry, otherwise set it
27672b20ef6eSJason M. Bills             // directly
27682b20ef6eSJason M. Bills             if (logEntryJson.is_array())
27692b20ef6eSJason M. Bills             {
27702b20ef6eSJason M. Bills                 logEntryJson.push_back(logEntry);
27712b20ef6eSJason M. Bills                 asyncResp->res.jsonValue["Members@odata.count"] =
27722b20ef6eSJason M. Bills                     logEntryJson.size();
27732b20ef6eSJason M. Bills             }
27742b20ef6eSJason M. Bills             else
27752b20ef6eSJason M. Bills             {
2776d405bb51SJason M. Bills                 logEntryJson.update(logEntry);
27772b20ef6eSJason M. Bills             }
2778e855dd28SJason M. Bills         };
2779deae6a78SEd Tanous     dbus::utility::getAllProperties(
2780deae6a78SEd Tanous         crashdumpObject, crashdumpPath + std::string("/") + logID,
2781deae6a78SEd Tanous         crashdumpInterface, std::move(getStoredLogCallback));
2782e855dd28SJason M. Bills }
2783e855dd28SJason M. Bills 
27847e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpEntryCollection(App& app)
27851da66f75SEd Tanous {
27863946028dSAppaRao Puli     // Note: Deviated from redfish privilege registry for GET & HEAD
27873946028dSAppaRao Puli     // method for security reasons.
27881da66f75SEd Tanous     /**
27891da66f75SEd Tanous      * Functions triggers appropriate requests on DBus
27901da66f75SEd Tanous      */
27917e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
279222d268cbSEd Tanous                  "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/")
2793ed398213SEd Tanous         // This is incorrect, should be.
2794ed398213SEd Tanous         //.privileges(redfish::privileges::postLogEntryCollection)
2795432a890cSEd Tanous         .privileges({{"ConfigureComponents"}})
2796bd79bce8SPatrick Williams         .methods(
2797bd79bce8SPatrick Williams             boost::beast::http::verb::
2798bd79bce8SPatrick Williams                 get)([&app](const crow::Request& req,
279922d268cbSEd Tanous                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
280022d268cbSEd Tanous                             const std::string& systemName) {
28013ba00073SCarson Labrado             if (!redfish::setUpRedfishRoute(app, req, asyncResp))
280245ca1b86SEd Tanous             {
280345ca1b86SEd Tanous                 return;
280445ca1b86SEd Tanous             }
280525b54dbaSEd Tanous             if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
28067f3e84a1SEd Tanous             {
28077f3e84a1SEd Tanous                 // Option currently returns no systems.  TBD
28087f3e84a1SEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
28097f3e84a1SEd Tanous                                            systemName);
28107f3e84a1SEd Tanous                 return;
28117f3e84a1SEd Tanous             }
2812253f11b8SEd Tanous             if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
281322d268cbSEd Tanous             {
281422d268cbSEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
281522d268cbSEd Tanous                                            systemName);
281622d268cbSEd Tanous                 return;
281722d268cbSEd Tanous             }
281822d268cbSEd Tanous 
28197a1dbc48SGeorge Liu             constexpr std::array<std::string_view, 1> interfaces = {
28207a1dbc48SGeorge Liu                 crashdumpInterface};
28217a1dbc48SGeorge Liu             dbus::utility::getSubTreePaths(
28227a1dbc48SGeorge Liu                 "/", 0, interfaces,
28237a1dbc48SGeorge Liu                 [asyncResp](const boost::system::error_code& ec,
28242b20ef6eSJason M. Bills                             const std::vector<std::string>& resp) {
28251da66f75SEd Tanous                     if (ec)
28261da66f75SEd Tanous                     {
28271da66f75SEd Tanous                         if (ec.value() !=
28281da66f75SEd Tanous                             boost::system::errc::no_such_file_or_directory)
28291da66f75SEd Tanous                         {
283062598e31SEd Tanous                             BMCWEB_LOG_DEBUG("failed to get entries ec: {}",
283162598e31SEd Tanous                                              ec.message());
2832f12894f8SJason M. Bills                             messages::internalError(asyncResp->res);
28331da66f75SEd Tanous                             return;
28341da66f75SEd Tanous                         }
28351da66f75SEd Tanous                     }
2836e1f26343SJason M. Bills                     asyncResp->res.jsonValue["@odata.type"] =
28371da66f75SEd Tanous                         "#LogEntryCollection.LogEntryCollection";
2838253f11b8SEd Tanous                     asyncResp->res.jsonValue["@odata.id"] = std::format(
2839253f11b8SEd Tanous                         "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries",
2840253f11b8SEd Tanous                         BMCWEB_REDFISH_SYSTEM_URI_NAME);
2841bd79bce8SPatrick Williams                     asyncResp->res.jsonValue["Name"] =
2842bd79bce8SPatrick Williams                         "Open BMC Crashdump Entries";
2843e1f26343SJason M. Bills                     asyncResp->res.jsonValue["Description"] =
2844424c4176SJason M. Bills                         "Collection of Crashdump Entries";
2845bd79bce8SPatrick Williams                     asyncResp->res.jsonValue["Members"] =
2846bd79bce8SPatrick Williams                         nlohmann::json::array();
2847a2dd60a6SBrandon Kim                     asyncResp->res.jsonValue["Members@odata.count"] = 0;
28482b20ef6eSJason M. Bills 
28492b20ef6eSJason M. Bills                     for (const std::string& path : resp)
28501da66f75SEd Tanous                     {
28512b20ef6eSJason M. Bills                         const sdbusplus::message::object_path objPath(path);
2852e855dd28SJason M. Bills                         // Get the log ID
28532b20ef6eSJason M. Bills                         std::string logID = objPath.filename();
28542b20ef6eSJason M. Bills                         if (logID.empty())
28551da66f75SEd Tanous                         {
2856e855dd28SJason M. Bills                             continue;
28571da66f75SEd Tanous                         }
2858e855dd28SJason M. Bills                         // Add the log entry to the array
28592b20ef6eSJason M. Bills                         logCrashdumpEntry(asyncResp, logID,
28602b20ef6eSJason M. Bills                                           asyncResp->res.jsonValue["Members"]);
28611da66f75SEd Tanous                     }
28627a1dbc48SGeorge Liu                 });
28637e860f15SJohn Edward Broadbent         });
28641da66f75SEd Tanous }
28651da66f75SEd Tanous 
28667e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpEntry(App& app)
28671da66f75SEd Tanous {
28683946028dSAppaRao Puli     // Note: Deviated from redfish privilege registry for GET & HEAD
28693946028dSAppaRao Puli     // method for security reasons.
28701da66f75SEd Tanous 
28717e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
287222d268cbSEd Tanous         app, "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/<str>/")
2873ed398213SEd Tanous         // this is incorrect, should be
2874ed398213SEd Tanous         // .privileges(redfish::privileges::getLogEntry)
2875432a890cSEd Tanous         .privileges({{"ConfigureComponents"}})
28767e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
287745ca1b86SEd Tanous             [&app](const crow::Request& req,
28787e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
287922d268cbSEd Tanous                    const std::string& systemName, const std::string& param) {
28803ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
288145ca1b86SEd Tanous                 {
288245ca1b86SEd Tanous                     return;
288345ca1b86SEd Tanous                 }
288425b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
28857f3e84a1SEd Tanous                 {
28867f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
28877f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
28887f3e84a1SEd Tanous                                                systemName);
28897f3e84a1SEd Tanous                     return;
28907f3e84a1SEd Tanous                 }
2891253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
289222d268cbSEd Tanous                 {
289322d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
289422d268cbSEd Tanous                                                systemName);
289522d268cbSEd Tanous                     return;
289622d268cbSEd Tanous                 }
28977e860f15SJohn Edward Broadbent                 const std::string& logID = param;
2898e855dd28SJason M. Bills                 logCrashdumpEntry(asyncResp, logID, asyncResp->res.jsonValue);
28997e860f15SJohn Edward Broadbent             });
2900e855dd28SJason M. Bills }
2901e855dd28SJason M. Bills 
29027e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpFile(App& app)
2903e855dd28SJason M. Bills {
29043946028dSAppaRao Puli     // Note: Deviated from redfish privilege registry for GET & HEAD
29053946028dSAppaRao Puli     // method for security reasons.
29067e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
29077e860f15SJohn Edward Broadbent         app,
290822d268cbSEd Tanous         "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/<str>/<str>/")
2909ed398213SEd Tanous         .privileges(redfish::privileges::getLogEntry)
29107e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
2911a4ce114aSNan Zhou             [](const crow::Request& req,
29127e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
291322d268cbSEd Tanous                const std::string& systemName, const std::string& logID,
291422d268cbSEd Tanous                const std::string& fileName) {
2915bd79bce8SPatrick Williams                 // Do not call getRedfishRoute here since the crashdump file is
2916bd79bce8SPatrick Williams                 // not a Redfish resource.
291722d268cbSEd Tanous 
291825b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
29197f3e84a1SEd Tanous                 {
29207f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
29217f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
29227f3e84a1SEd Tanous                                                systemName);
29237f3e84a1SEd Tanous                     return;
29247f3e84a1SEd Tanous                 }
2925253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
292622d268cbSEd Tanous                 {
292722d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
292822d268cbSEd Tanous                                                systemName);
292922d268cbSEd Tanous                     return;
293022d268cbSEd Tanous                 }
293122d268cbSEd Tanous 
2932043a0536SJohnathan Mantey                 auto getStoredLogCallback =
2933bd79bce8SPatrick Williams                     [asyncResp, logID, fileName,
2934bd79bce8SPatrick Williams                      url(boost::urls::url(req.url()))](
29355e7e2dc5SEd Tanous                         const boost::system::error_code& ec,
2936bd79bce8SPatrick Williams                         const std::vector<std::pair<
2937bd79bce8SPatrick Williams                             std::string, dbus::utility::DbusVariantType>>&
29387e860f15SJohn Edward Broadbent                             resp) {
29391da66f75SEd Tanous                         if (ec)
29401da66f75SEd Tanous                         {
2941bd79bce8SPatrick Williams                             BMCWEB_LOG_DEBUG("failed to get log ec: {}",
2942bd79bce8SPatrick Williams                                              ec.message());
2943f12894f8SJason M. Bills                             messages::internalError(asyncResp->res);
29441da66f75SEd Tanous                             return;
29451da66f75SEd Tanous                         }
2946e855dd28SJason M. Bills 
2947043a0536SJohnathan Mantey                         std::string dbusFilename{};
2948043a0536SJohnathan Mantey                         std::string dbusTimestamp{};
2949043a0536SJohnathan Mantey                         std::string dbusFilepath{};
2950043a0536SJohnathan Mantey 
2951bd79bce8SPatrick Williams                         parseCrashdumpParameters(resp, dbusFilename,
2952bd79bce8SPatrick Williams                                                  dbusTimestamp, dbusFilepath);
2953043a0536SJohnathan Mantey 
2954043a0536SJohnathan Mantey                         if (dbusFilename.empty() || dbusTimestamp.empty() ||
2955043a0536SJohnathan Mantey                             dbusFilepath.empty())
29561da66f75SEd Tanous                         {
2957bd79bce8SPatrick Williams                             messages::resourceNotFound(asyncResp->res,
2958bd79bce8SPatrick Williams                                                        "LogEntry", logID);
29591da66f75SEd Tanous                             return;
29601da66f75SEd Tanous                         }
2961e855dd28SJason M. Bills 
2962043a0536SJohnathan Mantey                         // Verify the file name parameter is correct
2963043a0536SJohnathan Mantey                         if (fileName != dbusFilename)
2964043a0536SJohnathan Mantey                         {
2965bd79bce8SPatrick Williams                             messages::resourceNotFound(asyncResp->res,
2966bd79bce8SPatrick Williams                                                        "LogEntry", logID);
2967043a0536SJohnathan Mantey                             return;
2968043a0536SJohnathan Mantey                         }
2969043a0536SJohnathan Mantey 
2970d51c61b4SMyung Bae                         if (asyncResp->res.openFile(dbusFilepath) !=
2971d51c61b4SMyung Bae                             crow::OpenCode::Success)
2972043a0536SJohnathan Mantey                         {
2973bd79bce8SPatrick Williams                             messages::resourceNotFound(asyncResp->res,
2974bd79bce8SPatrick Williams                                                        "LogEntry", logID);
2975043a0536SJohnathan Mantey                             return;
2976043a0536SJohnathan Mantey                         }
2977043a0536SJohnathan Mantey 
29787e860f15SJohn Edward Broadbent                         // Configure this to be a file download when accessed
29797e860f15SJohn Edward Broadbent                         // from a browser
2980d9f6c621SEd Tanous                         asyncResp->res.addHeader(
2981bd79bce8SPatrick Williams                             boost::beast::http::field::content_disposition,
2982bd79bce8SPatrick Williams                             "attachment");
29831da66f75SEd Tanous                     };
2984deae6a78SEd Tanous                 dbus::utility::getAllProperties(
2985d1bde9e5SKrzysztof Grobelny                     *crow::connections::systemBus, crashdumpObject,
2986bd79bce8SPatrick Williams                     crashdumpPath + std::string("/") + logID,
2987bd79bce8SPatrick Williams                     crashdumpInterface, std::move(getStoredLogCallback));
29887e860f15SJohn Edward Broadbent             });
29891da66f75SEd Tanous }
29901da66f75SEd Tanous 
2991c5a4c82aSJason M. Bills enum class OEMDiagnosticType
2992c5a4c82aSJason M. Bills {
2993c5a4c82aSJason M. Bills     onDemand,
2994c5a4c82aSJason M. Bills     telemetry,
2995c5a4c82aSJason M. Bills     invalid,
2996c5a4c82aSJason M. Bills };
2997c5a4c82aSJason M. Bills 
299826ccae32SEd Tanous inline OEMDiagnosticType getOEMDiagnosticType(std::string_view oemDiagStr)
2999c5a4c82aSJason M. Bills {
3000c5a4c82aSJason M. Bills     if (oemDiagStr == "OnDemand")
3001c5a4c82aSJason M. Bills     {
3002c5a4c82aSJason M. Bills         return OEMDiagnosticType::onDemand;
3003c5a4c82aSJason M. Bills     }
3004c5a4c82aSJason M. Bills     if (oemDiagStr == "Telemetry")
3005c5a4c82aSJason M. Bills     {
3006c5a4c82aSJason M. Bills         return OEMDiagnosticType::telemetry;
3007c5a4c82aSJason M. Bills     }
3008c5a4c82aSJason M. Bills 
3009c5a4c82aSJason M. Bills     return OEMDiagnosticType::invalid;
3010c5a4c82aSJason M. Bills }
3011c5a4c82aSJason M. Bills 
30127e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpCollect(App& app)
30131da66f75SEd Tanous {
30143946028dSAppaRao Puli     // Note: Deviated from redfish privilege registry for GET & HEAD
30153946028dSAppaRao Puli     // method for security reasons.
30160fda0f12SGeorge Liu     BMCWEB_ROUTE(
30170fda0f12SGeorge Liu         app,
301822d268cbSEd Tanous         "/redfish/v1/Systems/<str>/LogServices/Crashdump/Actions/LogService.CollectDiagnosticData/")
3019ed398213SEd Tanous         // The below is incorrect;  Should be ConfigureManager
3020ed398213SEd Tanous         //.privileges(redfish::privileges::postLogService)
3021432a890cSEd Tanous         .privileges({{"ConfigureComponents"}})
3022002d39b4SEd Tanous         .methods(boost::beast::http::verb::post)(
3023002d39b4SEd Tanous             [&app](const crow::Request& req,
302422d268cbSEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
302522d268cbSEd Tanous                    const std::string& systemName) {
30263ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
302745ca1b86SEd Tanous                 {
302845ca1b86SEd Tanous                     return;
302945ca1b86SEd Tanous                 }
303022d268cbSEd Tanous 
303125b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
30327f3e84a1SEd Tanous                 {
30337f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
30347f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
30357f3e84a1SEd Tanous                                                systemName);
30367f3e84a1SEd Tanous                     return;
30377f3e84a1SEd Tanous                 }
3038253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
303922d268cbSEd Tanous                 {
304022d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
304122d268cbSEd Tanous                                                systemName);
304222d268cbSEd Tanous                     return;
304322d268cbSEd Tanous                 }
304422d268cbSEd Tanous 
30458e6c099aSJason M. Bills                 std::string diagnosticDataType;
30468e6c099aSJason M. Bills                 std::string oemDiagnosticDataType;
3047afc474aeSMyung Bae                 if (!redfish::json_util::readJsonAction( //
3048afc474aeSMyung Bae                         req, asyncResp->res, //
3049afc474aeSMyung Bae                         "DiagnosticDataType", diagnosticDataType, //
3050afc474aeSMyung Bae                         "OEMDiagnosticDataType", oemDiagnosticDataType //
3051afc474aeSMyung Bae                         ))
30528e6c099aSJason M. Bills                 {
30538e6c099aSJason M. Bills                     return;
30548e6c099aSJason M. Bills                 }
30558e6c099aSJason M. Bills 
30568e6c099aSJason M. Bills                 if (diagnosticDataType != "OEM")
30578e6c099aSJason M. Bills                 {
305862598e31SEd Tanous                     BMCWEB_LOG_ERROR(
305962598e31SEd Tanous                         "Only OEM DiagnosticDataType supported for Crashdump");
30608e6c099aSJason M. Bills                     messages::actionParameterValueFormatError(
3061bd79bce8SPatrick Williams                         asyncResp->res, diagnosticDataType,
3062bd79bce8SPatrick Williams                         "DiagnosticDataType", "CollectDiagnosticData");
30638e6c099aSJason M. Bills                     return;
30648e6c099aSJason M. Bills                 }
30658e6c099aSJason M. Bills 
3066c5a4c82aSJason M. Bills                 OEMDiagnosticType oemDiagType =
3067c5a4c82aSJason M. Bills                     getOEMDiagnosticType(oemDiagnosticDataType);
3068c5a4c82aSJason M. Bills 
3069c5a4c82aSJason M. Bills                 std::string iface;
3070c5a4c82aSJason M. Bills                 std::string method;
3071c5a4c82aSJason M. Bills                 std::string taskMatchStr;
3072c5a4c82aSJason M. Bills                 if (oemDiagType == OEMDiagnosticType::onDemand)
3073c5a4c82aSJason M. Bills                 {
3074c5a4c82aSJason M. Bills                     iface = crashdumpOnDemandInterface;
3075c5a4c82aSJason M. Bills                     method = "GenerateOnDemandLog";
3076bd79bce8SPatrick Williams                     taskMatchStr =
3077bd79bce8SPatrick Williams                         "type='signal',"
3078c5a4c82aSJason M. Bills                         "interface='org.freedesktop.DBus.Properties',"
3079c5a4c82aSJason M. Bills                         "member='PropertiesChanged',"
3080c5a4c82aSJason M. Bills                         "arg0namespace='com.intel.crashdump'";
3081c5a4c82aSJason M. Bills                 }
3082c5a4c82aSJason M. Bills                 else if (oemDiagType == OEMDiagnosticType::telemetry)
3083c5a4c82aSJason M. Bills                 {
3084c5a4c82aSJason M. Bills                     iface = crashdumpTelemetryInterface;
3085c5a4c82aSJason M. Bills                     method = "GenerateTelemetryLog";
3086bd79bce8SPatrick Williams                     taskMatchStr =
3087bd79bce8SPatrick Williams                         "type='signal',"
3088c5a4c82aSJason M. Bills                         "interface='org.freedesktop.DBus.Properties',"
3089c5a4c82aSJason M. Bills                         "member='PropertiesChanged',"
3090c5a4c82aSJason M. Bills                         "arg0namespace='com.intel.crashdump'";
3091c5a4c82aSJason M. Bills                 }
3092c5a4c82aSJason M. Bills                 else
3093c5a4c82aSJason M. Bills                 {
309462598e31SEd Tanous                     BMCWEB_LOG_ERROR("Unsupported OEMDiagnosticDataType: {}",
309562598e31SEd Tanous                                      oemDiagnosticDataType);
3096c5a4c82aSJason M. Bills                     messages::actionParameterValueFormatError(
3097bd79bce8SPatrick Williams                         asyncResp->res, oemDiagnosticDataType,
3098bd79bce8SPatrick Williams                         "OEMDiagnosticDataType", "CollectDiagnosticData");
3099c5a4c82aSJason M. Bills                     return;
3100c5a4c82aSJason M. Bills                 }
3101c5a4c82aSJason M. Bills 
3102c5a4c82aSJason M. Bills                 auto collectCrashdumpCallback =
3103c5a4c82aSJason M. Bills                     [asyncResp, payload(task::Payload(req)),
31045e7e2dc5SEd Tanous                      taskMatchStr](const boost::system::error_code& ec,
310598be3e39SEd Tanous                                    const std::string&) mutable {
31061da66f75SEd Tanous                         if (ec)
31071da66f75SEd Tanous                         {
3108bd79bce8SPatrick Williams                             if (ec.value() ==
3109bd79bce8SPatrick Williams                                 boost::system::errc::operation_not_supported)
31101da66f75SEd Tanous                             {
3111f12894f8SJason M. Bills                                 messages::resourceInStandby(asyncResp->res);
31121da66f75SEd Tanous                             }
3113bd79bce8SPatrick Williams                             else if (ec.value() == boost::system::errc::
3114bd79bce8SPatrick Williams                                                        device_or_resource_busy)
31154363d3b2SJason M. Bills                             {
3116bd79bce8SPatrick Williams                                 messages::serviceTemporarilyUnavailable(
3117bd79bce8SPatrick Williams                                     asyncResp->res, "60");
31184363d3b2SJason M. Bills                             }
31191da66f75SEd Tanous                             else
31201da66f75SEd Tanous                             {
3121f12894f8SJason M. Bills                                 messages::internalError(asyncResp->res);
31221da66f75SEd Tanous                             }
31231da66f75SEd Tanous                             return;
31241da66f75SEd Tanous                         }
3125bd79bce8SPatrick Williams                         std::shared_ptr<task::TaskData> task =
3126bd79bce8SPatrick Williams                             task::TaskData::createTask(
3127bd79bce8SPatrick Williams                                 [](const boost::system::error_code& ec2,
3128bd79bce8SPatrick Williams                                    sdbusplus::message_t&,
3129bd79bce8SPatrick Williams                                    const std::shared_ptr<task::TaskData>&
3130bd79bce8SPatrick Williams                                        taskData) {
31318b24275dSEd Tanous                                     if (!ec2)
313266afe4faSJames Feist                                     {
3133bd79bce8SPatrick Williams                                         taskData->messages.emplace_back(
3134bd79bce8SPatrick Williams                                             messages::taskCompletedOK(
3135bd79bce8SPatrick Williams                                                 std::to_string(
3136bd79bce8SPatrick Williams                                                     taskData->index)));
3137831d6b09SJames Feist                                         taskData->state = "Completed";
313866afe4faSJames Feist                                     }
313932898ceaSJames Feist                                     return task::completed;
314066afe4faSJames Feist                                 },
3141c5a4c82aSJason M. Bills                                 taskMatchStr);
3142c5a4c82aSJason M. Bills 
314346229577SJames Feist                         task->startTimer(std::chrono::minutes(5));
314446229577SJames Feist                         task->populateResp(asyncResp->res);
314598be3e39SEd Tanous                         task->payload.emplace(std::move(payload));
31461da66f75SEd Tanous                     };
31478e6c099aSJason M. Bills 
31481da66f75SEd Tanous                 crow::connections::systemBus->async_method_call(
3149bd79bce8SPatrick Williams                     std::move(collectCrashdumpCallback), crashdumpObject,
3150bd79bce8SPatrick Williams                     crashdumpPath, iface, method);
31517e860f15SJohn Edward Broadbent             });
31526eda7685SKenny L. Ku }
31536eda7685SKenny L. Ku 
3154599b9af3SAlexander Hansen inline void dBusLogServiceActionsClear(
3155599b9af3SAlexander Hansen     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
3156599b9af3SAlexander Hansen {
3157599b9af3SAlexander Hansen     BMCWEB_LOG_DEBUG("Do delete all entries.");
3158599b9af3SAlexander Hansen 
3159599b9af3SAlexander Hansen     // Process response from Logging service.
3160599b9af3SAlexander Hansen     auto respHandler = [asyncResp](const boost::system::error_code& ec) {
3161599b9af3SAlexander Hansen         BMCWEB_LOG_DEBUG("doClearLog resp_handler callback: Done");
3162599b9af3SAlexander Hansen         if (ec)
3163599b9af3SAlexander Hansen         {
3164599b9af3SAlexander Hansen             // TODO Handle for specific error code
3165599b9af3SAlexander Hansen             BMCWEB_LOG_ERROR("doClearLog resp_handler got error {}", ec);
3166599b9af3SAlexander Hansen             asyncResp->res.result(
3167599b9af3SAlexander Hansen                 boost::beast::http::status::internal_server_error);
3168599b9af3SAlexander Hansen             return;
3169599b9af3SAlexander Hansen         }
3170599b9af3SAlexander Hansen 
3171599b9af3SAlexander Hansen         asyncResp->res.result(boost::beast::http::status::no_content);
3172599b9af3SAlexander Hansen     };
3173599b9af3SAlexander Hansen 
3174599b9af3SAlexander Hansen     // Make call to Logging service to request Clear Log
3175599b9af3SAlexander Hansen     crow::connections::systemBus->async_method_call(
3176599b9af3SAlexander Hansen         respHandler, "xyz.openbmc_project.Logging",
3177599b9af3SAlexander Hansen         "/xyz/openbmc_project/logging",
3178599b9af3SAlexander Hansen         "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
3179599b9af3SAlexander Hansen }
3180599b9af3SAlexander Hansen 
3181cb92c03bSAndrew Geissler /**
3182cb92c03bSAndrew Geissler  * DBusLogServiceActionsClear class supports POST method for ClearLog action.
3183cb92c03bSAndrew Geissler  */
31847e860f15SJohn Edward Broadbent inline void requestRoutesDBusLogServiceActionsClear(App& app)
3185cb92c03bSAndrew Geissler {
3186cb92c03bSAndrew Geissler     /**
3187cb92c03bSAndrew Geissler      * Function handles POST method request.
3188cb92c03bSAndrew Geissler      * The Clear Log actions does not require any parameter.The action deletes
3189cb92c03bSAndrew Geissler      * all entries found in the Entries collection for this Log Service.
3190cb92c03bSAndrew Geissler      */
31917e860f15SJohn Edward Broadbent 
31920fda0f12SGeorge Liu     BMCWEB_ROUTE(
31930fda0f12SGeorge Liu         app,
319422d268cbSEd Tanous         "/redfish/v1/Systems/<str>/LogServices/EventLog/Actions/LogService.ClearLog/")
3195ed398213SEd Tanous         .privileges(redfish::privileges::postLogService)
31967e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
319745ca1b86SEd Tanous             [&app](const crow::Request& req,
319822d268cbSEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
319922d268cbSEd Tanous                    const std::string& systemName) {
32003ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
320145ca1b86SEd Tanous                 {
320245ca1b86SEd Tanous                     return;
320345ca1b86SEd Tanous                 }
320425b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
32057f3e84a1SEd Tanous                 {
32067f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
32077f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
32087f3e84a1SEd Tanous                                                systemName);
32097f3e84a1SEd Tanous                     return;
32107f3e84a1SEd Tanous                 }
3211253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
321222d268cbSEd Tanous                 {
321322d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
321422d268cbSEd Tanous                                                systemName);
321522d268cbSEd Tanous                     return;
321622d268cbSEd Tanous                 }
3217599b9af3SAlexander Hansen                 dBusLogServiceActionsClear(asyncResp);
32187e860f15SJohn Edward Broadbent             });
3219cb92c03bSAndrew Geissler }
3220a3316fc6SZhikuiRen 
32211da66f75SEd Tanous } // namespace redfish
3222