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