xref: /openbmc/bmcweb/features/redfish/lib/log_services.hpp (revision bd79bce8c3f1deb1fb2773868b9ece25233cf27b)
11da66f75SEd Tanous /*
21da66f75SEd Tanous // Copyright (c) 2018 Intel Corporation
31da66f75SEd Tanous //
41da66f75SEd Tanous // Licensed under the Apache License, Version 2.0 (the "License");
51da66f75SEd Tanous // you may not use this file except in compliance with the License.
61da66f75SEd Tanous // You may obtain a copy of the License at
71da66f75SEd Tanous //
81da66f75SEd Tanous //      http://www.apache.org/licenses/LICENSE-2.0
91da66f75SEd Tanous //
101da66f75SEd Tanous // Unless required by applicable law or agreed to in writing, software
111da66f75SEd Tanous // distributed under the License is distributed on an "AS IS" BASIS,
121da66f75SEd Tanous // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131da66f75SEd Tanous // See the License for the specific language governing permissions and
141da66f75SEd Tanous // limitations under the License.
151da66f75SEd Tanous */
161da66f75SEd Tanous #pragma once
171da66f75SEd Tanous 
183ccb3adbSEd Tanous #include "app.hpp"
197a1dbc48SGeorge Liu #include "dbus_utility.hpp"
203ccb3adbSEd Tanous #include "error_messages.hpp"
2168dd075aSAsmitha Karunanithi #include "generated/enums/log_entry.hpp"
22539d8c6bSEd Tanous #include "generated/enums/log_service.hpp"
23b7028ebfSSpencer Ku #include "gzfile.hpp"
24647b3cdcSGeorge Liu #include "http_utility.hpp"
25b7028ebfSSpencer Ku #include "human_sort.hpp"
263ccb3adbSEd Tanous #include "query.hpp"
274851d45dSJason M. Bills #include "registries.hpp"
284851d45dSJason M. Bills #include "registries/base_message_registry.hpp"
294851d45dSJason M. Bills #include "registries/openbmc_message_registry.hpp"
303ccb3adbSEd Tanous #include "registries/privilege_registry.hpp"
3146229577SJames Feist #include "task.hpp"
325b90429aSEd Tanous #include "task_messages.hpp"
333ccb3adbSEd Tanous #include "utils/dbus_utils.hpp"
345b90429aSEd Tanous #include "utils/json_utils.hpp"
353ccb3adbSEd Tanous #include "utils/time_utils.hpp"
361da66f75SEd Tanous 
3775e8e218SMyung Bae #include <systemd/sd-id128.h>
388e31778eSAsmitha Karunanithi #include <tinyxml2.h>
39400fd1fbSAdriana Kobylak #include <unistd.h>
40e1f26343SJason M. Bills 
4107c8c20dSEd Tanous #include <boost/beast/http/verb.hpp>
421da66f75SEd Tanous #include <boost/container/flat_map.hpp>
431ddcf01aSJason M. Bills #include <boost/system/linux_error.hpp>
44ef4c65b7SEd Tanous #include <boost/url/format.hpp>
45d1bde9e5SKrzysztof Grobelny #include <sdbusplus/asio/property.hpp>
46d1bde9e5SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp>
471214b7e7SGunnar Mills 
487a1dbc48SGeorge Liu #include <array>
49647b3cdcSGeorge Liu #include <charconv>
50b5f288d2SAbhilash Raju #include <cstddef>
514418c7f0SJames Feist #include <filesystem>
5218f8f608SEd Tanous #include <iterator>
5375710de2SXiaochao Ma #include <optional>
543544d2a7SEd Tanous #include <ranges>
5526702d01SEd Tanous #include <span>
5618f8f608SEd Tanous #include <string>
57cd225da8SJason M. Bills #include <string_view>
58abf2add6SEd Tanous #include <variant>
591da66f75SEd Tanous 
601da66f75SEd Tanous namespace redfish
611da66f75SEd Tanous {
621da66f75SEd Tanous 
6389492a15SPatrick Williams constexpr const char* crashdumpObject = "com.intel.crashdump";
6489492a15SPatrick Williams constexpr const char* crashdumpPath = "/com/intel/crashdump";
6589492a15SPatrick Williams constexpr const char* crashdumpInterface = "com.intel.crashdump";
6689492a15SPatrick Williams constexpr const char* deleteAllInterface =
675b61b5e8SJason M. Bills     "xyz.openbmc_project.Collection.DeleteAll";
6889492a15SPatrick Williams constexpr const char* crashdumpOnDemandInterface =
69424c4176SJason M. Bills     "com.intel.crashdump.OnDemand";
7089492a15SPatrick Williams constexpr const char* crashdumpTelemetryInterface =
716eda7685SKenny L. Ku     "com.intel.crashdump.Telemetry";
721da66f75SEd Tanous 
738e31778eSAsmitha Karunanithi enum class DumpCreationProgress
748e31778eSAsmitha Karunanithi {
758e31778eSAsmitha Karunanithi     DUMP_CREATE_SUCCESS,
768e31778eSAsmitha Karunanithi     DUMP_CREATE_FAILED,
778e31778eSAsmitha Karunanithi     DUMP_CREATE_INPROGRESS
788e31778eSAsmitha Karunanithi };
798e31778eSAsmitha Karunanithi 
80f6150403SJames Feist namespace fs = std::filesystem;
811da66f75SEd Tanous 
82cb92c03bSAndrew Geissler inline std::string translateSeverityDbusToRedfish(const std::string& s)
83cb92c03bSAndrew Geissler {
84d4d25793SEd Tanous     if ((s == "xyz.openbmc_project.Logging.Entry.Level.Alert") ||
85d4d25793SEd Tanous         (s == "xyz.openbmc_project.Logging.Entry.Level.Critical") ||
86d4d25793SEd Tanous         (s == "xyz.openbmc_project.Logging.Entry.Level.Emergency") ||
87d4d25793SEd Tanous         (s == "xyz.openbmc_project.Logging.Entry.Level.Error"))
88cb92c03bSAndrew Geissler     {
89cb92c03bSAndrew Geissler         return "Critical";
90cb92c03bSAndrew Geissler     }
913174e4dfSEd Tanous     if ((s == "xyz.openbmc_project.Logging.Entry.Level.Debug") ||
92d4d25793SEd Tanous         (s == "xyz.openbmc_project.Logging.Entry.Level.Informational") ||
93d4d25793SEd Tanous         (s == "xyz.openbmc_project.Logging.Entry.Level.Notice"))
94cb92c03bSAndrew Geissler     {
95cb92c03bSAndrew Geissler         return "OK";
96cb92c03bSAndrew Geissler     }
973174e4dfSEd Tanous     if (s == "xyz.openbmc_project.Logging.Entry.Level.Warning")
98cb92c03bSAndrew Geissler     {
99cb92c03bSAndrew Geissler         return "Warning";
100cb92c03bSAndrew Geissler     }
101cb92c03bSAndrew Geissler     return "";
102cb92c03bSAndrew Geissler }
103cb92c03bSAndrew Geissler 
1049017faf2SAbhishek Patel inline std::optional<bool> getProviderNotifyAction(const std::string& notify)
1059017faf2SAbhishek Patel {
1069017faf2SAbhishek Patel     std::optional<bool> notifyAction;
1079017faf2SAbhishek Patel     if (notify == "xyz.openbmc_project.Logging.Entry.Notify.Notify")
1089017faf2SAbhishek Patel     {
1099017faf2SAbhishek Patel         notifyAction = true;
1109017faf2SAbhishek Patel     }
1119017faf2SAbhishek Patel     else if (notify == "xyz.openbmc_project.Logging.Entry.Notify.Inhibit")
1129017faf2SAbhishek Patel     {
1139017faf2SAbhishek Patel         notifyAction = false;
1149017faf2SAbhishek Patel     }
1159017faf2SAbhishek Patel 
1169017faf2SAbhishek Patel     return notifyAction;
1179017faf2SAbhishek Patel }
1189017faf2SAbhishek Patel 
11918f8f608SEd Tanous inline std::string getDumpPath(std::string_view dumpType)
12018f8f608SEd Tanous {
12118f8f608SEd Tanous     std::string dbusDumpPath = "/xyz/openbmc_project/dump/";
12218f8f608SEd Tanous     std::ranges::transform(dumpType, std::back_inserter(dbusDumpPath),
12318f8f608SEd Tanous                            bmcweb::asciiToLower);
12418f8f608SEd Tanous 
12518f8f608SEd Tanous     return dbusDumpPath;
12618f8f608SEd Tanous }
12718f8f608SEd Tanous 
128055713e4SEd Tanous inline bool getUniqueEntryID(const std::string& logEntry, std::string& entryID,
129e85d6b16SJason M. Bills                              const bool firstEntry = true)
13095820184SJason M. Bills {
131271584abSEd Tanous     static time_t prevTs = 0;
13295820184SJason M. Bills     static int index = 0;
133e85d6b16SJason M. Bills     if (firstEntry)
134e85d6b16SJason M. Bills     {
135e85d6b16SJason M. Bills         prevTs = 0;
136e85d6b16SJason M. Bills     }
137e85d6b16SJason M. Bills 
13895820184SJason M. Bills     // Get the entry timestamp
139271584abSEd Tanous     std::time_t curTs = 0;
14095820184SJason M. Bills     std::tm timeStruct = {};
14195820184SJason M. Bills     std::istringstream entryStream(logEntry);
14295820184SJason M. Bills     if (entryStream >> std::get_time(&timeStruct, "%Y-%m-%dT%H:%M:%S"))
14395820184SJason M. Bills     {
14495820184SJason M. Bills         curTs = std::mktime(&timeStruct);
14595820184SJason M. Bills     }
14695820184SJason M. Bills     // If the timestamp isn't unique, increment the index
14795820184SJason M. Bills     if (curTs == prevTs)
14895820184SJason M. Bills     {
14995820184SJason M. Bills         index++;
15095820184SJason M. Bills     }
15195820184SJason M. Bills     else
15295820184SJason M. Bills     {
15395820184SJason M. Bills         // Otherwise, reset it
15495820184SJason M. Bills         index = 0;
15595820184SJason M. Bills     }
15695820184SJason M. Bills     // Save the timestamp
15795820184SJason M. Bills     prevTs = curTs;
15895820184SJason M. Bills 
15995820184SJason M. Bills     entryID = std::to_string(curTs);
16095820184SJason M. Bills     if (index > 0)
16195820184SJason M. Bills     {
16295820184SJason M. Bills         entryID += "_" + std::to_string(index);
16395820184SJason M. Bills     }
16495820184SJason M. Bills     return true;
16595820184SJason M. Bills }
16695820184SJason M. Bills 
16795820184SJason M. Bills static bool
16895820184SJason M. Bills     getRedfishLogFiles(std::vector<std::filesystem::path>& redfishLogFiles)
16995820184SJason M. Bills {
17095820184SJason M. Bills     static const std::filesystem::path redfishLogDir = "/var/log";
17195820184SJason M. Bills     static const std::string redfishLogFilename = "redfish";
17295820184SJason M. Bills 
17395820184SJason M. Bills     // Loop through the directory looking for redfish log files
17495820184SJason M. Bills     for (const std::filesystem::directory_entry& dirEnt :
17595820184SJason M. Bills          std::filesystem::directory_iterator(redfishLogDir))
17695820184SJason M. Bills     {
17795820184SJason M. Bills         // If we find a redfish log file, save the path
17895820184SJason M. Bills         std::string filename = dirEnt.path().filename();
17911ba3979SEd Tanous         if (filename.starts_with(redfishLogFilename))
18095820184SJason M. Bills         {
18195820184SJason M. Bills             redfishLogFiles.emplace_back(redfishLogDir / filename);
18295820184SJason M. Bills         }
18395820184SJason M. Bills     }
18495820184SJason M. Bills     // As the log files rotate, they are appended with a ".#" that is higher for
18595820184SJason M. Bills     // the older logs. Since we don't expect more than 10 log files, we
18695820184SJason M. Bills     // can just sort the list to get them in order from newest to oldest
1873544d2a7SEd Tanous     std::ranges::sort(redfishLogFiles);
18895820184SJason M. Bills 
18995820184SJason M. Bills     return !redfishLogFiles.empty();
19095820184SJason M. Bills }
19195820184SJason M. Bills 
19268dd075aSAsmitha Karunanithi inline log_entry::OriginatorTypes
19368dd075aSAsmitha Karunanithi     mapDbusOriginatorTypeToRedfish(const std::string& originatorType)
19468dd075aSAsmitha Karunanithi {
19568dd075aSAsmitha Karunanithi     if (originatorType ==
19668dd075aSAsmitha Karunanithi         "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Client")
19768dd075aSAsmitha Karunanithi     {
19868dd075aSAsmitha Karunanithi         return log_entry::OriginatorTypes::Client;
19968dd075aSAsmitha Karunanithi     }
20068dd075aSAsmitha Karunanithi     if (originatorType ==
20168dd075aSAsmitha Karunanithi         "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Internal")
20268dd075aSAsmitha Karunanithi     {
20368dd075aSAsmitha Karunanithi         return log_entry::OriginatorTypes::Internal;
20468dd075aSAsmitha Karunanithi     }
20568dd075aSAsmitha Karunanithi     if (originatorType ==
20668dd075aSAsmitha Karunanithi         "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.SupportingService")
20768dd075aSAsmitha Karunanithi     {
20868dd075aSAsmitha Karunanithi         return log_entry::OriginatorTypes::SupportingService;
20968dd075aSAsmitha Karunanithi     }
21068dd075aSAsmitha Karunanithi     return log_entry::OriginatorTypes::Invalid;
21168dd075aSAsmitha Karunanithi }
21268dd075aSAsmitha Karunanithi 
213aefe3786SClaire Weinan inline void parseDumpEntryFromDbusObject(
2142d613eb6SJiaqing Zhao     const dbus::utility::ManagedObjectType::value_type& object,
215c6fecdabSClaire Weinan     std::string& dumpStatus, uint64_t& size, uint64_t& timestampUs,
21668dd075aSAsmitha Karunanithi     std::string& originatorId, log_entry::OriginatorTypes& originatorType,
217aefe3786SClaire Weinan     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
218aefe3786SClaire Weinan {
219aefe3786SClaire Weinan     for (const auto& interfaceMap : object.second)
220aefe3786SClaire Weinan     {
221aefe3786SClaire Weinan         if (interfaceMap.first == "xyz.openbmc_project.Common.Progress")
222aefe3786SClaire Weinan         {
223aefe3786SClaire Weinan             for (const auto& propertyMap : interfaceMap.second)
224aefe3786SClaire Weinan             {
225aefe3786SClaire Weinan                 if (propertyMap.first == "Status")
226aefe3786SClaire Weinan                 {
227aefe3786SClaire Weinan                     const auto* status =
228aefe3786SClaire Weinan                         std::get_if<std::string>(&propertyMap.second);
229aefe3786SClaire Weinan                     if (status == nullptr)
230aefe3786SClaire Weinan                     {
231aefe3786SClaire Weinan                         messages::internalError(asyncResp->res);
232aefe3786SClaire Weinan                         break;
233aefe3786SClaire Weinan                     }
234aefe3786SClaire Weinan                     dumpStatus = *status;
235aefe3786SClaire Weinan                 }
236aefe3786SClaire Weinan             }
237aefe3786SClaire Weinan         }
238aefe3786SClaire Weinan         else if (interfaceMap.first == "xyz.openbmc_project.Dump.Entry")
239aefe3786SClaire Weinan         {
240aefe3786SClaire Weinan             for (const auto& propertyMap : interfaceMap.second)
241aefe3786SClaire Weinan             {
242aefe3786SClaire Weinan                 if (propertyMap.first == "Size")
243aefe3786SClaire Weinan                 {
244aefe3786SClaire Weinan                     const auto* sizePtr =
245aefe3786SClaire Weinan                         std::get_if<uint64_t>(&propertyMap.second);
246aefe3786SClaire Weinan                     if (sizePtr == nullptr)
247aefe3786SClaire Weinan                     {
248aefe3786SClaire Weinan                         messages::internalError(asyncResp->res);
249aefe3786SClaire Weinan                         break;
250aefe3786SClaire Weinan                     }
251aefe3786SClaire Weinan                     size = *sizePtr;
252aefe3786SClaire Weinan                     break;
253aefe3786SClaire Weinan                 }
254aefe3786SClaire Weinan             }
255aefe3786SClaire Weinan         }
256aefe3786SClaire Weinan         else if (interfaceMap.first == "xyz.openbmc_project.Time.EpochTime")
257aefe3786SClaire Weinan         {
258aefe3786SClaire Weinan             for (const auto& propertyMap : interfaceMap.second)
259aefe3786SClaire Weinan             {
260aefe3786SClaire Weinan                 if (propertyMap.first == "Elapsed")
261aefe3786SClaire Weinan                 {
262aefe3786SClaire Weinan                     const uint64_t* usecsTimeStamp =
263aefe3786SClaire Weinan                         std::get_if<uint64_t>(&propertyMap.second);
264aefe3786SClaire Weinan                     if (usecsTimeStamp == nullptr)
265aefe3786SClaire Weinan                     {
266aefe3786SClaire Weinan                         messages::internalError(asyncResp->res);
267aefe3786SClaire Weinan                         break;
268aefe3786SClaire Weinan                     }
269c6fecdabSClaire Weinan                     timestampUs = *usecsTimeStamp;
270aefe3786SClaire Weinan                     break;
271aefe3786SClaire Weinan                 }
272aefe3786SClaire Weinan             }
273aefe3786SClaire Weinan         }
27468dd075aSAsmitha Karunanithi         else if (interfaceMap.first ==
27568dd075aSAsmitha Karunanithi                  "xyz.openbmc_project.Common.OriginatedBy")
27668dd075aSAsmitha Karunanithi         {
27768dd075aSAsmitha Karunanithi             for (const auto& propertyMap : interfaceMap.second)
27868dd075aSAsmitha Karunanithi             {
27968dd075aSAsmitha Karunanithi                 if (propertyMap.first == "OriginatorId")
28068dd075aSAsmitha Karunanithi                 {
28168dd075aSAsmitha Karunanithi                     const std::string* id =
28268dd075aSAsmitha Karunanithi                         std::get_if<std::string>(&propertyMap.second);
28368dd075aSAsmitha Karunanithi                     if (id == nullptr)
28468dd075aSAsmitha Karunanithi                     {
28568dd075aSAsmitha Karunanithi                         messages::internalError(asyncResp->res);
28668dd075aSAsmitha Karunanithi                         break;
28768dd075aSAsmitha Karunanithi                     }
28868dd075aSAsmitha Karunanithi                     originatorId = *id;
28968dd075aSAsmitha Karunanithi                 }
29068dd075aSAsmitha Karunanithi 
29168dd075aSAsmitha Karunanithi                 if (propertyMap.first == "OriginatorType")
29268dd075aSAsmitha Karunanithi                 {
29368dd075aSAsmitha Karunanithi                     const std::string* type =
29468dd075aSAsmitha Karunanithi                         std::get_if<std::string>(&propertyMap.second);
29568dd075aSAsmitha Karunanithi                     if (type == nullptr)
29668dd075aSAsmitha Karunanithi                     {
29768dd075aSAsmitha Karunanithi                         messages::internalError(asyncResp->res);
29868dd075aSAsmitha Karunanithi                         break;
29968dd075aSAsmitha Karunanithi                     }
30068dd075aSAsmitha Karunanithi 
30168dd075aSAsmitha Karunanithi                     originatorType = mapDbusOriginatorTypeToRedfish(*type);
30268dd075aSAsmitha Karunanithi                     if (originatorType == log_entry::OriginatorTypes::Invalid)
30368dd075aSAsmitha Karunanithi                     {
30468dd075aSAsmitha Karunanithi                         messages::internalError(asyncResp->res);
30568dd075aSAsmitha Karunanithi                         break;
30668dd075aSAsmitha Karunanithi                     }
30768dd075aSAsmitha Karunanithi                 }
30868dd075aSAsmitha Karunanithi             }
30968dd075aSAsmitha Karunanithi         }
310aefe3786SClaire Weinan     }
311aefe3786SClaire Weinan }
312aefe3786SClaire Weinan 
31321ab404cSNan Zhou static std::string getDumpEntriesPath(const std::string& dumpType)
314fdd26906SClaire Weinan {
315fdd26906SClaire Weinan     std::string entriesPath;
316fdd26906SClaire Weinan 
317fdd26906SClaire Weinan     if (dumpType == "BMC")
318fdd26906SClaire Weinan     {
319253f11b8SEd Tanous         entriesPath =
320253f11b8SEd Tanous             std::format("/redfish/v1/Managers/{}/LogServices/Dump/Entries/",
321253f11b8SEd Tanous                         BMCWEB_REDFISH_MANAGER_URI_NAME);
322fdd26906SClaire Weinan     }
323fdd26906SClaire Weinan     else if (dumpType == "FaultLog")
324fdd26906SClaire Weinan     {
325253f11b8SEd Tanous         entriesPath =
326253f11b8SEd Tanous             std::format("/redfish/v1/Managers/{}/LogServices/FaultLog/Entries/",
327253f11b8SEd Tanous                         BMCWEB_REDFISH_MANAGER_URI_NAME);
328fdd26906SClaire Weinan     }
329fdd26906SClaire Weinan     else if (dumpType == "System")
330fdd26906SClaire Weinan     {
331253f11b8SEd Tanous         entriesPath =
332253f11b8SEd Tanous             std::format("/redfish/v1/Systems/{}/LogServices/Dump/Entries/",
333253f11b8SEd Tanous                         BMCWEB_REDFISH_SYSTEM_URI_NAME);
334fdd26906SClaire Weinan     }
335fdd26906SClaire Weinan     else
336fdd26906SClaire Weinan     {
33762598e31SEd Tanous         BMCWEB_LOG_ERROR("getDumpEntriesPath() invalid dump type: {}",
33862598e31SEd Tanous                          dumpType);
339fdd26906SClaire Weinan     }
340fdd26906SClaire Weinan 
341fdd26906SClaire Weinan     // Returns empty string on error
342fdd26906SClaire Weinan     return entriesPath;
343fdd26906SClaire Weinan }
344fdd26906SClaire Weinan 
3458d1b46d7Szhanghch05 inline void
3468d1b46d7Szhanghch05     getDumpEntryCollection(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3475cb1dd27SAsmitha Karunanithi                            const std::string& dumpType)
3485cb1dd27SAsmitha Karunanithi {
349fdd26906SClaire Weinan     std::string entriesPath = getDumpEntriesPath(dumpType);
350fdd26906SClaire Weinan     if (entriesPath.empty())
3515cb1dd27SAsmitha Karunanithi     {
3525cb1dd27SAsmitha Karunanithi         messages::internalError(asyncResp->res);
3535cb1dd27SAsmitha Karunanithi         return;
3545cb1dd27SAsmitha Karunanithi     }
3555cb1dd27SAsmitha Karunanithi 
3565eb468daSGeorge Liu     sdbusplus::message::object_path path("/xyz/openbmc_project/dump");
3575eb468daSGeorge Liu     dbus::utility::getManagedObjects(
3585eb468daSGeorge Liu         "xyz.openbmc_project.Dump.Manager", path,
359fdd26906SClaire Weinan         [asyncResp, entriesPath,
3605e7e2dc5SEd Tanous          dumpType](const boost::system::error_code& ec,
3615eb468daSGeorge Liu                    const dbus::utility::ManagedObjectType& objects) {
3625cb1dd27SAsmitha Karunanithi             if (ec)
3635cb1dd27SAsmitha Karunanithi             {
36462598e31SEd Tanous                 BMCWEB_LOG_ERROR("DumpEntry resp_handler got error {}", ec);
3655cb1dd27SAsmitha Karunanithi                 messages::internalError(asyncResp->res);
3665cb1dd27SAsmitha Karunanithi                 return;
3675cb1dd27SAsmitha Karunanithi             }
3685cb1dd27SAsmitha Karunanithi 
369fdd26906SClaire Weinan             // Remove ending slash
370fdd26906SClaire Weinan             std::string odataIdStr = entriesPath;
371fdd26906SClaire Weinan             if (!odataIdStr.empty())
372fdd26906SClaire Weinan             {
373fdd26906SClaire Weinan                 odataIdStr.pop_back();
374fdd26906SClaire Weinan             }
375fdd26906SClaire Weinan 
376fdd26906SClaire Weinan             asyncResp->res.jsonValue["@odata.type"] =
377fdd26906SClaire Weinan                 "#LogEntryCollection.LogEntryCollection";
378fdd26906SClaire Weinan             asyncResp->res.jsonValue["@odata.id"] = std::move(odataIdStr);
379fdd26906SClaire Weinan             asyncResp->res.jsonValue["Name"] = dumpType + " Dump Entries";
380*bd79bce8SPatrick Williams             asyncResp->res.jsonValue["Description"] =
381*bd79bce8SPatrick Williams                 "Collection of " + dumpType + " Dump Entries";
382fdd26906SClaire Weinan 
3833544d2a7SEd Tanous             nlohmann::json::array_t entriesArray;
38418f8f608SEd Tanous             std::string dumpEntryPath = getDumpPath(dumpType) + "/entry/";
3855cb1dd27SAsmitha Karunanithi 
3865eb468daSGeorge Liu             dbus::utility::ManagedObjectType resp(objects);
3873544d2a7SEd Tanous             std::ranges::sort(resp, [](const auto& l, const auto& r) {
388002d39b4SEd Tanous                 return AlphanumLess<std::string>()(l.first.filename(),
389002d39b4SEd Tanous                                                    r.first.filename());
390565dfb6fSClaire Weinan             });
391565dfb6fSClaire Weinan 
3925cb1dd27SAsmitha Karunanithi             for (auto& object : resp)
3935cb1dd27SAsmitha Karunanithi             {
394b47452b2SAsmitha Karunanithi                 if (object.first.str.find(dumpEntryPath) == std::string::npos)
3955cb1dd27SAsmitha Karunanithi                 {
3965cb1dd27SAsmitha Karunanithi                     continue;
3975cb1dd27SAsmitha Karunanithi                 }
398c6fecdabSClaire Weinan                 uint64_t timestampUs = 0;
3995cb1dd27SAsmitha Karunanithi                 uint64_t size = 0;
40035440d18SAsmitha Karunanithi                 std::string dumpStatus;
40168dd075aSAsmitha Karunanithi                 std::string originatorId;
40268dd075aSAsmitha Karunanithi                 log_entry::OriginatorTypes originatorType =
40368dd075aSAsmitha Karunanithi                     log_entry::OriginatorTypes::Internal;
404433b68b4SJason M. Bills                 nlohmann::json::object_t thisEntry;
4052dfd18efSEd Tanous 
4062dfd18efSEd Tanous                 std::string entryID = object.first.filename();
4072dfd18efSEd Tanous                 if (entryID.empty())
4085cb1dd27SAsmitha Karunanithi                 {
4095cb1dd27SAsmitha Karunanithi                     continue;
4105cb1dd27SAsmitha Karunanithi                 }
4115cb1dd27SAsmitha Karunanithi 
412*bd79bce8SPatrick Williams                 parseDumpEntryFromDbusObject(object, dumpStatus, size,
413*bd79bce8SPatrick Williams                                              timestampUs, originatorId,
414*bd79bce8SPatrick Williams                                              originatorType, asyncResp);
4155cb1dd27SAsmitha Karunanithi 
4160fda0f12SGeorge Liu                 if (dumpStatus !=
4170fda0f12SGeorge Liu                         "xyz.openbmc_project.Common.Progress.OperationStatus.Completed" &&
41835440d18SAsmitha Karunanithi                     !dumpStatus.empty())
41935440d18SAsmitha Karunanithi                 {
42035440d18SAsmitha Karunanithi                     // Dump status is not Complete, no need to enumerate
42135440d18SAsmitha Karunanithi                     continue;
42235440d18SAsmitha Karunanithi                 }
42335440d18SAsmitha Karunanithi 
42468dd075aSAsmitha Karunanithi                 thisEntry["@odata.type"] = "#LogEntry.v1_11_0.LogEntry";
425fdd26906SClaire Weinan                 thisEntry["@odata.id"] = entriesPath + entryID;
4265cb1dd27SAsmitha Karunanithi                 thisEntry["Id"] = entryID;
4275cb1dd27SAsmitha Karunanithi                 thisEntry["EntryType"] = "Event";
4285cb1dd27SAsmitha Karunanithi                 thisEntry["Name"] = dumpType + " Dump Entry";
429bbd80db8SClaire Weinan                 thisEntry["Created"] =
430bbd80db8SClaire Weinan                     redfish::time_utils::getDateTimeUintUs(timestampUs);
4315cb1dd27SAsmitha Karunanithi 
43268dd075aSAsmitha Karunanithi                 if (!originatorId.empty())
43368dd075aSAsmitha Karunanithi                 {
43468dd075aSAsmitha Karunanithi                     thisEntry["Originator"] = originatorId;
43568dd075aSAsmitha Karunanithi                     thisEntry["OriginatorType"] = originatorType;
43668dd075aSAsmitha Karunanithi                 }
43768dd075aSAsmitha Karunanithi 
4385cb1dd27SAsmitha Karunanithi                 if (dumpType == "BMC")
4395cb1dd27SAsmitha Karunanithi                 {
440d337bb72SAsmitha Karunanithi                     thisEntry["DiagnosticDataType"] = "Manager";
441*bd79bce8SPatrick Williams                     thisEntry["AdditionalDataURI"] =
442*bd79bce8SPatrick Williams                         entriesPath + entryID + "/attachment";
443fdd26906SClaire Weinan                     thisEntry["AdditionalDataSizeBytes"] = size;
4445cb1dd27SAsmitha Karunanithi                 }
4455cb1dd27SAsmitha Karunanithi                 else if (dumpType == "System")
4465cb1dd27SAsmitha Karunanithi                 {
447d337bb72SAsmitha Karunanithi                     thisEntry["DiagnosticDataType"] = "OEM";
448d337bb72SAsmitha Karunanithi                     thisEntry["OEMDiagnosticDataType"] = "System";
449*bd79bce8SPatrick Williams                     thisEntry["AdditionalDataURI"] =
450*bd79bce8SPatrick Williams                         entriesPath + entryID + "/attachment";
451fdd26906SClaire Weinan                     thisEntry["AdditionalDataSizeBytes"] = size;
4525cb1dd27SAsmitha Karunanithi                 }
453b2ba3072SPatrick Williams                 entriesArray.emplace_back(std::move(thisEntry));
4545cb1dd27SAsmitha Karunanithi             }
455*bd79bce8SPatrick Williams             asyncResp->res.jsonValue["Members@odata.count"] =
456*bd79bce8SPatrick Williams                 entriesArray.size();
4573544d2a7SEd Tanous             asyncResp->res.jsonValue["Members"] = std::move(entriesArray);
4585eb468daSGeorge Liu         });
4595cb1dd27SAsmitha Karunanithi }
4605cb1dd27SAsmitha Karunanithi 
4618d1b46d7Szhanghch05 inline void
462c7a6d660SClaire Weinan     getDumpEntryById(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
4638d1b46d7Szhanghch05                      const std::string& entryID, const std::string& dumpType)
4645cb1dd27SAsmitha Karunanithi {
465fdd26906SClaire Weinan     std::string entriesPath = getDumpEntriesPath(dumpType);
466fdd26906SClaire Weinan     if (entriesPath.empty())
4675cb1dd27SAsmitha Karunanithi     {
4685cb1dd27SAsmitha Karunanithi         messages::internalError(asyncResp->res);
4695cb1dd27SAsmitha Karunanithi         return;
4705cb1dd27SAsmitha Karunanithi     }
4715cb1dd27SAsmitha Karunanithi 
4725eb468daSGeorge Liu     sdbusplus::message::object_path path("/xyz/openbmc_project/dump");
4735eb468daSGeorge Liu     dbus::utility::getManagedObjects(
4745eb468daSGeorge Liu         "xyz.openbmc_project.Dump.Manager", path,
475fdd26906SClaire Weinan         [asyncResp, entryID, dumpType,
4765e7e2dc5SEd Tanous          entriesPath](const boost::system::error_code& ec,
47702cad96eSEd Tanous                       const dbus::utility::ManagedObjectType& resp) {
4785cb1dd27SAsmitha Karunanithi             if (ec)
4795cb1dd27SAsmitha Karunanithi             {
48062598e31SEd Tanous                 BMCWEB_LOG_ERROR("DumpEntry resp_handler got error {}", ec);
4815cb1dd27SAsmitha Karunanithi                 messages::internalError(asyncResp->res);
4825cb1dd27SAsmitha Karunanithi                 return;
4835cb1dd27SAsmitha Karunanithi             }
4845cb1dd27SAsmitha Karunanithi 
485b47452b2SAsmitha Karunanithi             bool foundDumpEntry = false;
48618f8f608SEd Tanous             std::string dumpEntryPath = getDumpPath(dumpType) + "/entry/";
487b47452b2SAsmitha Karunanithi 
4889eb808c1SEd Tanous             for (const auto& objectPath : resp)
4895cb1dd27SAsmitha Karunanithi             {
490b47452b2SAsmitha Karunanithi                 if (objectPath.first.str != dumpEntryPath + entryID)
4915cb1dd27SAsmitha Karunanithi                 {
4925cb1dd27SAsmitha Karunanithi                     continue;
4935cb1dd27SAsmitha Karunanithi                 }
4945cb1dd27SAsmitha Karunanithi 
4955cb1dd27SAsmitha Karunanithi                 foundDumpEntry = true;
496c6fecdabSClaire Weinan                 uint64_t timestampUs = 0;
4975cb1dd27SAsmitha Karunanithi                 uint64_t size = 0;
49835440d18SAsmitha Karunanithi                 std::string dumpStatus;
49968dd075aSAsmitha Karunanithi                 std::string originatorId;
50068dd075aSAsmitha Karunanithi                 log_entry::OriginatorTypes originatorType =
50168dd075aSAsmitha Karunanithi                     log_entry::OriginatorTypes::Internal;
5025cb1dd27SAsmitha Karunanithi 
503aefe3786SClaire Weinan                 parseDumpEntryFromDbusObject(objectPath, dumpStatus, size,
50468dd075aSAsmitha Karunanithi                                              timestampUs, originatorId,
50568dd075aSAsmitha Karunanithi                                              originatorType, asyncResp);
5065cb1dd27SAsmitha Karunanithi 
5070fda0f12SGeorge Liu                 if (dumpStatus !=
5080fda0f12SGeorge Liu                         "xyz.openbmc_project.Common.Progress.OperationStatus.Completed" &&
50935440d18SAsmitha Karunanithi                     !dumpStatus.empty())
51035440d18SAsmitha Karunanithi                 {
51135440d18SAsmitha Karunanithi                     // Dump status is not Complete
51235440d18SAsmitha Karunanithi                     // return not found until status is changed to Completed
513*bd79bce8SPatrick Williams                     messages::resourceNotFound(asyncResp->res,
514*bd79bce8SPatrick Williams                                                dumpType + " dump", entryID);
51535440d18SAsmitha Karunanithi                     return;
51635440d18SAsmitha Karunanithi                 }
51735440d18SAsmitha Karunanithi 
5185cb1dd27SAsmitha Karunanithi                 asyncResp->res.jsonValue["@odata.type"] =
51968dd075aSAsmitha Karunanithi                     "#LogEntry.v1_11_0.LogEntry";
520fdd26906SClaire Weinan                 asyncResp->res.jsonValue["@odata.id"] = entriesPath + entryID;
5215cb1dd27SAsmitha Karunanithi                 asyncResp->res.jsonValue["Id"] = entryID;
5225cb1dd27SAsmitha Karunanithi                 asyncResp->res.jsonValue["EntryType"] = "Event";
5235cb1dd27SAsmitha Karunanithi                 asyncResp->res.jsonValue["Name"] = dumpType + " Dump Entry";
524bbd80db8SClaire Weinan                 asyncResp->res.jsonValue["Created"] =
525bbd80db8SClaire Weinan                     redfish::time_utils::getDateTimeUintUs(timestampUs);
5265cb1dd27SAsmitha Karunanithi 
52768dd075aSAsmitha Karunanithi                 if (!originatorId.empty())
52868dd075aSAsmitha Karunanithi                 {
52968dd075aSAsmitha Karunanithi                     asyncResp->res.jsonValue["Originator"] = originatorId;
53068dd075aSAsmitha Karunanithi                     asyncResp->res.jsonValue["OriginatorType"] = originatorType;
53168dd075aSAsmitha Karunanithi                 }
53268dd075aSAsmitha Karunanithi 
5335cb1dd27SAsmitha Karunanithi                 if (dumpType == "BMC")
5345cb1dd27SAsmitha Karunanithi                 {
535d337bb72SAsmitha Karunanithi                     asyncResp->res.jsonValue["DiagnosticDataType"] = "Manager";
536d337bb72SAsmitha Karunanithi                     asyncResp->res.jsonValue["AdditionalDataURI"] =
537fdd26906SClaire Weinan                         entriesPath + entryID + "/attachment";
538fdd26906SClaire Weinan                     asyncResp->res.jsonValue["AdditionalDataSizeBytes"] = size;
5395cb1dd27SAsmitha Karunanithi                 }
5405cb1dd27SAsmitha Karunanithi                 else if (dumpType == "System")
5415cb1dd27SAsmitha Karunanithi                 {
542d337bb72SAsmitha Karunanithi                     asyncResp->res.jsonValue["DiagnosticDataType"] = "OEM";
543*bd79bce8SPatrick Williams                     asyncResp->res.jsonValue["OEMDiagnosticDataType"] =
544*bd79bce8SPatrick Williams                         "System";
545d337bb72SAsmitha Karunanithi                     asyncResp->res.jsonValue["AdditionalDataURI"] =
546fdd26906SClaire Weinan                         entriesPath + entryID + "/attachment";
547fdd26906SClaire Weinan                     asyncResp->res.jsonValue["AdditionalDataSizeBytes"] = size;
5485cb1dd27SAsmitha Karunanithi                 }
5495cb1dd27SAsmitha Karunanithi             }
550e05aec50SEd Tanous             if (!foundDumpEntry)
551b47452b2SAsmitha Karunanithi             {
55262598e31SEd Tanous                 BMCWEB_LOG_WARNING("Can't find Dump Entry {}", entryID);
553b90d14f2SMyung Bae                 messages::resourceNotFound(asyncResp->res, dumpType + " dump",
554b90d14f2SMyung Bae                                            entryID);
555b47452b2SAsmitha Karunanithi                 return;
556b47452b2SAsmitha Karunanithi             }
5575eb468daSGeorge Liu         });
5585cb1dd27SAsmitha Karunanithi }
5595cb1dd27SAsmitha Karunanithi 
5608d1b46d7Szhanghch05 inline void deleteDumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
5619878256fSStanley Chu                             const std::string& entryID,
562b47452b2SAsmitha Karunanithi                             const std::string& dumpType)
5635cb1dd27SAsmitha Karunanithi {
5645a39f77aSPatrick Williams     auto respHandler = [asyncResp,
5655a39f77aSPatrick Williams                         entryID](const boost::system::error_code& ec) {
56662598e31SEd Tanous         BMCWEB_LOG_DEBUG("Dump Entry doDelete callback: Done");
5675cb1dd27SAsmitha Karunanithi         if (ec)
5685cb1dd27SAsmitha Karunanithi         {
5693de8d8baSGeorge Liu             if (ec.value() == EBADR)
5703de8d8baSGeorge Liu             {
5713de8d8baSGeorge Liu                 messages::resourceNotFound(asyncResp->res, "LogEntry", entryID);
5723de8d8baSGeorge Liu                 return;
5733de8d8baSGeorge Liu             }
57462598e31SEd Tanous             BMCWEB_LOG_ERROR(
57562598e31SEd Tanous                 "Dump (DBus) doDelete respHandler got error {} entryID={}", ec,
57662598e31SEd Tanous                 entryID);
5775cb1dd27SAsmitha Karunanithi             messages::internalError(asyncResp->res);
5785cb1dd27SAsmitha Karunanithi             return;
5795cb1dd27SAsmitha Karunanithi         }
5805cb1dd27SAsmitha Karunanithi     };
58118f8f608SEd Tanous 
5825cb1dd27SAsmitha Karunanithi     crow::connections::systemBus->async_method_call(
5835cb1dd27SAsmitha Karunanithi         respHandler, "xyz.openbmc_project.Dump.Manager",
58418f8f608SEd Tanous         std::format("{}/entry/{}", getDumpPath(dumpType), entryID),
5855cb1dd27SAsmitha Karunanithi         "xyz.openbmc_project.Object.Delete", "Delete");
5865cb1dd27SAsmitha Karunanithi }
587b5f288d2SAbhilash Raju inline bool checkSizeLimit(int fd, crow::Response& res)
588b5f288d2SAbhilash Raju {
589b5f288d2SAbhilash Raju     long long int size = lseek(fd, 0, SEEK_END);
590b5f288d2SAbhilash Raju     if (size <= 0)
591b5f288d2SAbhilash Raju     {
592b5f288d2SAbhilash Raju         BMCWEB_LOG_ERROR("Failed to get size of file, lseek() returned {}",
593b5f288d2SAbhilash Raju                          size);
594b5f288d2SAbhilash Raju         messages::internalError(res);
595b5f288d2SAbhilash Raju         return false;
596b5f288d2SAbhilash Raju     }
5975cb1dd27SAsmitha Karunanithi 
598b5f288d2SAbhilash Raju     // Arbitrary max size of 20MB to accommodate BMC dumps
599b5f288d2SAbhilash Raju     constexpr long long int maxFileSize = 20LL * 1024LL * 1024LL;
600b5f288d2SAbhilash Raju     if (size > maxFileSize)
601b5f288d2SAbhilash Raju     {
602b5f288d2SAbhilash Raju         BMCWEB_LOG_ERROR("File size {} exceeds maximum allowed size of {}",
603b5f288d2SAbhilash Raju                          size, maxFileSize);
604b5f288d2SAbhilash Raju         messages::internalError(res);
605b5f288d2SAbhilash Raju         return false;
606b5f288d2SAbhilash Raju     }
607b5f288d2SAbhilash Raju     off_t rc = lseek(fd, 0, SEEK_SET);
608b5f288d2SAbhilash Raju     if (rc < 0)
609b5f288d2SAbhilash Raju     {
610b5f288d2SAbhilash Raju         BMCWEB_LOG_ERROR("Failed to reset file offset to 0");
611b5f288d2SAbhilash Raju         messages::internalError(res);
612b5f288d2SAbhilash Raju         return false;
613b5f288d2SAbhilash Raju     }
614b5f288d2SAbhilash Raju     return true;
615b5f288d2SAbhilash Raju }
616*bd79bce8SPatrick Williams inline void downloadEntryCallback(
617*bd79bce8SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
618*bd79bce8SPatrick Williams     const std::string& entryID, const std::string& downloadEntryType,
619168d1b1aSCarson Labrado     const boost::system::error_code& ec,
620168d1b1aSCarson Labrado     const sdbusplus::message::unix_fd& unixfd)
621168d1b1aSCarson Labrado {
622168d1b1aSCarson Labrado     if (ec.value() == EBADR)
623168d1b1aSCarson Labrado     {
624168d1b1aSCarson Labrado         messages::resourceNotFound(asyncResp->res, "EntryAttachment", entryID);
625168d1b1aSCarson Labrado         return;
626168d1b1aSCarson Labrado     }
627168d1b1aSCarson Labrado     if (ec)
628168d1b1aSCarson Labrado     {
629168d1b1aSCarson Labrado         BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
630168d1b1aSCarson Labrado         messages::internalError(asyncResp->res);
631168d1b1aSCarson Labrado         return;
632168d1b1aSCarson Labrado     }
633168d1b1aSCarson Labrado 
634168d1b1aSCarson Labrado     // Make sure we know how to process the retrieved entry attachment
635168d1b1aSCarson Labrado     if ((downloadEntryType != "BMC") && (downloadEntryType != "System"))
636168d1b1aSCarson Labrado     {
637168d1b1aSCarson Labrado         BMCWEB_LOG_ERROR("downloadEntryCallback() invalid entry type: {}",
638168d1b1aSCarson Labrado                          downloadEntryType);
639168d1b1aSCarson Labrado         messages::internalError(asyncResp->res);
640168d1b1aSCarson Labrado     }
641168d1b1aSCarson Labrado 
642168d1b1aSCarson Labrado     int fd = -1;
643168d1b1aSCarson Labrado     fd = dup(unixfd);
644168d1b1aSCarson Labrado     if (fd < 0)
645168d1b1aSCarson Labrado     {
646168d1b1aSCarson Labrado         BMCWEB_LOG_ERROR("Failed to open file");
647168d1b1aSCarson Labrado         messages::internalError(asyncResp->res);
648168d1b1aSCarson Labrado         return;
649168d1b1aSCarson Labrado     }
650b5f288d2SAbhilash Raju     if (!checkSizeLimit(fd, asyncResp->res))
651168d1b1aSCarson Labrado     {
652168d1b1aSCarson Labrado         close(fd);
653168d1b1aSCarson Labrado         return;
654168d1b1aSCarson Labrado     }
655168d1b1aSCarson Labrado     if (downloadEntryType == "System")
656168d1b1aSCarson Labrado     {
657b5f288d2SAbhilash Raju         if (!asyncResp->res.openFd(fd, bmcweb::EncodingType::Base64))
658b5f288d2SAbhilash Raju         {
659b5f288d2SAbhilash Raju             messages::internalError(asyncResp->res);
660b5f288d2SAbhilash Raju             close(fd);
661b5f288d2SAbhilash Raju             return;
662b5f288d2SAbhilash Raju         }
663168d1b1aSCarson Labrado         asyncResp->res.addHeader(
664168d1b1aSCarson Labrado             boost::beast::http::field::content_transfer_encoding, "Base64");
665b5f288d2SAbhilash Raju         return;
666168d1b1aSCarson Labrado     }
667b5f288d2SAbhilash Raju     if (!asyncResp->res.openFd(fd))
66827b0cf90SEd Tanous     {
669b5f288d2SAbhilash Raju         messages::internalError(asyncResp->res);
670b5f288d2SAbhilash Raju         close(fd);
671b5f288d2SAbhilash Raju         return;
67227b0cf90SEd Tanous     }
673168d1b1aSCarson Labrado     asyncResp->res.addHeader(boost::beast::http::field::content_type,
674168d1b1aSCarson Labrado                              "application/octet-stream");
675168d1b1aSCarson Labrado }
676168d1b1aSCarson Labrado 
677168d1b1aSCarson Labrado inline void
678168d1b1aSCarson Labrado     downloadDumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
679168d1b1aSCarson Labrado                       const std::string& entryID, const std::string& dumpType)
680168d1b1aSCarson Labrado {
681168d1b1aSCarson Labrado     if (dumpType != "BMC")
682168d1b1aSCarson Labrado     {
683168d1b1aSCarson Labrado         BMCWEB_LOG_WARNING("Can't find Dump Entry {}", entryID);
684168d1b1aSCarson Labrado         messages::resourceNotFound(asyncResp->res, dumpType + " dump", entryID);
685168d1b1aSCarson Labrado         return;
686168d1b1aSCarson Labrado     }
687168d1b1aSCarson Labrado 
688*bd79bce8SPatrick Williams     std::string dumpEntryPath =
689*bd79bce8SPatrick Williams         std::format("{}/entry/{}", getDumpPath(dumpType), entryID);
690168d1b1aSCarson Labrado 
691168d1b1aSCarson Labrado     auto downloadDumpEntryHandler =
692168d1b1aSCarson Labrado         [asyncResp, entryID,
693168d1b1aSCarson Labrado          dumpType](const boost::system::error_code& ec,
694168d1b1aSCarson Labrado                    const sdbusplus::message::unix_fd& unixfd) {
695168d1b1aSCarson Labrado             downloadEntryCallback(asyncResp, entryID, dumpType, ec, unixfd);
696168d1b1aSCarson Labrado         };
697168d1b1aSCarson Labrado 
698168d1b1aSCarson Labrado     crow::connections::systemBus->async_method_call(
699168d1b1aSCarson Labrado         std::move(downloadDumpEntryHandler), "xyz.openbmc_project.Dump.Manager",
700168d1b1aSCarson Labrado         dumpEntryPath, "xyz.openbmc_project.Dump.Entry", "GetFileHandle");
701168d1b1aSCarson Labrado }
702168d1b1aSCarson Labrado 
703*bd79bce8SPatrick Williams inline void downloadEventLogEntry(
704*bd79bce8SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
705*bd79bce8SPatrick Williams     const std::string& systemName, const std::string& entryID,
706168d1b1aSCarson Labrado     const std::string& dumpType)
707168d1b1aSCarson Labrado {
70825b54dbaSEd Tanous     if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
709168d1b1aSCarson Labrado     {
710168d1b1aSCarson Labrado         // Option currently returns no systems.  TBD
711168d1b1aSCarson Labrado         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
712168d1b1aSCarson Labrado                                    systemName);
713168d1b1aSCarson Labrado         return;
714168d1b1aSCarson Labrado     }
715253f11b8SEd Tanous     if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
716168d1b1aSCarson Labrado     {
717168d1b1aSCarson Labrado         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
718168d1b1aSCarson Labrado                                    systemName);
719168d1b1aSCarson Labrado         return;
720168d1b1aSCarson Labrado     }
721168d1b1aSCarson Labrado 
722168d1b1aSCarson Labrado     std::string entryPath =
723168d1b1aSCarson Labrado         sdbusplus::message::object_path("/xyz/openbmc_project/logging/entry") /
724168d1b1aSCarson Labrado         entryID;
725168d1b1aSCarson Labrado 
726168d1b1aSCarson Labrado     auto downloadEventLogEntryHandler =
727168d1b1aSCarson Labrado         [asyncResp, entryID,
728168d1b1aSCarson Labrado          dumpType](const boost::system::error_code& ec,
729168d1b1aSCarson Labrado                    const sdbusplus::message::unix_fd& unixfd) {
730168d1b1aSCarson Labrado             downloadEntryCallback(asyncResp, entryID, dumpType, ec, unixfd);
731168d1b1aSCarson Labrado         };
732168d1b1aSCarson Labrado 
733168d1b1aSCarson Labrado     crow::connections::systemBus->async_method_call(
734168d1b1aSCarson Labrado         std::move(downloadEventLogEntryHandler), "xyz.openbmc_project.Logging",
735168d1b1aSCarson Labrado         entryPath, "xyz.openbmc_project.Logging.Entry", "GetEntry");
736168d1b1aSCarson Labrado }
737168d1b1aSCarson Labrado 
7388e31778eSAsmitha Karunanithi inline DumpCreationProgress
7398e31778eSAsmitha Karunanithi     mapDbusStatusToDumpProgress(const std::string& status)
740a43be80fSAsmitha Karunanithi {
7418e31778eSAsmitha Karunanithi     if (status ==
7428e31778eSAsmitha Karunanithi             "xyz.openbmc_project.Common.Progress.OperationStatus.Failed" ||
7438e31778eSAsmitha Karunanithi         status == "xyz.openbmc_project.Common.Progress.OperationStatus.Aborted")
7448e31778eSAsmitha Karunanithi     {
7458e31778eSAsmitha Karunanithi         return DumpCreationProgress::DUMP_CREATE_FAILED;
7468e31778eSAsmitha Karunanithi     }
7478e31778eSAsmitha Karunanithi     if (status ==
7488e31778eSAsmitha Karunanithi         "xyz.openbmc_project.Common.Progress.OperationStatus.Completed")
7498e31778eSAsmitha Karunanithi     {
7508e31778eSAsmitha Karunanithi         return DumpCreationProgress::DUMP_CREATE_SUCCESS;
7518e31778eSAsmitha Karunanithi     }
7528e31778eSAsmitha Karunanithi     return DumpCreationProgress::DUMP_CREATE_INPROGRESS;
7538e31778eSAsmitha Karunanithi }
7548e31778eSAsmitha Karunanithi 
7558e31778eSAsmitha Karunanithi inline DumpCreationProgress
7568e31778eSAsmitha Karunanithi     getDumpCompletionStatus(const dbus::utility::DBusPropertiesMap& values)
7578e31778eSAsmitha Karunanithi {
7588e31778eSAsmitha Karunanithi     for (const auto& [key, val] : values)
7598e31778eSAsmitha Karunanithi     {
7608e31778eSAsmitha Karunanithi         if (key == "Status")
7618e31778eSAsmitha Karunanithi         {
7628e31778eSAsmitha Karunanithi             const std::string* value = std::get_if<std::string>(&val);
7638e31778eSAsmitha Karunanithi             if (value == nullptr)
7648e31778eSAsmitha Karunanithi             {
76562598e31SEd Tanous                 BMCWEB_LOG_ERROR("Status property value is null");
7668e31778eSAsmitha Karunanithi                 return DumpCreationProgress::DUMP_CREATE_FAILED;
7678e31778eSAsmitha Karunanithi             }
7688e31778eSAsmitha Karunanithi             return mapDbusStatusToDumpProgress(*value);
7698e31778eSAsmitha Karunanithi         }
7708e31778eSAsmitha Karunanithi     }
7718e31778eSAsmitha Karunanithi     return DumpCreationProgress::DUMP_CREATE_INPROGRESS;
7728e31778eSAsmitha Karunanithi }
7738e31778eSAsmitha Karunanithi 
7748e31778eSAsmitha Karunanithi inline std::string getDumpEntryPath(const std::string& dumpPath)
7758e31778eSAsmitha Karunanithi {
7768e31778eSAsmitha Karunanithi     if (dumpPath == "/xyz/openbmc_project/dump/bmc/entry")
7778e31778eSAsmitha Karunanithi     {
778253f11b8SEd Tanous         return std::format("/redfish/v1/Managers/{}/LogServices/Dump/Entries/",
7799f565090SEd Tanous                            BMCWEB_REDFISH_MANAGER_URI_NAME);
7808e31778eSAsmitha Karunanithi     }
7818e31778eSAsmitha Karunanithi     if (dumpPath == "/xyz/openbmc_project/dump/system/entry")
7828e31778eSAsmitha Karunanithi     {
783253f11b8SEd Tanous         return std::format("/redfish/v1/Systems/{}/LogServices/Dump/Entries/",
784253f11b8SEd Tanous                            BMCWEB_REDFISH_SYSTEM_URI_NAME);
7858e31778eSAsmitha Karunanithi     }
7868e31778eSAsmitha Karunanithi     return "";
7878e31778eSAsmitha Karunanithi }
7888e31778eSAsmitha Karunanithi 
7898e31778eSAsmitha Karunanithi inline void createDumpTaskCallback(
7908e31778eSAsmitha Karunanithi     task::Payload&& payload,
7918e31778eSAsmitha Karunanithi     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
7928e31778eSAsmitha Karunanithi     const sdbusplus::message::object_path& createdObjPath)
7938e31778eSAsmitha Karunanithi {
7948e31778eSAsmitha Karunanithi     const std::string dumpPath = createdObjPath.parent_path().str;
7958e31778eSAsmitha Karunanithi     const std::string dumpId = createdObjPath.filename();
7968e31778eSAsmitha Karunanithi 
7978e31778eSAsmitha Karunanithi     std::string dumpEntryPath = getDumpEntryPath(dumpPath);
7988e31778eSAsmitha Karunanithi 
7998e31778eSAsmitha Karunanithi     if (dumpEntryPath.empty())
8008e31778eSAsmitha Karunanithi     {
80162598e31SEd Tanous         BMCWEB_LOG_ERROR("Invalid dump type received");
8028e31778eSAsmitha Karunanithi         messages::internalError(asyncResp->res);
8038e31778eSAsmitha Karunanithi         return;
8048e31778eSAsmitha Karunanithi     }
8058e31778eSAsmitha Karunanithi 
8068e31778eSAsmitha Karunanithi     crow::connections::systemBus->async_method_call(
8078cb2c024SEd Tanous         [asyncResp, payload = std::move(payload), createdObjPath,
8088e31778eSAsmitha Karunanithi          dumpEntryPath{std::move(dumpEntryPath)},
8095e7e2dc5SEd Tanous          dumpId](const boost::system::error_code& ec,
8108e31778eSAsmitha Karunanithi                  const std::string& introspectXml) {
8118e31778eSAsmitha Karunanithi             if (ec)
8128e31778eSAsmitha Karunanithi             {
81362598e31SEd Tanous                 BMCWEB_LOG_ERROR("Introspect call failed with error: {}",
81462598e31SEd Tanous                                  ec.message());
8158e31778eSAsmitha Karunanithi                 messages::internalError(asyncResp->res);
8168e31778eSAsmitha Karunanithi                 return;
8178e31778eSAsmitha Karunanithi             }
8188e31778eSAsmitha Karunanithi 
8198e31778eSAsmitha Karunanithi             // Check if the created dump object has implemented Progress
8208e31778eSAsmitha Karunanithi             // interface to track dump completion. If yes, fetch the "Status"
8218e31778eSAsmitha Karunanithi             // property of the interface, modify the task state accordingly.
8228e31778eSAsmitha Karunanithi             // Else, return task completed.
8238e31778eSAsmitha Karunanithi             tinyxml2::XMLDocument doc;
8248e31778eSAsmitha Karunanithi 
8258e31778eSAsmitha Karunanithi             doc.Parse(introspectXml.data(), introspectXml.size());
8268e31778eSAsmitha Karunanithi             tinyxml2::XMLNode* pRoot = doc.FirstChildElement("node");
8278e31778eSAsmitha Karunanithi             if (pRoot == nullptr)
8288e31778eSAsmitha Karunanithi             {
82962598e31SEd Tanous                 BMCWEB_LOG_ERROR("XML document failed to parse");
8308e31778eSAsmitha Karunanithi                 messages::internalError(asyncResp->res);
8318e31778eSAsmitha Karunanithi                 return;
8328e31778eSAsmitha Karunanithi             }
8338e31778eSAsmitha Karunanithi             tinyxml2::XMLElement* interfaceNode =
8348e31778eSAsmitha Karunanithi                 pRoot->FirstChildElement("interface");
8358e31778eSAsmitha Karunanithi 
8368e31778eSAsmitha Karunanithi             bool isProgressIntfPresent = false;
8378e31778eSAsmitha Karunanithi             while (interfaceNode != nullptr)
8388e31778eSAsmitha Karunanithi             {
839*bd79bce8SPatrick Williams                 const char* thisInterfaceName =
840*bd79bce8SPatrick Williams                     interfaceNode->Attribute("name");
8418e31778eSAsmitha Karunanithi                 if (thisInterfaceName != nullptr)
8428e31778eSAsmitha Karunanithi                 {
8438e31778eSAsmitha Karunanithi                     if (thisInterfaceName ==
8448e31778eSAsmitha Karunanithi                         std::string_view("xyz.openbmc_project.Common.Progress"))
8458e31778eSAsmitha Karunanithi                     {
8468e31778eSAsmitha Karunanithi                         interfaceNode =
8478e31778eSAsmitha Karunanithi                             interfaceNode->NextSiblingElement("interface");
8488e31778eSAsmitha Karunanithi                         continue;
8498e31778eSAsmitha Karunanithi                     }
8508e31778eSAsmitha Karunanithi                     isProgressIntfPresent = true;
8518e31778eSAsmitha Karunanithi                     break;
8528e31778eSAsmitha Karunanithi                 }
8538e31778eSAsmitha Karunanithi                 interfaceNode = interfaceNode->NextSiblingElement("interface");
8548e31778eSAsmitha Karunanithi             }
8558e31778eSAsmitha Karunanithi 
856a43be80fSAsmitha Karunanithi             std::shared_ptr<task::TaskData> task = task::TaskData::createTask(
8578e31778eSAsmitha Karunanithi                 [createdObjPath, dumpEntryPath, dumpId, isProgressIntfPresent](
858*bd79bce8SPatrick Williams                     const boost::system::error_code& ec2,
859*bd79bce8SPatrick Williams                     sdbusplus::message_t& msg,
860a43be80fSAsmitha Karunanithi                     const std::shared_ptr<task::TaskData>& taskData) {
8618b24275dSEd Tanous                     if (ec2)
862cb13a392SEd Tanous                     {
86362598e31SEd Tanous                         BMCWEB_LOG_ERROR("{}: Error in creating dump",
86462598e31SEd Tanous                                          createdObjPath.str);
865*bd79bce8SPatrick Williams                         taskData->messages.emplace_back(
866*bd79bce8SPatrick Williams                             messages::internalError());
8676145ed6fSAsmitha Karunanithi                         taskData->state = "Cancelled";
8686145ed6fSAsmitha Karunanithi                         return task::completed;
869cb13a392SEd Tanous                     }
870b9d36b47SEd Tanous 
8718e31778eSAsmitha Karunanithi                     if (isProgressIntfPresent)
872a43be80fSAsmitha Karunanithi                     {
8738e31778eSAsmitha Karunanithi                         dbus::utility::DBusPropertiesMap values;
8748e31778eSAsmitha Karunanithi                         std::string prop;
8758e31778eSAsmitha Karunanithi                         msg.read(prop, values);
8768e31778eSAsmitha Karunanithi 
8778e31778eSAsmitha Karunanithi                         DumpCreationProgress dumpStatus =
8788e31778eSAsmitha Karunanithi                             getDumpCompletionStatus(values);
879*bd79bce8SPatrick Williams                         if (dumpStatus ==
880*bd79bce8SPatrick Williams                             DumpCreationProgress::DUMP_CREATE_FAILED)
8818e31778eSAsmitha Karunanithi                         {
88262598e31SEd Tanous                             BMCWEB_LOG_ERROR("{}: Error in creating dump",
88362598e31SEd Tanous                                              createdObjPath.str);
8848e31778eSAsmitha Karunanithi                             taskData->state = "Cancelled";
8858e31778eSAsmitha Karunanithi                             return task::completed;
8868e31778eSAsmitha Karunanithi                         }
8878e31778eSAsmitha Karunanithi 
888*bd79bce8SPatrick Williams                         if (dumpStatus ==
889*bd79bce8SPatrick Williams                             DumpCreationProgress::DUMP_CREATE_INPROGRESS)
8908e31778eSAsmitha Karunanithi                         {
891*bd79bce8SPatrick Williams                             BMCWEB_LOG_DEBUG(
892*bd79bce8SPatrick Williams                                 "{}: Dump creation task is in progress",
89362598e31SEd Tanous                                 createdObjPath.str);
8948e31778eSAsmitha Karunanithi                             return !task::completed;
8958e31778eSAsmitha Karunanithi                         }
8968e31778eSAsmitha Karunanithi                     }
8978e31778eSAsmitha Karunanithi 
898a43be80fSAsmitha Karunanithi                     nlohmann::json retMessage = messages::success();
899a43be80fSAsmitha Karunanithi                     taskData->messages.emplace_back(retMessage);
900a43be80fSAsmitha Karunanithi 
901c51a58eeSEd Tanous                     boost::urls::url url = boost::urls::format(
902253f11b8SEd Tanous                         "/redfish/v1/Managers/{}/LogServices/Dump/Entries/{}",
903253f11b8SEd Tanous                         BMCWEB_REDFISH_MANAGER_URI_NAME, dumpId);
904c51a58eeSEd Tanous 
905c51a58eeSEd Tanous                     std::string headerLoc = "Location: ";
906c51a58eeSEd Tanous                     headerLoc += url.buffer();
907c51a58eeSEd Tanous 
908*bd79bce8SPatrick Williams                     taskData->payload->httpHeaders.emplace_back(
909*bd79bce8SPatrick Williams                         std::move(headerLoc));
910a43be80fSAsmitha Karunanithi 
91162598e31SEd Tanous                     BMCWEB_LOG_DEBUG("{}: Dump creation task completed",
91262598e31SEd Tanous                                      createdObjPath.str);
913a43be80fSAsmitha Karunanithi                     taskData->state = "Completed";
914b47452b2SAsmitha Karunanithi                     return task::completed;
915a43be80fSAsmitha Karunanithi                 },
9168e31778eSAsmitha Karunanithi                 "type='signal',interface='org.freedesktop.DBus.Properties',"
9178e31778eSAsmitha Karunanithi                 "member='PropertiesChanged',path='" +
9188e31778eSAsmitha Karunanithi                     createdObjPath.str + "'");
919a43be80fSAsmitha Karunanithi 
9208e31778eSAsmitha Karunanithi             // The task timer is set to max time limit within which the
9218e31778eSAsmitha Karunanithi             // requested dump will be collected.
9228e31778eSAsmitha Karunanithi             task->startTimer(std::chrono::minutes(6));
923a43be80fSAsmitha Karunanithi             task->populateResp(asyncResp->res);
9248e31778eSAsmitha Karunanithi             task->payload.emplace(payload);
9258e31778eSAsmitha Karunanithi         },
9268e31778eSAsmitha Karunanithi         "xyz.openbmc_project.Dump.Manager", createdObjPath,
9278e31778eSAsmitha Karunanithi         "org.freedesktop.DBus.Introspectable", "Introspect");
928a43be80fSAsmitha Karunanithi }
929a43be80fSAsmitha Karunanithi 
9308d1b46d7Szhanghch05 inline void createDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
9318d1b46d7Szhanghch05                        const crow::Request& req, const std::string& dumpType)
932a43be80fSAsmitha Karunanithi {
933fdd26906SClaire Weinan     std::string dumpPath = getDumpEntriesPath(dumpType);
934fdd26906SClaire Weinan     if (dumpPath.empty())
935a43be80fSAsmitha Karunanithi     {
936a43be80fSAsmitha Karunanithi         messages::internalError(asyncResp->res);
937a43be80fSAsmitha Karunanithi         return;
938a43be80fSAsmitha Karunanithi     }
939a43be80fSAsmitha Karunanithi 
940a43be80fSAsmitha Karunanithi     std::optional<std::string> diagnosticDataType;
941a43be80fSAsmitha Karunanithi     std::optional<std::string> oemDiagnosticDataType;
942a43be80fSAsmitha Karunanithi 
94315ed6780SWilly Tu     if (!redfish::json_util::readJsonAction(
944a43be80fSAsmitha Karunanithi             req, asyncResp->res, "DiagnosticDataType", diagnosticDataType,
945a43be80fSAsmitha Karunanithi             "OEMDiagnosticDataType", oemDiagnosticDataType))
946a43be80fSAsmitha Karunanithi     {
947a43be80fSAsmitha Karunanithi         return;
948a43be80fSAsmitha Karunanithi     }
949a43be80fSAsmitha Karunanithi 
950a43be80fSAsmitha Karunanithi     if (dumpType == "System")
951a43be80fSAsmitha Karunanithi     {
952a43be80fSAsmitha Karunanithi         if (!oemDiagnosticDataType || !diagnosticDataType)
953a43be80fSAsmitha Karunanithi         {
95462598e31SEd Tanous             BMCWEB_LOG_ERROR(
95562598e31SEd Tanous                 "CreateDump action parameter 'DiagnosticDataType'/'OEMDiagnosticDataType' value not found!");
956a43be80fSAsmitha Karunanithi             messages::actionParameterMissing(
957a43be80fSAsmitha Karunanithi                 asyncResp->res, "CollectDiagnosticData",
958a43be80fSAsmitha Karunanithi                 "DiagnosticDataType & OEMDiagnosticDataType");
959a43be80fSAsmitha Karunanithi             return;
960a43be80fSAsmitha Karunanithi         }
9613174e4dfSEd Tanous         if ((*oemDiagnosticDataType != "System") ||
962a43be80fSAsmitha Karunanithi             (*diagnosticDataType != "OEM"))
963a43be80fSAsmitha Karunanithi         {
96462598e31SEd Tanous             BMCWEB_LOG_ERROR("Wrong parameter values passed");
965ace85d60SEd Tanous             messages::internalError(asyncResp->res);
966a43be80fSAsmitha Karunanithi             return;
967a43be80fSAsmitha Karunanithi         }
968253f11b8SEd Tanous         dumpPath = std::format("/redfish/v1/Systems/{}/LogServices/Dump/",
969253f11b8SEd Tanous                                BMCWEB_REDFISH_SYSTEM_URI_NAME);
970a43be80fSAsmitha Karunanithi     }
971a43be80fSAsmitha Karunanithi     else if (dumpType == "BMC")
972a43be80fSAsmitha Karunanithi     {
973a43be80fSAsmitha Karunanithi         if (!diagnosticDataType)
974a43be80fSAsmitha Karunanithi         {
97562598e31SEd Tanous             BMCWEB_LOG_ERROR(
97662598e31SEd Tanous                 "CreateDump action parameter 'DiagnosticDataType' not found!");
977a43be80fSAsmitha Karunanithi             messages::actionParameterMissing(
978a43be80fSAsmitha Karunanithi                 asyncResp->res, "CollectDiagnosticData", "DiagnosticDataType");
979a43be80fSAsmitha Karunanithi             return;
980a43be80fSAsmitha Karunanithi         }
9813174e4dfSEd Tanous         if (*diagnosticDataType != "Manager")
982a43be80fSAsmitha Karunanithi         {
98362598e31SEd Tanous             BMCWEB_LOG_ERROR(
98462598e31SEd Tanous                 "Wrong parameter value passed for 'DiagnosticDataType'");
985ace85d60SEd Tanous             messages::internalError(asyncResp->res);
986a43be80fSAsmitha Karunanithi             return;
987a43be80fSAsmitha Karunanithi         }
988253f11b8SEd Tanous         dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/Dump/",
989253f11b8SEd Tanous                                BMCWEB_REDFISH_MANAGER_URI_NAME);
9905907571dSAsmitha Karunanithi     }
9915907571dSAsmitha Karunanithi     else
9925907571dSAsmitha Karunanithi     {
99362598e31SEd Tanous         BMCWEB_LOG_ERROR("CreateDump failed. Unknown dump type");
9945907571dSAsmitha Karunanithi         messages::internalError(asyncResp->res);
9955907571dSAsmitha Karunanithi         return;
996a43be80fSAsmitha Karunanithi     }
997a43be80fSAsmitha Karunanithi 
9988e31778eSAsmitha Karunanithi     std::vector<std::pair<std::string, std::variant<std::string, uint64_t>>>
9998e31778eSAsmitha Karunanithi         createDumpParamVec;
10008e31778eSAsmitha Karunanithi 
1001f574a8e1SCarson Labrado     if (req.session != nullptr)
1002f574a8e1SCarson Labrado     {
100368dd075aSAsmitha Karunanithi         createDumpParamVec.emplace_back(
100468dd075aSAsmitha Karunanithi             "xyz.openbmc_project.Dump.Create.CreateParameters.OriginatorId",
100568dd075aSAsmitha Karunanithi             req.session->clientIp);
100668dd075aSAsmitha Karunanithi         createDumpParamVec.emplace_back(
100768dd075aSAsmitha Karunanithi             "xyz.openbmc_project.Dump.Create.CreateParameters.OriginatorType",
100868dd075aSAsmitha Karunanithi             "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Client");
1009f574a8e1SCarson Labrado     }
101068dd075aSAsmitha Karunanithi 
1011a43be80fSAsmitha Karunanithi     crow::connections::systemBus->async_method_call(
10125e7e2dc5SEd Tanous         [asyncResp, payload(task::Payload(req)),
10135e7e2dc5SEd Tanous          dumpPath](const boost::system::error_code& ec,
10145e7e2dc5SEd Tanous                    const sdbusplus::message_t& msg,
10158e31778eSAsmitha Karunanithi                    const sdbusplus::message::object_path& objPath) mutable {
1016a43be80fSAsmitha Karunanithi             if (ec)
1017a43be80fSAsmitha Karunanithi             {
101862598e31SEd Tanous                 BMCWEB_LOG_ERROR("CreateDump resp_handler got error {}", ec);
10195907571dSAsmitha Karunanithi                 const sd_bus_error* dbusError = msg.get_error();
10205907571dSAsmitha Karunanithi                 if (dbusError == nullptr)
10215907571dSAsmitha Karunanithi                 {
10225907571dSAsmitha Karunanithi                     messages::internalError(asyncResp->res);
10235907571dSAsmitha Karunanithi                     return;
10245907571dSAsmitha Karunanithi                 }
10255907571dSAsmitha Karunanithi 
102662598e31SEd Tanous                 BMCWEB_LOG_ERROR("CreateDump DBus error: {} and error msg: {}",
102762598e31SEd Tanous                                  dbusError->name, dbusError->message);
10285907571dSAsmitha Karunanithi                 if (std::string_view(
10295907571dSAsmitha Karunanithi                         "xyz.openbmc_project.Common.Error.NotAllowed") ==
10305907571dSAsmitha Karunanithi                     dbusError->name)
10315907571dSAsmitha Karunanithi                 {
10325907571dSAsmitha Karunanithi                     messages::resourceInStandby(asyncResp->res);
10335907571dSAsmitha Karunanithi                     return;
10345907571dSAsmitha Karunanithi                 }
10355907571dSAsmitha Karunanithi                 if (std::string_view(
10365907571dSAsmitha Karunanithi                         "xyz.openbmc_project.Dump.Create.Error.Disabled") ==
10375907571dSAsmitha Karunanithi                     dbusError->name)
10385907571dSAsmitha Karunanithi                 {
10395907571dSAsmitha Karunanithi                     messages::serviceDisabled(asyncResp->res, dumpPath);
10405907571dSAsmitha Karunanithi                     return;
10415907571dSAsmitha Karunanithi                 }
10425907571dSAsmitha Karunanithi                 if (std::string_view(
10435907571dSAsmitha Karunanithi                         "xyz.openbmc_project.Common.Error.Unavailable") ==
10445907571dSAsmitha Karunanithi                     dbusError->name)
10455907571dSAsmitha Karunanithi                 {
10465907571dSAsmitha Karunanithi                     messages::resourceInUse(asyncResp->res);
10475907571dSAsmitha Karunanithi                     return;
10485907571dSAsmitha Karunanithi                 }
10495907571dSAsmitha Karunanithi                 // Other Dbus errors such as:
10505907571dSAsmitha Karunanithi                 // xyz.openbmc_project.Common.Error.InvalidArgument &
10515907571dSAsmitha Karunanithi                 // org.freedesktop.DBus.Error.InvalidArgs are all related to
10525907571dSAsmitha Karunanithi                 // the dbus call that is made here in the bmcweb
10535907571dSAsmitha Karunanithi                 // implementation and has nothing to do with the client's
10545907571dSAsmitha Karunanithi                 // input in the request. Hence, returning internal error
10555907571dSAsmitha Karunanithi                 // back to the client.
1056a43be80fSAsmitha Karunanithi                 messages::internalError(asyncResp->res);
1057a43be80fSAsmitha Karunanithi                 return;
1058a43be80fSAsmitha Karunanithi             }
105962598e31SEd Tanous             BMCWEB_LOG_DEBUG("Dump Created. Path: {}", objPath.str);
10608e31778eSAsmitha Karunanithi             createDumpTaskCallback(std::move(payload), asyncResp, objPath);
1061a43be80fSAsmitha Karunanithi         },
106218f8f608SEd Tanous         "xyz.openbmc_project.Dump.Manager", getDumpPath(dumpType),
10638e31778eSAsmitha Karunanithi         "xyz.openbmc_project.Dump.Create", "CreateDump", createDumpParamVec);
1064a43be80fSAsmitha Karunanithi }
1065a43be80fSAsmitha Karunanithi 
10668d1b46d7Szhanghch05 inline void clearDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
10678d1b46d7Szhanghch05                       const std::string& dumpType)
106880319af1SAsmitha Karunanithi {
10690d946211SClaire Weinan     crow::connections::systemBus->async_method_call(
10700d946211SClaire Weinan         [asyncResp](const boost::system::error_code& ec) {
107180319af1SAsmitha Karunanithi             if (ec)
107280319af1SAsmitha Karunanithi             {
107362598e31SEd Tanous                 BMCWEB_LOG_ERROR("clearDump resp_handler got error {}", ec);
107480319af1SAsmitha Karunanithi                 messages::internalError(asyncResp->res);
107580319af1SAsmitha Karunanithi                 return;
107680319af1SAsmitha Karunanithi             }
10770d946211SClaire Weinan         },
107818f8f608SEd Tanous         "xyz.openbmc_project.Dump.Manager", getDumpPath(dumpType),
10790d946211SClaire Weinan         "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
108080319af1SAsmitha Karunanithi }
108180319af1SAsmitha Karunanithi 
1082*bd79bce8SPatrick Williams inline void parseCrashdumpParameters(
1083*bd79bce8SPatrick Williams     const dbus::utility::DBusPropertiesMap& params, std::string& filename,
1084*bd79bce8SPatrick Williams     std::string& timestamp, std::string& logfile)
1085043a0536SJohnathan Mantey {
1086d1bde9e5SKrzysztof Grobelny     const std::string* filenamePtr = nullptr;
1087d1bde9e5SKrzysztof Grobelny     const std::string* timestampPtr = nullptr;
1088d1bde9e5SKrzysztof Grobelny     const std::string* logfilePtr = nullptr;
1089d1bde9e5SKrzysztof Grobelny 
1090d1bde9e5SKrzysztof Grobelny     const bool success = sdbusplus::unpackPropertiesNoThrow(
1091d1bde9e5SKrzysztof Grobelny         dbus_utils::UnpackErrorPrinter(), params, "Timestamp", timestampPtr,
1092d1bde9e5SKrzysztof Grobelny         "Filename", filenamePtr, "Log", logfilePtr);
1093d1bde9e5SKrzysztof Grobelny 
1094d1bde9e5SKrzysztof Grobelny     if (!success)
1095043a0536SJohnathan Mantey     {
1096d1bde9e5SKrzysztof Grobelny         return;
1097043a0536SJohnathan Mantey     }
1098d1bde9e5SKrzysztof Grobelny 
1099d1bde9e5SKrzysztof Grobelny     if (filenamePtr != nullptr)
1100043a0536SJohnathan Mantey     {
1101d1bde9e5SKrzysztof Grobelny         filename = *filenamePtr;
1102d1bde9e5SKrzysztof Grobelny     }
1103d1bde9e5SKrzysztof Grobelny 
1104d1bde9e5SKrzysztof Grobelny     if (timestampPtr != nullptr)
1105043a0536SJohnathan Mantey     {
1106d1bde9e5SKrzysztof Grobelny         timestamp = *timestampPtr;
1107043a0536SJohnathan Mantey     }
1108d1bde9e5SKrzysztof Grobelny 
1109d1bde9e5SKrzysztof Grobelny     if (logfilePtr != nullptr)
1110043a0536SJohnathan Mantey     {
1111d1bde9e5SKrzysztof Grobelny         logfile = *logfilePtr;
1112043a0536SJohnathan Mantey     }
1113043a0536SJohnathan Mantey }
1114043a0536SJohnathan Mantey 
11157e860f15SJohn Edward Broadbent inline void requestRoutesSystemLogServiceCollection(App& app)
11161da66f75SEd Tanous {
1117c4bf6374SJason M. Bills     /**
1118c4bf6374SJason M. Bills      * Functions triggers appropriate requests on DBus
1119c4bf6374SJason M. Bills      */
112022d268cbSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/")
1121ed398213SEd Tanous         .privileges(redfish::privileges::getLogServiceCollection)
1122*bd79bce8SPatrick Williams         .methods(
1123*bd79bce8SPatrick Williams             boost::beast::http::verb::
1124*bd79bce8SPatrick Williams                 get)([&app](const crow::Request& req,
112522d268cbSEd Tanous                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
112622d268cbSEd Tanous                             const std::string& systemName) {
11273ba00073SCarson Labrado             if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1128c4bf6374SJason M. Bills             {
112945ca1b86SEd Tanous                 return;
113045ca1b86SEd Tanous             }
113125b54dbaSEd Tanous             if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
11327f3e84a1SEd Tanous             {
11337f3e84a1SEd Tanous                 // Option currently returns no systems.  TBD
11347f3e84a1SEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
11357f3e84a1SEd Tanous                                            systemName);
11367f3e84a1SEd Tanous                 return;
11377f3e84a1SEd Tanous             }
1138253f11b8SEd Tanous             if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
113922d268cbSEd Tanous             {
114022d268cbSEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
114122d268cbSEd Tanous                                            systemName);
114222d268cbSEd Tanous                 return;
114322d268cbSEd Tanous             }
114422d268cbSEd Tanous 
11457e860f15SJohn Edward Broadbent             // Collections don't include the static data added by SubRoute
11467e860f15SJohn Edward Broadbent             // because it has a duplicate entry for members
1147c4bf6374SJason M. Bills             asyncResp->res.jsonValue["@odata.type"] =
1148c4bf6374SJason M. Bills                 "#LogServiceCollection.LogServiceCollection";
1149c4bf6374SJason M. Bills             asyncResp->res.jsonValue["@odata.id"] =
1150253f11b8SEd Tanous                 std::format("/redfish/v1/Systems/{}/LogServices",
1151253f11b8SEd Tanous                             BMCWEB_REDFISH_SYSTEM_URI_NAME);
115245ca1b86SEd Tanous             asyncResp->res.jsonValue["Name"] = "System Log Services Collection";
1153c4bf6374SJason M. Bills             asyncResp->res.jsonValue["Description"] =
1154c4bf6374SJason M. Bills                 "Collection of LogServices for this Computer System";
1155*bd79bce8SPatrick Williams             nlohmann::json& logServiceArray =
1156*bd79bce8SPatrick Williams                 asyncResp->res.jsonValue["Members"];
1157c4bf6374SJason M. Bills             logServiceArray = nlohmann::json::array();
11581476687dSEd Tanous             nlohmann::json::object_t eventLog;
11591476687dSEd Tanous             eventLog["@odata.id"] =
1160253f11b8SEd Tanous                 std::format("/redfish/v1/Systems/{}/LogServices/EventLog",
1161253f11b8SEd Tanous                             BMCWEB_REDFISH_SYSTEM_URI_NAME);
1162b2ba3072SPatrick Williams             logServiceArray.emplace_back(std::move(eventLog));
116325b54dbaSEd Tanous             if constexpr (BMCWEB_REDFISH_DUMP_LOG)
116425b54dbaSEd Tanous             {
11651476687dSEd Tanous                 nlohmann::json::object_t dumpLog;
116625b54dbaSEd Tanous                 dumpLog["@odata.id"] =
1167253f11b8SEd Tanous                     std::format("/redfish/v1/Systems/{}/LogServices/Dump",
1168253f11b8SEd Tanous                                 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1169b2ba3072SPatrick Williams                 logServiceArray.emplace_back(std::move(dumpLog));
117025b54dbaSEd Tanous             }
1171c9bb6861Sraviteja-b 
11725ffd11f2SGunnar Mills             if constexpr (BMCWEB_REDFISH_CPU_LOG)
117325b54dbaSEd Tanous             {
11741476687dSEd Tanous                 nlohmann::json::object_t crashdump;
11751476687dSEd Tanous                 crashdump["@odata.id"] =
1176253f11b8SEd Tanous                     std::format("/redfish/v1/Systems/{}/LogServices/Crashdump",
1177253f11b8SEd Tanous                                 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1178b2ba3072SPatrick Williams                 logServiceArray.emplace_back(std::move(crashdump));
117925b54dbaSEd Tanous             }
1180b7028ebfSSpencer Ku 
118125b54dbaSEd Tanous             if constexpr (BMCWEB_REDFISH_HOST_LOGGER)
118225b54dbaSEd Tanous             {
11831476687dSEd Tanous                 nlohmann::json::object_t hostlogger;
11841476687dSEd Tanous                 hostlogger["@odata.id"] =
1185253f11b8SEd Tanous                     std::format("/redfish/v1/Systems/{}/LogServices/HostLogger",
1186253f11b8SEd Tanous                                 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1187b2ba3072SPatrick Williams                 logServiceArray.emplace_back(std::move(hostlogger));
118825b54dbaSEd Tanous             }
1189c4bf6374SJason M. Bills             asyncResp->res.jsonValue["Members@odata.count"] =
1190c4bf6374SJason M. Bills                 logServiceArray.size();
1191a3316fc6SZhikuiRen 
11927a1dbc48SGeorge Liu             constexpr std::array<std::string_view, 1> interfaces = {
11937a1dbc48SGeorge Liu                 "xyz.openbmc_project.State.Boot.PostCode"};
11947a1dbc48SGeorge Liu             dbus::utility::getSubTreePaths(
11957a1dbc48SGeorge Liu                 "/", 0, interfaces,
11967a1dbc48SGeorge Liu                 [asyncResp](const boost::system::error_code& ec,
1197b9d36b47SEd Tanous                             const dbus::utility::MapperGetSubTreePathsResponse&
1198b9d36b47SEd Tanous                                 subtreePath) {
1199a3316fc6SZhikuiRen                     if (ec)
1200a3316fc6SZhikuiRen                     {
120162598e31SEd Tanous                         BMCWEB_LOG_ERROR("{}", ec);
1202a3316fc6SZhikuiRen                         return;
1203a3316fc6SZhikuiRen                     }
1204a3316fc6SZhikuiRen 
120555f79e6fSEd Tanous                     for (const auto& pathStr : subtreePath)
1206a3316fc6SZhikuiRen                     {
1207a3316fc6SZhikuiRen                         if (pathStr.find("PostCode") != std::string::npos)
1208a3316fc6SZhikuiRen                         {
120923a21a1cSEd Tanous                             nlohmann::json& logServiceArrayLocal =
1210a3316fc6SZhikuiRen                                 asyncResp->res.jsonValue["Members"];
1211613dabeaSEd Tanous                             nlohmann::json::object_t member;
1212253f11b8SEd Tanous                             member["@odata.id"] = std::format(
1213253f11b8SEd Tanous                                 "/redfish/v1/Systems/{}/LogServices/PostCodes",
1214253f11b8SEd Tanous                                 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1215613dabeaSEd Tanous 
1216*bd79bce8SPatrick Williams                             logServiceArrayLocal.emplace_back(
1217*bd79bce8SPatrick Williams                                 std::move(member));
1218613dabeaSEd Tanous 
121945ca1b86SEd Tanous                             asyncResp->res.jsonValue["Members@odata.count"] =
122023a21a1cSEd Tanous                                 logServiceArrayLocal.size();
1221a3316fc6SZhikuiRen                             return;
1222a3316fc6SZhikuiRen                         }
1223a3316fc6SZhikuiRen                     }
12247a1dbc48SGeorge Liu                 });
12257e860f15SJohn Edward Broadbent         });
1226c4bf6374SJason M. Bills }
1227c4bf6374SJason M. Bills 
12287e860f15SJohn Edward Broadbent inline void requestRoutesEventLogService(App& app)
1229c4bf6374SJason M. Bills {
123022d268cbSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/")
1231ed398213SEd Tanous         .privileges(redfish::privileges::getLogService)
1232*bd79bce8SPatrick Williams         .methods(
1233*bd79bce8SPatrick Williams             boost::beast::http::verb::
1234*bd79bce8SPatrick Williams                 get)([&app](const crow::Request& req,
123522d268cbSEd Tanous                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
123622d268cbSEd Tanous                             const std::string& systemName) {
12373ba00073SCarson Labrado             if (!redfish::setUpRedfishRoute(app, req, asyncResp))
123845ca1b86SEd Tanous             {
123945ca1b86SEd Tanous                 return;
124045ca1b86SEd Tanous             }
1241253f11b8SEd Tanous             if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
124222d268cbSEd Tanous             {
124322d268cbSEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
124422d268cbSEd Tanous                                            systemName);
124522d268cbSEd Tanous                 return;
124622d268cbSEd Tanous             }
1247c4bf6374SJason M. Bills             asyncResp->res.jsonValue["@odata.id"] =
1248253f11b8SEd Tanous                 std::format("/redfish/v1/Systems/{}/LogServices/EventLog",
1249253f11b8SEd Tanous                             BMCWEB_REDFISH_SYSTEM_URI_NAME);
1250c4bf6374SJason M. Bills             asyncResp->res.jsonValue["@odata.type"] =
1251b25644a1SJanet Adkins                 "#LogService.v1_2_0.LogService";
1252c4bf6374SJason M. Bills             asyncResp->res.jsonValue["Name"] = "Event Log Service";
1253*bd79bce8SPatrick Williams             asyncResp->res.jsonValue["Description"] =
1254*bd79bce8SPatrick Williams                 "System Event Log Service";
1255c4bf6374SJason M. Bills             asyncResp->res.jsonValue["Id"] = "EventLog";
1256539d8c6bSEd Tanous             asyncResp->res.jsonValue["OverWritePolicy"] =
1257539d8c6bSEd Tanous                 log_service::OverWritePolicy::WrapsWhenFull;
12587c8c4058STejas Patil 
12597c8c4058STejas Patil             std::pair<std::string, std::string> redfishDateTimeOffset =
12602b82937eSEd Tanous                 redfish::time_utils::getDateTimeOffsetNow();
12617c8c4058STejas Patil 
12627c8c4058STejas Patil             asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
12637c8c4058STejas Patil             asyncResp->res.jsonValue["DateTimeLocalOffset"] =
12647c8c4058STejas Patil                 redfishDateTimeOffset.second;
12657c8c4058STejas Patil 
1266*bd79bce8SPatrick Williams             asyncResp->res.jsonValue["Entries"]["@odata.id"] = std::format(
1267*bd79bce8SPatrick Williams                 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
1268253f11b8SEd Tanous                 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1269*bd79bce8SPatrick Williams             asyncResp->res
1270*bd79bce8SPatrick Williams                 .jsonValue["Actions"]["#LogService.ClearLog"]["target"]
1271e7d6c8b2SGunnar Mills 
127220fa6a2cSEd Tanous                 = std::format(
1273253f11b8SEd Tanous                     "/redfish/v1/Systems/{}/LogServices/EventLog/Actions/LogService.ClearLog",
127420fa6a2cSEd Tanous                     BMCWEB_REDFISH_SYSTEM_URI_NAME);
12757e860f15SJohn Edward Broadbent         });
1276489640c6SJason M. Bills }
1277489640c6SJason M. Bills 
1278599b9af3SAlexander Hansen inline void handleSystemsLogServicesEventLogActionsClearPost(
1279599b9af3SAlexander Hansen     App& app, const crow::Request& req,
128022d268cbSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1281599b9af3SAlexander Hansen     const std::string& systemName)
1282599b9af3SAlexander Hansen {
12833ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
128445ca1b86SEd Tanous     {
128545ca1b86SEd Tanous         return;
128645ca1b86SEd Tanous     }
1287253f11b8SEd Tanous     if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
128822d268cbSEd Tanous     {
128922d268cbSEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
129022d268cbSEd Tanous                                    systemName);
129122d268cbSEd Tanous         return;
129222d268cbSEd Tanous     }
1293599b9af3SAlexander Hansen 
1294489640c6SJason M. Bills     // Clear the EventLog by deleting the log files
1295489640c6SJason M. Bills     std::vector<std::filesystem::path> redfishLogFiles;
1296489640c6SJason M. Bills     if (getRedfishLogFiles(redfishLogFiles))
1297489640c6SJason M. Bills     {
1298489640c6SJason M. Bills         for (const std::filesystem::path& file : redfishLogFiles)
1299489640c6SJason M. Bills         {
1300489640c6SJason M. Bills             std::error_code ec;
1301489640c6SJason M. Bills             std::filesystem::remove(file, ec);
1302489640c6SJason M. Bills         }
1303489640c6SJason M. Bills     }
1304489640c6SJason M. Bills 
1305489640c6SJason M. Bills     // Reload rsyslog so it knows to start new log files
1306489640c6SJason M. Bills     crow::connections::systemBus->async_method_call(
13075e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
1308489640c6SJason M. Bills             if (ec)
1309489640c6SJason M. Bills             {
131062598e31SEd Tanous                 BMCWEB_LOG_ERROR("Failed to reload rsyslog: {}", ec);
1311489640c6SJason M. Bills                 messages::internalError(asyncResp->res);
1312489640c6SJason M. Bills                 return;
1313489640c6SJason M. Bills             }
1314489640c6SJason M. Bills 
1315489640c6SJason M. Bills             messages::success(asyncResp->res);
1316489640c6SJason M. Bills         },
1317489640c6SJason M. Bills         "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
1318002d39b4SEd Tanous         "org.freedesktop.systemd1.Manager", "ReloadUnit", "rsyslog.service",
1319002d39b4SEd Tanous         "replace");
1320599b9af3SAlexander Hansen }
1321599b9af3SAlexander Hansen 
1322599b9af3SAlexander Hansen inline void requestRoutesJournalEventLogClear(App& app)
1323599b9af3SAlexander Hansen {
1324599b9af3SAlexander Hansen     BMCWEB_ROUTE(
1325599b9af3SAlexander Hansen         app,
1326599b9af3SAlexander Hansen         "/redfish/v1/Systems/<str>/LogServices/EventLog/Actions/LogService.ClearLog/")
1327599b9af3SAlexander Hansen         .privileges({{"ConfigureComponents"}})
1328599b9af3SAlexander Hansen         .methods(boost::beast::http::verb::post)(std::bind_front(
1329599b9af3SAlexander Hansen             handleSystemsLogServicesEventLogActionsClearPost, std::ref(app)));
1330c4bf6374SJason M. Bills }
1331c4bf6374SJason M. Bills 
1332ac992cdeSJason M. Bills enum class LogParseError
1333ac992cdeSJason M. Bills {
1334ac992cdeSJason M. Bills     success,
1335ac992cdeSJason M. Bills     parseFailed,
1336ac992cdeSJason M. Bills     messageIdNotInRegistry,
1337ac992cdeSJason M. Bills };
1338ac992cdeSJason M. Bills 
1339*bd79bce8SPatrick Williams static LogParseError fillEventLogEntryJson(
1340*bd79bce8SPatrick Williams     const std::string& logEntryID, const std::string& logEntry,
1341de703c5dSJason M. Bills     nlohmann::json::object_t& logEntryJson)
1342c4bf6374SJason M. Bills {
134395820184SJason M. Bills     // The redfish log format is "<Timestamp> <MessageId>,<MessageArgs>"
1344cd225da8SJason M. Bills     // First get the Timestamp
1345f23b7296SEd Tanous     size_t space = logEntry.find_first_of(' ');
1346cd225da8SJason M. Bills     if (space == std::string::npos)
134795820184SJason M. Bills     {
1348ac992cdeSJason M. Bills         return LogParseError::parseFailed;
134995820184SJason M. Bills     }
1350cd225da8SJason M. Bills     std::string timestamp = logEntry.substr(0, space);
1351cd225da8SJason M. Bills     // Then get the log contents
1352f23b7296SEd Tanous     size_t entryStart = logEntry.find_first_not_of(' ', space);
1353cd225da8SJason M. Bills     if (entryStart == std::string::npos)
1354cd225da8SJason M. Bills     {
1355ac992cdeSJason M. Bills         return LogParseError::parseFailed;
1356cd225da8SJason M. Bills     }
1357cd225da8SJason M. Bills     std::string_view entry(logEntry);
1358cd225da8SJason M. Bills     entry.remove_prefix(entryStart);
1359cd225da8SJason M. Bills     // Use split to separate the entry into its fields
1360cd225da8SJason M. Bills     std::vector<std::string> logEntryFields;
136150ebd4afSEd Tanous     bmcweb::split(logEntryFields, entry, ',');
1362cd225da8SJason M. Bills     // We need at least a MessageId to be valid
13631e6deaf6SEd Tanous     auto logEntryIter = logEntryFields.begin();
13641e6deaf6SEd Tanous     if (logEntryIter == logEntryFields.end())
1365cd225da8SJason M. Bills     {
1366ac992cdeSJason M. Bills         return LogParseError::parseFailed;
1367cd225da8SJason M. Bills     }
13681e6deaf6SEd Tanous     std::string& messageID = *logEntryIter;
13694851d45dSJason M. Bills     // Get the Message from the MessageRegistry
1370fffb8c1fSEd Tanous     const registries::Message* message = registries::getMessage(messageID);
1371c4bf6374SJason M. Bills 
13721e6deaf6SEd Tanous     logEntryIter++;
137354417b02SSui Chen     if (message == nullptr)
1374c4bf6374SJason M. Bills     {
137562598e31SEd Tanous         BMCWEB_LOG_WARNING("Log entry not found in registry: {}", logEntry);
1376ac992cdeSJason M. Bills         return LogParseError::messageIdNotInRegistry;
1377c4bf6374SJason M. Bills     }
1378c4bf6374SJason M. Bills 
13791e6deaf6SEd Tanous     std::vector<std::string_view> messageArgs(logEntryIter,
13801e6deaf6SEd Tanous                                               logEntryFields.end());
1381c05bba45SEd Tanous     messageArgs.resize(message->numberOfArgs);
1382c05bba45SEd Tanous 
1383*bd79bce8SPatrick Williams     std::string msg =
1384*bd79bce8SPatrick Williams         redfish::registries::fillMessageArgs(messageArgs, message->message);
13851e6deaf6SEd Tanous     if (msg.empty())
138615a86ff6SJason M. Bills     {
13871e6deaf6SEd Tanous         return LogParseError::parseFailed;
138815a86ff6SJason M. Bills     }
13894851d45dSJason M. Bills 
139095820184SJason M. Bills     // Get the Created time from the timestamp. The log timestamp is in RFC3339
139195820184SJason M. Bills     // format which matches the Redfish format except for the fractional seconds
139295820184SJason M. Bills     // between the '.' and the '+', so just remove them.
1393f23b7296SEd Tanous     std::size_t dot = timestamp.find_first_of('.');
1394f23b7296SEd Tanous     std::size_t plus = timestamp.find_first_of('+');
139595820184SJason M. Bills     if (dot != std::string::npos && plus != std::string::npos)
1396c4bf6374SJason M. Bills     {
139795820184SJason M. Bills         timestamp.erase(dot, plus - dot);
1398c4bf6374SJason M. Bills     }
1399c4bf6374SJason M. Bills 
1400c4bf6374SJason M. Bills     // Fill in the log entry with the gathered data
14019c11a172SVijay Lobo     logEntryJson["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
1402ef4c65b7SEd Tanous     logEntryJson["@odata.id"] = boost::urls::format(
1403253f11b8SEd Tanous         "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}",
1404253f11b8SEd Tanous         BMCWEB_REDFISH_SYSTEM_URI_NAME, logEntryID);
140584afc48bSJason M. Bills     logEntryJson["Name"] = "System Event Log Entry";
140684afc48bSJason M. Bills     logEntryJson["Id"] = logEntryID;
140784afc48bSJason M. Bills     logEntryJson["Message"] = std::move(msg);
140884afc48bSJason M. Bills     logEntryJson["MessageId"] = std::move(messageID);
140984afc48bSJason M. Bills     logEntryJson["MessageArgs"] = messageArgs;
141084afc48bSJason M. Bills     logEntryJson["EntryType"] = "Event";
141184afc48bSJason M. Bills     logEntryJson["Severity"] = message->messageSeverity;
141284afc48bSJason M. Bills     logEntryJson["Created"] = std::move(timestamp);
1413ac992cdeSJason M. Bills     return LogParseError::success;
1414c4bf6374SJason M. Bills }
1415c4bf6374SJason M. Bills 
1416898f2aa2SEd Tanous inline void fillEventLogLogEntryFromPropertyMap(
1417898f2aa2SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1418898f2aa2SEd Tanous     const dbus::utility::DBusPropertiesMap& resp,
1419898f2aa2SEd Tanous     nlohmann::json& objectToFillOut)
1420898f2aa2SEd Tanous {
1421898f2aa2SEd Tanous     uint32_t id = 0;
1422898f2aa2SEd Tanous     uint64_t timestamp = 0;
1423898f2aa2SEd Tanous     uint64_t updateTimestamp = 0;
1424898f2aa2SEd Tanous     std::string severity;
1425898f2aa2SEd Tanous     std::string message;
1426898f2aa2SEd Tanous     const std::string* filePath = nullptr;
1427898f2aa2SEd Tanous     const std::string* resolution = nullptr;
1428898f2aa2SEd Tanous     bool resolved = false;
1429898f2aa2SEd Tanous     std::string notify;
1430898f2aa2SEd Tanous     // clang-format off
1431898f2aa2SEd Tanous     bool success = sdbusplus::unpackPropertiesNoThrow(
1432898f2aa2SEd Tanous         dbus_utils::UnpackErrorPrinter(), resp,
1433898f2aa2SEd Tanous         "Id", id,
1434898f2aa2SEd Tanous         "Message", message,
1435898f2aa2SEd Tanous         "Path", filePath,
1436898f2aa2SEd Tanous         "Resolution", resolution,
1437898f2aa2SEd Tanous         "Resolved", resolved,
1438898f2aa2SEd Tanous         "ServiceProviderNotify", notify,
1439898f2aa2SEd Tanous         "Severity", severity,
1440898f2aa2SEd Tanous         "Timestamp", timestamp,
1441898f2aa2SEd Tanous         "UpdateTimestamp", updateTimestamp
1442898f2aa2SEd Tanous     );
1443898f2aa2SEd Tanous     // clang-format on
1444898f2aa2SEd Tanous 
1445898f2aa2SEd Tanous     if (!success)
1446898f2aa2SEd Tanous     {
1447898f2aa2SEd Tanous         messages::internalError(asyncResp->res);
1448898f2aa2SEd Tanous         return;
1449898f2aa2SEd Tanous     }
1450898f2aa2SEd Tanous 
1451898f2aa2SEd Tanous     objectToFillOut["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
1452898f2aa2SEd Tanous     objectToFillOut["@odata.id"] = boost::urls::format(
1453898f2aa2SEd Tanous         "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}",
1454898f2aa2SEd Tanous         BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(id));
1455898f2aa2SEd Tanous     objectToFillOut["Name"] = "System Event Log Entry";
1456898f2aa2SEd Tanous     objectToFillOut["Id"] = std::to_string(id);
1457898f2aa2SEd Tanous     objectToFillOut["Message"] = message;
1458898f2aa2SEd Tanous     objectToFillOut["Resolved"] = resolved;
1459898f2aa2SEd Tanous     std::optional<bool> notifyAction = getProviderNotifyAction(notify);
1460898f2aa2SEd Tanous     if (notifyAction)
1461898f2aa2SEd Tanous     {
1462898f2aa2SEd Tanous         objectToFillOut["ServiceProviderNotified"] = *notifyAction;
1463898f2aa2SEd Tanous     }
1464898f2aa2SEd Tanous     if ((resolution != nullptr) && !resolution->empty())
1465898f2aa2SEd Tanous     {
1466898f2aa2SEd Tanous         objectToFillOut["Resolution"] = *resolution;
1467898f2aa2SEd Tanous     }
1468898f2aa2SEd Tanous     objectToFillOut["EntryType"] = "Event";
1469898f2aa2SEd Tanous     objectToFillOut["Severity"] = translateSeverityDbusToRedfish(severity);
1470898f2aa2SEd Tanous     objectToFillOut["Created"] =
1471898f2aa2SEd Tanous         redfish::time_utils::getDateTimeUintMs(timestamp);
1472898f2aa2SEd Tanous     objectToFillOut["Modified"] =
1473898f2aa2SEd Tanous         redfish::time_utils::getDateTimeUintMs(updateTimestamp);
1474898f2aa2SEd Tanous     if (filePath != nullptr)
1475898f2aa2SEd Tanous     {
1476898f2aa2SEd Tanous         objectToFillOut["AdditionalDataURI"] = boost::urls::format(
1477898f2aa2SEd Tanous             "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}/attachment",
1478898f2aa2SEd Tanous             BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(id));
1479898f2aa2SEd Tanous     }
1480898f2aa2SEd Tanous }
1481898f2aa2SEd Tanous 
1482b729096dSEd Tanous inline void afterLogEntriesGetManagedObjects(
1483b729096dSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1484b729096dSEd Tanous     const boost::system::error_code& ec,
1485b729096dSEd Tanous     const dbus::utility::ManagedObjectType& resp)
1486b729096dSEd Tanous {
1487b729096dSEd Tanous     if (ec)
1488b729096dSEd Tanous     {
1489b729096dSEd Tanous         // TODO Handle for specific error code
1490b729096dSEd Tanous         BMCWEB_LOG_ERROR("getLogEntriesIfaceData resp_handler got error {}",
1491b729096dSEd Tanous                          ec);
1492b729096dSEd Tanous         messages::internalError(asyncResp->res);
1493b729096dSEd Tanous         return;
1494b729096dSEd Tanous     }
1495b729096dSEd Tanous     nlohmann::json::array_t entriesArray;
1496b729096dSEd Tanous     for (const auto& objectPath : resp)
1497b729096dSEd Tanous     {
1498898f2aa2SEd Tanous         dbus::utility::DBusPropertiesMap propsFlattened;
1499*bd79bce8SPatrick Williams         auto isEntry =
1500*bd79bce8SPatrick Williams             std::ranges::find_if(objectPath.second, [](const auto& object) {
1501898f2aa2SEd Tanous                 return object.first == "xyz.openbmc_project.Logging.Entry";
1502898f2aa2SEd Tanous             });
1503898f2aa2SEd Tanous         if (isEntry == objectPath.second.end())
1504b729096dSEd Tanous         {
1505b729096dSEd Tanous             continue;
1506b729096dSEd Tanous         }
1507898f2aa2SEd Tanous         for (const auto& interfaceMap : objectPath.second)
1508b729096dSEd Tanous         {
1509898f2aa2SEd Tanous             for (const auto& propertyMap : interfaceMap.second)
1510b729096dSEd Tanous             {
1511898f2aa2SEd Tanous                 propsFlattened.emplace_back(propertyMap.first,
1512898f2aa2SEd Tanous                                             propertyMap.second);
1513b729096dSEd Tanous             }
1514b729096dSEd Tanous         }
1515898f2aa2SEd Tanous         fillEventLogLogEntryFromPropertyMap(asyncResp, propsFlattened,
1516898f2aa2SEd Tanous                                             entriesArray.emplace_back());
1517b729096dSEd Tanous     }
1518898f2aa2SEd Tanous 
1519b729096dSEd Tanous     std::ranges::sort(entriesArray, [](const nlohmann::json& left,
1520b729096dSEd Tanous                                        const nlohmann::json& right) {
1521b729096dSEd Tanous         return (left["Id"] <= right["Id"]);
1522b729096dSEd Tanous     });
1523b729096dSEd Tanous     asyncResp->res.jsonValue["Members@odata.count"] = entriesArray.size();
1524b729096dSEd Tanous     asyncResp->res.jsonValue["Members"] = std::move(entriesArray);
1525b729096dSEd Tanous }
1526b729096dSEd Tanous 
1527599b9af3SAlexander Hansen inline void handleSystemsLogServiceEventLogLogEntryCollection(
1528599b9af3SAlexander Hansen     App& app, const crow::Request& req,
152922d268cbSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1530599b9af3SAlexander Hansen     const std::string& systemName)
1531599b9af3SAlexander Hansen {
1532c937d2bfSEd Tanous     query_param::QueryCapabilities capabilities = {
1533c937d2bfSEd Tanous         .canDelegateTop = true,
1534c937d2bfSEd Tanous         .canDelegateSkip = true,
1535c937d2bfSEd Tanous     };
1536c937d2bfSEd Tanous     query_param::Query delegatedQuery;
1537599b9af3SAlexander Hansen     if (!redfish::setUpRedfishRouteWithDelegation(app, req, asyncResp,
1538599b9af3SAlexander Hansen                                                   delegatedQuery, capabilities))
1539c4bf6374SJason M. Bills     {
1540c4bf6374SJason M. Bills         return;
1541c4bf6374SJason M. Bills     }
154225b54dbaSEd Tanous     if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
15437f3e84a1SEd Tanous     {
15447f3e84a1SEd Tanous         // Option currently returns no systems.  TBD
15457f3e84a1SEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
15467f3e84a1SEd Tanous                                    systemName);
15477f3e84a1SEd Tanous         return;
15487f3e84a1SEd Tanous     }
1549253f11b8SEd Tanous     if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
155022d268cbSEd Tanous     {
155122d268cbSEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
155222d268cbSEd Tanous                                    systemName);
155322d268cbSEd Tanous         return;
155422d268cbSEd Tanous     }
155522d268cbSEd Tanous 
15565143f7a5SJiaqing Zhao     size_t top = delegatedQuery.top.value_or(query_param::Query::maxTop);
15573648c8beSEd Tanous     size_t skip = delegatedQuery.skip.value_or(0);
15583648c8beSEd Tanous 
15597e860f15SJohn Edward Broadbent     // Collections don't include the static data added by SubRoute
15607e860f15SJohn Edward Broadbent     // because it has a duplicate entry for members
1561c4bf6374SJason M. Bills     asyncResp->res.jsonValue["@odata.type"] =
1562c4bf6374SJason M. Bills         "#LogEntryCollection.LogEntryCollection";
1563c4bf6374SJason M. Bills     asyncResp->res.jsonValue["@odata.id"] =
1564253f11b8SEd Tanous         std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
1565253f11b8SEd Tanous                     BMCWEB_REDFISH_SYSTEM_URI_NAME);
1566c4bf6374SJason M. Bills     asyncResp->res.jsonValue["Name"] = "System Event Log Entries";
1567c4bf6374SJason M. Bills     asyncResp->res.jsonValue["Description"] =
1568c4bf6374SJason M. Bills         "Collection of System Event Log Entries";
1569cb92c03bSAndrew Geissler 
15704978b63fSJason M. Bills     nlohmann::json& logEntryArray = asyncResp->res.jsonValue["Members"];
1571c4bf6374SJason M. Bills     logEntryArray = nlohmann::json::array();
15727e860f15SJohn Edward Broadbent     // Go through the log files and create a unique ID for each
15737e860f15SJohn Edward Broadbent     // entry
157495820184SJason M. Bills     std::vector<std::filesystem::path> redfishLogFiles;
157595820184SJason M. Bills     getRedfishLogFiles(redfishLogFiles);
1576b01bf299SEd Tanous     uint64_t entryCount = 0;
1577cd225da8SJason M. Bills     std::string logEntry;
157895820184SJason M. Bills 
15797e860f15SJohn Edward Broadbent     // Oldest logs are in the last file, so start there and loop
15807e860f15SJohn Edward Broadbent     // backwards
1581599b9af3SAlexander Hansen     for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend(); it++)
1582c4bf6374SJason M. Bills     {
1583cd225da8SJason M. Bills         std::ifstream logStream(*it);
158495820184SJason M. Bills         if (!logStream.is_open())
1585c4bf6374SJason M. Bills         {
1586c4bf6374SJason M. Bills             continue;
1587c4bf6374SJason M. Bills         }
1588c4bf6374SJason M. Bills 
1589e85d6b16SJason M. Bills         // Reset the unique ID on the first entry
1590e85d6b16SJason M. Bills         bool firstEntry = true;
159195820184SJason M. Bills         while (std::getline(logStream, logEntry))
159295820184SJason M. Bills         {
1593c4bf6374SJason M. Bills             std::string idStr;
1594e85d6b16SJason M. Bills             if (!getUniqueEntryID(logEntry, idStr, firstEntry))
1595c4bf6374SJason M. Bills             {
1596c4bf6374SJason M. Bills                 continue;
1597c4bf6374SJason M. Bills             }
1598e85d6b16SJason M. Bills             firstEntry = false;
1599e85d6b16SJason M. Bills 
1600de703c5dSJason M. Bills             nlohmann::json::object_t bmcLogEntry;
1601*bd79bce8SPatrick Williams             LogParseError status =
1602*bd79bce8SPatrick Williams                 fillEventLogEntryJson(idStr, logEntry, bmcLogEntry);
1603ac992cdeSJason M. Bills             if (status == LogParseError::messageIdNotInRegistry)
1604ac992cdeSJason M. Bills             {
1605ac992cdeSJason M. Bills                 continue;
1606ac992cdeSJason M. Bills             }
1607ac992cdeSJason M. Bills             if (status != LogParseError::success)
1608c4bf6374SJason M. Bills             {
1609c4bf6374SJason M. Bills                 messages::internalError(asyncResp->res);
1610c4bf6374SJason M. Bills                 return;
1611c4bf6374SJason M. Bills             }
1612de703c5dSJason M. Bills 
1613de703c5dSJason M. Bills             entryCount++;
1614de703c5dSJason M. Bills             // Handle paging using skip (number of entries to skip from the
1615de703c5dSJason M. Bills             // start) and top (number of entries to display)
16163648c8beSEd Tanous             if (entryCount <= skip || entryCount > skip + top)
1617de703c5dSJason M. Bills             {
1618de703c5dSJason M. Bills                 continue;
1619de703c5dSJason M. Bills             }
1620de703c5dSJason M. Bills 
1621b2ba3072SPatrick Williams             logEntryArray.emplace_back(std::move(bmcLogEntry));
1622c4bf6374SJason M. Bills         }
162395820184SJason M. Bills     }
1624c4bf6374SJason M. Bills     asyncResp->res.jsonValue["Members@odata.count"] = entryCount;
16253648c8beSEd Tanous     if (skip + top < entryCount)
1626c4bf6374SJason M. Bills     {
1627599b9af3SAlexander Hansen         asyncResp->res.jsonValue["Members@odata.nextLink"] =
1628599b9af3SAlexander Hansen             boost::urls::format(
1629253f11b8SEd Tanous                 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries?$skip={}",
1630253f11b8SEd Tanous                 BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(skip + top));
1631c4bf6374SJason M. Bills     }
1632897967deSJason M. Bills }
1633897967deSJason M. Bills 
1634599b9af3SAlexander Hansen inline void requestRoutesJournalEventLogEntryCollection(App& app)
1635897967deSJason M. Bills {
1636599b9af3SAlexander Hansen     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/")
1637599b9af3SAlexander Hansen         .privileges(redfish::privileges::getLogEntryCollection)
1638599b9af3SAlexander Hansen         .methods(boost::beast::http::verb::get)(std::bind_front(
1639599b9af3SAlexander Hansen             handleSystemsLogServiceEventLogLogEntryCollection, std::ref(app)));
1640599b9af3SAlexander Hansen }
1641599b9af3SAlexander Hansen 
1642599b9af3SAlexander Hansen inline void handleSystemsLogServiceEventLogEntriesGet(
1643599b9af3SAlexander Hansen     App& app, const crow::Request& req,
16447e860f15SJohn Edward Broadbent     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1645599b9af3SAlexander Hansen     const std::string& systemName, const std::string& param)
1646599b9af3SAlexander Hansen {
16473ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
164845ca1b86SEd Tanous     {
164945ca1b86SEd Tanous         return;
165045ca1b86SEd Tanous     }
165125b54dbaSEd Tanous     if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
16527f3e84a1SEd Tanous     {
16537f3e84a1SEd Tanous         // Option currently returns no systems.  TBD
16547f3e84a1SEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
16557f3e84a1SEd Tanous                                    systemName);
16567f3e84a1SEd Tanous         return;
16577f3e84a1SEd Tanous     }
165822d268cbSEd Tanous 
1659253f11b8SEd Tanous     if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
166022d268cbSEd Tanous     {
166122d268cbSEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
166222d268cbSEd Tanous                                    systemName);
166322d268cbSEd Tanous         return;
166422d268cbSEd Tanous     }
166522d268cbSEd Tanous 
16667e860f15SJohn Edward Broadbent     const std::string& targetID = param;
16678d1b46d7Szhanghch05 
16687e860f15SJohn Edward Broadbent     // Go through the log files and check the unique ID for each
16697e860f15SJohn Edward Broadbent     // entry to find the target entry
1670897967deSJason M. Bills     std::vector<std::filesystem::path> redfishLogFiles;
1671897967deSJason M. Bills     getRedfishLogFiles(redfishLogFiles);
1672897967deSJason M. Bills     std::string logEntry;
1673897967deSJason M. Bills 
16747e860f15SJohn Edward Broadbent     // Oldest logs are in the last file, so start there and loop
16757e860f15SJohn Edward Broadbent     // backwards
1676599b9af3SAlexander Hansen     for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend(); it++)
1677897967deSJason M. Bills     {
1678897967deSJason M. Bills         std::ifstream logStream(*it);
1679897967deSJason M. Bills         if (!logStream.is_open())
1680897967deSJason M. Bills         {
1681897967deSJason M. Bills             continue;
1682897967deSJason M. Bills         }
1683897967deSJason M. Bills 
1684897967deSJason M. Bills         // Reset the unique ID on the first entry
1685897967deSJason M. Bills         bool firstEntry = true;
1686897967deSJason M. Bills         while (std::getline(logStream, logEntry))
1687897967deSJason M. Bills         {
1688897967deSJason M. Bills             std::string idStr;
1689897967deSJason M. Bills             if (!getUniqueEntryID(logEntry, idStr, firstEntry))
1690897967deSJason M. Bills             {
1691897967deSJason M. Bills                 continue;
1692897967deSJason M. Bills             }
1693897967deSJason M. Bills             firstEntry = false;
1694897967deSJason M. Bills 
1695897967deSJason M. Bills             if (idStr == targetID)
1696897967deSJason M. Bills             {
1697de703c5dSJason M. Bills                 nlohmann::json::object_t bmcLogEntry;
1698*bd79bce8SPatrick Williams                 LogParseError status =
1699*bd79bce8SPatrick Williams                     fillEventLogEntryJson(idStr, logEntry, bmcLogEntry);
1700ac992cdeSJason M. Bills                 if (status != LogParseError::success)
1701897967deSJason M. Bills                 {
1702897967deSJason M. Bills                     messages::internalError(asyncResp->res);
1703897967deSJason M. Bills                     return;
1704897967deSJason M. Bills                 }
1705d405bb51SJason M. Bills                 asyncResp->res.jsonValue.update(bmcLogEntry);
1706897967deSJason M. Bills                 return;
1707897967deSJason M. Bills             }
1708897967deSJason M. Bills         }
1709897967deSJason M. Bills     }
1710897967deSJason M. Bills     // Requested ID was not found
17119db4ba25SJiaqing Zhao     messages::resourceNotFound(asyncResp->res, "LogEntry", targetID);
1712599b9af3SAlexander Hansen }
1713599b9af3SAlexander Hansen 
1714599b9af3SAlexander Hansen inline void requestRoutesJournalEventLogEntry(App& app)
1715599b9af3SAlexander Hansen {
1716599b9af3SAlexander Hansen     BMCWEB_ROUTE(
1717599b9af3SAlexander Hansen         app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
1718599b9af3SAlexander Hansen         .privileges(redfish::privileges::getLogEntry)
1719599b9af3SAlexander Hansen         .methods(boost::beast::http::verb::get)(std::bind_front(
1720599b9af3SAlexander Hansen             handleSystemsLogServiceEventLogEntriesGet, std::ref(app)));
1721599b9af3SAlexander Hansen }
1722599b9af3SAlexander Hansen 
1723599b9af3SAlexander Hansen inline void dBusEventLogEntryCollection(
1724599b9af3SAlexander Hansen     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1725599b9af3SAlexander Hansen {
1726599b9af3SAlexander Hansen     // Collections don't include the static data added by SubRoute
1727599b9af3SAlexander Hansen     // because it has a duplicate entry for members
1728599b9af3SAlexander Hansen     asyncResp->res.jsonValue["@odata.type"] =
1729599b9af3SAlexander Hansen         "#LogEntryCollection.LogEntryCollection";
1730599b9af3SAlexander Hansen     asyncResp->res.jsonValue["@odata.id"] =
1731599b9af3SAlexander Hansen         std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
1732599b9af3SAlexander Hansen                     BMCWEB_REDFISH_SYSTEM_URI_NAME);
1733599b9af3SAlexander Hansen     asyncResp->res.jsonValue["Name"] = "System Event Log Entries";
1734599b9af3SAlexander Hansen     asyncResp->res.jsonValue["Description"] =
1735599b9af3SAlexander Hansen         "Collection of System Event Log Entries";
1736599b9af3SAlexander Hansen 
1737599b9af3SAlexander Hansen     // DBus implementation of EventLog/Entries
1738599b9af3SAlexander Hansen     // Make call to Logging Service to find all log entry objects
1739599b9af3SAlexander Hansen     sdbusplus::message::object_path path("/xyz/openbmc_project/logging");
1740599b9af3SAlexander Hansen     dbus::utility::getManagedObjects(
1741599b9af3SAlexander Hansen         "xyz.openbmc_project.Logging", path,
1742599b9af3SAlexander Hansen         [asyncResp](const boost::system::error_code& ec,
1743599b9af3SAlexander Hansen                     const dbus::utility::ManagedObjectType& resp) {
1744b729096dSEd Tanous             afterLogEntriesGetManagedObjects(asyncResp, ec, resp);
17457e860f15SJohn Edward Broadbent         });
174608a4e4b5SAnthony Wilson }
174708a4e4b5SAnthony Wilson 
17487e860f15SJohn Edward Broadbent inline void requestRoutesDBusEventLogEntryCollection(App& app)
174908a4e4b5SAnthony Wilson {
175022d268cbSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/")
1751ed398213SEd Tanous         .privileges(redfish::privileges::getLogEntryCollection)
1752002d39b4SEd Tanous         .methods(boost::beast::http::verb::get)(
1753002d39b4SEd Tanous             [&app](const crow::Request& req,
175422d268cbSEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
175522d268cbSEd Tanous                    const std::string& systemName) {
17563ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
175745ca1b86SEd Tanous                 {
175845ca1b86SEd Tanous                     return;
175945ca1b86SEd Tanous                 }
176025b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
17617f3e84a1SEd Tanous                 {
17627f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
17637f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
17647f3e84a1SEd Tanous                                                systemName);
17657f3e84a1SEd Tanous                     return;
17667f3e84a1SEd Tanous                 }
1767253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
176822d268cbSEd Tanous                 {
176922d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
177022d268cbSEd Tanous                                                systemName);
177122d268cbSEd Tanous                     return;
177222d268cbSEd Tanous                 }
1773599b9af3SAlexander Hansen                 dBusEventLogEntryCollection(asyncResp);
1774599b9af3SAlexander Hansen             });
1775599b9af3SAlexander Hansen }
177622d268cbSEd Tanous 
1777*bd79bce8SPatrick Williams inline void dBusEventLogEntryGet(
1778*bd79bce8SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID)
1779599b9af3SAlexander Hansen {
1780599b9af3SAlexander Hansen     dbus::utility::escapePathForDbus(entryID);
178108a4e4b5SAnthony Wilson 
1782cb92c03bSAndrew Geissler     // DBus implementation of EventLog/Entries
1783cb92c03bSAndrew Geissler     // Make call to Logging Service to find all log entry objects
1784599b9af3SAlexander Hansen     sdbusplus::asio::getAllProperties(
1785599b9af3SAlexander Hansen         *crow::connections::systemBus, "xyz.openbmc_project.Logging",
1786599b9af3SAlexander Hansen         "/xyz/openbmc_project/logging/entry/" + entryID, "",
1787599b9af3SAlexander Hansen         [asyncResp, entryID](const boost::system::error_code& ec,
1788599b9af3SAlexander Hansen                              const dbus::utility::DBusPropertiesMap& resp) {
1789599b9af3SAlexander Hansen             if (ec.value() == EBADR)
1790599b9af3SAlexander Hansen             {
1791599b9af3SAlexander Hansen                 messages::resourceNotFound(asyncResp->res, "EventLogEntry",
1792599b9af3SAlexander Hansen                                            entryID);
1793599b9af3SAlexander Hansen                 return;
1794599b9af3SAlexander Hansen             }
1795cb92c03bSAndrew Geissler             if (ec)
1796cb92c03bSAndrew Geissler             {
1797*bd79bce8SPatrick Williams                 BMCWEB_LOG_ERROR(
1798*bd79bce8SPatrick Williams                     "EventLogEntry (DBus) resp_handler got error {}", ec);
1799cb92c03bSAndrew Geissler                 messages::internalError(asyncResp->res);
1800cb92c03bSAndrew Geissler                 return;
1801cb92c03bSAndrew Geissler             }
18029017faf2SAbhishek Patel 
1803898f2aa2SEd Tanous             fillEventLogLogEntryFromPropertyMap(asyncResp, resp,
1804898f2aa2SEd Tanous                                                 asyncResp->res.jsonValue);
1805599b9af3SAlexander Hansen         });
18067e860f15SJohn Edward Broadbent }
1807599b9af3SAlexander Hansen 
1808599b9af3SAlexander Hansen inline void
1809599b9af3SAlexander Hansen     dBusEventLogEntryPatch(const crow::Request& req,
1810599b9af3SAlexander Hansen                            const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1811599b9af3SAlexander Hansen                            const std::string& entryId)
1812599b9af3SAlexander Hansen {
1813599b9af3SAlexander Hansen     std::optional<bool> resolved;
1814599b9af3SAlexander Hansen 
1815599b9af3SAlexander Hansen     if (!json_util::readJsonPatch(req, asyncResp->res, "Resolved", resolved))
1816599b9af3SAlexander Hansen     {
1817599b9af3SAlexander Hansen         return;
1818599b9af3SAlexander Hansen     }
1819599b9af3SAlexander Hansen     BMCWEB_LOG_DEBUG("Set Resolved");
1820599b9af3SAlexander Hansen 
1821599b9af3SAlexander Hansen     setDbusProperty(asyncResp, "Resolved", "xyz.openbmc_project.Logging",
1822599b9af3SAlexander Hansen                     "/xyz/openbmc_project/logging/entry/" + entryId,
1823599b9af3SAlexander Hansen                     "xyz.openbmc_project.Logging.Entry", "Resolved",
1824599b9af3SAlexander Hansen                     resolved.value_or(false));
1825599b9af3SAlexander Hansen }
1826599b9af3SAlexander Hansen 
1827*bd79bce8SPatrick Williams inline void dBusEventLogEntryDelete(
1828*bd79bce8SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID)
1829599b9af3SAlexander Hansen {
1830599b9af3SAlexander Hansen     BMCWEB_LOG_DEBUG("Do delete single event entries.");
1831599b9af3SAlexander Hansen 
1832599b9af3SAlexander Hansen     dbus::utility::escapePathForDbus(entryID);
1833599b9af3SAlexander Hansen 
1834599b9af3SAlexander Hansen     // Process response from Logging service.
1835599b9af3SAlexander Hansen     auto respHandler = [asyncResp,
1836599b9af3SAlexander Hansen                         entryID](const boost::system::error_code& ec) {
1837599b9af3SAlexander Hansen         BMCWEB_LOG_DEBUG("EventLogEntry (DBus) doDelete callback: Done");
1838599b9af3SAlexander Hansen         if (ec)
1839599b9af3SAlexander Hansen         {
1840599b9af3SAlexander Hansen             if (ec.value() == EBADR)
1841599b9af3SAlexander Hansen             {
1842599b9af3SAlexander Hansen                 messages::resourceNotFound(asyncResp->res, "LogEntry", entryID);
1843599b9af3SAlexander Hansen                 return;
1844599b9af3SAlexander Hansen             }
1845599b9af3SAlexander Hansen             // TODO Handle for specific error code
1846599b9af3SAlexander Hansen             BMCWEB_LOG_ERROR(
1847599b9af3SAlexander Hansen                 "EventLogEntry (DBus) doDelete respHandler got error {}", ec);
1848599b9af3SAlexander Hansen             asyncResp->res.result(
1849599b9af3SAlexander Hansen                 boost::beast::http::status::internal_server_error);
1850599b9af3SAlexander Hansen             return;
1851599b9af3SAlexander Hansen         }
1852599b9af3SAlexander Hansen 
1853599b9af3SAlexander Hansen         asyncResp->res.result(boost::beast::http::status::ok);
1854599b9af3SAlexander Hansen     };
1855599b9af3SAlexander Hansen 
1856599b9af3SAlexander Hansen     // Make call to Logging service to request Delete Log
1857599b9af3SAlexander Hansen     crow::connections::systemBus->async_method_call(
1858599b9af3SAlexander Hansen         respHandler, "xyz.openbmc_project.Logging",
1859599b9af3SAlexander Hansen         "/xyz/openbmc_project/logging/entry/" + entryID,
1860599b9af3SAlexander Hansen         "xyz.openbmc_project.Object.Delete", "Delete");
18617e860f15SJohn Edward Broadbent }
18627e860f15SJohn Edward Broadbent 
18637e860f15SJohn Edward Broadbent inline void requestRoutesDBusEventLogEntry(App& app)
18647e860f15SJohn Edward Broadbent {
18657e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
186622d268cbSEd Tanous         app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
1867ed398213SEd Tanous         .privileges(redfish::privileges::getLogEntry)
1868002d39b4SEd Tanous         .methods(boost::beast::http::verb::get)(
1869002d39b4SEd Tanous             [&app](const crow::Request& req,
18707e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1871898f2aa2SEd Tanous                    const std::string& systemName, const std::string& entryId) {
18723ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
18737e860f15SJohn Edward Broadbent                 {
187445ca1b86SEd Tanous                     return;
187545ca1b86SEd Tanous                 }
187625b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
18777f3e84a1SEd Tanous                 {
18787f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
18797f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
18807f3e84a1SEd Tanous                                                systemName);
18817f3e84a1SEd Tanous                     return;
18827f3e84a1SEd Tanous                 }
1883253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
188422d268cbSEd Tanous                 {
188522d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
188622d268cbSEd Tanous                                                systemName);
188722d268cbSEd Tanous                     return;
188822d268cbSEd Tanous                 }
188922d268cbSEd Tanous 
1890898f2aa2SEd Tanous                 dBusEventLogEntryGet(asyncResp, entryId);
18917e860f15SJohn Edward Broadbent             });
1892336e96c6SChicago Duan 
18937e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
189422d268cbSEd Tanous         app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
1895ed398213SEd Tanous         .privileges(redfish::privileges::patchLogEntry)
18967e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::patch)(
189745ca1b86SEd Tanous             [&app](const crow::Request& req,
18987e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
189922d268cbSEd Tanous                    const std::string& systemName, const std::string& entryId) {
19003ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
190145ca1b86SEd Tanous                 {
190245ca1b86SEd Tanous                     return;
190345ca1b86SEd Tanous                 }
190425b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
19057f3e84a1SEd Tanous                 {
19067f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
19077f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
19087f3e84a1SEd Tanous                                                systemName);
19097f3e84a1SEd Tanous                     return;
19107f3e84a1SEd Tanous                 }
1911253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
191222d268cbSEd Tanous                 {
191322d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
191422d268cbSEd Tanous                                                systemName);
191522d268cbSEd Tanous                     return;
191622d268cbSEd Tanous                 }
191775710de2SXiaochao Ma 
1918599b9af3SAlexander Hansen                 dBusEventLogEntryPatch(req, asyncResp, entryId);
19197e860f15SJohn Edward Broadbent             });
192075710de2SXiaochao Ma 
19217e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
192222d268cbSEd Tanous         app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
1923ed398213SEd Tanous         .privileges(redfish::privileges::deleteLogEntry)
1924ed398213SEd Tanous 
1925002d39b4SEd Tanous         .methods(boost::beast::http::verb::delete_)(
1926002d39b4SEd Tanous             [&app](const crow::Request& req,
1927002d39b4SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
192822d268cbSEd Tanous                    const std::string& systemName, const std::string& param) {
19293ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1930336e96c6SChicago Duan                 {
193145ca1b86SEd Tanous                     return;
193245ca1b86SEd Tanous                 }
193325b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
19347f3e84a1SEd Tanous                 {
19357f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
19367f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
19377f3e84a1SEd Tanous                                                systemName);
19387f3e84a1SEd Tanous                     return;
19397f3e84a1SEd Tanous                 }
1940253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
194122d268cbSEd Tanous                 {
194222d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
194322d268cbSEd Tanous                                                systemName);
194422d268cbSEd Tanous                     return;
194522d268cbSEd Tanous                 }
1946599b9af3SAlexander Hansen                 dBusEventLogEntryDelete(asyncResp, param);
19477e860f15SJohn Edward Broadbent             });
1948400fd1fbSAdriana Kobylak }
1949400fd1fbSAdriana Kobylak 
1950b7028ebfSSpencer Ku constexpr const char* hostLoggerFolderPath = "/var/log/console";
1951b7028ebfSSpencer Ku 
1952b7028ebfSSpencer Ku inline bool
1953b7028ebfSSpencer Ku     getHostLoggerFiles(const std::string& hostLoggerFilePath,
1954b7028ebfSSpencer Ku                        std::vector<std::filesystem::path>& hostLoggerFiles)
1955b7028ebfSSpencer Ku {
1956b7028ebfSSpencer Ku     std::error_code ec;
1957b7028ebfSSpencer Ku     std::filesystem::directory_iterator logPath(hostLoggerFilePath, ec);
1958b7028ebfSSpencer Ku     if (ec)
1959b7028ebfSSpencer Ku     {
1960bf2ddedeSCarson Labrado         BMCWEB_LOG_WARNING("{}", ec.message());
1961b7028ebfSSpencer Ku         return false;
1962b7028ebfSSpencer Ku     }
1963b7028ebfSSpencer Ku     for (const std::filesystem::directory_entry& it : logPath)
1964b7028ebfSSpencer Ku     {
1965b7028ebfSSpencer Ku         std::string filename = it.path().filename();
1966b7028ebfSSpencer Ku         // Prefix of each log files is "log". Find the file and save the
1967b7028ebfSSpencer Ku         // path
196811ba3979SEd Tanous         if (filename.starts_with("log"))
1969b7028ebfSSpencer Ku         {
1970b7028ebfSSpencer Ku             hostLoggerFiles.emplace_back(it.path());
1971b7028ebfSSpencer Ku         }
1972b7028ebfSSpencer Ku     }
1973b7028ebfSSpencer Ku     // As the log files rotate, they are appended with a ".#" that is higher for
1974b7028ebfSSpencer Ku     // the older logs. Since we start from oldest logs, sort the name in
1975b7028ebfSSpencer Ku     // descending order.
1976b7028ebfSSpencer Ku     std::sort(hostLoggerFiles.rbegin(), hostLoggerFiles.rend(),
1977b7028ebfSSpencer Ku               AlphanumLess<std::string>());
1978b7028ebfSSpencer Ku 
1979b7028ebfSSpencer Ku     return true;
1980b7028ebfSSpencer Ku }
1981b7028ebfSSpencer Ku 
198202cad96eSEd Tanous inline bool getHostLoggerEntries(
198302cad96eSEd Tanous     const std::vector<std::filesystem::path>& hostLoggerFiles, uint64_t skip,
198402cad96eSEd Tanous     uint64_t top, std::vector<std::string>& logEntries, size_t& logCount)
1985b7028ebfSSpencer Ku {
1986b7028ebfSSpencer Ku     GzFileReader logFile;
1987b7028ebfSSpencer Ku 
1988b7028ebfSSpencer Ku     // Go though all log files and expose host logs.
1989b7028ebfSSpencer Ku     for (const std::filesystem::path& it : hostLoggerFiles)
1990b7028ebfSSpencer Ku     {
1991b7028ebfSSpencer Ku         if (!logFile.gzGetLines(it.string(), skip, top, logEntries, logCount))
1992b7028ebfSSpencer Ku         {
199362598e31SEd Tanous             BMCWEB_LOG_ERROR("fail to expose host logs");
1994b7028ebfSSpencer Ku             return false;
1995b7028ebfSSpencer Ku         }
1996b7028ebfSSpencer Ku     }
1997b7028ebfSSpencer Ku     // Get lastMessage from constructor by getter
1998b7028ebfSSpencer Ku     std::string lastMessage = logFile.getLastMessage();
1999b7028ebfSSpencer Ku     if (!lastMessage.empty())
2000b7028ebfSSpencer Ku     {
2001b7028ebfSSpencer Ku         logCount++;
2002b7028ebfSSpencer Ku         if (logCount > skip && logCount <= (skip + top))
2003b7028ebfSSpencer Ku         {
2004b7028ebfSSpencer Ku             logEntries.push_back(lastMessage);
2005b7028ebfSSpencer Ku         }
2006b7028ebfSSpencer Ku     }
2007b7028ebfSSpencer Ku     return true;
2008b7028ebfSSpencer Ku }
2009b7028ebfSSpencer Ku 
20106f056f24SEd Tanous inline void fillHostLoggerEntryJson(std::string_view logEntryID,
20116f056f24SEd Tanous                                     std::string_view msg,
20126d6574c9SJason M. Bills                                     nlohmann::json::object_t& logEntryJson)
2013b7028ebfSSpencer Ku {
2014b7028ebfSSpencer Ku     // Fill in the log entry with the gathered data.
20159c11a172SVijay Lobo     logEntryJson["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
2016ef4c65b7SEd Tanous     logEntryJson["@odata.id"] = boost::urls::format(
2017253f11b8SEd Tanous         "/redfish/v1/Systems/{}/LogServices/HostLogger/Entries/{}",
2018253f11b8SEd Tanous         BMCWEB_REDFISH_SYSTEM_URI_NAME, logEntryID);
20196d6574c9SJason M. Bills     logEntryJson["Name"] = "Host Logger Entry";
20206d6574c9SJason M. Bills     logEntryJson["Id"] = logEntryID;
20216d6574c9SJason M. Bills     logEntryJson["Message"] = msg;
2022539d8c6bSEd Tanous     logEntryJson["EntryType"] = log_entry::LogEntryType::Oem;
2023539d8c6bSEd Tanous     logEntryJson["Severity"] = log_entry::EventSeverity::OK;
20246d6574c9SJason M. Bills     logEntryJson["OemRecordFormat"] = "Host Logger Entry";
2025b7028ebfSSpencer Ku }
2026b7028ebfSSpencer Ku 
2027b7028ebfSSpencer Ku inline void requestRoutesSystemHostLogger(App& app)
2028b7028ebfSSpencer Ku {
202922d268cbSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/HostLogger/")
2030b7028ebfSSpencer Ku         .privileges(redfish::privileges::getLogService)
20311476687dSEd Tanous         .methods(boost::beast::http::verb::get)(
20321476687dSEd Tanous             [&app](const crow::Request& req,
203322d268cbSEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
203422d268cbSEd Tanous                    const std::string& systemName) {
20353ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
203645ca1b86SEd Tanous                 {
203745ca1b86SEd Tanous                     return;
203845ca1b86SEd Tanous                 }
203925b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
20407f3e84a1SEd Tanous                 {
20417f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
20427f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
20437f3e84a1SEd Tanous                                                systemName);
20447f3e84a1SEd Tanous                     return;
20457f3e84a1SEd Tanous                 }
2046253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
204722d268cbSEd Tanous                 {
204822d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
204922d268cbSEd Tanous                                                systemName);
205022d268cbSEd Tanous                     return;
205122d268cbSEd Tanous                 }
2052b7028ebfSSpencer Ku                 asyncResp->res.jsonValue["@odata.id"] =
2053253f11b8SEd Tanous                     std::format("/redfish/v1/Systems/{}/LogServices/HostLogger",
2054253f11b8SEd Tanous                                 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2055b7028ebfSSpencer Ku                 asyncResp->res.jsonValue["@odata.type"] =
2056b25644a1SJanet Adkins                     "#LogService.v1_2_0.LogService";
2057b7028ebfSSpencer Ku                 asyncResp->res.jsonValue["Name"] = "Host Logger Service";
2058b7028ebfSSpencer Ku                 asyncResp->res.jsonValue["Description"] = "Host Logger Service";
2059b7028ebfSSpencer Ku                 asyncResp->res.jsonValue["Id"] = "HostLogger";
2060*bd79bce8SPatrick Williams                 asyncResp->res.jsonValue["Entries"]["@odata.id"] = std::format(
2061*bd79bce8SPatrick Williams                     "/redfish/v1/Systems/{}/LogServices/HostLogger/Entries",
2062253f11b8SEd Tanous                     BMCWEB_REDFISH_SYSTEM_URI_NAME);
2063b7028ebfSSpencer Ku             });
2064b7028ebfSSpencer Ku }
2065b7028ebfSSpencer Ku 
2066b7028ebfSSpencer Ku inline void requestRoutesSystemHostLoggerCollection(App& app)
2067b7028ebfSSpencer Ku {
2068b7028ebfSSpencer Ku     BMCWEB_ROUTE(app,
206922d268cbSEd Tanous                  "/redfish/v1/Systems/<str>/LogServices/HostLogger/Entries/")
2070b7028ebfSSpencer Ku         .privileges(redfish::privileges::getLogEntry)
2071*bd79bce8SPatrick Williams         .methods(
2072*bd79bce8SPatrick Williams             boost::beast::http::verb::
2073*bd79bce8SPatrick Williams                 get)([&app](const crow::Request& req,
207422d268cbSEd Tanous                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
207522d268cbSEd Tanous                             const std::string& systemName) {
2076c937d2bfSEd Tanous             query_param::QueryCapabilities capabilities = {
2077c937d2bfSEd Tanous                 .canDelegateTop = true,
2078c937d2bfSEd Tanous                 .canDelegateSkip = true,
2079c937d2bfSEd Tanous             };
2080c937d2bfSEd Tanous             query_param::Query delegatedQuery;
2081c937d2bfSEd Tanous             if (!redfish::setUpRedfishRouteWithDelegation(
20823ba00073SCarson Labrado                     app, req, asyncResp, delegatedQuery, capabilities))
2083b7028ebfSSpencer Ku             {
2084b7028ebfSSpencer Ku                 return;
2085b7028ebfSSpencer Ku             }
208625b54dbaSEd Tanous             if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
20877f3e84a1SEd Tanous             {
20887f3e84a1SEd Tanous                 // Option currently returns no systems.  TBD
20897f3e84a1SEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
20907f3e84a1SEd Tanous                                            systemName);
20917f3e84a1SEd Tanous                 return;
20927f3e84a1SEd Tanous             }
2093253f11b8SEd Tanous             if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
209422d268cbSEd Tanous             {
209522d268cbSEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
209622d268cbSEd Tanous                                            systemName);
209722d268cbSEd Tanous                 return;
209822d268cbSEd Tanous             }
2099*bd79bce8SPatrick Williams             asyncResp->res.jsonValue["@odata.id"] = std::format(
2100*bd79bce8SPatrick Williams                 "/redfish/v1/Systems/{}/LogServices/HostLogger/Entries",
2101253f11b8SEd Tanous                 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2102b7028ebfSSpencer Ku             asyncResp->res.jsonValue["@odata.type"] =
2103b7028ebfSSpencer Ku                 "#LogEntryCollection.LogEntryCollection";
2104b7028ebfSSpencer Ku             asyncResp->res.jsonValue["Name"] = "HostLogger Entries";
2105b7028ebfSSpencer Ku             asyncResp->res.jsonValue["Description"] =
2106b7028ebfSSpencer Ku                 "Collection of HostLogger Entries";
21070fda0f12SGeorge Liu             nlohmann::json& logEntryArray = asyncResp->res.jsonValue["Members"];
2108b7028ebfSSpencer Ku             logEntryArray = nlohmann::json::array();
2109b7028ebfSSpencer Ku             asyncResp->res.jsonValue["Members@odata.count"] = 0;
2110b7028ebfSSpencer Ku 
2111b7028ebfSSpencer Ku             std::vector<std::filesystem::path> hostLoggerFiles;
2112b7028ebfSSpencer Ku             if (!getHostLoggerFiles(hostLoggerFolderPath, hostLoggerFiles))
2113b7028ebfSSpencer Ku             {
2114bf2ddedeSCarson Labrado                 BMCWEB_LOG_DEBUG("Failed to get host log file path");
2115b7028ebfSSpencer Ku                 return;
2116b7028ebfSSpencer Ku             }
21173648c8beSEd Tanous             // If we weren't provided top and skip limits, use the defaults.
21183648c8beSEd Tanous             size_t skip = delegatedQuery.skip.value_or(0);
2119*bd79bce8SPatrick Williams             size_t top =
2120*bd79bce8SPatrick Williams                 delegatedQuery.top.value_or(query_param::Query::maxTop);
2121b7028ebfSSpencer Ku             size_t logCount = 0;
2122b7028ebfSSpencer Ku             // This vector only store the entries we want to expose that
2123b7028ebfSSpencer Ku             // control by skip and top.
2124b7028ebfSSpencer Ku             std::vector<std::string> logEntries;
21253648c8beSEd Tanous             if (!getHostLoggerEntries(hostLoggerFiles, skip, top, logEntries,
21263648c8beSEd Tanous                                       logCount))
2127b7028ebfSSpencer Ku             {
2128b7028ebfSSpencer Ku                 messages::internalError(asyncResp->res);
2129b7028ebfSSpencer Ku                 return;
2130b7028ebfSSpencer Ku             }
2131b7028ebfSSpencer Ku             // If vector is empty, that means skip value larger than total
2132b7028ebfSSpencer Ku             // log count
213326f6976fSEd Tanous             if (logEntries.empty())
2134b7028ebfSSpencer Ku             {
2135b7028ebfSSpencer Ku                 asyncResp->res.jsonValue["Members@odata.count"] = logCount;
2136b7028ebfSSpencer Ku                 return;
2137b7028ebfSSpencer Ku             }
213826f6976fSEd Tanous             if (!logEntries.empty())
2139b7028ebfSSpencer Ku             {
2140b7028ebfSSpencer Ku                 for (size_t i = 0; i < logEntries.size(); i++)
2141b7028ebfSSpencer Ku                 {
21426d6574c9SJason M. Bills                     nlohmann::json::object_t hostLogEntry;
2143*bd79bce8SPatrick Williams                     fillHostLoggerEntryJson(std::to_string(skip + i),
2144*bd79bce8SPatrick Williams                                             logEntries[i], hostLogEntry);
2145b2ba3072SPatrick Williams                     logEntryArray.emplace_back(std::move(hostLogEntry));
2146b7028ebfSSpencer Ku                 }
2147b7028ebfSSpencer Ku 
2148b7028ebfSSpencer Ku                 asyncResp->res.jsonValue["Members@odata.count"] = logCount;
21493648c8beSEd Tanous                 if (skip + top < logCount)
2150b7028ebfSSpencer Ku                 {
2151b7028ebfSSpencer Ku                     asyncResp->res.jsonValue["Members@odata.nextLink"] =
2152253f11b8SEd Tanous                         std::format(
2153253f11b8SEd Tanous                             "/redfish/v1/Systems/{}/LogServices/HostLogger/Entries?$skip=",
2154253f11b8SEd Tanous                             BMCWEB_REDFISH_SYSTEM_URI_NAME) +
21553648c8beSEd Tanous                         std::to_string(skip + top);
2156b7028ebfSSpencer Ku                 }
2157b7028ebfSSpencer Ku             }
2158b7028ebfSSpencer Ku         });
2159b7028ebfSSpencer Ku }
2160b7028ebfSSpencer Ku 
2161b7028ebfSSpencer Ku inline void requestRoutesSystemHostLoggerLogEntry(App& app)
2162b7028ebfSSpencer Ku {
2163b7028ebfSSpencer Ku     BMCWEB_ROUTE(
216422d268cbSEd Tanous         app, "/redfish/v1/Systems/<str>/LogServices/HostLogger/Entries/<str>/")
2165b7028ebfSSpencer Ku         .privileges(redfish::privileges::getLogEntry)
2166b7028ebfSSpencer Ku         .methods(boost::beast::http::verb::get)(
216745ca1b86SEd Tanous             [&app](const crow::Request& req,
2168b7028ebfSSpencer Ku                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
216922d268cbSEd Tanous                    const std::string& systemName, const std::string& param) {
21703ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
217145ca1b86SEd Tanous                 {
217245ca1b86SEd Tanous                     return;
217345ca1b86SEd Tanous                 }
217425b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
21757f3e84a1SEd Tanous                 {
21767f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
21777f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
21787f3e84a1SEd Tanous                                                systemName);
21797f3e84a1SEd Tanous                     return;
21807f3e84a1SEd Tanous                 }
2181253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
218222d268cbSEd Tanous                 {
218322d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
218422d268cbSEd Tanous                                                systemName);
218522d268cbSEd Tanous                     return;
218622d268cbSEd Tanous                 }
21876f056f24SEd Tanous                 std::string_view targetID = param;
2188b7028ebfSSpencer Ku 
2189b7028ebfSSpencer Ku                 uint64_t idInt = 0;
2190ca45aa3cSEd Tanous 
2191*bd79bce8SPatrick Williams                 auto [ptr, ec] =
2192*bd79bce8SPatrick Williams                     std::from_chars(targetID.begin(), targetID.end(), idInt);
21936f056f24SEd Tanous                 if (ec != std::errc{} || ptr != targetID.end())
2194b7028ebfSSpencer Ku                 {
2195*bd79bce8SPatrick Williams                     messages::resourceNotFound(asyncResp->res, "LogEntry",
2196*bd79bce8SPatrick Williams                                                param);
2197b7028ebfSSpencer Ku                     return;
2198b7028ebfSSpencer Ku                 }
2199b7028ebfSSpencer Ku 
2200b7028ebfSSpencer Ku                 std::vector<std::filesystem::path> hostLoggerFiles;
2201b7028ebfSSpencer Ku                 if (!getHostLoggerFiles(hostLoggerFolderPath, hostLoggerFiles))
2202b7028ebfSSpencer Ku                 {
2203bf2ddedeSCarson Labrado                     BMCWEB_LOG_DEBUG("Failed to get host log file path");
2204b7028ebfSSpencer Ku                     return;
2205b7028ebfSSpencer Ku                 }
2206b7028ebfSSpencer Ku 
2207b7028ebfSSpencer Ku                 size_t logCount = 0;
22083648c8beSEd Tanous                 size_t top = 1;
2209b7028ebfSSpencer Ku                 std::vector<std::string> logEntries;
2210b7028ebfSSpencer Ku                 // We can get specific entry by skip and top. For example, if we
2211b7028ebfSSpencer Ku                 // want to get nth entry, we can set skip = n-1 and top = 1 to
2212b7028ebfSSpencer Ku                 // get that entry
2213*bd79bce8SPatrick Williams                 if (!getHostLoggerEntries(hostLoggerFiles, idInt, top,
2214*bd79bce8SPatrick Williams                                           logEntries, logCount))
2215b7028ebfSSpencer Ku                 {
2216b7028ebfSSpencer Ku                     messages::internalError(asyncResp->res);
2217b7028ebfSSpencer Ku                     return;
2218b7028ebfSSpencer Ku                 }
2219b7028ebfSSpencer Ku 
2220b7028ebfSSpencer Ku                 if (!logEntries.empty())
2221b7028ebfSSpencer Ku                 {
22226d6574c9SJason M. Bills                     nlohmann::json::object_t hostLogEntry;
2223*bd79bce8SPatrick Williams                     fillHostLoggerEntryJson(targetID, logEntries[0],
2224*bd79bce8SPatrick Williams                                             hostLogEntry);
22256d6574c9SJason M. Bills                     asyncResp->res.jsonValue.update(hostLogEntry);
2226b7028ebfSSpencer Ku                     return;
2227b7028ebfSSpencer Ku                 }
2228b7028ebfSSpencer Ku 
2229b7028ebfSSpencer Ku                 // Requested ID was not found
22309db4ba25SJiaqing Zhao                 messages::resourceNotFound(asyncResp->res, "LogEntry", param);
2231b7028ebfSSpencer Ku             });
2232b7028ebfSSpencer Ku }
2233b7028ebfSSpencer Ku 
2234dd72e87bSClaire Weinan inline void handleBMCLogServicesCollectionGet(
2235fdd26906SClaire Weinan     crow::App& app, const crow::Request& req,
2236253f11b8SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2237253f11b8SEd Tanous     const std::string& managerId)
22381da66f75SEd Tanous {
22393ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
224045ca1b86SEd Tanous     {
224145ca1b86SEd Tanous         return;
224245ca1b86SEd Tanous     }
2243253f11b8SEd Tanous 
2244253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2245253f11b8SEd Tanous     {
2246253f11b8SEd Tanous         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2247253f11b8SEd Tanous         return;
2248253f11b8SEd Tanous     }
2249253f11b8SEd Tanous 
22507e860f15SJohn Edward Broadbent     // Collections don't include the static data added by SubRoute
22517e860f15SJohn Edward Broadbent     // because it has a duplicate entry for members
2252e1f26343SJason M. Bills     asyncResp->res.jsonValue["@odata.type"] =
22531da66f75SEd Tanous         "#LogServiceCollection.LogServiceCollection";
2254253f11b8SEd Tanous     asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
2255253f11b8SEd Tanous         "/redfish/v1/Managers/{}/LogServices", BMCWEB_REDFISH_MANAGER_URI_NAME);
2256002d39b4SEd Tanous     asyncResp->res.jsonValue["Name"] = "Open BMC Log Services Collection";
2257e1f26343SJason M. Bills     asyncResp->res.jsonValue["Description"] =
22581da66f75SEd Tanous         "Collection of LogServices for this Manager";
2259002d39b4SEd Tanous     nlohmann::json& logServiceArray = asyncResp->res.jsonValue["Members"];
2260c4bf6374SJason M. Bills     logServiceArray = nlohmann::json::array();
2261fdd26906SClaire Weinan 
226225b54dbaSEd Tanous     if constexpr (BMCWEB_REDFISH_BMC_JOURNAL)
226325b54dbaSEd Tanous     {
2264613dabeaSEd Tanous         nlohmann::json::object_t journal;
2265253f11b8SEd Tanous         journal["@odata.id"] =
2266253f11b8SEd Tanous             boost::urls::format("/redfish/v1/Managers/{}/LogServices/Journal",
2267253f11b8SEd Tanous                                 BMCWEB_REDFISH_MANAGER_URI_NAME);
2268b2ba3072SPatrick Williams         logServiceArray.emplace_back(std::move(journal));
226925b54dbaSEd Tanous     }
2270fdd26906SClaire Weinan 
2271fdd26906SClaire Weinan     asyncResp->res.jsonValue["Members@odata.count"] = logServiceArray.size();
2272fdd26906SClaire Weinan 
227325b54dbaSEd Tanous     if constexpr (BMCWEB_REDFISH_DUMP_LOG)
227425b54dbaSEd Tanous     {
227515912159SGeorge Liu         constexpr std::array<std::string_view, 1> interfaces = {
22767a1dbc48SGeorge Liu             "xyz.openbmc_project.Collection.DeleteAll"};
22777a1dbc48SGeorge Liu         dbus::utility::getSubTreePaths(
22787a1dbc48SGeorge Liu             "/xyz/openbmc_project/dump", 0, interfaces,
227925b54dbaSEd Tanous             [asyncResp](const boost::system::error_code& ec,
228025b54dbaSEd Tanous                         const dbus::utility::MapperGetSubTreePathsResponse&
228125b54dbaSEd Tanous                             subTreePaths) {
2282fdd26906SClaire Weinan                 if (ec)
2283fdd26906SClaire Weinan                 {
228462598e31SEd Tanous                     BMCWEB_LOG_ERROR(
228562598e31SEd Tanous                         "handleBMCLogServicesCollectionGet respHandler got error {}",
228662598e31SEd Tanous                         ec);
2287*bd79bce8SPatrick Williams                     // Assume that getting an error simply means there are no
2288*bd79bce8SPatrick Williams                     // dump LogServices. Return without adding any error
2289*bd79bce8SPatrick Williams                     // response.
2290fdd26906SClaire Weinan                     return;
2291fdd26906SClaire Weinan                 }
2292fdd26906SClaire Weinan 
2293fdd26906SClaire Weinan                 nlohmann::json& logServiceArrayLocal =
2294fdd26906SClaire Weinan                     asyncResp->res.jsonValue["Members"];
2295fdd26906SClaire Weinan 
2296fdd26906SClaire Weinan                 for (const std::string& path : subTreePaths)
2297fdd26906SClaire Weinan                 {
2298fdd26906SClaire Weinan                     if (path == "/xyz/openbmc_project/dump/bmc")
2299fdd26906SClaire Weinan                     {
2300613dabeaSEd Tanous                         nlohmann::json::object_t member;
2301253f11b8SEd Tanous                         member["@odata.id"] = boost::urls::format(
2302253f11b8SEd Tanous                             "/redfish/v1/Managers/{}/LogServices/Dump",
2303253f11b8SEd Tanous                             BMCWEB_REDFISH_MANAGER_URI_NAME);
2304b2ba3072SPatrick Williams                         logServiceArrayLocal.emplace_back(std::move(member));
2305fdd26906SClaire Weinan                     }
2306fdd26906SClaire Weinan                     else if (path == "/xyz/openbmc_project/dump/faultlog")
2307fdd26906SClaire Weinan                     {
2308613dabeaSEd Tanous                         nlohmann::json::object_t member;
2309253f11b8SEd Tanous                         member["@odata.id"] = boost::urls::format(
2310253f11b8SEd Tanous                             "/redfish/v1/Managers/{}/LogServices/FaultLog",
2311253f11b8SEd Tanous                             BMCWEB_REDFISH_MANAGER_URI_NAME);
2312b2ba3072SPatrick Williams                         logServiceArrayLocal.emplace_back(std::move(member));
2313fdd26906SClaire Weinan                     }
2314fdd26906SClaire Weinan                 }
2315fdd26906SClaire Weinan 
2316e1f26343SJason M. Bills                 asyncResp->res.jsonValue["Members@odata.count"] =
2317fdd26906SClaire Weinan                     logServiceArrayLocal.size();
23187a1dbc48SGeorge Liu             });
231925b54dbaSEd Tanous     }
2320fdd26906SClaire Weinan }
2321fdd26906SClaire Weinan 
2322fdd26906SClaire Weinan inline void requestRoutesBMCLogServiceCollection(App& app)
2323fdd26906SClaire Weinan {
2324253f11b8SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/")
2325fdd26906SClaire Weinan         .privileges(redfish::privileges::getLogServiceCollection)
2326fdd26906SClaire Weinan         .methods(boost::beast::http::verb::get)(
2327dd72e87bSClaire Weinan             std::bind_front(handleBMCLogServicesCollectionGet, std::ref(app)));
2328e1f26343SJason M. Bills }
2329e1f26343SJason M. Bills 
2330fdd26906SClaire Weinan inline void
2331fdd26906SClaire Weinan     getDumpServiceInfo(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2332fdd26906SClaire Weinan                        const std::string& dumpType)
2333c9bb6861Sraviteja-b {
2334fdd26906SClaire Weinan     std::string dumpPath;
2335539d8c6bSEd Tanous     log_service::OverWritePolicy overWritePolicy =
2336539d8c6bSEd Tanous         log_service::OverWritePolicy::Invalid;
2337fdd26906SClaire Weinan     bool collectDiagnosticDataSupported = false;
2338fdd26906SClaire Weinan 
2339fdd26906SClaire Weinan     if (dumpType == "BMC")
234045ca1b86SEd Tanous     {
2341253f11b8SEd Tanous         dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/Dump",
2342253f11b8SEd Tanous                                BMCWEB_REDFISH_MANAGER_URI_NAME);
2343539d8c6bSEd Tanous         overWritePolicy = log_service::OverWritePolicy::WrapsWhenFull;
2344fdd26906SClaire Weinan         collectDiagnosticDataSupported = true;
2345fdd26906SClaire Weinan     }
2346fdd26906SClaire Weinan     else if (dumpType == "FaultLog")
2347fdd26906SClaire Weinan     {
2348253f11b8SEd Tanous         dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/FaultLog",
2349253f11b8SEd Tanous                                BMCWEB_REDFISH_MANAGER_URI_NAME);
2350539d8c6bSEd Tanous         overWritePolicy = log_service::OverWritePolicy::Unknown;
2351fdd26906SClaire Weinan         collectDiagnosticDataSupported = false;
2352fdd26906SClaire Weinan     }
2353fdd26906SClaire Weinan     else if (dumpType == "System")
2354fdd26906SClaire Weinan     {
2355253f11b8SEd Tanous         dumpPath = std::format("/redfish/v1/Systems/{}/LogServices/Dump",
2356253f11b8SEd Tanous                                BMCWEB_REDFISH_SYSTEM_URI_NAME);
2357539d8c6bSEd Tanous         overWritePolicy = log_service::OverWritePolicy::WrapsWhenFull;
2358fdd26906SClaire Weinan         collectDiagnosticDataSupported = true;
2359fdd26906SClaire Weinan     }
2360fdd26906SClaire Weinan     else
2361fdd26906SClaire Weinan     {
236262598e31SEd Tanous         BMCWEB_LOG_ERROR("getDumpServiceInfo() invalid dump type: {}",
236362598e31SEd Tanous                          dumpType);
2364fdd26906SClaire Weinan         messages::internalError(asyncResp->res);
236545ca1b86SEd Tanous         return;
236645ca1b86SEd Tanous     }
2367fdd26906SClaire Weinan 
2368fdd26906SClaire Weinan     asyncResp->res.jsonValue["@odata.id"] = dumpPath;
2369fdd26906SClaire Weinan     asyncResp->res.jsonValue["@odata.type"] = "#LogService.v1_2_0.LogService";
2370c9bb6861Sraviteja-b     asyncResp->res.jsonValue["Name"] = "Dump LogService";
2371fdd26906SClaire Weinan     asyncResp->res.jsonValue["Description"] = dumpType + " Dump LogService";
2372fdd26906SClaire Weinan     asyncResp->res.jsonValue["Id"] = std::filesystem::path(dumpPath).filename();
2373539d8c6bSEd Tanous     asyncResp->res.jsonValue["OverWritePolicy"] = overWritePolicy;
23747c8c4058STejas Patil 
23757c8c4058STejas Patil     std::pair<std::string, std::string> redfishDateTimeOffset =
23762b82937eSEd Tanous         redfish::time_utils::getDateTimeOffsetNow();
23770fda0f12SGeorge Liu     asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
23787c8c4058STejas Patil     asyncResp->res.jsonValue["DateTimeLocalOffset"] =
23797c8c4058STejas Patil         redfishDateTimeOffset.second;
23807c8c4058STejas Patil 
2381fdd26906SClaire Weinan     asyncResp->res.jsonValue["Entries"]["@odata.id"] = dumpPath + "/Entries";
2382fdd26906SClaire Weinan 
2383fdd26906SClaire Weinan     if (collectDiagnosticDataSupported)
2384fdd26906SClaire Weinan     {
2385002d39b4SEd Tanous         asyncResp->res.jsonValue["Actions"]["#LogService.CollectDiagnosticData"]
23861476687dSEd Tanous                                 ["target"] =
2387fdd26906SClaire Weinan             dumpPath + "/Actions/LogService.CollectDiagnosticData";
2388fdd26906SClaire Weinan     }
23890d946211SClaire Weinan 
23900d946211SClaire Weinan     constexpr std::array<std::string_view, 1> interfaces = {deleteAllInterface};
23910d946211SClaire Weinan     dbus::utility::getSubTreePaths(
23920d946211SClaire Weinan         "/xyz/openbmc_project/dump", 0, interfaces,
23930d946211SClaire Weinan         [asyncResp, dumpType, dumpPath](
23940d946211SClaire Weinan             const boost::system::error_code& ec,
23950d946211SClaire Weinan             const dbus::utility::MapperGetSubTreePathsResponse& subTreePaths) {
23960d946211SClaire Weinan             if (ec)
23970d946211SClaire Weinan             {
2398*bd79bce8SPatrick Williams                 BMCWEB_LOG_ERROR("getDumpServiceInfo respHandler got error {}",
2399*bd79bce8SPatrick Williams                                  ec);
24000d946211SClaire Weinan                 // Assume that getting an error simply means there are no dump
24010d946211SClaire Weinan                 // LogServices. Return without adding any error response.
24020d946211SClaire Weinan                 return;
24030d946211SClaire Weinan             }
240418f8f608SEd Tanous             std::string dbusDumpPath = getDumpPath(dumpType);
24050d946211SClaire Weinan             for (const std::string& path : subTreePaths)
24060d946211SClaire Weinan             {
24070d946211SClaire Weinan                 if (path == dbusDumpPath)
24080d946211SClaire Weinan                 {
2409*bd79bce8SPatrick Williams                     asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"]
2410*bd79bce8SPatrick Williams                                             ["target"] =
24110d946211SClaire Weinan                         dumpPath + "/Actions/LogService.ClearLog";
24120d946211SClaire Weinan                     break;
24130d946211SClaire Weinan                 }
24140d946211SClaire Weinan             }
24150d946211SClaire Weinan         });
2416c9bb6861Sraviteja-b }
2417c9bb6861Sraviteja-b 
2418fdd26906SClaire Weinan inline void handleLogServicesDumpServiceGet(
2419fdd26906SClaire Weinan     crow::App& app, const std::string& dumpType, const crow::Request& req,
2420253f11b8SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2421253f11b8SEd Tanous     const std::string& managerId)
24227e860f15SJohn Edward Broadbent {
24233ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
242445ca1b86SEd Tanous     {
242545ca1b86SEd Tanous         return;
242645ca1b86SEd Tanous     }
2427253f11b8SEd Tanous 
2428253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2429253f11b8SEd Tanous     {
2430253f11b8SEd Tanous         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2431253f11b8SEd Tanous         return;
2432253f11b8SEd Tanous     }
2433253f11b8SEd Tanous 
2434fdd26906SClaire Weinan     getDumpServiceInfo(asyncResp, dumpType);
2435fdd26906SClaire Weinan }
2436c9bb6861Sraviteja-b 
243722d268cbSEd Tanous inline void handleLogServicesDumpServiceComputerSystemGet(
243822d268cbSEd Tanous     crow::App& app, const crow::Request& req,
243922d268cbSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
244022d268cbSEd Tanous     const std::string& chassisId)
244122d268cbSEd Tanous {
244222d268cbSEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
244322d268cbSEd Tanous     {
244422d268cbSEd Tanous         return;
244522d268cbSEd Tanous     }
2446253f11b8SEd Tanous     if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
244722d268cbSEd Tanous     {
244822d268cbSEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
244922d268cbSEd Tanous         return;
245022d268cbSEd Tanous     }
245122d268cbSEd Tanous     getDumpServiceInfo(asyncResp, "System");
245222d268cbSEd Tanous }
245322d268cbSEd Tanous 
2454fdd26906SClaire Weinan inline void handleLogServicesDumpEntriesCollectionGet(
2455fdd26906SClaire Weinan     crow::App& app, const std::string& dumpType, const crow::Request& req,
2456253f11b8SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2457253f11b8SEd Tanous     const std::string& managerId)
2458fdd26906SClaire Weinan {
2459fdd26906SClaire Weinan     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2460fdd26906SClaire Weinan     {
2461fdd26906SClaire Weinan         return;
2462fdd26906SClaire Weinan     }
2463253f11b8SEd Tanous 
2464253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2465253f11b8SEd Tanous     {
2466253f11b8SEd Tanous         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2467253f11b8SEd Tanous         return;
2468253f11b8SEd Tanous     }
2469fdd26906SClaire Weinan     getDumpEntryCollection(asyncResp, dumpType);
2470fdd26906SClaire Weinan }
2471fdd26906SClaire Weinan 
247222d268cbSEd Tanous inline void handleLogServicesDumpEntriesCollectionComputerSystemGet(
247322d268cbSEd Tanous     crow::App& app, const crow::Request& req,
247422d268cbSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
247522d268cbSEd Tanous     const std::string& chassisId)
247622d268cbSEd Tanous {
247722d268cbSEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
247822d268cbSEd Tanous     {
247922d268cbSEd Tanous         return;
248022d268cbSEd Tanous     }
2481253f11b8SEd Tanous     if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
248222d268cbSEd Tanous     {
248322d268cbSEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
248422d268cbSEd Tanous         return;
248522d268cbSEd Tanous     }
248622d268cbSEd Tanous     getDumpEntryCollection(asyncResp, "System");
248722d268cbSEd Tanous }
248822d268cbSEd Tanous 
2489fdd26906SClaire Weinan inline void handleLogServicesDumpEntryGet(
2490fdd26906SClaire Weinan     crow::App& app, const std::string& dumpType, const crow::Request& req,
2491fdd26906SClaire Weinan     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2492253f11b8SEd Tanous     const std::string& managerId, const std::string& dumpId)
2493fdd26906SClaire Weinan {
2494fdd26906SClaire Weinan     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2495fdd26906SClaire Weinan     {
2496fdd26906SClaire Weinan         return;
2497fdd26906SClaire Weinan     }
2498253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2499253f11b8SEd Tanous     {
2500253f11b8SEd Tanous         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2501253f11b8SEd Tanous         return;
2502253f11b8SEd Tanous     }
2503fdd26906SClaire Weinan     getDumpEntryById(asyncResp, dumpId, dumpType);
2504fdd26906SClaire Weinan }
2505168d1b1aSCarson Labrado 
250622d268cbSEd Tanous inline void handleLogServicesDumpEntryComputerSystemGet(
250722d268cbSEd Tanous     crow::App& app, const crow::Request& req,
250822d268cbSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
250922d268cbSEd Tanous     const std::string& chassisId, const std::string& dumpId)
251022d268cbSEd Tanous {
251122d268cbSEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
251222d268cbSEd Tanous     {
251322d268cbSEd Tanous         return;
251422d268cbSEd Tanous     }
2515253f11b8SEd Tanous     if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
251622d268cbSEd Tanous     {
251722d268cbSEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
251822d268cbSEd Tanous         return;
251922d268cbSEd Tanous     }
252022d268cbSEd Tanous     getDumpEntryById(asyncResp, dumpId, "System");
252122d268cbSEd Tanous }
2522fdd26906SClaire Weinan 
2523fdd26906SClaire Weinan inline void handleLogServicesDumpEntryDelete(
2524fdd26906SClaire Weinan     crow::App& app, const std::string& dumpType, const crow::Request& req,
2525fdd26906SClaire Weinan     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2526253f11b8SEd Tanous     const std::string& managerId, const std::string& dumpId)
2527fdd26906SClaire Weinan {
2528fdd26906SClaire Weinan     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2529fdd26906SClaire Weinan     {
2530fdd26906SClaire Weinan         return;
2531fdd26906SClaire Weinan     }
2532253f11b8SEd Tanous 
2533253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2534253f11b8SEd Tanous     {
2535253f11b8SEd Tanous         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2536253f11b8SEd Tanous         return;
2537253f11b8SEd Tanous     }
2538fdd26906SClaire Weinan     deleteDumpEntry(asyncResp, dumpId, dumpType);
2539fdd26906SClaire Weinan }
2540fdd26906SClaire Weinan 
254122d268cbSEd Tanous inline void handleLogServicesDumpEntryComputerSystemDelete(
254222d268cbSEd Tanous     crow::App& app, const crow::Request& req,
254322d268cbSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
254422d268cbSEd Tanous     const std::string& chassisId, const std::string& dumpId)
254522d268cbSEd Tanous {
254622d268cbSEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
254722d268cbSEd Tanous     {
254822d268cbSEd Tanous         return;
254922d268cbSEd Tanous     }
2550253f11b8SEd Tanous     if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
255122d268cbSEd Tanous     {
255222d268cbSEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
255322d268cbSEd Tanous         return;
255422d268cbSEd Tanous     }
255522d268cbSEd Tanous     deleteDumpEntry(asyncResp, dumpId, "System");
255622d268cbSEd Tanous }
255722d268cbSEd Tanous 
2558168d1b1aSCarson Labrado inline void handleLogServicesDumpEntryDownloadGet(
2559168d1b1aSCarson Labrado     crow::App& app, const std::string& dumpType, const crow::Request& req,
2560168d1b1aSCarson Labrado     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2561253f11b8SEd Tanous     const std::string& managerId, const std::string& dumpId)
2562168d1b1aSCarson Labrado {
2563168d1b1aSCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2564168d1b1aSCarson Labrado     {
2565168d1b1aSCarson Labrado         return;
2566168d1b1aSCarson Labrado     }
2567253f11b8SEd Tanous 
2568253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2569253f11b8SEd Tanous     {
2570253f11b8SEd Tanous         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2571253f11b8SEd Tanous         return;
2572253f11b8SEd Tanous     }
2573168d1b1aSCarson Labrado     downloadDumpEntry(asyncResp, dumpId, dumpType);
2574168d1b1aSCarson Labrado }
2575168d1b1aSCarson Labrado 
2576168d1b1aSCarson Labrado inline void handleDBusEventLogEntryDownloadGet(
2577168d1b1aSCarson Labrado     crow::App& app, const std::string& dumpType, const crow::Request& req,
2578168d1b1aSCarson Labrado     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2579168d1b1aSCarson Labrado     const std::string& systemName, const std::string& entryID)
2580168d1b1aSCarson Labrado {
2581168d1b1aSCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2582168d1b1aSCarson Labrado     {
2583168d1b1aSCarson Labrado         return;
2584168d1b1aSCarson Labrado     }
2585168d1b1aSCarson Labrado     if (!http_helpers::isContentTypeAllowed(
2586168d1b1aSCarson Labrado             req.getHeaderValue("Accept"),
2587168d1b1aSCarson Labrado             http_helpers::ContentType::OctetStream, true))
2588168d1b1aSCarson Labrado     {
2589168d1b1aSCarson Labrado         asyncResp->res.result(boost::beast::http::status::bad_request);
2590168d1b1aSCarson Labrado         return;
2591168d1b1aSCarson Labrado     }
2592168d1b1aSCarson Labrado     downloadEventLogEntry(asyncResp, systemName, entryID, dumpType);
2593168d1b1aSCarson Labrado }
2594168d1b1aSCarson Labrado 
2595fdd26906SClaire Weinan inline void handleLogServicesDumpCollectDiagnosticDataPost(
2596fdd26906SClaire Weinan     crow::App& app, const std::string& dumpType, const crow::Request& req,
2597253f11b8SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2598253f11b8SEd Tanous     const std::string& managerId)
2599fdd26906SClaire Weinan {
2600fdd26906SClaire Weinan     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2601fdd26906SClaire Weinan     {
2602fdd26906SClaire Weinan         return;
2603fdd26906SClaire Weinan     }
2604253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2605253f11b8SEd Tanous     {
2606253f11b8SEd Tanous         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2607253f11b8SEd Tanous         return;
2608253f11b8SEd Tanous     }
2609253f11b8SEd Tanous 
2610fdd26906SClaire Weinan     createDump(asyncResp, req, dumpType);
2611fdd26906SClaire Weinan }
2612fdd26906SClaire Weinan 
261322d268cbSEd Tanous inline void handleLogServicesDumpCollectDiagnosticDataComputerSystemPost(
261422d268cbSEd Tanous     crow::App& app, const crow::Request& req,
261522d268cbSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
26167f3e84a1SEd Tanous     const std::string& systemName)
261722d268cbSEd Tanous {
261822d268cbSEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
261922d268cbSEd Tanous     {
262022d268cbSEd Tanous         return;
262122d268cbSEd Tanous     }
26227f3e84a1SEd Tanous 
262325b54dbaSEd Tanous     if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
262422d268cbSEd Tanous     {
26257f3e84a1SEd Tanous         // Option currently returns no systems.  TBD
26267f3e84a1SEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
26277f3e84a1SEd Tanous                                    systemName);
26287f3e84a1SEd Tanous         return;
26297f3e84a1SEd Tanous     }
2630253f11b8SEd Tanous     if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
26317f3e84a1SEd Tanous     {
26327f3e84a1SEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
26337f3e84a1SEd Tanous                                    systemName);
263422d268cbSEd Tanous         return;
263522d268cbSEd Tanous     }
263622d268cbSEd Tanous     createDump(asyncResp, req, "System");
263722d268cbSEd Tanous }
263822d268cbSEd Tanous 
2639fdd26906SClaire Weinan inline void handleLogServicesDumpClearLogPost(
2640fdd26906SClaire Weinan     crow::App& app, const std::string& dumpType, const crow::Request& req,
2641253f11b8SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2642253f11b8SEd Tanous     const std::string& managerId)
2643fdd26906SClaire Weinan {
2644fdd26906SClaire Weinan     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2645fdd26906SClaire Weinan     {
2646fdd26906SClaire Weinan         return;
2647fdd26906SClaire Weinan     }
2648253f11b8SEd Tanous 
2649253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2650253f11b8SEd Tanous     {
2651253f11b8SEd Tanous         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2652253f11b8SEd Tanous         return;
2653253f11b8SEd Tanous     }
2654fdd26906SClaire Weinan     clearDump(asyncResp, dumpType);
2655fdd26906SClaire Weinan }
2656fdd26906SClaire Weinan 
265722d268cbSEd Tanous inline void handleLogServicesDumpClearLogComputerSystemPost(
265822d268cbSEd Tanous     crow::App& app, const crow::Request& req,
265922d268cbSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
26607f3e84a1SEd Tanous     const std::string& systemName)
266122d268cbSEd Tanous {
266222d268cbSEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
266322d268cbSEd Tanous     {
266422d268cbSEd Tanous         return;
266522d268cbSEd Tanous     }
266625b54dbaSEd Tanous     if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
266722d268cbSEd Tanous     {
26687f3e84a1SEd Tanous         // Option currently returns no systems.  TBD
26697f3e84a1SEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
26707f3e84a1SEd Tanous                                    systemName);
26717f3e84a1SEd Tanous         return;
26727f3e84a1SEd Tanous     }
2673253f11b8SEd Tanous     if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
26747f3e84a1SEd Tanous     {
26757f3e84a1SEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
26767f3e84a1SEd Tanous                                    systemName);
267722d268cbSEd Tanous         return;
267822d268cbSEd Tanous     }
267922d268cbSEd Tanous     clearDump(asyncResp, "System");
268022d268cbSEd Tanous }
268122d268cbSEd Tanous 
2682fdd26906SClaire Weinan inline void requestRoutesBMCDumpService(App& app)
2683fdd26906SClaire Weinan {
2684253f11b8SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/Dump/")
2685fdd26906SClaire Weinan         .privileges(redfish::privileges::getLogService)
2686fdd26906SClaire Weinan         .methods(boost::beast::http::verb::get)(std::bind_front(
2687fdd26906SClaire Weinan             handleLogServicesDumpServiceGet, std::ref(app), "BMC"));
2688fdd26906SClaire Weinan }
2689fdd26906SClaire Weinan 
2690fdd26906SClaire Weinan inline void requestRoutesBMCDumpEntryCollection(App& app)
2691fdd26906SClaire Weinan {
2692253f11b8SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/")
2693fdd26906SClaire Weinan         .privileges(redfish::privileges::getLogEntryCollection)
2694fdd26906SClaire Weinan         .methods(boost::beast::http::verb::get)(std::bind_front(
2695fdd26906SClaire Weinan             handleLogServicesDumpEntriesCollectionGet, std::ref(app), "BMC"));
2696c9bb6861Sraviteja-b }
2697c9bb6861Sraviteja-b 
26987e860f15SJohn Edward Broadbent inline void requestRoutesBMCDumpEntry(App& app)
2699c9bb6861Sraviteja-b {
27007e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
2701253f11b8SEd Tanous                  "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/")
2702ed398213SEd Tanous         .privileges(redfish::privileges::getLogEntry)
2703fdd26906SClaire Weinan         .methods(boost::beast::http::verb::get)(std::bind_front(
2704fdd26906SClaire Weinan             handleLogServicesDumpEntryGet, std::ref(app), "BMC"));
2705fdd26906SClaire Weinan 
27067e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
2707253f11b8SEd Tanous                  "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/")
2708ed398213SEd Tanous         .privileges(redfish::privileges::deleteLogEntry)
2709fdd26906SClaire Weinan         .methods(boost::beast::http::verb::delete_)(std::bind_front(
2710fdd26906SClaire Weinan             handleLogServicesDumpEntryDelete, std::ref(app), "BMC"));
2711c9bb6861Sraviteja-b }
2712c9bb6861Sraviteja-b 
2713168d1b1aSCarson Labrado inline void requestRoutesBMCDumpEntryDownload(App& app)
2714168d1b1aSCarson Labrado {
2715168d1b1aSCarson Labrado     BMCWEB_ROUTE(
2716168d1b1aSCarson Labrado         app,
2717253f11b8SEd Tanous         "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/attachment/")
2718168d1b1aSCarson Labrado         .privileges(redfish::privileges::getLogEntry)
2719168d1b1aSCarson Labrado         .methods(boost::beast::http::verb::get)(std::bind_front(
2720168d1b1aSCarson Labrado             handleLogServicesDumpEntryDownloadGet, std::ref(app), "BMC"));
2721168d1b1aSCarson Labrado }
2722168d1b1aSCarson Labrado 
27237e860f15SJohn Edward Broadbent inline void requestRoutesBMCDumpCreate(App& app)
2724c9bb6861Sraviteja-b {
27250fda0f12SGeorge Liu     BMCWEB_ROUTE(
27260fda0f12SGeorge Liu         app,
2727253f11b8SEd Tanous         "/redfish/v1/Managers/<str>/LogServices/Dump/Actions/LogService.CollectDiagnosticData/")
2728ed398213SEd Tanous         .privileges(redfish::privileges::postLogService)
27297e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
2730fdd26906SClaire Weinan             std::bind_front(handleLogServicesDumpCollectDiagnosticDataPost,
2731fdd26906SClaire Weinan                             std::ref(app), "BMC"));
2732a43be80fSAsmitha Karunanithi }
2733a43be80fSAsmitha Karunanithi 
27347e860f15SJohn Edward Broadbent inline void requestRoutesBMCDumpClear(App& app)
273580319af1SAsmitha Karunanithi {
27360fda0f12SGeorge Liu     BMCWEB_ROUTE(
27370fda0f12SGeorge Liu         app,
2738253f11b8SEd Tanous         "/redfish/v1/Managers/<str>/LogServices/Dump/Actions/LogService.ClearLog/")
2739ed398213SEd Tanous         .privileges(redfish::privileges::postLogService)
2740fdd26906SClaire Weinan         .methods(boost::beast::http::verb::post)(std::bind_front(
2741fdd26906SClaire Weinan             handleLogServicesDumpClearLogPost, std::ref(app), "BMC"));
274245ca1b86SEd Tanous }
2743fdd26906SClaire Weinan 
2744168d1b1aSCarson Labrado inline void requestRoutesDBusEventLogEntryDownload(App& app)
2745168d1b1aSCarson Labrado {
2746168d1b1aSCarson Labrado     BMCWEB_ROUTE(
2747168d1b1aSCarson Labrado         app,
27489e9d99daSRavi Teja         "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/attachment/")
2749168d1b1aSCarson Labrado         .privileges(redfish::privileges::getLogEntry)
2750168d1b1aSCarson Labrado         .methods(boost::beast::http::verb::get)(std::bind_front(
2751168d1b1aSCarson Labrado             handleDBusEventLogEntryDownloadGet, std::ref(app), "System"));
2752168d1b1aSCarson Labrado }
2753168d1b1aSCarson Labrado 
2754fdd26906SClaire Weinan inline void requestRoutesFaultLogDumpService(App& app)
2755fdd26906SClaire Weinan {
2756253f11b8SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/")
2757fdd26906SClaire Weinan         .privileges(redfish::privileges::getLogService)
2758fdd26906SClaire Weinan         .methods(boost::beast::http::verb::get)(std::bind_front(
2759fdd26906SClaire Weinan             handleLogServicesDumpServiceGet, std::ref(app), "FaultLog"));
2760fdd26906SClaire Weinan }
2761fdd26906SClaire Weinan 
2762fdd26906SClaire Weinan inline void requestRoutesFaultLogDumpEntryCollection(App& app)
2763fdd26906SClaire Weinan {
2764253f11b8SEd Tanous     BMCWEB_ROUTE(app,
2765253f11b8SEd Tanous                  "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/")
2766fdd26906SClaire Weinan         .privileges(redfish::privileges::getLogEntryCollection)
2767fdd26906SClaire Weinan         .methods(boost::beast::http::verb::get)(
2768fdd26906SClaire Weinan             std::bind_front(handleLogServicesDumpEntriesCollectionGet,
2769fdd26906SClaire Weinan                             std::ref(app), "FaultLog"));
2770fdd26906SClaire Weinan }
2771fdd26906SClaire Weinan 
2772fdd26906SClaire Weinan inline void requestRoutesFaultLogDumpEntry(App& app)
2773fdd26906SClaire Weinan {
2774253f11b8SEd Tanous     BMCWEB_ROUTE(
2775253f11b8SEd Tanous         app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/<str>/")
2776fdd26906SClaire Weinan         .privileges(redfish::privileges::getLogEntry)
2777fdd26906SClaire Weinan         .methods(boost::beast::http::verb::get)(std::bind_front(
2778fdd26906SClaire Weinan             handleLogServicesDumpEntryGet, std::ref(app), "FaultLog"));
2779fdd26906SClaire Weinan 
2780253f11b8SEd Tanous     BMCWEB_ROUTE(
2781253f11b8SEd Tanous         app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/<str>/")
2782fdd26906SClaire Weinan         .privileges(redfish::privileges::deleteLogEntry)
2783fdd26906SClaire Weinan         .methods(boost::beast::http::verb::delete_)(std::bind_front(
2784fdd26906SClaire Weinan             handleLogServicesDumpEntryDelete, std::ref(app), "FaultLog"));
2785fdd26906SClaire Weinan }
2786fdd26906SClaire Weinan 
2787fdd26906SClaire Weinan inline void requestRoutesFaultLogDumpClear(App& app)
2788fdd26906SClaire Weinan {
2789fdd26906SClaire Weinan     BMCWEB_ROUTE(
2790fdd26906SClaire Weinan         app,
2791253f11b8SEd Tanous         "/redfish/v1/Managers/<str>/LogServices/FaultLog/Actions/LogService.ClearLog/")
2792fdd26906SClaire Weinan         .privileges(redfish::privileges::postLogService)
2793fdd26906SClaire Weinan         .methods(boost::beast::http::verb::post)(std::bind_front(
2794fdd26906SClaire Weinan             handleLogServicesDumpClearLogPost, std::ref(app), "FaultLog"));
27955cb1dd27SAsmitha Karunanithi }
27965cb1dd27SAsmitha Karunanithi 
27977e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpService(App& app)
27985cb1dd27SAsmitha Karunanithi {
279922d268cbSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Dump/")
2800ed398213SEd Tanous         .privileges(redfish::privileges::getLogService)
28016ab9ad54SClaire Weinan         .methods(boost::beast::http::verb::get)(std::bind_front(
280222d268cbSEd Tanous             handleLogServicesDumpServiceComputerSystemGet, std::ref(app)));
28035cb1dd27SAsmitha Karunanithi }
28045cb1dd27SAsmitha Karunanithi 
28057e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpEntryCollection(App& app)
28067e860f15SJohn Edward Broadbent {
280722d268cbSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/")
2808ed398213SEd Tanous         .privileges(redfish::privileges::getLogEntryCollection)
280922d268cbSEd Tanous         .methods(boost::beast::http::verb::get)(std::bind_front(
281022d268cbSEd Tanous             handleLogServicesDumpEntriesCollectionComputerSystemGet,
281122d268cbSEd Tanous             std::ref(app)));
28125cb1dd27SAsmitha Karunanithi }
28135cb1dd27SAsmitha Karunanithi 
28147e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpEntry(App& app)
28155cb1dd27SAsmitha Karunanithi {
28167e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
281722d268cbSEd Tanous                  "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/<str>/")
2818ed398213SEd Tanous         .privileges(redfish::privileges::getLogEntry)
28196ab9ad54SClaire Weinan         .methods(boost::beast::http::verb::get)(std::bind_front(
282022d268cbSEd Tanous             handleLogServicesDumpEntryComputerSystemGet, std::ref(app)));
28218d1b46d7Szhanghch05 
28227e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
282322d268cbSEd Tanous                  "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/<str>/")
2824ed398213SEd Tanous         .privileges(redfish::privileges::deleteLogEntry)
28256ab9ad54SClaire Weinan         .methods(boost::beast::http::verb::delete_)(std::bind_front(
282622d268cbSEd Tanous             handleLogServicesDumpEntryComputerSystemDelete, std::ref(app)));
28275cb1dd27SAsmitha Karunanithi }
2828c9bb6861Sraviteja-b 
28297e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpCreate(App& app)
2830c9bb6861Sraviteja-b {
28310fda0f12SGeorge Liu     BMCWEB_ROUTE(
28320fda0f12SGeorge Liu         app,
283322d268cbSEd Tanous         "/redfish/v1/Systems/<str>/LogServices/Dump/Actions/LogService.CollectDiagnosticData/")
2834ed398213SEd Tanous         .privileges(redfish::privileges::postLogService)
283522d268cbSEd Tanous         .methods(boost::beast::http::verb::post)(std::bind_front(
283622d268cbSEd Tanous             handleLogServicesDumpCollectDiagnosticDataComputerSystemPost,
283722d268cbSEd Tanous             std::ref(app)));
2838a43be80fSAsmitha Karunanithi }
2839a43be80fSAsmitha Karunanithi 
28407e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpClear(App& app)
2841a43be80fSAsmitha Karunanithi {
28420fda0f12SGeorge Liu     BMCWEB_ROUTE(
28430fda0f12SGeorge Liu         app,
284422d268cbSEd Tanous         "/redfish/v1/Systems/<str>/LogServices/Dump/Actions/LogService.ClearLog/")
2845ed398213SEd Tanous         .privileges(redfish::privileges::postLogService)
28466ab9ad54SClaire Weinan         .methods(boost::beast::http::verb::post)(std::bind_front(
284722d268cbSEd Tanous             handleLogServicesDumpClearLogComputerSystemPost, std::ref(app)));
2848013487e5Sraviteja-b }
2849013487e5Sraviteja-b 
28507e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpService(App& app)
28511da66f75SEd Tanous {
28523946028dSAppaRao Puli     // Note: Deviated from redfish privilege registry for GET & HEAD
28533946028dSAppaRao Puli     // method for security reasons.
28541da66f75SEd Tanous     /**
28551da66f75SEd Tanous      * Functions triggers appropriate requests on DBus
28561da66f75SEd Tanous      */
285722d268cbSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Crashdump/")
2858ed398213SEd Tanous         // This is incorrect, should be:
2859ed398213SEd Tanous         //.privileges(redfish::privileges::getLogService)
2860432a890cSEd Tanous         .privileges({{"ConfigureManager"}})
2861*bd79bce8SPatrick Williams         .methods(
2862*bd79bce8SPatrick Williams             boost::beast::http::verb::
2863*bd79bce8SPatrick Williams                 get)([&app](const crow::Request& req,
286422d268cbSEd Tanous                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
286522d268cbSEd Tanous                             const std::string& systemName) {
28663ba00073SCarson Labrado             if (!redfish::setUpRedfishRoute(app, req, asyncResp))
286745ca1b86SEd Tanous             {
286845ca1b86SEd Tanous                 return;
286945ca1b86SEd Tanous             }
287025b54dbaSEd Tanous             if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
28717f3e84a1SEd Tanous             {
28727f3e84a1SEd Tanous                 // Option currently returns no systems.  TBD
28737f3e84a1SEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
28747f3e84a1SEd Tanous                                            systemName);
28757f3e84a1SEd Tanous                 return;
28767f3e84a1SEd Tanous             }
2877253f11b8SEd Tanous             if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
287822d268cbSEd Tanous             {
287922d268cbSEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
288022d268cbSEd Tanous                                            systemName);
288122d268cbSEd Tanous                 return;
288222d268cbSEd Tanous             }
288322d268cbSEd Tanous 
28847e860f15SJohn Edward Broadbent             // Copy over the static data to include the entries added by
28857e860f15SJohn Edward Broadbent             // SubRoute
28860f74e643SEd Tanous             asyncResp->res.jsonValue["@odata.id"] =
2887253f11b8SEd Tanous                 std::format("/redfish/v1/Systems/{}/LogServices/Crashdump",
2888253f11b8SEd Tanous                             BMCWEB_REDFISH_SYSTEM_URI_NAME);
2889e1f26343SJason M. Bills             asyncResp->res.jsonValue["@odata.type"] =
28908e6c099aSJason M. Bills                 "#LogService.v1_2_0.LogService";
28914f50ae4bSGunnar Mills             asyncResp->res.jsonValue["Name"] = "Open BMC Oem Crashdump Service";
28924f50ae4bSGunnar Mills             asyncResp->res.jsonValue["Description"] = "Oem Crashdump Service";
289315b89725SV-Sanjana             asyncResp->res.jsonValue["Id"] = "Crashdump";
2894539d8c6bSEd Tanous             asyncResp->res.jsonValue["OverWritePolicy"] =
2895539d8c6bSEd Tanous                 log_service::OverWritePolicy::WrapsWhenFull;
2896e1f26343SJason M. Bills             asyncResp->res.jsonValue["MaxNumberOfRecords"] = 3;
28977c8c4058STejas Patil 
28987c8c4058STejas Patil             std::pair<std::string, std::string> redfishDateTimeOffset =
28992b82937eSEd Tanous                 redfish::time_utils::getDateTimeOffsetNow();
29007c8c4058STejas Patil             asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
29017c8c4058STejas Patil             asyncResp->res.jsonValue["DateTimeLocalOffset"] =
29027c8c4058STejas Patil                 redfishDateTimeOffset.second;
29037c8c4058STejas Patil 
2904*bd79bce8SPatrick Williams             asyncResp->res.jsonValue["Entries"]["@odata.id"] = std::format(
2905*bd79bce8SPatrick Williams                 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries",
2906253f11b8SEd Tanous                 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2907253f11b8SEd Tanous             asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"]
2908253f11b8SEd Tanous                                     ["target"] = std::format(
2909253f11b8SEd Tanous                 "/redfish/v1/Systems/{}/LogServices/Crashdump/Actions/LogService.ClearLog",
2910253f11b8SEd Tanous                 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2911*bd79bce8SPatrick Williams             asyncResp->res
2912*bd79bce8SPatrick Williams                 .jsonValue["Actions"]["#LogService.CollectDiagnosticData"]
2913253f11b8SEd Tanous                           ["target"] = std::format(
2914253f11b8SEd Tanous                 "/redfish/v1/Systems/{}/LogServices/Crashdump/Actions/LogService.CollectDiagnosticData",
2915253f11b8SEd Tanous                 BMCWEB_REDFISH_SYSTEM_URI_NAME);
29167e860f15SJohn Edward Broadbent         });
29171da66f75SEd Tanous }
29181da66f75SEd Tanous 
29197e860f15SJohn Edward Broadbent void inline requestRoutesCrashdumpClear(App& app)
29205b61b5e8SJason M. Bills {
29210fda0f12SGeorge Liu     BMCWEB_ROUTE(
29220fda0f12SGeorge Liu         app,
292322d268cbSEd Tanous         "/redfish/v1/Systems/<str>/LogServices/Crashdump/Actions/LogService.ClearLog/")
2924ed398213SEd Tanous         // This is incorrect, should be:
2925ed398213SEd Tanous         //.privileges(redfish::privileges::postLogService)
2926432a890cSEd Tanous         .privileges({{"ConfigureComponents"}})
29277e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
292845ca1b86SEd Tanous             [&app](const crow::Request& req,
292922d268cbSEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
293022d268cbSEd Tanous                    const std::string& systemName) {
29313ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
293245ca1b86SEd Tanous                 {
293345ca1b86SEd Tanous                     return;
293445ca1b86SEd Tanous                 }
293525b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
29367f3e84a1SEd Tanous                 {
29377f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
29387f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
29397f3e84a1SEd Tanous                                                systemName);
29407f3e84a1SEd Tanous                     return;
29417f3e84a1SEd Tanous                 }
2942253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
294322d268cbSEd Tanous                 {
294422d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
294522d268cbSEd Tanous                                                systemName);
294622d268cbSEd Tanous                     return;
294722d268cbSEd Tanous                 }
29485b61b5e8SJason M. Bills                 crow::connections::systemBus->async_method_call(
29495e7e2dc5SEd Tanous                     [asyncResp](const boost::system::error_code& ec,
2950cb13a392SEd Tanous                                 const std::string&) {
29515b61b5e8SJason M. Bills                         if (ec)
29525b61b5e8SJason M. Bills                         {
29535b61b5e8SJason M. Bills                             messages::internalError(asyncResp->res);
29545b61b5e8SJason M. Bills                             return;
29555b61b5e8SJason M. Bills                         }
29565b61b5e8SJason M. Bills                         messages::success(asyncResp->res);
29575b61b5e8SJason M. Bills                     },
2958*bd79bce8SPatrick Williams                     crashdumpObject, crashdumpPath, deleteAllInterface,
2959*bd79bce8SPatrick Williams                     "DeleteAll");
29607e860f15SJohn Edward Broadbent             });
29615b61b5e8SJason M. Bills }
29625b61b5e8SJason M. Bills 
29638d1b46d7Szhanghch05 static void
29648d1b46d7Szhanghch05     logCrashdumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
29658d1b46d7Szhanghch05                       const std::string& logID, nlohmann::json& logEntryJson)
2966e855dd28SJason M. Bills {
2967043a0536SJohnathan Mantey     auto getStoredLogCallback =
2968b9d36b47SEd Tanous         [asyncResp, logID,
29695e7e2dc5SEd Tanous          &logEntryJson](const boost::system::error_code& ec,
2970b9d36b47SEd Tanous                         const dbus::utility::DBusPropertiesMap& params) {
2971e855dd28SJason M. Bills             if (ec)
2972e855dd28SJason M. Bills             {
297362598e31SEd Tanous                 BMCWEB_LOG_DEBUG("failed to get log ec: {}", ec.message());
29741ddcf01aSJason M. Bills                 if (ec.value() ==
29751ddcf01aSJason M. Bills                     boost::system::linux_error::bad_request_descriptor)
29761ddcf01aSJason M. Bills                 {
2977*bd79bce8SPatrick Williams                     messages::resourceNotFound(asyncResp->res, "LogEntry",
2978*bd79bce8SPatrick Williams                                                logID);
29791ddcf01aSJason M. Bills                 }
29801ddcf01aSJason M. Bills                 else
29811ddcf01aSJason M. Bills                 {
2982e855dd28SJason M. Bills                     messages::internalError(asyncResp->res);
29831ddcf01aSJason M. Bills                 }
2984e855dd28SJason M. Bills                 return;
2985e855dd28SJason M. Bills             }
2986043a0536SJohnathan Mantey 
2987043a0536SJohnathan Mantey             std::string timestamp{};
2988043a0536SJohnathan Mantey             std::string filename{};
2989043a0536SJohnathan Mantey             std::string logfile{};
29902c70f800SEd Tanous             parseCrashdumpParameters(params, filename, timestamp, logfile);
2991043a0536SJohnathan Mantey 
2992043a0536SJohnathan Mantey             if (filename.empty() || timestamp.empty())
2993e855dd28SJason M. Bills             {
29949db4ba25SJiaqing Zhao                 messages::resourceNotFound(asyncResp->res, "LogEntry", logID);
2995e855dd28SJason M. Bills                 return;
2996e855dd28SJason M. Bills             }
2997e855dd28SJason M. Bills 
2998043a0536SJohnathan Mantey             std::string crashdumpURI =
2999*bd79bce8SPatrick Williams                 std::format(
3000*bd79bce8SPatrick Williams                     "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries/",
3001253f11b8SEd Tanous                     BMCWEB_REDFISH_SYSTEM_URI_NAME) +
3002043a0536SJohnathan Mantey                 logID + "/" + filename;
300384afc48bSJason M. Bills             nlohmann::json::object_t logEntry;
30049c11a172SVijay Lobo             logEntry["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
3005ef4c65b7SEd Tanous             logEntry["@odata.id"] = boost::urls::format(
3006253f11b8SEd Tanous                 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries/{}",
3007253f11b8SEd Tanous                 BMCWEB_REDFISH_SYSTEM_URI_NAME, logID);
300884afc48bSJason M. Bills             logEntry["Name"] = "CPU Crashdump";
300984afc48bSJason M. Bills             logEntry["Id"] = logID;
3010539d8c6bSEd Tanous             logEntry["EntryType"] = log_entry::LogEntryType::Oem;
301184afc48bSJason M. Bills             logEntry["AdditionalDataURI"] = std::move(crashdumpURI);
301284afc48bSJason M. Bills             logEntry["DiagnosticDataType"] = "OEM";
301384afc48bSJason M. Bills             logEntry["OEMDiagnosticDataType"] = "PECICrashdump";
301484afc48bSJason M. Bills             logEntry["Created"] = std::move(timestamp);
30152b20ef6eSJason M. Bills 
30162b20ef6eSJason M. Bills             // If logEntryJson references an array of LogEntry resources
30172b20ef6eSJason M. Bills             // ('Members' list), then push this as a new entry, otherwise set it
30182b20ef6eSJason M. Bills             // directly
30192b20ef6eSJason M. Bills             if (logEntryJson.is_array())
30202b20ef6eSJason M. Bills             {
30212b20ef6eSJason M. Bills                 logEntryJson.push_back(logEntry);
30222b20ef6eSJason M. Bills                 asyncResp->res.jsonValue["Members@odata.count"] =
30232b20ef6eSJason M. Bills                     logEntryJson.size();
30242b20ef6eSJason M. Bills             }
30252b20ef6eSJason M. Bills             else
30262b20ef6eSJason M. Bills             {
3027d405bb51SJason M. Bills                 logEntryJson.update(logEntry);
30282b20ef6eSJason M. Bills             }
3029e855dd28SJason M. Bills         };
3030d1bde9e5SKrzysztof Grobelny     sdbusplus::asio::getAllProperties(
3031d1bde9e5SKrzysztof Grobelny         *crow::connections::systemBus, crashdumpObject,
3032d1bde9e5SKrzysztof Grobelny         crashdumpPath + std::string("/") + logID, crashdumpInterface,
3033d1bde9e5SKrzysztof Grobelny         std::move(getStoredLogCallback));
3034e855dd28SJason M. Bills }
3035e855dd28SJason M. Bills 
30367e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpEntryCollection(App& app)
30371da66f75SEd Tanous {
30383946028dSAppaRao Puli     // Note: Deviated from redfish privilege registry for GET & HEAD
30393946028dSAppaRao Puli     // method for security reasons.
30401da66f75SEd Tanous     /**
30411da66f75SEd Tanous      * Functions triggers appropriate requests on DBus
30421da66f75SEd Tanous      */
30437e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
304422d268cbSEd Tanous                  "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/")
3045ed398213SEd Tanous         // This is incorrect, should be.
3046ed398213SEd Tanous         //.privileges(redfish::privileges::postLogEntryCollection)
3047432a890cSEd Tanous         .privileges({{"ConfigureComponents"}})
3048*bd79bce8SPatrick Williams         .methods(
3049*bd79bce8SPatrick Williams             boost::beast::http::verb::
3050*bd79bce8SPatrick Williams                 get)([&app](const crow::Request& req,
305122d268cbSEd Tanous                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
305222d268cbSEd Tanous                             const std::string& systemName) {
30533ba00073SCarson Labrado             if (!redfish::setUpRedfishRoute(app, req, asyncResp))
305445ca1b86SEd Tanous             {
305545ca1b86SEd Tanous                 return;
305645ca1b86SEd Tanous             }
305725b54dbaSEd Tanous             if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
30587f3e84a1SEd Tanous             {
30597f3e84a1SEd Tanous                 // Option currently returns no systems.  TBD
30607f3e84a1SEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
30617f3e84a1SEd Tanous                                            systemName);
30627f3e84a1SEd Tanous                 return;
30637f3e84a1SEd Tanous             }
3064253f11b8SEd Tanous             if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
306522d268cbSEd Tanous             {
306622d268cbSEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
306722d268cbSEd Tanous                                            systemName);
306822d268cbSEd Tanous                 return;
306922d268cbSEd Tanous             }
307022d268cbSEd Tanous 
30717a1dbc48SGeorge Liu             constexpr std::array<std::string_view, 1> interfaces = {
30727a1dbc48SGeorge Liu                 crashdumpInterface};
30737a1dbc48SGeorge Liu             dbus::utility::getSubTreePaths(
30747a1dbc48SGeorge Liu                 "/", 0, interfaces,
30757a1dbc48SGeorge Liu                 [asyncResp](const boost::system::error_code& ec,
30762b20ef6eSJason M. Bills                             const std::vector<std::string>& resp) {
30771da66f75SEd Tanous                     if (ec)
30781da66f75SEd Tanous                     {
30791da66f75SEd Tanous                         if (ec.value() !=
30801da66f75SEd Tanous                             boost::system::errc::no_such_file_or_directory)
30811da66f75SEd Tanous                         {
308262598e31SEd Tanous                             BMCWEB_LOG_DEBUG("failed to get entries ec: {}",
308362598e31SEd Tanous                                              ec.message());
3084f12894f8SJason M. Bills                             messages::internalError(asyncResp->res);
30851da66f75SEd Tanous                             return;
30861da66f75SEd Tanous                         }
30871da66f75SEd Tanous                     }
3088e1f26343SJason M. Bills                     asyncResp->res.jsonValue["@odata.type"] =
30891da66f75SEd Tanous                         "#LogEntryCollection.LogEntryCollection";
3090253f11b8SEd Tanous                     asyncResp->res.jsonValue["@odata.id"] = std::format(
3091253f11b8SEd Tanous                         "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries",
3092253f11b8SEd Tanous                         BMCWEB_REDFISH_SYSTEM_URI_NAME);
3093*bd79bce8SPatrick Williams                     asyncResp->res.jsonValue["Name"] =
3094*bd79bce8SPatrick Williams                         "Open BMC Crashdump Entries";
3095e1f26343SJason M. Bills                     asyncResp->res.jsonValue["Description"] =
3096424c4176SJason M. Bills                         "Collection of Crashdump Entries";
3097*bd79bce8SPatrick Williams                     asyncResp->res.jsonValue["Members"] =
3098*bd79bce8SPatrick Williams                         nlohmann::json::array();
3099a2dd60a6SBrandon Kim                     asyncResp->res.jsonValue["Members@odata.count"] = 0;
31002b20ef6eSJason M. Bills 
31012b20ef6eSJason M. Bills                     for (const std::string& path : resp)
31021da66f75SEd Tanous                     {
31032b20ef6eSJason M. Bills                         const sdbusplus::message::object_path objPath(path);
3104e855dd28SJason M. Bills                         // Get the log ID
31052b20ef6eSJason M. Bills                         std::string logID = objPath.filename();
31062b20ef6eSJason M. Bills                         if (logID.empty())
31071da66f75SEd Tanous                         {
3108e855dd28SJason M. Bills                             continue;
31091da66f75SEd Tanous                         }
3110e855dd28SJason M. Bills                         // Add the log entry to the array
31112b20ef6eSJason M. Bills                         logCrashdumpEntry(asyncResp, logID,
31122b20ef6eSJason M. Bills                                           asyncResp->res.jsonValue["Members"]);
31131da66f75SEd Tanous                     }
31147a1dbc48SGeorge Liu                 });
31157e860f15SJohn Edward Broadbent         });
31161da66f75SEd Tanous }
31171da66f75SEd Tanous 
31187e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpEntry(App& app)
31191da66f75SEd Tanous {
31203946028dSAppaRao Puli     // Note: Deviated from redfish privilege registry for GET & HEAD
31213946028dSAppaRao Puli     // method for security reasons.
31221da66f75SEd Tanous 
31237e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
312422d268cbSEd Tanous         app, "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/<str>/")
3125ed398213SEd Tanous         // this is incorrect, should be
3126ed398213SEd Tanous         // .privileges(redfish::privileges::getLogEntry)
3127432a890cSEd Tanous         .privileges({{"ConfigureComponents"}})
31287e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
312945ca1b86SEd Tanous             [&app](const crow::Request& req,
31307e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
313122d268cbSEd Tanous                    const std::string& systemName, const std::string& param) {
31323ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
313345ca1b86SEd Tanous                 {
313445ca1b86SEd Tanous                     return;
313545ca1b86SEd Tanous                 }
313625b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
31377f3e84a1SEd Tanous                 {
31387f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
31397f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
31407f3e84a1SEd Tanous                                                systemName);
31417f3e84a1SEd Tanous                     return;
31427f3e84a1SEd Tanous                 }
3143253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
314422d268cbSEd Tanous                 {
314522d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
314622d268cbSEd Tanous                                                systemName);
314722d268cbSEd Tanous                     return;
314822d268cbSEd Tanous                 }
31497e860f15SJohn Edward Broadbent                 const std::string& logID = param;
3150e855dd28SJason M. Bills                 logCrashdumpEntry(asyncResp, logID, asyncResp->res.jsonValue);
31517e860f15SJohn Edward Broadbent             });
3152e855dd28SJason M. Bills }
3153e855dd28SJason M. Bills 
31547e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpFile(App& app)
3155e855dd28SJason M. Bills {
31563946028dSAppaRao Puli     // Note: Deviated from redfish privilege registry for GET & HEAD
31573946028dSAppaRao Puli     // method for security reasons.
31587e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
31597e860f15SJohn Edward Broadbent         app,
316022d268cbSEd Tanous         "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/<str>/<str>/")
3161ed398213SEd Tanous         .privileges(redfish::privileges::getLogEntry)
31627e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
3163a4ce114aSNan Zhou             [](const crow::Request& req,
31647e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
316522d268cbSEd Tanous                const std::string& systemName, const std::string& logID,
316622d268cbSEd Tanous                const std::string& fileName) {
3167*bd79bce8SPatrick Williams                 // Do not call getRedfishRoute here since the crashdump file is
3168*bd79bce8SPatrick Williams                 // not a Redfish resource.
316922d268cbSEd Tanous 
317025b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
31717f3e84a1SEd Tanous                 {
31727f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
31737f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
31747f3e84a1SEd Tanous                                                systemName);
31757f3e84a1SEd Tanous                     return;
31767f3e84a1SEd Tanous                 }
3177253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
317822d268cbSEd Tanous                 {
317922d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
318022d268cbSEd Tanous                                                systemName);
318122d268cbSEd Tanous                     return;
318222d268cbSEd Tanous                 }
318322d268cbSEd Tanous 
3184043a0536SJohnathan Mantey                 auto getStoredLogCallback =
3185*bd79bce8SPatrick Williams                     [asyncResp, logID, fileName,
3186*bd79bce8SPatrick Williams                      url(boost::urls::url(req.url()))](
31875e7e2dc5SEd Tanous                         const boost::system::error_code& ec,
3188*bd79bce8SPatrick Williams                         const std::vector<std::pair<
3189*bd79bce8SPatrick Williams                             std::string, dbus::utility::DbusVariantType>>&
31907e860f15SJohn Edward Broadbent                             resp) {
31911da66f75SEd Tanous                         if (ec)
31921da66f75SEd Tanous                         {
3193*bd79bce8SPatrick Williams                             BMCWEB_LOG_DEBUG("failed to get log ec: {}",
3194*bd79bce8SPatrick Williams                                              ec.message());
3195f12894f8SJason M. Bills                             messages::internalError(asyncResp->res);
31961da66f75SEd Tanous                             return;
31971da66f75SEd Tanous                         }
3198e855dd28SJason M. Bills 
3199043a0536SJohnathan Mantey                         std::string dbusFilename{};
3200043a0536SJohnathan Mantey                         std::string dbusTimestamp{};
3201043a0536SJohnathan Mantey                         std::string dbusFilepath{};
3202043a0536SJohnathan Mantey 
3203*bd79bce8SPatrick Williams                         parseCrashdumpParameters(resp, dbusFilename,
3204*bd79bce8SPatrick Williams                                                  dbusTimestamp, dbusFilepath);
3205043a0536SJohnathan Mantey 
3206043a0536SJohnathan Mantey                         if (dbusFilename.empty() || dbusTimestamp.empty() ||
3207043a0536SJohnathan Mantey                             dbusFilepath.empty())
32081da66f75SEd Tanous                         {
3209*bd79bce8SPatrick Williams                             messages::resourceNotFound(asyncResp->res,
3210*bd79bce8SPatrick Williams                                                        "LogEntry", logID);
32111da66f75SEd Tanous                             return;
32121da66f75SEd Tanous                         }
3213e855dd28SJason M. Bills 
3214043a0536SJohnathan Mantey                         // Verify the file name parameter is correct
3215043a0536SJohnathan Mantey                         if (fileName != dbusFilename)
3216043a0536SJohnathan Mantey                         {
3217*bd79bce8SPatrick Williams                             messages::resourceNotFound(asyncResp->res,
3218*bd79bce8SPatrick Williams                                                        "LogEntry", logID);
3219043a0536SJohnathan Mantey                             return;
3220043a0536SJohnathan Mantey                         }
3221043a0536SJohnathan Mantey 
322227b0cf90SEd Tanous                         if (!asyncResp->res.openFile(dbusFilepath))
3223043a0536SJohnathan Mantey                         {
3224*bd79bce8SPatrick Williams                             messages::resourceNotFound(asyncResp->res,
3225*bd79bce8SPatrick Williams                                                        "LogEntry", logID);
3226043a0536SJohnathan Mantey                             return;
3227043a0536SJohnathan Mantey                         }
3228043a0536SJohnathan Mantey 
32297e860f15SJohn Edward Broadbent                         // Configure this to be a file download when accessed
32307e860f15SJohn Edward Broadbent                         // from a browser
3231d9f6c621SEd Tanous                         asyncResp->res.addHeader(
3232*bd79bce8SPatrick Williams                             boost::beast::http::field::content_disposition,
3233*bd79bce8SPatrick Williams                             "attachment");
32341da66f75SEd Tanous                     };
3235d1bde9e5SKrzysztof Grobelny                 sdbusplus::asio::getAllProperties(
3236d1bde9e5SKrzysztof Grobelny                     *crow::connections::systemBus, crashdumpObject,
3237*bd79bce8SPatrick Williams                     crashdumpPath + std::string("/") + logID,
3238*bd79bce8SPatrick Williams                     crashdumpInterface, std::move(getStoredLogCallback));
32397e860f15SJohn Edward Broadbent             });
32401da66f75SEd Tanous }
32411da66f75SEd Tanous 
3242c5a4c82aSJason M. Bills enum class OEMDiagnosticType
3243c5a4c82aSJason M. Bills {
3244c5a4c82aSJason M. Bills     onDemand,
3245c5a4c82aSJason M. Bills     telemetry,
3246c5a4c82aSJason M. Bills     invalid,
3247c5a4c82aSJason M. Bills };
3248c5a4c82aSJason M. Bills 
324926ccae32SEd Tanous inline OEMDiagnosticType getOEMDiagnosticType(std::string_view oemDiagStr)
3250c5a4c82aSJason M. Bills {
3251c5a4c82aSJason M. Bills     if (oemDiagStr == "OnDemand")
3252c5a4c82aSJason M. Bills     {
3253c5a4c82aSJason M. Bills         return OEMDiagnosticType::onDemand;
3254c5a4c82aSJason M. Bills     }
3255c5a4c82aSJason M. Bills     if (oemDiagStr == "Telemetry")
3256c5a4c82aSJason M. Bills     {
3257c5a4c82aSJason M. Bills         return OEMDiagnosticType::telemetry;
3258c5a4c82aSJason M. Bills     }
3259c5a4c82aSJason M. Bills 
3260c5a4c82aSJason M. Bills     return OEMDiagnosticType::invalid;
3261c5a4c82aSJason M. Bills }
3262c5a4c82aSJason M. Bills 
32637e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpCollect(App& app)
32641da66f75SEd Tanous {
32653946028dSAppaRao Puli     // Note: Deviated from redfish privilege registry for GET & HEAD
32663946028dSAppaRao Puli     // method for security reasons.
32670fda0f12SGeorge Liu     BMCWEB_ROUTE(
32680fda0f12SGeorge Liu         app,
326922d268cbSEd Tanous         "/redfish/v1/Systems/<str>/LogServices/Crashdump/Actions/LogService.CollectDiagnosticData/")
3270ed398213SEd Tanous         // The below is incorrect;  Should be ConfigureManager
3271ed398213SEd Tanous         //.privileges(redfish::privileges::postLogService)
3272432a890cSEd Tanous         .privileges({{"ConfigureComponents"}})
3273002d39b4SEd Tanous         .methods(boost::beast::http::verb::post)(
3274002d39b4SEd Tanous             [&app](const crow::Request& req,
327522d268cbSEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
327622d268cbSEd Tanous                    const std::string& systemName) {
32773ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
327845ca1b86SEd Tanous                 {
327945ca1b86SEd Tanous                     return;
328045ca1b86SEd Tanous                 }
328122d268cbSEd Tanous 
328225b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
32837f3e84a1SEd Tanous                 {
32847f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
32857f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
32867f3e84a1SEd Tanous                                                systemName);
32877f3e84a1SEd Tanous                     return;
32887f3e84a1SEd Tanous                 }
3289253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
329022d268cbSEd Tanous                 {
329122d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
329222d268cbSEd Tanous                                                systemName);
329322d268cbSEd Tanous                     return;
329422d268cbSEd Tanous                 }
329522d268cbSEd Tanous 
32968e6c099aSJason M. Bills                 std::string diagnosticDataType;
32978e6c099aSJason M. Bills                 std::string oemDiagnosticDataType;
329815ed6780SWilly Tu                 if (!redfish::json_util::readJsonAction(
3299*bd79bce8SPatrick Williams                         req, asyncResp->res, "DiagnosticDataType",
3300*bd79bce8SPatrick Williams                         diagnosticDataType, "OEMDiagnosticDataType",
3301*bd79bce8SPatrick Williams                         oemDiagnosticDataType))
33028e6c099aSJason M. Bills                 {
33038e6c099aSJason M. Bills                     return;
33048e6c099aSJason M. Bills                 }
33058e6c099aSJason M. Bills 
33068e6c099aSJason M. Bills                 if (diagnosticDataType != "OEM")
33078e6c099aSJason M. Bills                 {
330862598e31SEd Tanous                     BMCWEB_LOG_ERROR(
330962598e31SEd Tanous                         "Only OEM DiagnosticDataType supported for Crashdump");
33108e6c099aSJason M. Bills                     messages::actionParameterValueFormatError(
3311*bd79bce8SPatrick Williams                         asyncResp->res, diagnosticDataType,
3312*bd79bce8SPatrick Williams                         "DiagnosticDataType", "CollectDiagnosticData");
33138e6c099aSJason M. Bills                     return;
33148e6c099aSJason M. Bills                 }
33158e6c099aSJason M. Bills 
3316c5a4c82aSJason M. Bills                 OEMDiagnosticType oemDiagType =
3317c5a4c82aSJason M. Bills                     getOEMDiagnosticType(oemDiagnosticDataType);
3318c5a4c82aSJason M. Bills 
3319c5a4c82aSJason M. Bills                 std::string iface;
3320c5a4c82aSJason M. Bills                 std::string method;
3321c5a4c82aSJason M. Bills                 std::string taskMatchStr;
3322c5a4c82aSJason M. Bills                 if (oemDiagType == OEMDiagnosticType::onDemand)
3323c5a4c82aSJason M. Bills                 {
3324c5a4c82aSJason M. Bills                     iface = crashdumpOnDemandInterface;
3325c5a4c82aSJason M. Bills                     method = "GenerateOnDemandLog";
3326*bd79bce8SPatrick Williams                     taskMatchStr =
3327*bd79bce8SPatrick Williams                         "type='signal',"
3328c5a4c82aSJason M. Bills                         "interface='org.freedesktop.DBus.Properties',"
3329c5a4c82aSJason M. Bills                         "member='PropertiesChanged',"
3330c5a4c82aSJason M. Bills                         "arg0namespace='com.intel.crashdump'";
3331c5a4c82aSJason M. Bills                 }
3332c5a4c82aSJason M. Bills                 else if (oemDiagType == OEMDiagnosticType::telemetry)
3333c5a4c82aSJason M. Bills                 {
3334c5a4c82aSJason M. Bills                     iface = crashdumpTelemetryInterface;
3335c5a4c82aSJason M. Bills                     method = "GenerateTelemetryLog";
3336*bd79bce8SPatrick Williams                     taskMatchStr =
3337*bd79bce8SPatrick Williams                         "type='signal',"
3338c5a4c82aSJason M. Bills                         "interface='org.freedesktop.DBus.Properties',"
3339c5a4c82aSJason M. Bills                         "member='PropertiesChanged',"
3340c5a4c82aSJason M. Bills                         "arg0namespace='com.intel.crashdump'";
3341c5a4c82aSJason M. Bills                 }
3342c5a4c82aSJason M. Bills                 else
3343c5a4c82aSJason M. Bills                 {
334462598e31SEd Tanous                     BMCWEB_LOG_ERROR("Unsupported OEMDiagnosticDataType: {}",
334562598e31SEd Tanous                                      oemDiagnosticDataType);
3346c5a4c82aSJason M. Bills                     messages::actionParameterValueFormatError(
3347*bd79bce8SPatrick Williams                         asyncResp->res, oemDiagnosticDataType,
3348*bd79bce8SPatrick Williams                         "OEMDiagnosticDataType", "CollectDiagnosticData");
3349c5a4c82aSJason M. Bills                     return;
3350c5a4c82aSJason M. Bills                 }
3351c5a4c82aSJason M. Bills 
3352c5a4c82aSJason M. Bills                 auto collectCrashdumpCallback =
3353c5a4c82aSJason M. Bills                     [asyncResp, payload(task::Payload(req)),
33545e7e2dc5SEd Tanous                      taskMatchStr](const boost::system::error_code& ec,
335598be3e39SEd Tanous                                    const std::string&) mutable {
33561da66f75SEd Tanous                         if (ec)
33571da66f75SEd Tanous                         {
3358*bd79bce8SPatrick Williams                             if (ec.value() ==
3359*bd79bce8SPatrick Williams                                 boost::system::errc::operation_not_supported)
33601da66f75SEd Tanous                             {
3361f12894f8SJason M. Bills                                 messages::resourceInStandby(asyncResp->res);
33621da66f75SEd Tanous                             }
3363*bd79bce8SPatrick Williams                             else if (ec.value() == boost::system::errc::
3364*bd79bce8SPatrick Williams                                                        device_or_resource_busy)
33654363d3b2SJason M. Bills                             {
3366*bd79bce8SPatrick Williams                                 messages::serviceTemporarilyUnavailable(
3367*bd79bce8SPatrick Williams                                     asyncResp->res, "60");
33684363d3b2SJason M. Bills                             }
33691da66f75SEd Tanous                             else
33701da66f75SEd Tanous                             {
3371f12894f8SJason M. Bills                                 messages::internalError(asyncResp->res);
33721da66f75SEd Tanous                             }
33731da66f75SEd Tanous                             return;
33741da66f75SEd Tanous                         }
3375*bd79bce8SPatrick Williams                         std::shared_ptr<task::TaskData> task =
3376*bd79bce8SPatrick Williams                             task::TaskData::createTask(
3377*bd79bce8SPatrick Williams                                 [](const boost::system::error_code& ec2,
3378*bd79bce8SPatrick Williams                                    sdbusplus::message_t&,
3379*bd79bce8SPatrick Williams                                    const std::shared_ptr<task::TaskData>&
3380*bd79bce8SPatrick Williams                                        taskData) {
33818b24275dSEd Tanous                                     if (!ec2)
338266afe4faSJames Feist                                     {
3383*bd79bce8SPatrick Williams                                         taskData->messages.emplace_back(
3384*bd79bce8SPatrick Williams                                             messages::taskCompletedOK(
3385*bd79bce8SPatrick Williams                                                 std::to_string(
3386*bd79bce8SPatrick Williams                                                     taskData->index)));
3387831d6b09SJames Feist                                         taskData->state = "Completed";
338866afe4faSJames Feist                                     }
338932898ceaSJames Feist                                     return task::completed;
339066afe4faSJames Feist                                 },
3391c5a4c82aSJason M. Bills                                 taskMatchStr);
3392c5a4c82aSJason M. Bills 
339346229577SJames Feist                         task->startTimer(std::chrono::minutes(5));
339446229577SJames Feist                         task->populateResp(asyncResp->res);
339598be3e39SEd Tanous                         task->payload.emplace(std::move(payload));
33961da66f75SEd Tanous                     };
33978e6c099aSJason M. Bills 
33981da66f75SEd Tanous                 crow::connections::systemBus->async_method_call(
3399*bd79bce8SPatrick Williams                     std::move(collectCrashdumpCallback), crashdumpObject,
3400*bd79bce8SPatrick Williams                     crashdumpPath, iface, method);
34017e860f15SJohn Edward Broadbent             });
34026eda7685SKenny L. Ku }
34036eda7685SKenny L. Ku 
3404599b9af3SAlexander Hansen inline void dBusLogServiceActionsClear(
3405599b9af3SAlexander Hansen     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
3406599b9af3SAlexander Hansen {
3407599b9af3SAlexander Hansen     BMCWEB_LOG_DEBUG("Do delete all entries.");
3408599b9af3SAlexander Hansen 
3409599b9af3SAlexander Hansen     // Process response from Logging service.
3410599b9af3SAlexander Hansen     auto respHandler = [asyncResp](const boost::system::error_code& ec) {
3411599b9af3SAlexander Hansen         BMCWEB_LOG_DEBUG("doClearLog resp_handler callback: Done");
3412599b9af3SAlexander Hansen         if (ec)
3413599b9af3SAlexander Hansen         {
3414599b9af3SAlexander Hansen             // TODO Handle for specific error code
3415599b9af3SAlexander Hansen             BMCWEB_LOG_ERROR("doClearLog resp_handler got error {}", ec);
3416599b9af3SAlexander Hansen             asyncResp->res.result(
3417599b9af3SAlexander Hansen                 boost::beast::http::status::internal_server_error);
3418599b9af3SAlexander Hansen             return;
3419599b9af3SAlexander Hansen         }
3420599b9af3SAlexander Hansen 
3421599b9af3SAlexander Hansen         asyncResp->res.result(boost::beast::http::status::no_content);
3422599b9af3SAlexander Hansen     };
3423599b9af3SAlexander Hansen 
3424599b9af3SAlexander Hansen     // Make call to Logging service to request Clear Log
3425599b9af3SAlexander Hansen     crow::connections::systemBus->async_method_call(
3426599b9af3SAlexander Hansen         respHandler, "xyz.openbmc_project.Logging",
3427599b9af3SAlexander Hansen         "/xyz/openbmc_project/logging",
3428599b9af3SAlexander Hansen         "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
3429599b9af3SAlexander Hansen }
3430599b9af3SAlexander Hansen 
3431cb92c03bSAndrew Geissler /**
3432cb92c03bSAndrew Geissler  * DBusLogServiceActionsClear class supports POST method for ClearLog action.
3433cb92c03bSAndrew Geissler  */
34347e860f15SJohn Edward Broadbent inline void requestRoutesDBusLogServiceActionsClear(App& app)
3435cb92c03bSAndrew Geissler {
3436cb92c03bSAndrew Geissler     /**
3437cb92c03bSAndrew Geissler      * Function handles POST method request.
3438cb92c03bSAndrew Geissler      * The Clear Log actions does not require any parameter.The action deletes
3439cb92c03bSAndrew Geissler      * all entries found in the Entries collection for this Log Service.
3440cb92c03bSAndrew Geissler      */
34417e860f15SJohn Edward Broadbent 
34420fda0f12SGeorge Liu     BMCWEB_ROUTE(
34430fda0f12SGeorge Liu         app,
344422d268cbSEd Tanous         "/redfish/v1/Systems/<str>/LogServices/EventLog/Actions/LogService.ClearLog/")
3445ed398213SEd Tanous         .privileges(redfish::privileges::postLogService)
34467e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
344745ca1b86SEd Tanous             [&app](const crow::Request& req,
344822d268cbSEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
344922d268cbSEd Tanous                    const std::string& systemName) {
34503ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
345145ca1b86SEd Tanous                 {
345245ca1b86SEd Tanous                     return;
345345ca1b86SEd Tanous                 }
345425b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
34557f3e84a1SEd Tanous                 {
34567f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
34577f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
34587f3e84a1SEd Tanous                                                systemName);
34597f3e84a1SEd Tanous                     return;
34607f3e84a1SEd Tanous                 }
3461253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
346222d268cbSEd Tanous                 {
346322d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
346422d268cbSEd Tanous                                                systemName);
346522d268cbSEd Tanous                     return;
346622d268cbSEd Tanous                 }
3467599b9af3SAlexander Hansen                 dBusLogServiceActionsClear(asyncResp);
34687e860f15SJohn Edward Broadbent             });
3469cb92c03bSAndrew Geissler }
3470a3316fc6SZhikuiRen 
3471a3316fc6SZhikuiRen /****************************************************
3472a3316fc6SZhikuiRen  * Redfish PostCode interfaces
3473a3316fc6SZhikuiRen  * using DBUS interface: getPostCodesTS
3474a3316fc6SZhikuiRen  ******************************************************/
34757e860f15SJohn Edward Broadbent inline void requestRoutesPostCodesLogService(App& app)
3476a3316fc6SZhikuiRen {
347722d268cbSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/PostCodes/")
3478ed398213SEd Tanous         .privileges(redfish::privileges::getLogService)
3479*bd79bce8SPatrick Williams         .methods(
3480*bd79bce8SPatrick Williams             boost::beast::http::verb::
3481*bd79bce8SPatrick Williams                 get)([&app](const crow::Request& req,
348222d268cbSEd Tanous                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
348322d268cbSEd Tanous                             const std::string& systemName) {
34843ba00073SCarson Labrado             if (!redfish::setUpRedfishRoute(app, req, asyncResp))
348545ca1b86SEd Tanous             {
348645ca1b86SEd Tanous                 return;
348745ca1b86SEd Tanous             }
348825b54dbaSEd Tanous             if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
34897f3e84a1SEd Tanous             {
34907f3e84a1SEd Tanous                 // Option currently returns no systems.  TBD
34917f3e84a1SEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
34927f3e84a1SEd Tanous                                            systemName);
34937f3e84a1SEd Tanous                 return;
34947f3e84a1SEd Tanous             }
3495253f11b8SEd Tanous             if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
349622d268cbSEd Tanous             {
349722d268cbSEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
349822d268cbSEd Tanous                                            systemName);
349922d268cbSEd Tanous                 return;
350022d268cbSEd Tanous             }
35011476687dSEd Tanous             asyncResp->res.jsonValue["@odata.id"] =
3502253f11b8SEd Tanous                 std::format("/redfish/v1/Systems/{}/LogServices/PostCodes",
3503253f11b8SEd Tanous                             BMCWEB_REDFISH_SYSTEM_URI_NAME);
35041476687dSEd Tanous             asyncResp->res.jsonValue["@odata.type"] =
3505b25644a1SJanet Adkins                 "#LogService.v1_2_0.LogService";
35061476687dSEd Tanous             asyncResp->res.jsonValue["Name"] = "POST Code Log Service";
35071476687dSEd Tanous             asyncResp->res.jsonValue["Description"] = "POST Code Log Service";
3508ed34a4adSEd Tanous             asyncResp->res.jsonValue["Id"] = "PostCodes";
3509539d8c6bSEd Tanous             asyncResp->res.jsonValue["OverWritePolicy"] =
3510539d8c6bSEd Tanous                 log_service::OverWritePolicy::WrapsWhenFull;
3511*bd79bce8SPatrick Williams             asyncResp->res.jsonValue["Entries"]["@odata.id"] = std::format(
3512*bd79bce8SPatrick Williams                 "/redfish/v1/Systems/{}/LogServices/PostCodes/Entries",
3513253f11b8SEd Tanous                 BMCWEB_REDFISH_SYSTEM_URI_NAME);
35147c8c4058STejas Patil 
35157c8c4058STejas Patil             std::pair<std::string, std::string> redfishDateTimeOffset =
35162b82937eSEd Tanous                 redfish::time_utils::getDateTimeOffsetNow();
35170fda0f12SGeorge Liu             asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
35187c8c4058STejas Patil             asyncResp->res.jsonValue["DateTimeLocalOffset"] =
35197c8c4058STejas Patil                 redfishDateTimeOffset.second;
35207c8c4058STejas Patil 
352120fa6a2cSEd Tanous             asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"]
352220fa6a2cSEd Tanous                                     ["target"] = std::format(
3523253f11b8SEd Tanous                 "/redfish/v1/Systems/{}/LogServices/PostCodes/Actions/LogService.ClearLog",
352420fa6a2cSEd Tanous                 BMCWEB_REDFISH_SYSTEM_URI_NAME);
35257e860f15SJohn Edward Broadbent         });
3526a3316fc6SZhikuiRen }
3527a3316fc6SZhikuiRen 
35287e860f15SJohn Edward Broadbent inline void requestRoutesPostCodesClear(App& app)
3529a3316fc6SZhikuiRen {
35300fda0f12SGeorge Liu     BMCWEB_ROUTE(
35310fda0f12SGeorge Liu         app,
353222d268cbSEd Tanous         "/redfish/v1/Systems/<str>/LogServices/PostCodes/Actions/LogService.ClearLog/")
3533ed398213SEd Tanous         // The following privilege is incorrect;  It should be ConfigureManager
3534ed398213SEd Tanous         //.privileges(redfish::privileges::postLogService)
3535432a890cSEd Tanous         .privileges({{"ConfigureComponents"}})
35367e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
353745ca1b86SEd Tanous             [&app](const crow::Request& req,
353822d268cbSEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
353922d268cbSEd Tanous                    const std::string& systemName) {
35403ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
354145ca1b86SEd Tanous                 {
354245ca1b86SEd Tanous                     return;
354345ca1b86SEd Tanous                 }
354425b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
35457f3e84a1SEd Tanous                 {
35467f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
35477f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
35487f3e84a1SEd Tanous                                                systemName);
35497f3e84a1SEd Tanous                     return;
35507f3e84a1SEd Tanous                 }
3551253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
355222d268cbSEd Tanous                 {
355322d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
355422d268cbSEd Tanous                                                systemName);
355522d268cbSEd Tanous                     return;
355622d268cbSEd Tanous                 }
355762598e31SEd Tanous                 BMCWEB_LOG_DEBUG("Do delete all postcodes entries.");
3558a3316fc6SZhikuiRen 
3559a3316fc6SZhikuiRen                 // Make call to post-code service to request clear all
3560a3316fc6SZhikuiRen                 crow::connections::systemBus->async_method_call(
35615e7e2dc5SEd Tanous                     [asyncResp](const boost::system::error_code& ec) {
3562a3316fc6SZhikuiRen                         if (ec)
3563a3316fc6SZhikuiRen                         {
3564a3316fc6SZhikuiRen                             // TODO Handle for specific error code
3565*bd79bce8SPatrick Williams                             BMCWEB_LOG_ERROR(
3566*bd79bce8SPatrick Williams                                 "doClearPostCodes resp_handler got error {}",
356762598e31SEd Tanous                                 ec);
3568*bd79bce8SPatrick Williams                             asyncResp->res.result(boost::beast::http::status::
3569*bd79bce8SPatrick Williams                                                       internal_server_error);
3570a3316fc6SZhikuiRen                             messages::internalError(asyncResp->res);
3571a3316fc6SZhikuiRen                             return;
3572a3316fc6SZhikuiRen                         }
357318fc70c0STony Lee                         messages::success(asyncResp->res);
3574a3316fc6SZhikuiRen                     },
357515124765SJonathan Doman                     "xyz.openbmc_project.State.Boot.PostCode0",
357615124765SJonathan Doman                     "/xyz/openbmc_project/State/Boot/PostCode0",
3577a3316fc6SZhikuiRen                     "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
35787e860f15SJohn Edward Broadbent             });
3579a3316fc6SZhikuiRen }
3580a3316fc6SZhikuiRen 
35816f284d24SJiaqing Zhao /**
35826f284d24SJiaqing Zhao  * @brief Parse post code ID and get the current value and index value
35836f284d24SJiaqing Zhao  *        eg: postCodeID=B1-2, currentValue=1, index=2
35846f284d24SJiaqing Zhao  *
35856f284d24SJiaqing Zhao  * @param[in]  postCodeID     Post Code ID
35866f284d24SJiaqing Zhao  * @param[out] currentValue   Current value
35876f284d24SJiaqing Zhao  * @param[out] index          Index value
35886f284d24SJiaqing Zhao  *
35896f284d24SJiaqing Zhao  * @return bool true if the parsing is successful, false the parsing fails
35906f284d24SJiaqing Zhao  */
35916f056f24SEd Tanous inline bool parsePostCode(std::string_view postCodeID, uint64_t& currentValue,
3592df254f2cSEd Tanous                           uint16_t& index)
35936f284d24SJiaqing Zhao {
35946f284d24SJiaqing Zhao     std::vector<std::string> split;
359550ebd4afSEd Tanous     bmcweb::split(split, postCodeID, '-');
35966f056f24SEd Tanous     if (split.size() != 2)
35976f056f24SEd Tanous     {
35986f056f24SEd Tanous         return false;
35996f056f24SEd Tanous     }
36006f056f24SEd Tanous     std::string_view postCodeNumber = split[0];
36016f056f24SEd Tanous     if (postCodeNumber.size() < 2)
36026f056f24SEd Tanous     {
36036f056f24SEd Tanous         return false;
36046f056f24SEd Tanous     }
36056f056f24SEd Tanous     if (postCodeNumber[0] != 'B')
36066f056f24SEd Tanous     {
36076f056f24SEd Tanous         return false;
36086f056f24SEd Tanous     }
36096f056f24SEd Tanous     postCodeNumber.remove_prefix(1);
3610*bd79bce8SPatrick Williams     auto [ptrIndex, ecIndex] =
3611*bd79bce8SPatrick Williams         std::from_chars(postCodeNumber.begin(), postCodeNumber.end(), index);
36126f056f24SEd Tanous     if (ptrIndex != postCodeNumber.end() || ecIndex != std::errc())
36136f284d24SJiaqing Zhao     {
36146f284d24SJiaqing Zhao         return false;
36156f284d24SJiaqing Zhao     }
36166f284d24SJiaqing Zhao 
36176f056f24SEd Tanous     std::string_view postCodeIndex = split[1];
36186f284d24SJiaqing Zhao 
36196f056f24SEd Tanous     auto [ptrValue, ecValue] = std::from_chars(
36206f056f24SEd Tanous         postCodeIndex.begin(), postCodeIndex.end(), currentValue);
36216f284d24SJiaqing Zhao 
36226f056f24SEd Tanous     return ptrValue == postCodeIndex.end() && ecValue == std::errc();
36236f284d24SJiaqing Zhao }
36246f284d24SJiaqing Zhao 
36256f284d24SJiaqing Zhao static bool fillPostCodeEntry(
3626ac106bf6SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
36276c9a279eSManojkiran Eda     const boost::container::flat_map<
36286c9a279eSManojkiran Eda         uint64_t, std::tuple<uint64_t, std::vector<uint8_t>>>& postcode,
3629a3316fc6SZhikuiRen     const uint16_t bootIndex, const uint64_t codeIndex = 0,
3630a3316fc6SZhikuiRen     const uint64_t skip = 0, const uint64_t top = 0)
3631a3316fc6SZhikuiRen {
3632a3316fc6SZhikuiRen     // Get the Message from the MessageRegistry
3633fffb8c1fSEd Tanous     const registries::Message* message =
3634fffb8c1fSEd Tanous         registries::getMessage("OpenBMC.0.2.BIOSPOSTCode");
3635dc8cfa66SEd Tanous     if (message == nullptr)
3636dc8cfa66SEd Tanous     {
3637dc8cfa66SEd Tanous         BMCWEB_LOG_ERROR("Couldn't find known message?");
3638dc8cfa66SEd Tanous         return false;
3639dc8cfa66SEd Tanous     }
3640a3316fc6SZhikuiRen     uint64_t currentCodeIndex = 0;
3641a3316fc6SZhikuiRen     uint64_t firstCodeTimeUs = 0;
36426c9a279eSManojkiran Eda     for (const std::pair<uint64_t, std::tuple<uint64_t, std::vector<uint8_t>>>&
36436c9a279eSManojkiran Eda              code : postcode)
3644a3316fc6SZhikuiRen     {
3645a3316fc6SZhikuiRen         currentCodeIndex++;
3646a3316fc6SZhikuiRen         std::string postcodeEntryID =
3647a3316fc6SZhikuiRen             "B" + std::to_string(bootIndex) + "-" +
3648a3316fc6SZhikuiRen             std::to_string(currentCodeIndex); // 1 based index in EntryID string
3649a3316fc6SZhikuiRen 
3650a3316fc6SZhikuiRen         uint64_t usecSinceEpoch = code.first;
3651a3316fc6SZhikuiRen         uint64_t usTimeOffset = 0;
3652a3316fc6SZhikuiRen 
3653a3316fc6SZhikuiRen         if (1 == currentCodeIndex)
3654a3316fc6SZhikuiRen         { // already incremented
3655a3316fc6SZhikuiRen             firstCodeTimeUs = code.first;
3656a3316fc6SZhikuiRen         }
3657a3316fc6SZhikuiRen         else
3658a3316fc6SZhikuiRen         {
3659a3316fc6SZhikuiRen             usTimeOffset = code.first - firstCodeTimeUs;
3660a3316fc6SZhikuiRen         }
3661a3316fc6SZhikuiRen 
3662a3316fc6SZhikuiRen         // skip if no specific codeIndex is specified and currentCodeIndex does
3663a3316fc6SZhikuiRen         // not fall between top and skip
3664a3316fc6SZhikuiRen         if ((codeIndex == 0) &&
3665a3316fc6SZhikuiRen             (currentCodeIndex <= skip || currentCodeIndex > top))
3666a3316fc6SZhikuiRen         {
3667a3316fc6SZhikuiRen             continue;
3668a3316fc6SZhikuiRen         }
3669a3316fc6SZhikuiRen 
36704e0453b1SGunnar Mills         // skip if a specific codeIndex is specified and does not match the
3671a3316fc6SZhikuiRen         // currentIndex
3672a3316fc6SZhikuiRen         if ((codeIndex > 0) && (currentCodeIndex != codeIndex))
3673a3316fc6SZhikuiRen         {
3674a3316fc6SZhikuiRen             // This is done for simplicity. 1st entry is needed to calculate
3675a3316fc6SZhikuiRen             // time offset. To improve efficiency, one can get to the entry
3676a3316fc6SZhikuiRen             // directly (possibly with flatmap's nth method)
3677a3316fc6SZhikuiRen             continue;
3678a3316fc6SZhikuiRen         }
3679a3316fc6SZhikuiRen 
3680a3316fc6SZhikuiRen         // currentCodeIndex is within top and skip or equal to specified code
3681a3316fc6SZhikuiRen         // index
3682a3316fc6SZhikuiRen 
3683a3316fc6SZhikuiRen         // Get the Created time from the timestamp
3684a3316fc6SZhikuiRen         std::string entryTimeStr;
36852a025611SKonstantin Aladyshev         entryTimeStr = redfish::time_utils::getDateTimeUintUs(usecSinceEpoch);
3686a3316fc6SZhikuiRen 
3687a3316fc6SZhikuiRen         // assemble messageArgs: BootIndex, TimeOffset(100us), PostCode(hex)
3688a3316fc6SZhikuiRen         std::ostringstream hexCode;
3689a3316fc6SZhikuiRen         hexCode << "0x" << std::setfill('0') << std::setw(2) << std::hex
36906c9a279eSManojkiran Eda                 << std::get<0>(code.second);
3691a3316fc6SZhikuiRen         std::ostringstream timeOffsetStr;
3692a3316fc6SZhikuiRen         // Set Fixed -Point Notation
3693a3316fc6SZhikuiRen         timeOffsetStr << std::fixed;
3694a3316fc6SZhikuiRen         // Set precision to 4 digits
3695a3316fc6SZhikuiRen         timeOffsetStr << std::setprecision(4);
3696a3316fc6SZhikuiRen         // Add double to stream
3697a3316fc6SZhikuiRen         timeOffsetStr << static_cast<double>(usTimeOffset) / 1000 / 1000;
3698a3316fc6SZhikuiRen 
36991e6deaf6SEd Tanous         std::string bootIndexStr = std::to_string(bootIndex);
37001e6deaf6SEd Tanous         std::string timeOffsetString = timeOffsetStr.str();
37011e6deaf6SEd Tanous         std::string hexCodeStr = hexCode.str();
3702a3316fc6SZhikuiRen 
37031e6deaf6SEd Tanous         std::array<std::string_view, 3> messageArgs = {
37041e6deaf6SEd Tanous             bootIndexStr, timeOffsetString, hexCodeStr};
37051e6deaf6SEd Tanous 
37061e6deaf6SEd Tanous         std::string msg =
37071e6deaf6SEd Tanous             redfish::registries::fillMessageArgs(messageArgs, message->message);
37081e6deaf6SEd Tanous         if (msg.empty())
3709a3316fc6SZhikuiRen         {
37101e6deaf6SEd Tanous             messages::internalError(asyncResp->res);
37111e6deaf6SEd Tanous             return false;
3712a3316fc6SZhikuiRen         }
3713a3316fc6SZhikuiRen 
3714d4342a92STim Lee         // Get Severity template from message registry
3715d4342a92STim Lee         std::string severity;
3716d4342a92STim Lee         if (message != nullptr)
3717d4342a92STim Lee         {
37185f2b84eeSEd Tanous             severity = message->messageSeverity;
3719d4342a92STim Lee         }
3720d4342a92STim Lee 
37216f284d24SJiaqing Zhao         // Format entry
37226f284d24SJiaqing Zhao         nlohmann::json::object_t bmcLogEntry;
37239c11a172SVijay Lobo         bmcLogEntry["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
3724ef4c65b7SEd Tanous         bmcLogEntry["@odata.id"] = boost::urls::format(
3725253f11b8SEd Tanous             "/redfish/v1/Systems/{}/LogServices/PostCodes/Entries/{}",
3726253f11b8SEd Tanous             BMCWEB_REDFISH_SYSTEM_URI_NAME, postcodeEntryID);
372784afc48bSJason M. Bills         bmcLogEntry["Name"] = "POST Code Log Entry";
372884afc48bSJason M. Bills         bmcLogEntry["Id"] = postcodeEntryID;
372984afc48bSJason M. Bills         bmcLogEntry["Message"] = std::move(msg);
373084afc48bSJason M. Bills         bmcLogEntry["MessageId"] = "OpenBMC.0.2.BIOSPOSTCode";
37311e6deaf6SEd Tanous         bmcLogEntry["MessageArgs"] = messageArgs;
373284afc48bSJason M. Bills         bmcLogEntry["EntryType"] = "Event";
373384afc48bSJason M. Bills         bmcLogEntry["Severity"] = std::move(severity);
373484afc48bSJason M. Bills         bmcLogEntry["Created"] = entryTimeStr;
3735647b3cdcSGeorge Liu         if (!std::get<std::vector<uint8_t>>(code.second).empty())
3736647b3cdcSGeorge Liu         {
3737647b3cdcSGeorge Liu             bmcLogEntry["AdditionalDataURI"] =
3738253f11b8SEd Tanous                 std::format(
3739253f11b8SEd Tanous                     "/redfish/v1/Systems/{}/LogServices/PostCodes/Entries/",
3740253f11b8SEd Tanous                     BMCWEB_REDFISH_SYSTEM_URI_NAME) +
3741647b3cdcSGeorge Liu                 postcodeEntryID + "/attachment";
3742647b3cdcSGeorge Liu         }
37436f284d24SJiaqing Zhao 
37446f284d24SJiaqing Zhao         // codeIndex is only specified when querying single entry, return only
37456f284d24SJiaqing Zhao         // that entry in this case
37466f284d24SJiaqing Zhao         if (codeIndex != 0)
37476f284d24SJiaqing Zhao         {
3748ac106bf6SEd Tanous             asyncResp->res.jsonValue.update(bmcLogEntry);
37496f284d24SJiaqing Zhao             return true;
3750a3316fc6SZhikuiRen         }
37516f284d24SJiaqing Zhao 
3752ac106bf6SEd Tanous         nlohmann::json& logEntryArray = asyncResp->res.jsonValue["Members"];
3753b2ba3072SPatrick Williams         logEntryArray.emplace_back(std::move(bmcLogEntry));
37546f284d24SJiaqing Zhao     }
37556f284d24SJiaqing Zhao 
37566f284d24SJiaqing Zhao     // Return value is always false when querying multiple entries
37576f284d24SJiaqing Zhao     return false;
3758a3316fc6SZhikuiRen }
3759a3316fc6SZhikuiRen 
3760ac106bf6SEd Tanous static void
3761ac106bf6SEd Tanous     getPostCodeForEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
37626f284d24SJiaqing Zhao                         const std::string& entryId)
3763a3316fc6SZhikuiRen {
37646f284d24SJiaqing Zhao     uint16_t bootIndex = 0;
37656f284d24SJiaqing Zhao     uint64_t codeIndex = 0;
37666f284d24SJiaqing Zhao     if (!parsePostCode(entryId, codeIndex, bootIndex))
37676f284d24SJiaqing Zhao     {
37686f284d24SJiaqing Zhao         // Requested ID was not found
3769ac106bf6SEd Tanous         messages::resourceNotFound(asyncResp->res, "LogEntry", entryId);
37706f284d24SJiaqing Zhao         return;
37716f284d24SJiaqing Zhao     }
37726f284d24SJiaqing Zhao 
37736f284d24SJiaqing Zhao     if (bootIndex == 0 || codeIndex == 0)
37746f284d24SJiaqing Zhao     {
37756f284d24SJiaqing Zhao         // 0 is an invalid index
3776ac106bf6SEd Tanous         messages::resourceNotFound(asyncResp->res, "LogEntry", entryId);
37776f284d24SJiaqing Zhao         return;
37786f284d24SJiaqing Zhao     }
37796f284d24SJiaqing Zhao 
3780a3316fc6SZhikuiRen     crow::connections::systemBus->async_method_call(
3781ac106bf6SEd Tanous         [asyncResp, entryId, bootIndex,
37825e7e2dc5SEd Tanous          codeIndex](const boost::system::error_code& ec,
37836c9a279eSManojkiran Eda                     const boost::container::flat_map<
37846c9a279eSManojkiran Eda                         uint64_t, std::tuple<uint64_t, std::vector<uint8_t>>>&
37856c9a279eSManojkiran Eda                         postcode) {
3786a3316fc6SZhikuiRen             if (ec)
3787a3316fc6SZhikuiRen             {
378862598e31SEd Tanous                 BMCWEB_LOG_DEBUG("DBUS POST CODE PostCode response error");
3789ac106bf6SEd Tanous                 messages::internalError(asyncResp->res);
3790a3316fc6SZhikuiRen                 return;
3791a3316fc6SZhikuiRen             }
3792a3316fc6SZhikuiRen 
3793a3316fc6SZhikuiRen             if (postcode.empty())
3794a3316fc6SZhikuiRen             {
3795ac106bf6SEd Tanous                 messages::resourceNotFound(asyncResp->res, "LogEntry", entryId);
3796a3316fc6SZhikuiRen                 return;
3797a3316fc6SZhikuiRen             }
3798a3316fc6SZhikuiRen 
3799ac106bf6SEd Tanous             if (!fillPostCodeEntry(asyncResp, postcode, bootIndex, codeIndex))
38006f284d24SJiaqing Zhao             {
3801ac106bf6SEd Tanous                 messages::resourceNotFound(asyncResp->res, "LogEntry", entryId);
38026f284d24SJiaqing Zhao                 return;
38036f284d24SJiaqing Zhao             }
3804a3316fc6SZhikuiRen         },
380515124765SJonathan Doman         "xyz.openbmc_project.State.Boot.PostCode0",
380615124765SJonathan Doman         "/xyz/openbmc_project/State/Boot/PostCode0",
3807a3316fc6SZhikuiRen         "xyz.openbmc_project.State.Boot.PostCode", "GetPostCodesWithTimeStamp",
3808a3316fc6SZhikuiRen         bootIndex);
3809a3316fc6SZhikuiRen }
3810a3316fc6SZhikuiRen 
3811ac106bf6SEd Tanous static void
3812ac106bf6SEd Tanous     getPostCodeForBoot(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3813ac106bf6SEd Tanous                        const uint16_t bootIndex, const uint16_t bootCount,
3814ac106bf6SEd Tanous                        const uint64_t entryCount, size_t skip, size_t top)
3815a3316fc6SZhikuiRen {
3816a3316fc6SZhikuiRen     crow::connections::systemBus->async_method_call(
3817ac106bf6SEd Tanous         [asyncResp, bootIndex, bootCount, entryCount, skip,
38185e7e2dc5SEd Tanous          top](const boost::system::error_code& ec,
38196c9a279eSManojkiran Eda               const boost::container::flat_map<
38206c9a279eSManojkiran Eda                   uint64_t, std::tuple<uint64_t, std::vector<uint8_t>>>&
38216c9a279eSManojkiran Eda                   postcode) {
3822a3316fc6SZhikuiRen             if (ec)
3823a3316fc6SZhikuiRen             {
382462598e31SEd Tanous                 BMCWEB_LOG_DEBUG("DBUS POST CODE PostCode response error");
3825ac106bf6SEd Tanous                 messages::internalError(asyncResp->res);
3826a3316fc6SZhikuiRen                 return;
3827a3316fc6SZhikuiRen             }
3828a3316fc6SZhikuiRen 
3829a3316fc6SZhikuiRen             uint64_t endCount = entryCount;
3830a3316fc6SZhikuiRen             if (!postcode.empty())
3831a3316fc6SZhikuiRen             {
3832a3316fc6SZhikuiRen                 endCount = entryCount + postcode.size();
38333648c8beSEd Tanous                 if (skip < endCount && (top + skip) > entryCount)
3834a3316fc6SZhikuiRen                 {
3835*bd79bce8SPatrick Williams                     uint64_t thisBootSkip =
3836*bd79bce8SPatrick Williams                         std::max(static_cast<uint64_t>(skip), entryCount) -
38373648c8beSEd Tanous                         entryCount;
3838a3316fc6SZhikuiRen                     uint64_t thisBootTop =
38393648c8beSEd Tanous                         std::min(static_cast<uint64_t>(top + skip), endCount) -
38403648c8beSEd Tanous                         entryCount;
3841a3316fc6SZhikuiRen 
3842ac106bf6SEd Tanous                     fillPostCodeEntry(asyncResp, postcode, bootIndex, 0,
3843ac106bf6SEd Tanous                                       thisBootSkip, thisBootTop);
3844a3316fc6SZhikuiRen                 }
3845ac106bf6SEd Tanous                 asyncResp->res.jsonValue["Members@odata.count"] = endCount;
3846a3316fc6SZhikuiRen             }
3847a3316fc6SZhikuiRen 
3848a3316fc6SZhikuiRen             // continue to previous bootIndex
3849a3316fc6SZhikuiRen             if (bootIndex < bootCount)
3850a3316fc6SZhikuiRen             {
3851*bd79bce8SPatrick Williams                 getPostCodeForBoot(asyncResp,
3852*bd79bce8SPatrick Williams                                    static_cast<uint16_t>(bootIndex + 1),
3853a3316fc6SZhikuiRen                                    bootCount, endCount, skip, top);
3854a3316fc6SZhikuiRen             }
385581584abeSJiaqing Zhao             else if (skip + top < endCount)
3856a3316fc6SZhikuiRen             {
3857ac106bf6SEd Tanous                 asyncResp->res.jsonValue["Members@odata.nextLink"] =
3858253f11b8SEd Tanous                     std::format(
3859253f11b8SEd Tanous                         "/redfish/v1/Systems/{}/LogServices/PostCodes/Entries?$skip=",
3860253f11b8SEd Tanous                         BMCWEB_REDFISH_SYSTEM_URI_NAME) +
3861a3316fc6SZhikuiRen                     std::to_string(skip + top);
3862a3316fc6SZhikuiRen             }
3863a3316fc6SZhikuiRen         },
386415124765SJonathan Doman         "xyz.openbmc_project.State.Boot.PostCode0",
386515124765SJonathan Doman         "/xyz/openbmc_project/State/Boot/PostCode0",
3866a3316fc6SZhikuiRen         "xyz.openbmc_project.State.Boot.PostCode", "GetPostCodesWithTimeStamp",
3867a3316fc6SZhikuiRen         bootIndex);
3868a3316fc6SZhikuiRen }
3869a3316fc6SZhikuiRen 
38708d1b46d7Szhanghch05 static void
3871ac106bf6SEd Tanous     getCurrentBootNumber(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
38723648c8beSEd Tanous                          size_t skip, size_t top)
3873a3316fc6SZhikuiRen {
3874a3316fc6SZhikuiRen     uint64_t entryCount = 0;
38751e1e598dSJonathan Doman     sdbusplus::asio::getProperty<uint16_t>(
38761e1e598dSJonathan Doman         *crow::connections::systemBus,
38771e1e598dSJonathan Doman         "xyz.openbmc_project.State.Boot.PostCode0",
38781e1e598dSJonathan Doman         "/xyz/openbmc_project/State/Boot/PostCode0",
38791e1e598dSJonathan Doman         "xyz.openbmc_project.State.Boot.PostCode", "CurrentBootCycleCount",
3880*bd79bce8SPatrick Williams         [asyncResp, entryCount, skip,
3881*bd79bce8SPatrick Williams          top](const boost::system::error_code& ec, const uint16_t bootCount) {
3882a3316fc6SZhikuiRen             if (ec)
3883a3316fc6SZhikuiRen             {
388462598e31SEd Tanous                 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
3885ac106bf6SEd Tanous                 messages::internalError(asyncResp->res);
3886a3316fc6SZhikuiRen                 return;
3887a3316fc6SZhikuiRen             }
3888ac106bf6SEd Tanous             getPostCodeForBoot(asyncResp, 1, bootCount, entryCount, skip, top);
38891e1e598dSJonathan Doman         });
3890a3316fc6SZhikuiRen }
3891a3316fc6SZhikuiRen 
38927e860f15SJohn Edward Broadbent inline void requestRoutesPostCodesEntryCollection(App& app)
3893a3316fc6SZhikuiRen {
38947e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
389522d268cbSEd Tanous                  "/redfish/v1/Systems/<str>/LogServices/PostCodes/Entries/")
3896ed398213SEd Tanous         .privileges(redfish::privileges::getLogEntryCollection)
38977e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
389845ca1b86SEd Tanous             [&app](const crow::Request& req,
389922d268cbSEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
390022d268cbSEd Tanous                    const std::string& systemName) {
3901c937d2bfSEd Tanous                 query_param::QueryCapabilities capabilities = {
3902c937d2bfSEd Tanous                     .canDelegateTop = true,
3903c937d2bfSEd Tanous                     .canDelegateSkip = true,
3904c937d2bfSEd Tanous                 };
3905c937d2bfSEd Tanous                 query_param::Query delegatedQuery;
3906c937d2bfSEd Tanous                 if (!redfish::setUpRedfishRouteWithDelegation(
39073ba00073SCarson Labrado                         app, req, asyncResp, delegatedQuery, capabilities))
390845ca1b86SEd Tanous                 {
390945ca1b86SEd Tanous                     return;
391045ca1b86SEd Tanous                 }
391125b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
39127f3e84a1SEd Tanous                 {
39137f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
39147f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
39157f3e84a1SEd Tanous                                                systemName);
39167f3e84a1SEd Tanous                     return;
39177f3e84a1SEd Tanous                 }
391822d268cbSEd Tanous 
3919253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
392022d268cbSEd Tanous                 {
392122d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
392222d268cbSEd Tanous                                                systemName);
392322d268cbSEd Tanous                     return;
392422d268cbSEd Tanous                 }
3925a3316fc6SZhikuiRen                 asyncResp->res.jsonValue["@odata.type"] =
3926a3316fc6SZhikuiRen                     "#LogEntryCollection.LogEntryCollection";
3927*bd79bce8SPatrick Williams                 asyncResp->res.jsonValue["@odata.id"] = std::format(
3928*bd79bce8SPatrick Williams                     "/redfish/v1/Systems/{}/LogServices/PostCodes/Entries",
3929253f11b8SEd Tanous                     BMCWEB_REDFISH_SYSTEM_URI_NAME);
3930a3316fc6SZhikuiRen                 asyncResp->res.jsonValue["Name"] = "BIOS POST Code Log Entries";
3931a3316fc6SZhikuiRen                 asyncResp->res.jsonValue["Description"] =
3932a3316fc6SZhikuiRen                     "Collection of POST Code Log Entries";
3933a3316fc6SZhikuiRen                 asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
3934a3316fc6SZhikuiRen                 asyncResp->res.jsonValue["Members@odata.count"] = 0;
39353648c8beSEd Tanous                 size_t skip = delegatedQuery.skip.value_or(0);
3936*bd79bce8SPatrick Williams                 size_t top =
3937*bd79bce8SPatrick Williams                     delegatedQuery.top.value_or(query_param::Query::maxTop);
39383648c8beSEd Tanous                 getCurrentBootNumber(asyncResp, skip, top);
39397e860f15SJohn Edward Broadbent             });
3940a3316fc6SZhikuiRen }
3941a3316fc6SZhikuiRen 
3942647b3cdcSGeorge Liu inline void requestRoutesPostCodesEntryAdditionalData(App& app)
3943647b3cdcSGeorge Liu {
39440fda0f12SGeorge Liu     BMCWEB_ROUTE(
39450fda0f12SGeorge Liu         app,
394622d268cbSEd Tanous         "/redfish/v1/Systems/<str>/LogServices/PostCodes/Entries/<str>/attachment/")
3947647b3cdcSGeorge Liu         .privileges(redfish::privileges::getLogEntry)
3948*bd79bce8SPatrick Williams         .methods(
3949*bd79bce8SPatrick Williams             boost::beast::http::verb::
3950*bd79bce8SPatrick Williams                 get)([&app](const crow::Request& req,
3951647b3cdcSGeorge Liu                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
395222d268cbSEd Tanous                             const std::string& systemName,
3953647b3cdcSGeorge Liu                             const std::string& postCodeID) {
39543ba00073SCarson Labrado             if (!redfish::setUpRedfishRoute(app, req, asyncResp))
395545ca1b86SEd Tanous             {
395645ca1b86SEd Tanous                 return;
395745ca1b86SEd Tanous             }
395872e21377SMatt Spinler             if (!http_helpers::isContentTypeAllowed(
395999351cd8SEd Tanous                     req.getHeaderValue("Accept"),
39604a0e1a0cSEd Tanous                     http_helpers::ContentType::OctetStream, true))
3961647b3cdcSGeorge Liu             {
3962002d39b4SEd Tanous                 asyncResp->res.result(boost::beast::http::status::bad_request);
3963647b3cdcSGeorge Liu                 return;
3964647b3cdcSGeorge Liu             }
396525b54dbaSEd Tanous             if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
39667f3e84a1SEd Tanous             {
39677f3e84a1SEd Tanous                 // Option currently returns no systems.  TBD
39687f3e84a1SEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
39697f3e84a1SEd Tanous                                            systemName);
39707f3e84a1SEd Tanous                 return;
39717f3e84a1SEd Tanous             }
3972253f11b8SEd Tanous             if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
397322d268cbSEd Tanous             {
397422d268cbSEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
397522d268cbSEd Tanous                                            systemName);
397622d268cbSEd Tanous                 return;
397722d268cbSEd Tanous             }
3978647b3cdcSGeorge Liu 
3979647b3cdcSGeorge Liu             uint64_t currentValue = 0;
3980647b3cdcSGeorge Liu             uint16_t index = 0;
3981647b3cdcSGeorge Liu             if (!parsePostCode(postCodeID, currentValue, index))
3982647b3cdcSGeorge Liu             {
3983*bd79bce8SPatrick Williams                 messages::resourceNotFound(asyncResp->res, "LogEntry",
3984*bd79bce8SPatrick Williams                                            postCodeID);
3985647b3cdcSGeorge Liu                 return;
3986647b3cdcSGeorge Liu             }
3987647b3cdcSGeorge Liu 
3988647b3cdcSGeorge Liu             crow::connections::systemBus->async_method_call(
3989647b3cdcSGeorge Liu                 [asyncResp, postCodeID, currentValue](
39905e7e2dc5SEd Tanous                     const boost::system::error_code& ec,
3991*bd79bce8SPatrick Williams                     const std::vector<std::tuple<
3992*bd79bce8SPatrick Williams                         uint64_t, std::vector<uint8_t>>>& postcodes) {
3993647b3cdcSGeorge Liu                     if (ec.value() == EBADR)
3994647b3cdcSGeorge Liu                     {
3995002d39b4SEd Tanous                         messages::resourceNotFound(asyncResp->res, "LogEntry",
3996002d39b4SEd Tanous                                                    postCodeID);
3997647b3cdcSGeorge Liu                         return;
3998647b3cdcSGeorge Liu                     }
3999647b3cdcSGeorge Liu                     if (ec)
4000647b3cdcSGeorge Liu                     {
400162598e31SEd Tanous                         BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
4002647b3cdcSGeorge Liu                         messages::internalError(asyncResp->res);
4003647b3cdcSGeorge Liu                         return;
4004647b3cdcSGeorge Liu                     }
4005647b3cdcSGeorge Liu 
4006647b3cdcSGeorge Liu                     size_t value = static_cast<size_t>(currentValue) - 1;
4007*bd79bce8SPatrick Williams                     if (value == std::string::npos ||
4008*bd79bce8SPatrick Williams                         postcodes.size() < currentValue)
4009647b3cdcSGeorge Liu                     {
401062598e31SEd Tanous                         BMCWEB_LOG_WARNING("Wrong currentValue value");
4011002d39b4SEd Tanous                         messages::resourceNotFound(asyncResp->res, "LogEntry",
4012002d39b4SEd Tanous                                                    postCodeID);
4013647b3cdcSGeorge Liu                         return;
4014647b3cdcSGeorge Liu                     }
4015647b3cdcSGeorge Liu 
40169eb808c1SEd Tanous                     const auto& [tID, c] = postcodes[value];
401746ff87baSEd Tanous                     if (c.empty())
4018647b3cdcSGeorge Liu                     {
401962598e31SEd Tanous                         BMCWEB_LOG_WARNING("No found post code data");
4020002d39b4SEd Tanous                         messages::resourceNotFound(asyncResp->res, "LogEntry",
4021002d39b4SEd Tanous                                                    postCodeID);
4022647b3cdcSGeorge Liu                         return;
4023647b3cdcSGeorge Liu                     }
402446ff87baSEd Tanous                     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
402546ff87baSEd Tanous                     const char* d = reinterpret_cast<const char*>(c.data());
402646ff87baSEd Tanous                     std::string_view strData(d, c.size());
4027647b3cdcSGeorge Liu 
4028*bd79bce8SPatrick Williams                     asyncResp->res.addHeader(
4029*bd79bce8SPatrick Williams                         boost::beast::http::field::content_type,
4030647b3cdcSGeorge Liu                         "application/octet-stream");
4031d9f6c621SEd Tanous                     asyncResp->res.addHeader(
4032*bd79bce8SPatrick Williams                         boost::beast::http::field::content_transfer_encoding,
4033*bd79bce8SPatrick Williams                         "Base64");
403427b0cf90SEd Tanous                     asyncResp->res.write(crow::utility::base64encode(strData));
4035647b3cdcSGeorge Liu                 },
4036647b3cdcSGeorge Liu                 "xyz.openbmc_project.State.Boot.PostCode0",
4037647b3cdcSGeorge Liu                 "/xyz/openbmc_project/State/Boot/PostCode0",
4038*bd79bce8SPatrick Williams                 "xyz.openbmc_project.State.Boot.PostCode", "GetPostCodes",
4039*bd79bce8SPatrick Williams                 index);
4040647b3cdcSGeorge Liu         });
4041647b3cdcSGeorge Liu }
4042647b3cdcSGeorge Liu 
40437e860f15SJohn Edward Broadbent inline void requestRoutesPostCodesEntry(App& app)
4044a3316fc6SZhikuiRen {
40457e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
404622d268cbSEd Tanous         app, "/redfish/v1/Systems/<str>/LogServices/PostCodes/Entries/<str>/")
4047ed398213SEd Tanous         .privileges(redfish::privileges::getLogEntry)
40487e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
404945ca1b86SEd Tanous             [&app](const crow::Request& req,
40507e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
405122d268cbSEd Tanous                    const std::string& systemName, const std::string& targetID) {
40523ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
405345ca1b86SEd Tanous                 {
405445ca1b86SEd Tanous                     return;
405545ca1b86SEd Tanous                 }
405625b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
40577f3e84a1SEd Tanous                 {
40587f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
40597f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
40607f3e84a1SEd Tanous                                                systemName);
40617f3e84a1SEd Tanous                     return;
40627f3e84a1SEd Tanous                 }
4063253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
406422d268cbSEd Tanous                 {
406522d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
406622d268cbSEd Tanous                                                systemName);
406722d268cbSEd Tanous                     return;
406822d268cbSEd Tanous                 }
406922d268cbSEd Tanous 
40706f284d24SJiaqing Zhao                 getPostCodeForEntry(asyncResp, targetID);
40717e860f15SJohn Edward Broadbent             });
4072a3316fc6SZhikuiRen }
4073a3316fc6SZhikuiRen 
40741da66f75SEd Tanous } // namespace redfish
4075