xref: /openbmc/bmcweb/features/redfish/lib/log_services.hpp (revision afc474aef028555fc0a6deb425bdad86f0a34db6)
11da66f75SEd Tanous /*
26be832e2SEd Tanous Copyright (c) 2018 Intel Corporation
36be832e2SEd Tanous 
46be832e2SEd Tanous Licensed under the Apache License, Version 2.0 (the "License");
56be832e2SEd Tanous you may not use this file except in compliance with the License.
66be832e2SEd Tanous You may obtain a copy of the License at
76be832e2SEd Tanous 
86be832e2SEd Tanous       http://www.apache.org/licenses/LICENSE-2.0
96be832e2SEd Tanous 
106be832e2SEd Tanous Unless required by applicable law or agreed to in writing, software
116be832e2SEd Tanous distributed under the License is distributed on an "AS IS" BASIS,
126be832e2SEd Tanous WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136be832e2SEd Tanous See the License for the specific language governing permissions and
146be832e2SEd Tanous limitations under the License.
151da66f75SEd Tanous */
161da66f75SEd Tanous #pragma once
171da66f75SEd Tanous 
183ccb3adbSEd Tanous #include "app.hpp"
197a1dbc48SGeorge Liu #include "dbus_utility.hpp"
203ccb3adbSEd Tanous #include "error_messages.hpp"
2168dd075aSAsmitha Karunanithi #include "generated/enums/log_entry.hpp"
22539d8c6bSEd Tanous #include "generated/enums/log_service.hpp"
23b7028ebfSSpencer Ku #include "gzfile.hpp"
24647b3cdcSGeorge Liu #include "http_utility.hpp"
25b7028ebfSSpencer Ku #include "human_sort.hpp"
263ccb3adbSEd Tanous #include "query.hpp"
274851d45dSJason M. Bills #include "registries.hpp"
284851d45dSJason M. Bills #include "registries/base_message_registry.hpp"
294851d45dSJason M. Bills #include "registries/openbmc_message_registry.hpp"
303ccb3adbSEd Tanous #include "registries/privilege_registry.hpp"
3146229577SJames Feist #include "task.hpp"
325b90429aSEd Tanous #include "task_messages.hpp"
33262dcc1cSAlexander Hansen #include "utils/dbus_event_log_entry.hpp"
343ccb3adbSEd Tanous #include "utils/dbus_utils.hpp"
355b90429aSEd Tanous #include "utils/json_utils.hpp"
363ccb3adbSEd Tanous #include "utils/time_utils.hpp"
371da66f75SEd Tanous 
3875e8e218SMyung Bae #include <systemd/sd-id128.h>
398e31778eSAsmitha Karunanithi #include <tinyxml2.h>
40400fd1fbSAdriana Kobylak #include <unistd.h>
41e1f26343SJason M. Bills 
4207c8c20dSEd Tanous #include <boost/beast/http/verb.hpp>
431da66f75SEd Tanous #include <boost/container/flat_map.hpp>
441ddcf01aSJason M. Bills #include <boost/system/linux_error.hpp>
45ef4c65b7SEd Tanous #include <boost/url/format.hpp>
46d1bde9e5SKrzysztof Grobelny #include <sdbusplus/asio/property.hpp>
47d1bde9e5SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp>
481214b7e7SGunnar Mills 
497a1dbc48SGeorge Liu #include <array>
50647b3cdcSGeorge Liu #include <charconv>
51b5f288d2SAbhilash Raju #include <cstddef>
524418c7f0SJames Feist #include <filesystem>
5318f8f608SEd Tanous #include <iterator>
5475710de2SXiaochao Ma #include <optional>
553544d2a7SEd Tanous #include <ranges>
5626702d01SEd Tanous #include <span>
5718f8f608SEd Tanous #include <string>
58cd225da8SJason M. Bills #include <string_view>
59abf2add6SEd Tanous #include <variant>
601da66f75SEd Tanous 
611da66f75SEd Tanous namespace redfish
621da66f75SEd Tanous {
631da66f75SEd Tanous 
6489492a15SPatrick Williams constexpr const char* crashdumpObject = "com.intel.crashdump";
6589492a15SPatrick Williams constexpr const char* crashdumpPath = "/com/intel/crashdump";
6689492a15SPatrick Williams constexpr const char* crashdumpInterface = "com.intel.crashdump";
6789492a15SPatrick Williams constexpr const char* deleteAllInterface =
685b61b5e8SJason M. Bills     "xyz.openbmc_project.Collection.DeleteAll";
6989492a15SPatrick Williams constexpr const char* crashdumpOnDemandInterface =
70424c4176SJason M. Bills     "com.intel.crashdump.OnDemand";
7189492a15SPatrick Williams constexpr const char* crashdumpTelemetryInterface =
726eda7685SKenny L. Ku     "com.intel.crashdump.Telemetry";
731da66f75SEd Tanous 
748e31778eSAsmitha Karunanithi enum class DumpCreationProgress
758e31778eSAsmitha Karunanithi {
768e31778eSAsmitha Karunanithi     DUMP_CREATE_SUCCESS,
778e31778eSAsmitha Karunanithi     DUMP_CREATE_FAILED,
788e31778eSAsmitha Karunanithi     DUMP_CREATE_INPROGRESS
798e31778eSAsmitha Karunanithi };
808e31778eSAsmitha Karunanithi 
81f6150403SJames Feist namespace fs = std::filesystem;
821da66f75SEd Tanous 
83cb92c03bSAndrew Geissler inline std::string translateSeverityDbusToRedfish(const std::string& s)
84cb92c03bSAndrew Geissler {
85d4d25793SEd Tanous     if ((s == "xyz.openbmc_project.Logging.Entry.Level.Alert") ||
86d4d25793SEd Tanous         (s == "xyz.openbmc_project.Logging.Entry.Level.Critical") ||
87d4d25793SEd Tanous         (s == "xyz.openbmc_project.Logging.Entry.Level.Emergency") ||
88d4d25793SEd Tanous         (s == "xyz.openbmc_project.Logging.Entry.Level.Error"))
89cb92c03bSAndrew Geissler     {
90cb92c03bSAndrew Geissler         return "Critical";
91cb92c03bSAndrew Geissler     }
923174e4dfSEd Tanous     if ((s == "xyz.openbmc_project.Logging.Entry.Level.Debug") ||
93d4d25793SEd Tanous         (s == "xyz.openbmc_project.Logging.Entry.Level.Informational") ||
94d4d25793SEd Tanous         (s == "xyz.openbmc_project.Logging.Entry.Level.Notice"))
95cb92c03bSAndrew Geissler     {
96cb92c03bSAndrew Geissler         return "OK";
97cb92c03bSAndrew Geissler     }
983174e4dfSEd Tanous     if (s == "xyz.openbmc_project.Logging.Entry.Level.Warning")
99cb92c03bSAndrew Geissler     {
100cb92c03bSAndrew Geissler         return "Warning";
101cb92c03bSAndrew Geissler     }
102cb92c03bSAndrew Geissler     return "";
103cb92c03bSAndrew Geissler }
104cb92c03bSAndrew Geissler 
1059017faf2SAbhishek Patel inline std::optional<bool> getProviderNotifyAction(const std::string& notify)
1069017faf2SAbhishek Patel {
1079017faf2SAbhishek Patel     std::optional<bool> notifyAction;
1089017faf2SAbhishek Patel     if (notify == "xyz.openbmc_project.Logging.Entry.Notify.Notify")
1099017faf2SAbhishek Patel     {
1109017faf2SAbhishek Patel         notifyAction = true;
1119017faf2SAbhishek Patel     }
1129017faf2SAbhishek Patel     else if (notify == "xyz.openbmc_project.Logging.Entry.Notify.Inhibit")
1139017faf2SAbhishek Patel     {
1149017faf2SAbhishek Patel         notifyAction = false;
1159017faf2SAbhishek Patel     }
1169017faf2SAbhishek Patel 
1179017faf2SAbhishek Patel     return notifyAction;
1189017faf2SAbhishek Patel }
1199017faf2SAbhishek Patel 
12018f8f608SEd Tanous inline std::string getDumpPath(std::string_view dumpType)
12118f8f608SEd Tanous {
12218f8f608SEd Tanous     std::string dbusDumpPath = "/xyz/openbmc_project/dump/";
12318f8f608SEd Tanous     std::ranges::transform(dumpType, std::back_inserter(dbusDumpPath),
12418f8f608SEd Tanous                            bmcweb::asciiToLower);
12518f8f608SEd Tanous 
12618f8f608SEd Tanous     return dbusDumpPath;
12718f8f608SEd Tanous }
12818f8f608SEd Tanous 
129055713e4SEd Tanous inline bool getUniqueEntryID(const std::string& logEntry, std::string& entryID,
130e85d6b16SJason M. Bills                              const bool firstEntry = true)
13195820184SJason M. Bills {
132271584abSEd Tanous     static time_t prevTs = 0;
13395820184SJason M. Bills     static int index = 0;
134e85d6b16SJason M. Bills     if (firstEntry)
135e85d6b16SJason M. Bills     {
136e85d6b16SJason M. Bills         prevTs = 0;
137e85d6b16SJason M. Bills     }
138e85d6b16SJason M. Bills 
13995820184SJason M. Bills     // Get the entry timestamp
140271584abSEd Tanous     std::time_t curTs = 0;
14195820184SJason M. Bills     std::tm timeStruct = {};
14295820184SJason M. Bills     std::istringstream entryStream(logEntry);
14395820184SJason M. Bills     if (entryStream >> std::get_time(&timeStruct, "%Y-%m-%dT%H:%M:%S"))
14495820184SJason M. Bills     {
14595820184SJason M. Bills         curTs = std::mktime(&timeStruct);
14695820184SJason M. Bills     }
14795820184SJason M. Bills     // If the timestamp isn't unique, increment the index
14895820184SJason M. Bills     if (curTs == prevTs)
14995820184SJason M. Bills     {
15095820184SJason M. Bills         index++;
15195820184SJason M. Bills     }
15295820184SJason M. Bills     else
15395820184SJason M. Bills     {
15495820184SJason M. Bills         // Otherwise, reset it
15595820184SJason M. Bills         index = 0;
15695820184SJason M. Bills     }
15795820184SJason M. Bills     // Save the timestamp
15895820184SJason M. Bills     prevTs = curTs;
15995820184SJason M. Bills 
16095820184SJason M. Bills     entryID = std::to_string(curTs);
16195820184SJason M. Bills     if (index > 0)
16295820184SJason M. Bills     {
16395820184SJason M. Bills         entryID += "_" + std::to_string(index);
16495820184SJason M. Bills     }
16595820184SJason M. Bills     return true;
16695820184SJason M. Bills }
16795820184SJason M. Bills 
1684ff0f1f4SEd Tanous inline bool
16995820184SJason M. Bills     getRedfishLogFiles(std::vector<std::filesystem::path>& redfishLogFiles)
17095820184SJason M. Bills {
17195820184SJason M. Bills     static const std::filesystem::path redfishLogDir = "/var/log";
17295820184SJason M. Bills     static const std::string redfishLogFilename = "redfish";
17395820184SJason M. Bills 
17495820184SJason M. Bills     // Loop through the directory looking for redfish log files
17595820184SJason M. Bills     for (const std::filesystem::directory_entry& dirEnt :
17695820184SJason M. Bills          std::filesystem::directory_iterator(redfishLogDir))
17795820184SJason M. Bills     {
17895820184SJason M. Bills         // If we find a redfish log file, save the path
17995820184SJason M. Bills         std::string filename = dirEnt.path().filename();
18011ba3979SEd Tanous         if (filename.starts_with(redfishLogFilename))
18195820184SJason M. Bills         {
18295820184SJason M. Bills             redfishLogFiles.emplace_back(redfishLogDir / filename);
18395820184SJason M. Bills         }
18495820184SJason M. Bills     }
18595820184SJason M. Bills     // As the log files rotate, they are appended with a ".#" that is higher for
18695820184SJason M. Bills     // the older logs. Since we don't expect more than 10 log files, we
18795820184SJason M. Bills     // can just sort the list to get them in order from newest to oldest
1883544d2a7SEd Tanous     std::ranges::sort(redfishLogFiles);
18995820184SJason M. Bills 
19095820184SJason M. Bills     return !redfishLogFiles.empty();
19195820184SJason M. Bills }
19295820184SJason M. Bills 
19368dd075aSAsmitha Karunanithi inline log_entry::OriginatorTypes
19468dd075aSAsmitha Karunanithi     mapDbusOriginatorTypeToRedfish(const std::string& originatorType)
19568dd075aSAsmitha Karunanithi {
19668dd075aSAsmitha Karunanithi     if (originatorType ==
19768dd075aSAsmitha Karunanithi         "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Client")
19868dd075aSAsmitha Karunanithi     {
19968dd075aSAsmitha Karunanithi         return log_entry::OriginatorTypes::Client;
20068dd075aSAsmitha Karunanithi     }
20168dd075aSAsmitha Karunanithi     if (originatorType ==
20268dd075aSAsmitha Karunanithi         "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Internal")
20368dd075aSAsmitha Karunanithi     {
20468dd075aSAsmitha Karunanithi         return log_entry::OriginatorTypes::Internal;
20568dd075aSAsmitha Karunanithi     }
20668dd075aSAsmitha Karunanithi     if (originatorType ==
20768dd075aSAsmitha Karunanithi         "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.SupportingService")
20868dd075aSAsmitha Karunanithi     {
20968dd075aSAsmitha Karunanithi         return log_entry::OriginatorTypes::SupportingService;
21068dd075aSAsmitha Karunanithi     }
21168dd075aSAsmitha Karunanithi     return log_entry::OriginatorTypes::Invalid;
21268dd075aSAsmitha Karunanithi }
21368dd075aSAsmitha Karunanithi 
214aefe3786SClaire Weinan inline void parseDumpEntryFromDbusObject(
2152d613eb6SJiaqing Zhao     const dbus::utility::ManagedObjectType::value_type& object,
216c6fecdabSClaire Weinan     std::string& dumpStatus, uint64_t& size, uint64_t& timestampUs,
21768dd075aSAsmitha Karunanithi     std::string& originatorId, log_entry::OriginatorTypes& originatorType,
218aefe3786SClaire Weinan     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
219aefe3786SClaire Weinan {
220aefe3786SClaire Weinan     for (const auto& interfaceMap : object.second)
221aefe3786SClaire Weinan     {
222aefe3786SClaire Weinan         if (interfaceMap.first == "xyz.openbmc_project.Common.Progress")
223aefe3786SClaire Weinan         {
224aefe3786SClaire Weinan             for (const auto& propertyMap : interfaceMap.second)
225aefe3786SClaire Weinan             {
226aefe3786SClaire Weinan                 if (propertyMap.first == "Status")
227aefe3786SClaire Weinan                 {
228aefe3786SClaire Weinan                     const auto* status =
229aefe3786SClaire Weinan                         std::get_if<std::string>(&propertyMap.second);
230aefe3786SClaire Weinan                     if (status == nullptr)
231aefe3786SClaire Weinan                     {
232aefe3786SClaire Weinan                         messages::internalError(asyncResp->res);
233aefe3786SClaire Weinan                         break;
234aefe3786SClaire Weinan                     }
235aefe3786SClaire Weinan                     dumpStatus = *status;
236aefe3786SClaire Weinan                 }
237aefe3786SClaire Weinan             }
238aefe3786SClaire Weinan         }
239aefe3786SClaire Weinan         else if (interfaceMap.first == "xyz.openbmc_project.Dump.Entry")
240aefe3786SClaire Weinan         {
241aefe3786SClaire Weinan             for (const auto& propertyMap : interfaceMap.second)
242aefe3786SClaire Weinan             {
243aefe3786SClaire Weinan                 if (propertyMap.first == "Size")
244aefe3786SClaire Weinan                 {
245aefe3786SClaire Weinan                     const auto* sizePtr =
246aefe3786SClaire Weinan                         std::get_if<uint64_t>(&propertyMap.second);
247aefe3786SClaire Weinan                     if (sizePtr == nullptr)
248aefe3786SClaire Weinan                     {
249aefe3786SClaire Weinan                         messages::internalError(asyncResp->res);
250aefe3786SClaire Weinan                         break;
251aefe3786SClaire Weinan                     }
252aefe3786SClaire Weinan                     size = *sizePtr;
253aefe3786SClaire Weinan                     break;
254aefe3786SClaire Weinan                 }
255aefe3786SClaire Weinan             }
256aefe3786SClaire Weinan         }
257aefe3786SClaire Weinan         else if (interfaceMap.first == "xyz.openbmc_project.Time.EpochTime")
258aefe3786SClaire Weinan         {
259aefe3786SClaire Weinan             for (const auto& propertyMap : interfaceMap.second)
260aefe3786SClaire Weinan             {
261aefe3786SClaire Weinan                 if (propertyMap.first == "Elapsed")
262aefe3786SClaire Weinan                 {
263aefe3786SClaire Weinan                     const uint64_t* usecsTimeStamp =
264aefe3786SClaire Weinan                         std::get_if<uint64_t>(&propertyMap.second);
265aefe3786SClaire Weinan                     if (usecsTimeStamp == nullptr)
266aefe3786SClaire Weinan                     {
267aefe3786SClaire Weinan                         messages::internalError(asyncResp->res);
268aefe3786SClaire Weinan                         break;
269aefe3786SClaire Weinan                     }
270c6fecdabSClaire Weinan                     timestampUs = *usecsTimeStamp;
271aefe3786SClaire Weinan                     break;
272aefe3786SClaire Weinan                 }
273aefe3786SClaire Weinan             }
274aefe3786SClaire Weinan         }
27568dd075aSAsmitha Karunanithi         else if (interfaceMap.first ==
27668dd075aSAsmitha Karunanithi                  "xyz.openbmc_project.Common.OriginatedBy")
27768dd075aSAsmitha Karunanithi         {
27868dd075aSAsmitha Karunanithi             for (const auto& propertyMap : interfaceMap.second)
27968dd075aSAsmitha Karunanithi             {
28068dd075aSAsmitha Karunanithi                 if (propertyMap.first == "OriginatorId")
28168dd075aSAsmitha Karunanithi                 {
28268dd075aSAsmitha Karunanithi                     const std::string* id =
28368dd075aSAsmitha Karunanithi                         std::get_if<std::string>(&propertyMap.second);
28468dd075aSAsmitha Karunanithi                     if (id == nullptr)
28568dd075aSAsmitha Karunanithi                     {
28668dd075aSAsmitha Karunanithi                         messages::internalError(asyncResp->res);
28768dd075aSAsmitha Karunanithi                         break;
28868dd075aSAsmitha Karunanithi                     }
28968dd075aSAsmitha Karunanithi                     originatorId = *id;
29068dd075aSAsmitha Karunanithi                 }
29168dd075aSAsmitha Karunanithi 
29268dd075aSAsmitha Karunanithi                 if (propertyMap.first == "OriginatorType")
29368dd075aSAsmitha Karunanithi                 {
29468dd075aSAsmitha Karunanithi                     const std::string* type =
29568dd075aSAsmitha Karunanithi                         std::get_if<std::string>(&propertyMap.second);
29668dd075aSAsmitha Karunanithi                     if (type == nullptr)
29768dd075aSAsmitha Karunanithi                     {
29868dd075aSAsmitha Karunanithi                         messages::internalError(asyncResp->res);
29968dd075aSAsmitha Karunanithi                         break;
30068dd075aSAsmitha Karunanithi                     }
30168dd075aSAsmitha Karunanithi 
30268dd075aSAsmitha Karunanithi                     originatorType = mapDbusOriginatorTypeToRedfish(*type);
30368dd075aSAsmitha Karunanithi                     if (originatorType == log_entry::OriginatorTypes::Invalid)
30468dd075aSAsmitha Karunanithi                     {
30568dd075aSAsmitha Karunanithi                         messages::internalError(asyncResp->res);
30668dd075aSAsmitha Karunanithi                         break;
30768dd075aSAsmitha Karunanithi                     }
30868dd075aSAsmitha Karunanithi                 }
30968dd075aSAsmitha Karunanithi             }
31068dd075aSAsmitha Karunanithi         }
311aefe3786SClaire Weinan     }
312aefe3786SClaire Weinan }
313aefe3786SClaire Weinan 
31421ab404cSNan Zhou static std::string getDumpEntriesPath(const std::string& dumpType)
315fdd26906SClaire Weinan {
316fdd26906SClaire Weinan     std::string entriesPath;
317fdd26906SClaire Weinan 
318fdd26906SClaire Weinan     if (dumpType == "BMC")
319fdd26906SClaire Weinan     {
320253f11b8SEd Tanous         entriesPath =
321253f11b8SEd Tanous             std::format("/redfish/v1/Managers/{}/LogServices/Dump/Entries/",
322253f11b8SEd Tanous                         BMCWEB_REDFISH_MANAGER_URI_NAME);
323fdd26906SClaire Weinan     }
324fdd26906SClaire Weinan     else if (dumpType == "FaultLog")
325fdd26906SClaire Weinan     {
326253f11b8SEd Tanous         entriesPath =
327253f11b8SEd Tanous             std::format("/redfish/v1/Managers/{}/LogServices/FaultLog/Entries/",
328253f11b8SEd Tanous                         BMCWEB_REDFISH_MANAGER_URI_NAME);
329fdd26906SClaire Weinan     }
330fdd26906SClaire Weinan     else if (dumpType == "System")
331fdd26906SClaire Weinan     {
332253f11b8SEd Tanous         entriesPath =
333253f11b8SEd Tanous             std::format("/redfish/v1/Systems/{}/LogServices/Dump/Entries/",
334253f11b8SEd Tanous                         BMCWEB_REDFISH_SYSTEM_URI_NAME);
335fdd26906SClaire Weinan     }
336fdd26906SClaire Weinan     else
337fdd26906SClaire Weinan     {
33862598e31SEd Tanous         BMCWEB_LOG_ERROR("getDumpEntriesPath() invalid dump type: {}",
33962598e31SEd Tanous                          dumpType);
340fdd26906SClaire Weinan     }
341fdd26906SClaire Weinan 
342fdd26906SClaire Weinan     // Returns empty string on error
343fdd26906SClaire Weinan     return entriesPath;
344fdd26906SClaire Weinan }
345fdd26906SClaire Weinan 
3468d1b46d7Szhanghch05 inline void
3478d1b46d7Szhanghch05     getDumpEntryCollection(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3485cb1dd27SAsmitha Karunanithi                            const std::string& dumpType)
3495cb1dd27SAsmitha Karunanithi {
350fdd26906SClaire Weinan     std::string entriesPath = getDumpEntriesPath(dumpType);
351fdd26906SClaire Weinan     if (entriesPath.empty())
3525cb1dd27SAsmitha Karunanithi     {
3535cb1dd27SAsmitha Karunanithi         messages::internalError(asyncResp->res);
3545cb1dd27SAsmitha Karunanithi         return;
3555cb1dd27SAsmitha Karunanithi     }
3565cb1dd27SAsmitha Karunanithi 
3575eb468daSGeorge Liu     sdbusplus::message::object_path path("/xyz/openbmc_project/dump");
3585eb468daSGeorge Liu     dbus::utility::getManagedObjects(
3595eb468daSGeorge Liu         "xyz.openbmc_project.Dump.Manager", path,
360fdd26906SClaire Weinan         [asyncResp, entriesPath,
3615e7e2dc5SEd Tanous          dumpType](const boost::system::error_code& ec,
3625eb468daSGeorge Liu                    const dbus::utility::ManagedObjectType& objects) {
3635cb1dd27SAsmitha Karunanithi             if (ec)
3645cb1dd27SAsmitha Karunanithi             {
36562598e31SEd Tanous                 BMCWEB_LOG_ERROR("DumpEntry resp_handler got error {}", ec);
3665cb1dd27SAsmitha Karunanithi                 messages::internalError(asyncResp->res);
3675cb1dd27SAsmitha Karunanithi                 return;
3685cb1dd27SAsmitha Karunanithi             }
3695cb1dd27SAsmitha Karunanithi 
370fdd26906SClaire Weinan             // Remove ending slash
371fdd26906SClaire Weinan             std::string odataIdStr = entriesPath;
372fdd26906SClaire Weinan             if (!odataIdStr.empty())
373fdd26906SClaire Weinan             {
374fdd26906SClaire Weinan                 odataIdStr.pop_back();
375fdd26906SClaire Weinan             }
376fdd26906SClaire Weinan 
377fdd26906SClaire Weinan             asyncResp->res.jsonValue["@odata.type"] =
378fdd26906SClaire Weinan                 "#LogEntryCollection.LogEntryCollection";
379fdd26906SClaire Weinan             asyncResp->res.jsonValue["@odata.id"] = std::move(odataIdStr);
380fdd26906SClaire Weinan             asyncResp->res.jsonValue["Name"] = dumpType + " Dump Entries";
381bd79bce8SPatrick Williams             asyncResp->res.jsonValue["Description"] =
382bd79bce8SPatrick Williams                 "Collection of " + dumpType + " Dump Entries";
383fdd26906SClaire Weinan 
3843544d2a7SEd Tanous             nlohmann::json::array_t entriesArray;
38518f8f608SEd Tanous             std::string dumpEntryPath = getDumpPath(dumpType) + "/entry/";
3865cb1dd27SAsmitha Karunanithi 
3875eb468daSGeorge Liu             dbus::utility::ManagedObjectType resp(objects);
3883544d2a7SEd Tanous             std::ranges::sort(resp, [](const auto& l, const auto& r) {
389002d39b4SEd Tanous                 return AlphanumLess<std::string>()(l.first.filename(),
390002d39b4SEd Tanous                                                    r.first.filename());
391565dfb6fSClaire Weinan             });
392565dfb6fSClaire Weinan 
3935cb1dd27SAsmitha Karunanithi             for (auto& object : resp)
3945cb1dd27SAsmitha Karunanithi             {
395b47452b2SAsmitha Karunanithi                 if (object.first.str.find(dumpEntryPath) == std::string::npos)
3965cb1dd27SAsmitha Karunanithi                 {
3975cb1dd27SAsmitha Karunanithi                     continue;
3985cb1dd27SAsmitha Karunanithi                 }
399c6fecdabSClaire Weinan                 uint64_t timestampUs = 0;
4005cb1dd27SAsmitha Karunanithi                 uint64_t size = 0;
40135440d18SAsmitha Karunanithi                 std::string dumpStatus;
40268dd075aSAsmitha Karunanithi                 std::string originatorId;
40368dd075aSAsmitha Karunanithi                 log_entry::OriginatorTypes originatorType =
40468dd075aSAsmitha Karunanithi                     log_entry::OriginatorTypes::Internal;
405433b68b4SJason M. Bills                 nlohmann::json::object_t thisEntry;
4062dfd18efSEd Tanous 
4072dfd18efSEd Tanous                 std::string entryID = object.first.filename();
4082dfd18efSEd Tanous                 if (entryID.empty())
4095cb1dd27SAsmitha Karunanithi                 {
4105cb1dd27SAsmitha Karunanithi                     continue;
4115cb1dd27SAsmitha Karunanithi                 }
4125cb1dd27SAsmitha Karunanithi 
413bd79bce8SPatrick Williams                 parseDumpEntryFromDbusObject(object, dumpStatus, size,
414bd79bce8SPatrick Williams                                              timestampUs, originatorId,
415bd79bce8SPatrick Williams                                              originatorType, asyncResp);
4165cb1dd27SAsmitha Karunanithi 
4170fda0f12SGeorge Liu                 if (dumpStatus !=
4180fda0f12SGeorge Liu                         "xyz.openbmc_project.Common.Progress.OperationStatus.Completed" &&
41935440d18SAsmitha Karunanithi                     !dumpStatus.empty())
42035440d18SAsmitha Karunanithi                 {
42135440d18SAsmitha Karunanithi                     // Dump status is not Complete, no need to enumerate
42235440d18SAsmitha Karunanithi                     continue;
42335440d18SAsmitha Karunanithi                 }
42435440d18SAsmitha Karunanithi 
42568dd075aSAsmitha Karunanithi                 thisEntry["@odata.type"] = "#LogEntry.v1_11_0.LogEntry";
426fdd26906SClaire Weinan                 thisEntry["@odata.id"] = entriesPath + entryID;
4275cb1dd27SAsmitha Karunanithi                 thisEntry["Id"] = entryID;
4285cb1dd27SAsmitha Karunanithi                 thisEntry["EntryType"] = "Event";
4295cb1dd27SAsmitha Karunanithi                 thisEntry["Name"] = dumpType + " Dump Entry";
430bbd80db8SClaire Weinan                 thisEntry["Created"] =
431bbd80db8SClaire Weinan                     redfish::time_utils::getDateTimeUintUs(timestampUs);
4325cb1dd27SAsmitha Karunanithi 
43368dd075aSAsmitha Karunanithi                 if (!originatorId.empty())
43468dd075aSAsmitha Karunanithi                 {
43568dd075aSAsmitha Karunanithi                     thisEntry["Originator"] = originatorId;
43668dd075aSAsmitha Karunanithi                     thisEntry["OriginatorType"] = originatorType;
43768dd075aSAsmitha Karunanithi                 }
43868dd075aSAsmitha Karunanithi 
4395cb1dd27SAsmitha Karunanithi                 if (dumpType == "BMC")
4405cb1dd27SAsmitha Karunanithi                 {
441d337bb72SAsmitha Karunanithi                     thisEntry["DiagnosticDataType"] = "Manager";
442bd79bce8SPatrick Williams                     thisEntry["AdditionalDataURI"] =
443bd79bce8SPatrick Williams                         entriesPath + entryID + "/attachment";
444fdd26906SClaire Weinan                     thisEntry["AdditionalDataSizeBytes"] = size;
4455cb1dd27SAsmitha Karunanithi                 }
4465cb1dd27SAsmitha Karunanithi                 else if (dumpType == "System")
4475cb1dd27SAsmitha Karunanithi                 {
448d337bb72SAsmitha Karunanithi                     thisEntry["DiagnosticDataType"] = "OEM";
449d337bb72SAsmitha Karunanithi                     thisEntry["OEMDiagnosticDataType"] = "System";
450bd79bce8SPatrick Williams                     thisEntry["AdditionalDataURI"] =
451bd79bce8SPatrick Williams                         entriesPath + entryID + "/attachment";
452fdd26906SClaire Weinan                     thisEntry["AdditionalDataSizeBytes"] = size;
4535cb1dd27SAsmitha Karunanithi                 }
454b2ba3072SPatrick Williams                 entriesArray.emplace_back(std::move(thisEntry));
4555cb1dd27SAsmitha Karunanithi             }
456bd79bce8SPatrick Williams             asyncResp->res.jsonValue["Members@odata.count"] =
457bd79bce8SPatrick Williams                 entriesArray.size();
4583544d2a7SEd Tanous             asyncResp->res.jsonValue["Members"] = std::move(entriesArray);
4595eb468daSGeorge Liu         });
4605cb1dd27SAsmitha Karunanithi }
4615cb1dd27SAsmitha Karunanithi 
4628d1b46d7Szhanghch05 inline void
463c7a6d660SClaire Weinan     getDumpEntryById(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
4648d1b46d7Szhanghch05                      const std::string& entryID, const std::string& dumpType)
4655cb1dd27SAsmitha Karunanithi {
466fdd26906SClaire Weinan     std::string entriesPath = getDumpEntriesPath(dumpType);
467fdd26906SClaire Weinan     if (entriesPath.empty())
4685cb1dd27SAsmitha Karunanithi     {
4695cb1dd27SAsmitha Karunanithi         messages::internalError(asyncResp->res);
4705cb1dd27SAsmitha Karunanithi         return;
4715cb1dd27SAsmitha Karunanithi     }
4725cb1dd27SAsmitha Karunanithi 
4735eb468daSGeorge Liu     sdbusplus::message::object_path path("/xyz/openbmc_project/dump");
4745eb468daSGeorge Liu     dbus::utility::getManagedObjects(
4755eb468daSGeorge Liu         "xyz.openbmc_project.Dump.Manager", path,
476fdd26906SClaire Weinan         [asyncResp, entryID, dumpType,
4775e7e2dc5SEd Tanous          entriesPath](const boost::system::error_code& ec,
47802cad96eSEd Tanous                       const dbus::utility::ManagedObjectType& resp) {
4795cb1dd27SAsmitha Karunanithi             if (ec)
4805cb1dd27SAsmitha Karunanithi             {
48162598e31SEd Tanous                 BMCWEB_LOG_ERROR("DumpEntry resp_handler got error {}", ec);
4825cb1dd27SAsmitha Karunanithi                 messages::internalError(asyncResp->res);
4835cb1dd27SAsmitha Karunanithi                 return;
4845cb1dd27SAsmitha Karunanithi             }
4855cb1dd27SAsmitha Karunanithi 
486b47452b2SAsmitha Karunanithi             bool foundDumpEntry = false;
48718f8f608SEd Tanous             std::string dumpEntryPath = getDumpPath(dumpType) + "/entry/";
488b47452b2SAsmitha Karunanithi 
4899eb808c1SEd Tanous             for (const auto& objectPath : resp)
4905cb1dd27SAsmitha Karunanithi             {
491b47452b2SAsmitha Karunanithi                 if (objectPath.first.str != dumpEntryPath + entryID)
4925cb1dd27SAsmitha Karunanithi                 {
4935cb1dd27SAsmitha Karunanithi                     continue;
4945cb1dd27SAsmitha Karunanithi                 }
4955cb1dd27SAsmitha Karunanithi 
4965cb1dd27SAsmitha Karunanithi                 foundDumpEntry = true;
497c6fecdabSClaire Weinan                 uint64_t timestampUs = 0;
4985cb1dd27SAsmitha Karunanithi                 uint64_t size = 0;
49935440d18SAsmitha Karunanithi                 std::string dumpStatus;
50068dd075aSAsmitha Karunanithi                 std::string originatorId;
50168dd075aSAsmitha Karunanithi                 log_entry::OriginatorTypes originatorType =
50268dd075aSAsmitha Karunanithi                     log_entry::OriginatorTypes::Internal;
5035cb1dd27SAsmitha Karunanithi 
504aefe3786SClaire Weinan                 parseDumpEntryFromDbusObject(objectPath, dumpStatus, size,
50568dd075aSAsmitha Karunanithi                                              timestampUs, originatorId,
50668dd075aSAsmitha Karunanithi                                              originatorType, asyncResp);
5075cb1dd27SAsmitha Karunanithi 
5080fda0f12SGeorge Liu                 if (dumpStatus !=
5090fda0f12SGeorge Liu                         "xyz.openbmc_project.Common.Progress.OperationStatus.Completed" &&
51035440d18SAsmitha Karunanithi                     !dumpStatus.empty())
51135440d18SAsmitha Karunanithi                 {
51235440d18SAsmitha Karunanithi                     // Dump status is not Complete
51335440d18SAsmitha Karunanithi                     // return not found until status is changed to Completed
514bd79bce8SPatrick Williams                     messages::resourceNotFound(asyncResp->res,
515bd79bce8SPatrick Williams                                                dumpType + " dump", entryID);
51635440d18SAsmitha Karunanithi                     return;
51735440d18SAsmitha Karunanithi                 }
51835440d18SAsmitha Karunanithi 
5195cb1dd27SAsmitha Karunanithi                 asyncResp->res.jsonValue["@odata.type"] =
52068dd075aSAsmitha Karunanithi                     "#LogEntry.v1_11_0.LogEntry";
521fdd26906SClaire Weinan                 asyncResp->res.jsonValue["@odata.id"] = entriesPath + entryID;
5225cb1dd27SAsmitha Karunanithi                 asyncResp->res.jsonValue["Id"] = entryID;
5235cb1dd27SAsmitha Karunanithi                 asyncResp->res.jsonValue["EntryType"] = "Event";
5245cb1dd27SAsmitha Karunanithi                 asyncResp->res.jsonValue["Name"] = dumpType + " Dump Entry";
525bbd80db8SClaire Weinan                 asyncResp->res.jsonValue["Created"] =
526bbd80db8SClaire Weinan                     redfish::time_utils::getDateTimeUintUs(timestampUs);
5275cb1dd27SAsmitha Karunanithi 
52868dd075aSAsmitha Karunanithi                 if (!originatorId.empty())
52968dd075aSAsmitha Karunanithi                 {
53068dd075aSAsmitha Karunanithi                     asyncResp->res.jsonValue["Originator"] = originatorId;
53168dd075aSAsmitha Karunanithi                     asyncResp->res.jsonValue["OriginatorType"] = originatorType;
53268dd075aSAsmitha Karunanithi                 }
53368dd075aSAsmitha Karunanithi 
5345cb1dd27SAsmitha Karunanithi                 if (dumpType == "BMC")
5355cb1dd27SAsmitha Karunanithi                 {
536d337bb72SAsmitha Karunanithi                     asyncResp->res.jsonValue["DiagnosticDataType"] = "Manager";
537d337bb72SAsmitha Karunanithi                     asyncResp->res.jsonValue["AdditionalDataURI"] =
538fdd26906SClaire Weinan                         entriesPath + entryID + "/attachment";
539fdd26906SClaire Weinan                     asyncResp->res.jsonValue["AdditionalDataSizeBytes"] = size;
5405cb1dd27SAsmitha Karunanithi                 }
5415cb1dd27SAsmitha Karunanithi                 else if (dumpType == "System")
5425cb1dd27SAsmitha Karunanithi                 {
543d337bb72SAsmitha Karunanithi                     asyncResp->res.jsonValue["DiagnosticDataType"] = "OEM";
544bd79bce8SPatrick Williams                     asyncResp->res.jsonValue["OEMDiagnosticDataType"] =
545bd79bce8SPatrick Williams                         "System";
546d337bb72SAsmitha Karunanithi                     asyncResp->res.jsonValue["AdditionalDataURI"] =
547fdd26906SClaire Weinan                         entriesPath + entryID + "/attachment";
548fdd26906SClaire Weinan                     asyncResp->res.jsonValue["AdditionalDataSizeBytes"] = size;
5495cb1dd27SAsmitha Karunanithi                 }
5505cb1dd27SAsmitha Karunanithi             }
551e05aec50SEd Tanous             if (!foundDumpEntry)
552b47452b2SAsmitha Karunanithi             {
55362598e31SEd Tanous                 BMCWEB_LOG_WARNING("Can't find Dump Entry {}", entryID);
554b90d14f2SMyung Bae                 messages::resourceNotFound(asyncResp->res, dumpType + " dump",
555b90d14f2SMyung Bae                                            entryID);
556b47452b2SAsmitha Karunanithi                 return;
557b47452b2SAsmitha Karunanithi             }
5585eb468daSGeorge Liu         });
5595cb1dd27SAsmitha Karunanithi }
5605cb1dd27SAsmitha Karunanithi 
5618d1b46d7Szhanghch05 inline void deleteDumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
5629878256fSStanley Chu                             const std::string& entryID,
563b47452b2SAsmitha Karunanithi                             const std::string& dumpType)
5645cb1dd27SAsmitha Karunanithi {
5655a39f77aSPatrick Williams     auto respHandler = [asyncResp,
5665a39f77aSPatrick Williams                         entryID](const boost::system::error_code& ec) {
56762598e31SEd Tanous         BMCWEB_LOG_DEBUG("Dump Entry doDelete callback: Done");
5685cb1dd27SAsmitha Karunanithi         if (ec)
5695cb1dd27SAsmitha Karunanithi         {
5703de8d8baSGeorge Liu             if (ec.value() == EBADR)
5713de8d8baSGeorge Liu             {
5723de8d8baSGeorge Liu                 messages::resourceNotFound(asyncResp->res, "LogEntry", entryID);
5733de8d8baSGeorge Liu                 return;
5743de8d8baSGeorge Liu             }
57562598e31SEd Tanous             BMCWEB_LOG_ERROR(
57662598e31SEd Tanous                 "Dump (DBus) doDelete respHandler got error {} entryID={}", ec,
57762598e31SEd Tanous                 entryID);
5785cb1dd27SAsmitha Karunanithi             messages::internalError(asyncResp->res);
5795cb1dd27SAsmitha Karunanithi             return;
5805cb1dd27SAsmitha Karunanithi         }
5815cb1dd27SAsmitha Karunanithi     };
58218f8f608SEd Tanous 
5835cb1dd27SAsmitha Karunanithi     crow::connections::systemBus->async_method_call(
5845cb1dd27SAsmitha Karunanithi         respHandler, "xyz.openbmc_project.Dump.Manager",
58518f8f608SEd Tanous         std::format("{}/entry/{}", getDumpPath(dumpType), entryID),
5865cb1dd27SAsmitha Karunanithi         "xyz.openbmc_project.Object.Delete", "Delete");
5875cb1dd27SAsmitha Karunanithi }
588b5f288d2SAbhilash Raju inline bool checkSizeLimit(int fd, crow::Response& res)
589b5f288d2SAbhilash Raju {
590b5f288d2SAbhilash Raju     long long int size = lseek(fd, 0, SEEK_END);
591b5f288d2SAbhilash Raju     if (size <= 0)
592b5f288d2SAbhilash Raju     {
593b5f288d2SAbhilash Raju         BMCWEB_LOG_ERROR("Failed to get size of file, lseek() returned {}",
594b5f288d2SAbhilash Raju                          size);
595b5f288d2SAbhilash Raju         messages::internalError(res);
596b5f288d2SAbhilash Raju         return false;
597b5f288d2SAbhilash Raju     }
5985cb1dd27SAsmitha Karunanithi 
599b5f288d2SAbhilash Raju     // Arbitrary max size of 20MB to accommodate BMC dumps
600b5f288d2SAbhilash Raju     constexpr long long int maxFileSize = 20LL * 1024LL * 1024LL;
601b5f288d2SAbhilash Raju     if (size > maxFileSize)
602b5f288d2SAbhilash Raju     {
603b5f288d2SAbhilash Raju         BMCWEB_LOG_ERROR("File size {} exceeds maximum allowed size of {}",
604b5f288d2SAbhilash Raju                          size, maxFileSize);
605b5f288d2SAbhilash Raju         messages::internalError(res);
606b5f288d2SAbhilash Raju         return false;
607b5f288d2SAbhilash Raju     }
608b5f288d2SAbhilash Raju     off_t rc = lseek(fd, 0, SEEK_SET);
609b5f288d2SAbhilash Raju     if (rc < 0)
610b5f288d2SAbhilash Raju     {
611b5f288d2SAbhilash Raju         BMCWEB_LOG_ERROR("Failed to reset file offset to 0");
612b5f288d2SAbhilash Raju         messages::internalError(res);
613b5f288d2SAbhilash Raju         return false;
614b5f288d2SAbhilash Raju     }
615b5f288d2SAbhilash Raju     return true;
616b5f288d2SAbhilash Raju }
617bd79bce8SPatrick Williams inline void downloadEntryCallback(
618bd79bce8SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
619bd79bce8SPatrick Williams     const std::string& entryID, const std::string& downloadEntryType,
620168d1b1aSCarson Labrado     const boost::system::error_code& ec,
621168d1b1aSCarson Labrado     const sdbusplus::message::unix_fd& unixfd)
622168d1b1aSCarson Labrado {
623168d1b1aSCarson Labrado     if (ec.value() == EBADR)
624168d1b1aSCarson Labrado     {
625168d1b1aSCarson Labrado         messages::resourceNotFound(asyncResp->res, "EntryAttachment", entryID);
626168d1b1aSCarson Labrado         return;
627168d1b1aSCarson Labrado     }
628168d1b1aSCarson Labrado     if (ec)
629168d1b1aSCarson Labrado     {
630168d1b1aSCarson Labrado         BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
631168d1b1aSCarson Labrado         messages::internalError(asyncResp->res);
632168d1b1aSCarson Labrado         return;
633168d1b1aSCarson Labrado     }
634168d1b1aSCarson Labrado 
635168d1b1aSCarson Labrado     // Make sure we know how to process the retrieved entry attachment
636168d1b1aSCarson Labrado     if ((downloadEntryType != "BMC") && (downloadEntryType != "System"))
637168d1b1aSCarson Labrado     {
638168d1b1aSCarson Labrado         BMCWEB_LOG_ERROR("downloadEntryCallback() invalid entry type: {}",
639168d1b1aSCarson Labrado                          downloadEntryType);
640168d1b1aSCarson Labrado         messages::internalError(asyncResp->res);
641168d1b1aSCarson Labrado     }
642168d1b1aSCarson Labrado 
643168d1b1aSCarson Labrado     int fd = -1;
644168d1b1aSCarson Labrado     fd = dup(unixfd);
645168d1b1aSCarson Labrado     if (fd < 0)
646168d1b1aSCarson Labrado     {
647168d1b1aSCarson Labrado         BMCWEB_LOG_ERROR("Failed to open file");
648168d1b1aSCarson Labrado         messages::internalError(asyncResp->res);
649168d1b1aSCarson Labrado         return;
650168d1b1aSCarson Labrado     }
651b5f288d2SAbhilash Raju     if (!checkSizeLimit(fd, asyncResp->res))
652168d1b1aSCarson Labrado     {
653168d1b1aSCarson Labrado         close(fd);
654168d1b1aSCarson Labrado         return;
655168d1b1aSCarson Labrado     }
656168d1b1aSCarson Labrado     if (downloadEntryType == "System")
657168d1b1aSCarson Labrado     {
658b5f288d2SAbhilash Raju         if (!asyncResp->res.openFd(fd, bmcweb::EncodingType::Base64))
659b5f288d2SAbhilash Raju         {
660b5f288d2SAbhilash Raju             messages::internalError(asyncResp->res);
661b5f288d2SAbhilash Raju             close(fd);
662b5f288d2SAbhilash Raju             return;
663b5f288d2SAbhilash Raju         }
664168d1b1aSCarson Labrado         asyncResp->res.addHeader(
665168d1b1aSCarson Labrado             boost::beast::http::field::content_transfer_encoding, "Base64");
666b5f288d2SAbhilash Raju         return;
667168d1b1aSCarson Labrado     }
668b5f288d2SAbhilash Raju     if (!asyncResp->res.openFd(fd))
66927b0cf90SEd Tanous     {
670b5f288d2SAbhilash Raju         messages::internalError(asyncResp->res);
671b5f288d2SAbhilash Raju         close(fd);
672b5f288d2SAbhilash Raju         return;
67327b0cf90SEd Tanous     }
674168d1b1aSCarson Labrado     asyncResp->res.addHeader(boost::beast::http::field::content_type,
675168d1b1aSCarson Labrado                              "application/octet-stream");
676168d1b1aSCarson Labrado }
677168d1b1aSCarson Labrado 
678168d1b1aSCarson Labrado inline void
679168d1b1aSCarson Labrado     downloadDumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
680168d1b1aSCarson Labrado                       const std::string& entryID, const std::string& dumpType)
681168d1b1aSCarson Labrado {
682168d1b1aSCarson Labrado     if (dumpType != "BMC")
683168d1b1aSCarson Labrado     {
684168d1b1aSCarson Labrado         BMCWEB_LOG_WARNING("Can't find Dump Entry {}", entryID);
685168d1b1aSCarson Labrado         messages::resourceNotFound(asyncResp->res, dumpType + " dump", entryID);
686168d1b1aSCarson Labrado         return;
687168d1b1aSCarson Labrado     }
688168d1b1aSCarson Labrado 
689bd79bce8SPatrick Williams     std::string dumpEntryPath =
690bd79bce8SPatrick Williams         std::format("{}/entry/{}", getDumpPath(dumpType), entryID);
691168d1b1aSCarson Labrado 
692168d1b1aSCarson Labrado     auto downloadDumpEntryHandler =
693168d1b1aSCarson Labrado         [asyncResp, entryID,
694168d1b1aSCarson Labrado          dumpType](const boost::system::error_code& ec,
695168d1b1aSCarson Labrado                    const sdbusplus::message::unix_fd& unixfd) {
696168d1b1aSCarson Labrado             downloadEntryCallback(asyncResp, entryID, dumpType, ec, unixfd);
697168d1b1aSCarson Labrado         };
698168d1b1aSCarson Labrado 
699168d1b1aSCarson Labrado     crow::connections::systemBus->async_method_call(
700168d1b1aSCarson Labrado         std::move(downloadDumpEntryHandler), "xyz.openbmc_project.Dump.Manager",
701168d1b1aSCarson Labrado         dumpEntryPath, "xyz.openbmc_project.Dump.Entry", "GetFileHandle");
702168d1b1aSCarson Labrado }
703168d1b1aSCarson Labrado 
704bd79bce8SPatrick Williams inline void downloadEventLogEntry(
705bd79bce8SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
706bd79bce8SPatrick Williams     const std::string& systemName, const std::string& entryID,
707168d1b1aSCarson Labrado     const std::string& dumpType)
708168d1b1aSCarson Labrado {
70925b54dbaSEd Tanous     if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
710168d1b1aSCarson Labrado     {
711168d1b1aSCarson Labrado         // Option currently returns no systems.  TBD
712168d1b1aSCarson Labrado         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
713168d1b1aSCarson Labrado                                    systemName);
714168d1b1aSCarson Labrado         return;
715168d1b1aSCarson Labrado     }
716253f11b8SEd Tanous     if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
717168d1b1aSCarson Labrado     {
718168d1b1aSCarson Labrado         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
719168d1b1aSCarson Labrado                                    systemName);
720168d1b1aSCarson Labrado         return;
721168d1b1aSCarson Labrado     }
722168d1b1aSCarson Labrado 
723168d1b1aSCarson Labrado     std::string entryPath =
724168d1b1aSCarson Labrado         sdbusplus::message::object_path("/xyz/openbmc_project/logging/entry") /
725168d1b1aSCarson Labrado         entryID;
726168d1b1aSCarson Labrado 
727168d1b1aSCarson Labrado     auto downloadEventLogEntryHandler =
728168d1b1aSCarson Labrado         [asyncResp, entryID,
729168d1b1aSCarson Labrado          dumpType](const boost::system::error_code& ec,
730168d1b1aSCarson Labrado                    const sdbusplus::message::unix_fd& unixfd) {
731168d1b1aSCarson Labrado             downloadEntryCallback(asyncResp, entryID, dumpType, ec, unixfd);
732168d1b1aSCarson Labrado         };
733168d1b1aSCarson Labrado 
734168d1b1aSCarson Labrado     crow::connections::systemBus->async_method_call(
735168d1b1aSCarson Labrado         std::move(downloadEventLogEntryHandler), "xyz.openbmc_project.Logging",
736168d1b1aSCarson Labrado         entryPath, "xyz.openbmc_project.Logging.Entry", "GetEntry");
737168d1b1aSCarson Labrado }
738168d1b1aSCarson Labrado 
7398e31778eSAsmitha Karunanithi inline DumpCreationProgress
7408e31778eSAsmitha Karunanithi     mapDbusStatusToDumpProgress(const std::string& status)
741a43be80fSAsmitha Karunanithi {
7428e31778eSAsmitha Karunanithi     if (status ==
7438e31778eSAsmitha Karunanithi             "xyz.openbmc_project.Common.Progress.OperationStatus.Failed" ||
7448e31778eSAsmitha Karunanithi         status == "xyz.openbmc_project.Common.Progress.OperationStatus.Aborted")
7458e31778eSAsmitha Karunanithi     {
7468e31778eSAsmitha Karunanithi         return DumpCreationProgress::DUMP_CREATE_FAILED;
7478e31778eSAsmitha Karunanithi     }
7488e31778eSAsmitha Karunanithi     if (status ==
7498e31778eSAsmitha Karunanithi         "xyz.openbmc_project.Common.Progress.OperationStatus.Completed")
7508e31778eSAsmitha Karunanithi     {
7518e31778eSAsmitha Karunanithi         return DumpCreationProgress::DUMP_CREATE_SUCCESS;
7528e31778eSAsmitha Karunanithi     }
7538e31778eSAsmitha Karunanithi     return DumpCreationProgress::DUMP_CREATE_INPROGRESS;
7548e31778eSAsmitha Karunanithi }
7558e31778eSAsmitha Karunanithi 
7568e31778eSAsmitha Karunanithi inline DumpCreationProgress
7578e31778eSAsmitha Karunanithi     getDumpCompletionStatus(const dbus::utility::DBusPropertiesMap& values)
7588e31778eSAsmitha Karunanithi {
7598e31778eSAsmitha Karunanithi     for (const auto& [key, val] : values)
7608e31778eSAsmitha Karunanithi     {
7618e31778eSAsmitha Karunanithi         if (key == "Status")
7628e31778eSAsmitha Karunanithi         {
7638e31778eSAsmitha Karunanithi             const std::string* value = std::get_if<std::string>(&val);
7648e31778eSAsmitha Karunanithi             if (value == nullptr)
7658e31778eSAsmitha Karunanithi             {
76662598e31SEd Tanous                 BMCWEB_LOG_ERROR("Status property value is null");
7678e31778eSAsmitha Karunanithi                 return DumpCreationProgress::DUMP_CREATE_FAILED;
7688e31778eSAsmitha Karunanithi             }
7698e31778eSAsmitha Karunanithi             return mapDbusStatusToDumpProgress(*value);
7708e31778eSAsmitha Karunanithi         }
7718e31778eSAsmitha Karunanithi     }
7728e31778eSAsmitha Karunanithi     return DumpCreationProgress::DUMP_CREATE_INPROGRESS;
7738e31778eSAsmitha Karunanithi }
7748e31778eSAsmitha Karunanithi 
7758e31778eSAsmitha Karunanithi inline std::string getDumpEntryPath(const std::string& dumpPath)
7768e31778eSAsmitha Karunanithi {
7778e31778eSAsmitha Karunanithi     if (dumpPath == "/xyz/openbmc_project/dump/bmc/entry")
7788e31778eSAsmitha Karunanithi     {
779253f11b8SEd Tanous         return std::format("/redfish/v1/Managers/{}/LogServices/Dump/Entries/",
7809f565090SEd Tanous                            BMCWEB_REDFISH_MANAGER_URI_NAME);
7818e31778eSAsmitha Karunanithi     }
7828e31778eSAsmitha Karunanithi     if (dumpPath == "/xyz/openbmc_project/dump/system/entry")
7838e31778eSAsmitha Karunanithi     {
784253f11b8SEd Tanous         return std::format("/redfish/v1/Systems/{}/LogServices/Dump/Entries/",
785253f11b8SEd Tanous                            BMCWEB_REDFISH_SYSTEM_URI_NAME);
7868e31778eSAsmitha Karunanithi     }
7878e31778eSAsmitha Karunanithi     return "";
7888e31778eSAsmitha Karunanithi }
7898e31778eSAsmitha Karunanithi 
7908e31778eSAsmitha Karunanithi inline void createDumpTaskCallback(
7918e31778eSAsmitha Karunanithi     task::Payload&& payload,
7928e31778eSAsmitha Karunanithi     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
7938e31778eSAsmitha Karunanithi     const sdbusplus::message::object_path& createdObjPath)
7948e31778eSAsmitha Karunanithi {
7958e31778eSAsmitha Karunanithi     const std::string dumpPath = createdObjPath.parent_path().str;
7968e31778eSAsmitha Karunanithi     const std::string dumpId = createdObjPath.filename();
7978e31778eSAsmitha Karunanithi 
7988e31778eSAsmitha Karunanithi     std::string dumpEntryPath = getDumpEntryPath(dumpPath);
7998e31778eSAsmitha Karunanithi 
8008e31778eSAsmitha Karunanithi     if (dumpEntryPath.empty())
8018e31778eSAsmitha Karunanithi     {
80262598e31SEd Tanous         BMCWEB_LOG_ERROR("Invalid dump type received");
8038e31778eSAsmitha Karunanithi         messages::internalError(asyncResp->res);
8048e31778eSAsmitha Karunanithi         return;
8058e31778eSAsmitha Karunanithi     }
8068e31778eSAsmitha Karunanithi 
8078e31778eSAsmitha Karunanithi     crow::connections::systemBus->async_method_call(
8088cb2c024SEd Tanous         [asyncResp, payload = std::move(payload), createdObjPath,
8098e31778eSAsmitha Karunanithi          dumpEntryPath{std::move(dumpEntryPath)},
8105e7e2dc5SEd Tanous          dumpId](const boost::system::error_code& ec,
8118e31778eSAsmitha Karunanithi                  const std::string& introspectXml) {
8128e31778eSAsmitha Karunanithi             if (ec)
8138e31778eSAsmitha Karunanithi             {
81462598e31SEd Tanous                 BMCWEB_LOG_ERROR("Introspect call failed with error: {}",
81562598e31SEd Tanous                                  ec.message());
8168e31778eSAsmitha Karunanithi                 messages::internalError(asyncResp->res);
8178e31778eSAsmitha Karunanithi                 return;
8188e31778eSAsmitha Karunanithi             }
8198e31778eSAsmitha Karunanithi 
8208e31778eSAsmitha Karunanithi             // Check if the created dump object has implemented Progress
8218e31778eSAsmitha Karunanithi             // interface to track dump completion. If yes, fetch the "Status"
8228e31778eSAsmitha Karunanithi             // property of the interface, modify the task state accordingly.
8238e31778eSAsmitha Karunanithi             // Else, return task completed.
8248e31778eSAsmitha Karunanithi             tinyxml2::XMLDocument doc;
8258e31778eSAsmitha Karunanithi 
8268e31778eSAsmitha Karunanithi             doc.Parse(introspectXml.data(), introspectXml.size());
8278e31778eSAsmitha Karunanithi             tinyxml2::XMLNode* pRoot = doc.FirstChildElement("node");
8288e31778eSAsmitha Karunanithi             if (pRoot == nullptr)
8298e31778eSAsmitha Karunanithi             {
83062598e31SEd Tanous                 BMCWEB_LOG_ERROR("XML document failed to parse");
8318e31778eSAsmitha Karunanithi                 messages::internalError(asyncResp->res);
8328e31778eSAsmitha Karunanithi                 return;
8338e31778eSAsmitha Karunanithi             }
8348e31778eSAsmitha Karunanithi             tinyxml2::XMLElement* interfaceNode =
8358e31778eSAsmitha Karunanithi                 pRoot->FirstChildElement("interface");
8368e31778eSAsmitha Karunanithi 
8378e31778eSAsmitha Karunanithi             bool isProgressIntfPresent = false;
8388e31778eSAsmitha Karunanithi             while (interfaceNode != nullptr)
8398e31778eSAsmitha Karunanithi             {
840bd79bce8SPatrick Williams                 const char* thisInterfaceName =
841bd79bce8SPatrick Williams                     interfaceNode->Attribute("name");
8428e31778eSAsmitha Karunanithi                 if (thisInterfaceName != nullptr)
8438e31778eSAsmitha Karunanithi                 {
8448e31778eSAsmitha Karunanithi                     if (thisInterfaceName ==
8458e31778eSAsmitha Karunanithi                         std::string_view("xyz.openbmc_project.Common.Progress"))
8468e31778eSAsmitha Karunanithi                     {
8478e31778eSAsmitha Karunanithi                         interfaceNode =
8488e31778eSAsmitha Karunanithi                             interfaceNode->NextSiblingElement("interface");
8498e31778eSAsmitha Karunanithi                         continue;
8508e31778eSAsmitha Karunanithi                     }
8518e31778eSAsmitha Karunanithi                     isProgressIntfPresent = true;
8528e31778eSAsmitha Karunanithi                     break;
8538e31778eSAsmitha Karunanithi                 }
8548e31778eSAsmitha Karunanithi                 interfaceNode = interfaceNode->NextSiblingElement("interface");
8558e31778eSAsmitha Karunanithi             }
8568e31778eSAsmitha Karunanithi 
857a43be80fSAsmitha Karunanithi             std::shared_ptr<task::TaskData> task = task::TaskData::createTask(
8588e31778eSAsmitha Karunanithi                 [createdObjPath, dumpEntryPath, dumpId, isProgressIntfPresent](
859bd79bce8SPatrick Williams                     const boost::system::error_code& ec2,
860bd79bce8SPatrick Williams                     sdbusplus::message_t& msg,
861a43be80fSAsmitha Karunanithi                     const std::shared_ptr<task::TaskData>& taskData) {
8628b24275dSEd Tanous                     if (ec2)
863cb13a392SEd Tanous                     {
86462598e31SEd Tanous                         BMCWEB_LOG_ERROR("{}: Error in creating dump",
86562598e31SEd Tanous                                          createdObjPath.str);
866bd79bce8SPatrick Williams                         taskData->messages.emplace_back(
867bd79bce8SPatrick Williams                             messages::internalError());
8686145ed6fSAsmitha Karunanithi                         taskData->state = "Cancelled";
8696145ed6fSAsmitha Karunanithi                         return task::completed;
870cb13a392SEd Tanous                     }
871b9d36b47SEd Tanous 
8728e31778eSAsmitha Karunanithi                     if (isProgressIntfPresent)
873a43be80fSAsmitha Karunanithi                     {
8748e31778eSAsmitha Karunanithi                         dbus::utility::DBusPropertiesMap values;
8758e31778eSAsmitha Karunanithi                         std::string prop;
8768e31778eSAsmitha Karunanithi                         msg.read(prop, values);
8778e31778eSAsmitha Karunanithi 
8788e31778eSAsmitha Karunanithi                         DumpCreationProgress dumpStatus =
8798e31778eSAsmitha Karunanithi                             getDumpCompletionStatus(values);
880bd79bce8SPatrick Williams                         if (dumpStatus ==
881bd79bce8SPatrick Williams                             DumpCreationProgress::DUMP_CREATE_FAILED)
8828e31778eSAsmitha Karunanithi                         {
88362598e31SEd Tanous                             BMCWEB_LOG_ERROR("{}: Error in creating dump",
88462598e31SEd Tanous                                              createdObjPath.str);
8858e31778eSAsmitha Karunanithi                             taskData->state = "Cancelled";
8868e31778eSAsmitha Karunanithi                             return task::completed;
8878e31778eSAsmitha Karunanithi                         }
8888e31778eSAsmitha Karunanithi 
889bd79bce8SPatrick Williams                         if (dumpStatus ==
890bd79bce8SPatrick Williams                             DumpCreationProgress::DUMP_CREATE_INPROGRESS)
8918e31778eSAsmitha Karunanithi                         {
892bd79bce8SPatrick Williams                             BMCWEB_LOG_DEBUG(
893bd79bce8SPatrick Williams                                 "{}: Dump creation task is in progress",
89462598e31SEd Tanous                                 createdObjPath.str);
8958e31778eSAsmitha Karunanithi                             return !task::completed;
8968e31778eSAsmitha Karunanithi                         }
8978e31778eSAsmitha Karunanithi                     }
8988e31778eSAsmitha Karunanithi 
899a43be80fSAsmitha Karunanithi                     nlohmann::json retMessage = messages::success();
900a43be80fSAsmitha Karunanithi                     taskData->messages.emplace_back(retMessage);
901a43be80fSAsmitha Karunanithi 
902c51a58eeSEd Tanous                     boost::urls::url url = boost::urls::format(
903253f11b8SEd Tanous                         "/redfish/v1/Managers/{}/LogServices/Dump/Entries/{}",
904253f11b8SEd Tanous                         BMCWEB_REDFISH_MANAGER_URI_NAME, dumpId);
905c51a58eeSEd Tanous 
906c51a58eeSEd Tanous                     std::string headerLoc = "Location: ";
907c51a58eeSEd Tanous                     headerLoc += url.buffer();
908c51a58eeSEd Tanous 
909bd79bce8SPatrick Williams                     taskData->payload->httpHeaders.emplace_back(
910bd79bce8SPatrick Williams                         std::move(headerLoc));
911a43be80fSAsmitha Karunanithi 
91262598e31SEd Tanous                     BMCWEB_LOG_DEBUG("{}: Dump creation task completed",
91362598e31SEd Tanous                                      createdObjPath.str);
914a43be80fSAsmitha Karunanithi                     taskData->state = "Completed";
915b47452b2SAsmitha Karunanithi                     return task::completed;
916a43be80fSAsmitha Karunanithi                 },
9178e31778eSAsmitha Karunanithi                 "type='signal',interface='org.freedesktop.DBus.Properties',"
9188e31778eSAsmitha Karunanithi                 "member='PropertiesChanged',path='" +
9198e31778eSAsmitha Karunanithi                     createdObjPath.str + "'");
920a43be80fSAsmitha Karunanithi 
9218e31778eSAsmitha Karunanithi             // The task timer is set to max time limit within which the
9228e31778eSAsmitha Karunanithi             // requested dump will be collected.
9238e31778eSAsmitha Karunanithi             task->startTimer(std::chrono::minutes(6));
924a43be80fSAsmitha Karunanithi             task->populateResp(asyncResp->res);
9258e31778eSAsmitha Karunanithi             task->payload.emplace(payload);
9268e31778eSAsmitha Karunanithi         },
9278e31778eSAsmitha Karunanithi         "xyz.openbmc_project.Dump.Manager", createdObjPath,
9288e31778eSAsmitha Karunanithi         "org.freedesktop.DBus.Introspectable", "Introspect");
929a43be80fSAsmitha Karunanithi }
930a43be80fSAsmitha Karunanithi 
9318d1b46d7Szhanghch05 inline void createDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
9328d1b46d7Szhanghch05                        const crow::Request& req, const std::string& dumpType)
933a43be80fSAsmitha Karunanithi {
934fdd26906SClaire Weinan     std::string dumpPath = getDumpEntriesPath(dumpType);
935fdd26906SClaire Weinan     if (dumpPath.empty())
936a43be80fSAsmitha Karunanithi     {
937a43be80fSAsmitha Karunanithi         messages::internalError(asyncResp->res);
938a43be80fSAsmitha Karunanithi         return;
939a43be80fSAsmitha Karunanithi     }
940a43be80fSAsmitha Karunanithi 
941a43be80fSAsmitha Karunanithi     std::optional<std::string> diagnosticDataType;
942a43be80fSAsmitha Karunanithi     std::optional<std::string> oemDiagnosticDataType;
943a43be80fSAsmitha Karunanithi 
944*afc474aeSMyung Bae     if (!redfish::json_util::readJsonAction( //
945*afc474aeSMyung Bae             req, asyncResp->res, //
946*afc474aeSMyung Bae             "DiagnosticDataType", diagnosticDataType, //
947*afc474aeSMyung Bae             "OEMDiagnosticDataType", oemDiagnosticDataType //
948*afc474aeSMyung Bae             ))
949a43be80fSAsmitha Karunanithi     {
950a43be80fSAsmitha Karunanithi         return;
951a43be80fSAsmitha Karunanithi     }
952a43be80fSAsmitha Karunanithi 
953a43be80fSAsmitha Karunanithi     if (dumpType == "System")
954a43be80fSAsmitha Karunanithi     {
955a43be80fSAsmitha Karunanithi         if (!oemDiagnosticDataType || !diagnosticDataType)
956a43be80fSAsmitha Karunanithi         {
95762598e31SEd Tanous             BMCWEB_LOG_ERROR(
95862598e31SEd Tanous                 "CreateDump action parameter 'DiagnosticDataType'/'OEMDiagnosticDataType' value not found!");
959a43be80fSAsmitha Karunanithi             messages::actionParameterMissing(
960a43be80fSAsmitha Karunanithi                 asyncResp->res, "CollectDiagnosticData",
961a43be80fSAsmitha Karunanithi                 "DiagnosticDataType & OEMDiagnosticDataType");
962a43be80fSAsmitha Karunanithi             return;
963a43be80fSAsmitha Karunanithi         }
9643174e4dfSEd Tanous         if ((*oemDiagnosticDataType != "System") ||
965a43be80fSAsmitha Karunanithi             (*diagnosticDataType != "OEM"))
966a43be80fSAsmitha Karunanithi         {
96762598e31SEd Tanous             BMCWEB_LOG_ERROR("Wrong parameter values passed");
968ace85d60SEd Tanous             messages::internalError(asyncResp->res);
969a43be80fSAsmitha Karunanithi             return;
970a43be80fSAsmitha Karunanithi         }
971253f11b8SEd Tanous         dumpPath = std::format("/redfish/v1/Systems/{}/LogServices/Dump/",
972253f11b8SEd Tanous                                BMCWEB_REDFISH_SYSTEM_URI_NAME);
973a43be80fSAsmitha Karunanithi     }
974a43be80fSAsmitha Karunanithi     else if (dumpType == "BMC")
975a43be80fSAsmitha Karunanithi     {
976a43be80fSAsmitha Karunanithi         if (!diagnosticDataType)
977a43be80fSAsmitha Karunanithi         {
97862598e31SEd Tanous             BMCWEB_LOG_ERROR(
97962598e31SEd Tanous                 "CreateDump action parameter 'DiagnosticDataType' not found!");
980a43be80fSAsmitha Karunanithi             messages::actionParameterMissing(
981a43be80fSAsmitha Karunanithi                 asyncResp->res, "CollectDiagnosticData", "DiagnosticDataType");
982a43be80fSAsmitha Karunanithi             return;
983a43be80fSAsmitha Karunanithi         }
9843174e4dfSEd Tanous         if (*diagnosticDataType != "Manager")
985a43be80fSAsmitha Karunanithi         {
98662598e31SEd Tanous             BMCWEB_LOG_ERROR(
98762598e31SEd Tanous                 "Wrong parameter value passed for 'DiagnosticDataType'");
988ace85d60SEd Tanous             messages::internalError(asyncResp->res);
989a43be80fSAsmitha Karunanithi             return;
990a43be80fSAsmitha Karunanithi         }
991253f11b8SEd Tanous         dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/Dump/",
992253f11b8SEd Tanous                                BMCWEB_REDFISH_MANAGER_URI_NAME);
9935907571dSAsmitha Karunanithi     }
9945907571dSAsmitha Karunanithi     else
9955907571dSAsmitha Karunanithi     {
99662598e31SEd Tanous         BMCWEB_LOG_ERROR("CreateDump failed. Unknown dump type");
9975907571dSAsmitha Karunanithi         messages::internalError(asyncResp->res);
9985907571dSAsmitha Karunanithi         return;
999a43be80fSAsmitha Karunanithi     }
1000a43be80fSAsmitha Karunanithi 
10018e31778eSAsmitha Karunanithi     std::vector<std::pair<std::string, std::variant<std::string, uint64_t>>>
10028e31778eSAsmitha Karunanithi         createDumpParamVec;
10038e31778eSAsmitha Karunanithi 
1004f574a8e1SCarson Labrado     if (req.session != nullptr)
1005f574a8e1SCarson Labrado     {
100668dd075aSAsmitha Karunanithi         createDumpParamVec.emplace_back(
100768dd075aSAsmitha Karunanithi             "xyz.openbmc_project.Dump.Create.CreateParameters.OriginatorId",
100868dd075aSAsmitha Karunanithi             req.session->clientIp);
100968dd075aSAsmitha Karunanithi         createDumpParamVec.emplace_back(
101068dd075aSAsmitha Karunanithi             "xyz.openbmc_project.Dump.Create.CreateParameters.OriginatorType",
101168dd075aSAsmitha Karunanithi             "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Client");
1012f574a8e1SCarson Labrado     }
101368dd075aSAsmitha Karunanithi 
1014a43be80fSAsmitha Karunanithi     crow::connections::systemBus->async_method_call(
10155e7e2dc5SEd Tanous         [asyncResp, payload(task::Payload(req)),
10165e7e2dc5SEd Tanous          dumpPath](const boost::system::error_code& ec,
10175e7e2dc5SEd Tanous                    const sdbusplus::message_t& msg,
10188e31778eSAsmitha Karunanithi                    const sdbusplus::message::object_path& objPath) mutable {
1019a43be80fSAsmitha Karunanithi             if (ec)
1020a43be80fSAsmitha Karunanithi             {
102162598e31SEd Tanous                 BMCWEB_LOG_ERROR("CreateDump resp_handler got error {}", ec);
10225907571dSAsmitha Karunanithi                 const sd_bus_error* dbusError = msg.get_error();
10235907571dSAsmitha Karunanithi                 if (dbusError == nullptr)
10245907571dSAsmitha Karunanithi                 {
10255907571dSAsmitha Karunanithi                     messages::internalError(asyncResp->res);
10265907571dSAsmitha Karunanithi                     return;
10275907571dSAsmitha Karunanithi                 }
10285907571dSAsmitha Karunanithi 
102962598e31SEd Tanous                 BMCWEB_LOG_ERROR("CreateDump DBus error: {} and error msg: {}",
103062598e31SEd Tanous                                  dbusError->name, dbusError->message);
10315907571dSAsmitha Karunanithi                 if (std::string_view(
10325907571dSAsmitha Karunanithi                         "xyz.openbmc_project.Common.Error.NotAllowed") ==
10335907571dSAsmitha Karunanithi                     dbusError->name)
10345907571dSAsmitha Karunanithi                 {
10355907571dSAsmitha Karunanithi                     messages::resourceInStandby(asyncResp->res);
10365907571dSAsmitha Karunanithi                     return;
10375907571dSAsmitha Karunanithi                 }
10385907571dSAsmitha Karunanithi                 if (std::string_view(
10395907571dSAsmitha Karunanithi                         "xyz.openbmc_project.Dump.Create.Error.Disabled") ==
10405907571dSAsmitha Karunanithi                     dbusError->name)
10415907571dSAsmitha Karunanithi                 {
10425907571dSAsmitha Karunanithi                     messages::serviceDisabled(asyncResp->res, dumpPath);
10435907571dSAsmitha Karunanithi                     return;
10445907571dSAsmitha Karunanithi                 }
10455907571dSAsmitha Karunanithi                 if (std::string_view(
10465907571dSAsmitha Karunanithi                         "xyz.openbmc_project.Common.Error.Unavailable") ==
10475907571dSAsmitha Karunanithi                     dbusError->name)
10485907571dSAsmitha Karunanithi                 {
10495907571dSAsmitha Karunanithi                     messages::resourceInUse(asyncResp->res);
10505907571dSAsmitha Karunanithi                     return;
10515907571dSAsmitha Karunanithi                 }
10525907571dSAsmitha Karunanithi                 // Other Dbus errors such as:
10535907571dSAsmitha Karunanithi                 // xyz.openbmc_project.Common.Error.InvalidArgument &
10545907571dSAsmitha Karunanithi                 // org.freedesktop.DBus.Error.InvalidArgs are all related to
10555907571dSAsmitha Karunanithi                 // the dbus call that is made here in the bmcweb
10565907571dSAsmitha Karunanithi                 // implementation and has nothing to do with the client's
10575907571dSAsmitha Karunanithi                 // input in the request. Hence, returning internal error
10585907571dSAsmitha Karunanithi                 // back to the client.
1059a43be80fSAsmitha Karunanithi                 messages::internalError(asyncResp->res);
1060a43be80fSAsmitha Karunanithi                 return;
1061a43be80fSAsmitha Karunanithi             }
106262598e31SEd Tanous             BMCWEB_LOG_DEBUG("Dump Created. Path: {}", objPath.str);
10638e31778eSAsmitha Karunanithi             createDumpTaskCallback(std::move(payload), asyncResp, objPath);
1064a43be80fSAsmitha Karunanithi         },
106518f8f608SEd Tanous         "xyz.openbmc_project.Dump.Manager", getDumpPath(dumpType),
10668e31778eSAsmitha Karunanithi         "xyz.openbmc_project.Dump.Create", "CreateDump", createDumpParamVec);
1067a43be80fSAsmitha Karunanithi }
1068a43be80fSAsmitha Karunanithi 
10698d1b46d7Szhanghch05 inline void clearDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
10708d1b46d7Szhanghch05                       const std::string& dumpType)
107180319af1SAsmitha Karunanithi {
10720d946211SClaire Weinan     crow::connections::systemBus->async_method_call(
10730d946211SClaire Weinan         [asyncResp](const boost::system::error_code& ec) {
107480319af1SAsmitha Karunanithi             if (ec)
107580319af1SAsmitha Karunanithi             {
107662598e31SEd Tanous                 BMCWEB_LOG_ERROR("clearDump resp_handler got error {}", ec);
107780319af1SAsmitha Karunanithi                 messages::internalError(asyncResp->res);
107880319af1SAsmitha Karunanithi                 return;
107980319af1SAsmitha Karunanithi             }
10800d946211SClaire Weinan         },
108118f8f608SEd Tanous         "xyz.openbmc_project.Dump.Manager", getDumpPath(dumpType),
10820d946211SClaire Weinan         "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
108380319af1SAsmitha Karunanithi }
108480319af1SAsmitha Karunanithi 
1085bd79bce8SPatrick Williams inline void parseCrashdumpParameters(
1086bd79bce8SPatrick Williams     const dbus::utility::DBusPropertiesMap& params, std::string& filename,
1087bd79bce8SPatrick Williams     std::string& timestamp, std::string& logfile)
1088043a0536SJohnathan Mantey {
1089d1bde9e5SKrzysztof Grobelny     const std::string* filenamePtr = nullptr;
1090d1bde9e5SKrzysztof Grobelny     const std::string* timestampPtr = nullptr;
1091d1bde9e5SKrzysztof Grobelny     const std::string* logfilePtr = nullptr;
1092d1bde9e5SKrzysztof Grobelny 
1093d1bde9e5SKrzysztof Grobelny     const bool success = sdbusplus::unpackPropertiesNoThrow(
1094d1bde9e5SKrzysztof Grobelny         dbus_utils::UnpackErrorPrinter(), params, "Timestamp", timestampPtr,
1095d1bde9e5SKrzysztof Grobelny         "Filename", filenamePtr, "Log", logfilePtr);
1096d1bde9e5SKrzysztof Grobelny 
1097d1bde9e5SKrzysztof Grobelny     if (!success)
1098043a0536SJohnathan Mantey     {
1099d1bde9e5SKrzysztof Grobelny         return;
1100043a0536SJohnathan Mantey     }
1101d1bde9e5SKrzysztof Grobelny 
1102d1bde9e5SKrzysztof Grobelny     if (filenamePtr != nullptr)
1103043a0536SJohnathan Mantey     {
1104d1bde9e5SKrzysztof Grobelny         filename = *filenamePtr;
1105d1bde9e5SKrzysztof Grobelny     }
1106d1bde9e5SKrzysztof Grobelny 
1107d1bde9e5SKrzysztof Grobelny     if (timestampPtr != nullptr)
1108043a0536SJohnathan Mantey     {
1109d1bde9e5SKrzysztof Grobelny         timestamp = *timestampPtr;
1110043a0536SJohnathan Mantey     }
1111d1bde9e5SKrzysztof Grobelny 
1112d1bde9e5SKrzysztof Grobelny     if (logfilePtr != nullptr)
1113043a0536SJohnathan Mantey     {
1114d1bde9e5SKrzysztof Grobelny         logfile = *logfilePtr;
1115043a0536SJohnathan Mantey     }
1116043a0536SJohnathan Mantey }
1117043a0536SJohnathan Mantey 
11187e860f15SJohn Edward Broadbent inline void requestRoutesSystemLogServiceCollection(App& app)
11191da66f75SEd Tanous {
1120c4bf6374SJason M. Bills     /**
1121c4bf6374SJason M. Bills      * Functions triggers appropriate requests on DBus
1122c4bf6374SJason M. Bills      */
112322d268cbSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/")
1124ed398213SEd Tanous         .privileges(redfish::privileges::getLogServiceCollection)
1125bd79bce8SPatrick Williams         .methods(
1126bd79bce8SPatrick Williams             boost::beast::http::verb::
1127bd79bce8SPatrick Williams                 get)([&app](const crow::Request& req,
112822d268cbSEd Tanous                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
112922d268cbSEd Tanous                             const std::string& systemName) {
11303ba00073SCarson Labrado             if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1131c4bf6374SJason M. Bills             {
113245ca1b86SEd Tanous                 return;
113345ca1b86SEd Tanous             }
113425b54dbaSEd Tanous             if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
11357f3e84a1SEd Tanous             {
11367f3e84a1SEd Tanous                 // Option currently returns no systems.  TBD
11377f3e84a1SEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
11387f3e84a1SEd Tanous                                            systemName);
11397f3e84a1SEd Tanous                 return;
11407f3e84a1SEd Tanous             }
1141253f11b8SEd Tanous             if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
114222d268cbSEd Tanous             {
114322d268cbSEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
114422d268cbSEd Tanous                                            systemName);
114522d268cbSEd Tanous                 return;
114622d268cbSEd Tanous             }
114722d268cbSEd Tanous 
11487e860f15SJohn Edward Broadbent             // Collections don't include the static data added by SubRoute
11497e860f15SJohn Edward Broadbent             // because it has a duplicate entry for members
1150c4bf6374SJason M. Bills             asyncResp->res.jsonValue["@odata.type"] =
1151c4bf6374SJason M. Bills                 "#LogServiceCollection.LogServiceCollection";
1152c4bf6374SJason M. Bills             asyncResp->res.jsonValue["@odata.id"] =
1153253f11b8SEd Tanous                 std::format("/redfish/v1/Systems/{}/LogServices",
1154253f11b8SEd Tanous                             BMCWEB_REDFISH_SYSTEM_URI_NAME);
115545ca1b86SEd Tanous             asyncResp->res.jsonValue["Name"] = "System Log Services Collection";
1156c4bf6374SJason M. Bills             asyncResp->res.jsonValue["Description"] =
1157c4bf6374SJason M. Bills                 "Collection of LogServices for this Computer System";
1158bd79bce8SPatrick Williams             nlohmann::json& logServiceArray =
1159bd79bce8SPatrick Williams                 asyncResp->res.jsonValue["Members"];
1160c4bf6374SJason M. Bills             logServiceArray = nlohmann::json::array();
11611476687dSEd Tanous             nlohmann::json::object_t eventLog;
11621476687dSEd Tanous             eventLog["@odata.id"] =
1163253f11b8SEd Tanous                 std::format("/redfish/v1/Systems/{}/LogServices/EventLog",
1164253f11b8SEd Tanous                             BMCWEB_REDFISH_SYSTEM_URI_NAME);
1165b2ba3072SPatrick Williams             logServiceArray.emplace_back(std::move(eventLog));
116625b54dbaSEd Tanous             if constexpr (BMCWEB_REDFISH_DUMP_LOG)
116725b54dbaSEd Tanous             {
11681476687dSEd Tanous                 nlohmann::json::object_t dumpLog;
116925b54dbaSEd Tanous                 dumpLog["@odata.id"] =
1170253f11b8SEd Tanous                     std::format("/redfish/v1/Systems/{}/LogServices/Dump",
1171253f11b8SEd Tanous                                 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1172b2ba3072SPatrick Williams                 logServiceArray.emplace_back(std::move(dumpLog));
117325b54dbaSEd Tanous             }
1174c9bb6861Sraviteja-b 
11755ffd11f2SGunnar Mills             if constexpr (BMCWEB_REDFISH_CPU_LOG)
117625b54dbaSEd Tanous             {
11771476687dSEd Tanous                 nlohmann::json::object_t crashdump;
11781476687dSEd Tanous                 crashdump["@odata.id"] =
1179253f11b8SEd Tanous                     std::format("/redfish/v1/Systems/{}/LogServices/Crashdump",
1180253f11b8SEd Tanous                                 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1181b2ba3072SPatrick Williams                 logServiceArray.emplace_back(std::move(crashdump));
118225b54dbaSEd Tanous             }
1183b7028ebfSSpencer Ku 
118425b54dbaSEd Tanous             if constexpr (BMCWEB_REDFISH_HOST_LOGGER)
118525b54dbaSEd Tanous             {
11861476687dSEd Tanous                 nlohmann::json::object_t hostlogger;
11871476687dSEd Tanous                 hostlogger["@odata.id"] =
1188253f11b8SEd Tanous                     std::format("/redfish/v1/Systems/{}/LogServices/HostLogger",
1189253f11b8SEd Tanous                                 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1190b2ba3072SPatrick Williams                 logServiceArray.emplace_back(std::move(hostlogger));
119125b54dbaSEd Tanous             }
1192c4bf6374SJason M. Bills             asyncResp->res.jsonValue["Members@odata.count"] =
1193c4bf6374SJason M. Bills                 logServiceArray.size();
1194a3316fc6SZhikuiRen 
11957a1dbc48SGeorge Liu             constexpr std::array<std::string_view, 1> interfaces = {
11967a1dbc48SGeorge Liu                 "xyz.openbmc_project.State.Boot.PostCode"};
11977a1dbc48SGeorge Liu             dbus::utility::getSubTreePaths(
11987a1dbc48SGeorge Liu                 "/", 0, interfaces,
11997a1dbc48SGeorge Liu                 [asyncResp](const boost::system::error_code& ec,
1200b9d36b47SEd Tanous                             const dbus::utility::MapperGetSubTreePathsResponse&
1201b9d36b47SEd Tanous                                 subtreePath) {
1202a3316fc6SZhikuiRen                     if (ec)
1203a3316fc6SZhikuiRen                     {
120462598e31SEd Tanous                         BMCWEB_LOG_ERROR("{}", ec);
1205a3316fc6SZhikuiRen                         return;
1206a3316fc6SZhikuiRen                     }
1207a3316fc6SZhikuiRen 
120855f79e6fSEd Tanous                     for (const auto& pathStr : subtreePath)
1209a3316fc6SZhikuiRen                     {
1210a3316fc6SZhikuiRen                         if (pathStr.find("PostCode") != std::string::npos)
1211a3316fc6SZhikuiRen                         {
121223a21a1cSEd Tanous                             nlohmann::json& logServiceArrayLocal =
1213a3316fc6SZhikuiRen                                 asyncResp->res.jsonValue["Members"];
1214613dabeaSEd Tanous                             nlohmann::json::object_t member;
1215253f11b8SEd Tanous                             member["@odata.id"] = std::format(
1216253f11b8SEd Tanous                                 "/redfish/v1/Systems/{}/LogServices/PostCodes",
1217253f11b8SEd Tanous                                 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1218613dabeaSEd Tanous 
1219bd79bce8SPatrick Williams                             logServiceArrayLocal.emplace_back(
1220bd79bce8SPatrick Williams                                 std::move(member));
1221613dabeaSEd Tanous 
122245ca1b86SEd Tanous                             asyncResp->res.jsonValue["Members@odata.count"] =
122323a21a1cSEd Tanous                                 logServiceArrayLocal.size();
1224a3316fc6SZhikuiRen                             return;
1225a3316fc6SZhikuiRen                         }
1226a3316fc6SZhikuiRen                     }
12277a1dbc48SGeorge Liu                 });
12287e860f15SJohn Edward Broadbent         });
1229c4bf6374SJason M. Bills }
1230c4bf6374SJason M. Bills 
12317e860f15SJohn Edward Broadbent inline void requestRoutesEventLogService(App& app)
1232c4bf6374SJason M. Bills {
123322d268cbSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/")
1234ed398213SEd Tanous         .privileges(redfish::privileges::getLogService)
1235bd79bce8SPatrick Williams         .methods(
1236bd79bce8SPatrick Williams             boost::beast::http::verb::
1237bd79bce8SPatrick Williams                 get)([&app](const crow::Request& req,
123822d268cbSEd Tanous                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
123922d268cbSEd Tanous                             const std::string& systemName) {
12403ba00073SCarson Labrado             if (!redfish::setUpRedfishRoute(app, req, asyncResp))
124145ca1b86SEd Tanous             {
124245ca1b86SEd Tanous                 return;
124345ca1b86SEd Tanous             }
1244253f11b8SEd Tanous             if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
124522d268cbSEd Tanous             {
124622d268cbSEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
124722d268cbSEd Tanous                                            systemName);
124822d268cbSEd Tanous                 return;
124922d268cbSEd Tanous             }
1250c4bf6374SJason M. Bills             asyncResp->res.jsonValue["@odata.id"] =
1251253f11b8SEd Tanous                 std::format("/redfish/v1/Systems/{}/LogServices/EventLog",
1252253f11b8SEd Tanous                             BMCWEB_REDFISH_SYSTEM_URI_NAME);
1253c4bf6374SJason M. Bills             asyncResp->res.jsonValue["@odata.type"] =
1254b25644a1SJanet Adkins                 "#LogService.v1_2_0.LogService";
1255c4bf6374SJason M. Bills             asyncResp->res.jsonValue["Name"] = "Event Log Service";
1256bd79bce8SPatrick Williams             asyncResp->res.jsonValue["Description"] =
1257bd79bce8SPatrick Williams                 "System Event Log Service";
1258c4bf6374SJason M. Bills             asyncResp->res.jsonValue["Id"] = "EventLog";
1259539d8c6bSEd Tanous             asyncResp->res.jsonValue["OverWritePolicy"] =
1260539d8c6bSEd Tanous                 log_service::OverWritePolicy::WrapsWhenFull;
12617c8c4058STejas Patil 
12627c8c4058STejas Patil             std::pair<std::string, std::string> redfishDateTimeOffset =
12632b82937eSEd Tanous                 redfish::time_utils::getDateTimeOffsetNow();
12647c8c4058STejas Patil 
12657c8c4058STejas Patil             asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
12667c8c4058STejas Patil             asyncResp->res.jsonValue["DateTimeLocalOffset"] =
12677c8c4058STejas Patil                 redfishDateTimeOffset.second;
12687c8c4058STejas Patil 
1269bd79bce8SPatrick Williams             asyncResp->res.jsonValue["Entries"]["@odata.id"] = std::format(
1270bd79bce8SPatrick Williams                 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
1271253f11b8SEd Tanous                 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1272bd79bce8SPatrick Williams             asyncResp->res
1273bd79bce8SPatrick Williams                 .jsonValue["Actions"]["#LogService.ClearLog"]["target"]
1274e7d6c8b2SGunnar Mills 
127520fa6a2cSEd Tanous                 = std::format(
1276253f11b8SEd Tanous                     "/redfish/v1/Systems/{}/LogServices/EventLog/Actions/LogService.ClearLog",
127720fa6a2cSEd Tanous                     BMCWEB_REDFISH_SYSTEM_URI_NAME);
12787e860f15SJohn Edward Broadbent         });
1279489640c6SJason M. Bills }
1280489640c6SJason M. Bills 
1281599b9af3SAlexander Hansen inline void handleSystemsLogServicesEventLogActionsClearPost(
1282599b9af3SAlexander Hansen     App& app, const crow::Request& req,
128322d268cbSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1284599b9af3SAlexander Hansen     const std::string& systemName)
1285599b9af3SAlexander Hansen {
12863ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
128745ca1b86SEd Tanous     {
128845ca1b86SEd Tanous         return;
128945ca1b86SEd Tanous     }
1290253f11b8SEd Tanous     if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
129122d268cbSEd Tanous     {
129222d268cbSEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
129322d268cbSEd Tanous                                    systemName);
129422d268cbSEd Tanous         return;
129522d268cbSEd Tanous     }
1296599b9af3SAlexander Hansen 
1297489640c6SJason M. Bills     // Clear the EventLog by deleting the log files
1298489640c6SJason M. Bills     std::vector<std::filesystem::path> redfishLogFiles;
1299489640c6SJason M. Bills     if (getRedfishLogFiles(redfishLogFiles))
1300489640c6SJason M. Bills     {
1301489640c6SJason M. Bills         for (const std::filesystem::path& file : redfishLogFiles)
1302489640c6SJason M. Bills         {
1303489640c6SJason M. Bills             std::error_code ec;
1304489640c6SJason M. Bills             std::filesystem::remove(file, ec);
1305489640c6SJason M. Bills         }
1306489640c6SJason M. Bills     }
1307489640c6SJason M. Bills 
1308489640c6SJason M. Bills     // Reload rsyslog so it knows to start new log files
1309489640c6SJason M. Bills     crow::connections::systemBus->async_method_call(
13105e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
1311489640c6SJason M. Bills             if (ec)
1312489640c6SJason M. Bills             {
131362598e31SEd Tanous                 BMCWEB_LOG_ERROR("Failed to reload rsyslog: {}", ec);
1314489640c6SJason M. Bills                 messages::internalError(asyncResp->res);
1315489640c6SJason M. Bills                 return;
1316489640c6SJason M. Bills             }
1317489640c6SJason M. Bills 
1318489640c6SJason M. Bills             messages::success(asyncResp->res);
1319489640c6SJason M. Bills         },
1320489640c6SJason M. Bills         "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
1321002d39b4SEd Tanous         "org.freedesktop.systemd1.Manager", "ReloadUnit", "rsyslog.service",
1322002d39b4SEd Tanous         "replace");
1323599b9af3SAlexander Hansen }
1324599b9af3SAlexander Hansen 
1325599b9af3SAlexander Hansen inline void requestRoutesJournalEventLogClear(App& app)
1326599b9af3SAlexander Hansen {
1327599b9af3SAlexander Hansen     BMCWEB_ROUTE(
1328599b9af3SAlexander Hansen         app,
1329599b9af3SAlexander Hansen         "/redfish/v1/Systems/<str>/LogServices/EventLog/Actions/LogService.ClearLog/")
1330599b9af3SAlexander Hansen         .privileges({{"ConfigureComponents"}})
1331599b9af3SAlexander Hansen         .methods(boost::beast::http::verb::post)(std::bind_front(
1332599b9af3SAlexander Hansen             handleSystemsLogServicesEventLogActionsClearPost, std::ref(app)));
1333c4bf6374SJason M. Bills }
1334c4bf6374SJason M. Bills 
1335ac992cdeSJason M. Bills enum class LogParseError
1336ac992cdeSJason M. Bills {
1337ac992cdeSJason M. Bills     success,
1338ac992cdeSJason M. Bills     parseFailed,
1339ac992cdeSJason M. Bills     messageIdNotInRegistry,
1340ac992cdeSJason M. Bills };
1341ac992cdeSJason M. Bills 
1342bd79bce8SPatrick Williams static LogParseError fillEventLogEntryJson(
1343bd79bce8SPatrick Williams     const std::string& logEntryID, const std::string& logEntry,
1344de703c5dSJason M. Bills     nlohmann::json::object_t& logEntryJson)
1345c4bf6374SJason M. Bills {
134695820184SJason M. Bills     // The redfish log format is "<Timestamp> <MessageId>,<MessageArgs>"
1347cd225da8SJason M. Bills     // First get the Timestamp
1348f23b7296SEd Tanous     size_t space = logEntry.find_first_of(' ');
1349cd225da8SJason M. Bills     if (space == std::string::npos)
135095820184SJason M. Bills     {
1351ac992cdeSJason M. Bills         return LogParseError::parseFailed;
135295820184SJason M. Bills     }
1353cd225da8SJason M. Bills     std::string timestamp = logEntry.substr(0, space);
1354cd225da8SJason M. Bills     // Then get the log contents
1355f23b7296SEd Tanous     size_t entryStart = logEntry.find_first_not_of(' ', space);
1356cd225da8SJason M. Bills     if (entryStart == std::string::npos)
1357cd225da8SJason M. Bills     {
1358ac992cdeSJason M. Bills         return LogParseError::parseFailed;
1359cd225da8SJason M. Bills     }
1360cd225da8SJason M. Bills     std::string_view entry(logEntry);
1361cd225da8SJason M. Bills     entry.remove_prefix(entryStart);
1362cd225da8SJason M. Bills     // Use split to separate the entry into its fields
1363cd225da8SJason M. Bills     std::vector<std::string> logEntryFields;
136450ebd4afSEd Tanous     bmcweb::split(logEntryFields, entry, ',');
1365cd225da8SJason M. Bills     // We need at least a MessageId to be valid
13661e6deaf6SEd Tanous     auto logEntryIter = logEntryFields.begin();
13671e6deaf6SEd Tanous     if (logEntryIter == logEntryFields.end())
1368cd225da8SJason M. Bills     {
1369ac992cdeSJason M. Bills         return LogParseError::parseFailed;
1370cd225da8SJason M. Bills     }
13711e6deaf6SEd Tanous     std::string& messageID = *logEntryIter;
13724851d45dSJason M. Bills     // Get the Message from the MessageRegistry
1373fffb8c1fSEd Tanous     const registries::Message* message = registries::getMessage(messageID);
1374c4bf6374SJason M. Bills 
13751e6deaf6SEd Tanous     logEntryIter++;
137654417b02SSui Chen     if (message == nullptr)
1377c4bf6374SJason M. Bills     {
137862598e31SEd Tanous         BMCWEB_LOG_WARNING("Log entry not found in registry: {}", logEntry);
1379ac992cdeSJason M. Bills         return LogParseError::messageIdNotInRegistry;
1380c4bf6374SJason M. Bills     }
1381c4bf6374SJason M. Bills 
13821e6deaf6SEd Tanous     std::vector<std::string_view> messageArgs(logEntryIter,
13831e6deaf6SEd Tanous                                               logEntryFields.end());
1384c05bba45SEd Tanous     messageArgs.resize(message->numberOfArgs);
1385c05bba45SEd Tanous 
1386bd79bce8SPatrick Williams     std::string msg =
1387bd79bce8SPatrick Williams         redfish::registries::fillMessageArgs(messageArgs, message->message);
13881e6deaf6SEd Tanous     if (msg.empty())
138915a86ff6SJason M. Bills     {
13901e6deaf6SEd Tanous         return LogParseError::parseFailed;
139115a86ff6SJason M. Bills     }
13924851d45dSJason M. Bills 
139395820184SJason M. Bills     // Get the Created time from the timestamp. The log timestamp is in RFC3339
139495820184SJason M. Bills     // format which matches the Redfish format except for the fractional seconds
139595820184SJason M. Bills     // between the '.' and the '+', so just remove them.
1396f23b7296SEd Tanous     std::size_t dot = timestamp.find_first_of('.');
1397f23b7296SEd Tanous     std::size_t plus = timestamp.find_first_of('+');
139895820184SJason M. Bills     if (dot != std::string::npos && plus != std::string::npos)
1399c4bf6374SJason M. Bills     {
140095820184SJason M. Bills         timestamp.erase(dot, plus - dot);
1401c4bf6374SJason M. Bills     }
1402c4bf6374SJason M. Bills 
1403c4bf6374SJason M. Bills     // Fill in the log entry with the gathered data
14049c11a172SVijay Lobo     logEntryJson["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
1405ef4c65b7SEd Tanous     logEntryJson["@odata.id"] = boost::urls::format(
1406253f11b8SEd Tanous         "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}",
1407253f11b8SEd Tanous         BMCWEB_REDFISH_SYSTEM_URI_NAME, logEntryID);
140884afc48bSJason M. Bills     logEntryJson["Name"] = "System Event Log Entry";
140984afc48bSJason M. Bills     logEntryJson["Id"] = logEntryID;
141084afc48bSJason M. Bills     logEntryJson["Message"] = std::move(msg);
141184afc48bSJason M. Bills     logEntryJson["MessageId"] = std::move(messageID);
141284afc48bSJason M. Bills     logEntryJson["MessageArgs"] = messageArgs;
141384afc48bSJason M. Bills     logEntryJson["EntryType"] = "Event";
141484afc48bSJason M. Bills     logEntryJson["Severity"] = message->messageSeverity;
141584afc48bSJason M. Bills     logEntryJson["Created"] = std::move(timestamp);
1416ac992cdeSJason M. Bills     return LogParseError::success;
1417c4bf6374SJason M. Bills }
1418c4bf6374SJason M. Bills 
1419898f2aa2SEd Tanous inline void fillEventLogLogEntryFromPropertyMap(
1420898f2aa2SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1421898f2aa2SEd Tanous     const dbus::utility::DBusPropertiesMap& resp,
1422898f2aa2SEd Tanous     nlohmann::json& objectToFillOut)
1423898f2aa2SEd Tanous {
1424262dcc1cSAlexander Hansen     std::optional<DbusEventLogEntry> optEntry =
1425262dcc1cSAlexander Hansen         fillDbusEventLogEntryFromPropertyMap(resp);
1426898f2aa2SEd Tanous 
1427262dcc1cSAlexander Hansen     if (!optEntry.has_value())
1428898f2aa2SEd Tanous     {
1429898f2aa2SEd Tanous         messages::internalError(asyncResp->res);
1430898f2aa2SEd Tanous         return;
1431898f2aa2SEd Tanous     }
1432262dcc1cSAlexander Hansen     DbusEventLogEntry entry = optEntry.value();
1433898f2aa2SEd Tanous 
1434898f2aa2SEd Tanous     objectToFillOut["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
1435898f2aa2SEd Tanous     objectToFillOut["@odata.id"] = boost::urls::format(
1436898f2aa2SEd Tanous         "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}",
1437262dcc1cSAlexander Hansen         BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(entry.Id));
1438898f2aa2SEd Tanous     objectToFillOut["Name"] = "System Event Log Entry";
1439262dcc1cSAlexander Hansen     objectToFillOut["Id"] = std::to_string(entry.Id);
1440262dcc1cSAlexander Hansen     objectToFillOut["Message"] = entry.Message;
1441262dcc1cSAlexander Hansen     objectToFillOut["Resolved"] = entry.Resolved;
1442262dcc1cSAlexander Hansen     std::optional<bool> notifyAction =
1443262dcc1cSAlexander Hansen         getProviderNotifyAction(entry.ServiceProviderNotify);
1444898f2aa2SEd Tanous     if (notifyAction)
1445898f2aa2SEd Tanous     {
1446898f2aa2SEd Tanous         objectToFillOut["ServiceProviderNotified"] = *notifyAction;
1447898f2aa2SEd Tanous     }
1448262dcc1cSAlexander Hansen     if ((entry.Resolution != nullptr) && !entry.Resolution->empty())
1449898f2aa2SEd Tanous     {
1450262dcc1cSAlexander Hansen         objectToFillOut["Resolution"] = *entry.Resolution;
1451898f2aa2SEd Tanous     }
1452898f2aa2SEd Tanous     objectToFillOut["EntryType"] = "Event";
1453262dcc1cSAlexander Hansen     objectToFillOut["Severity"] =
1454262dcc1cSAlexander Hansen         translateSeverityDbusToRedfish(entry.Severity);
1455898f2aa2SEd Tanous     objectToFillOut["Created"] =
1456262dcc1cSAlexander Hansen         redfish::time_utils::getDateTimeUintMs(entry.Timestamp);
1457898f2aa2SEd Tanous     objectToFillOut["Modified"] =
1458262dcc1cSAlexander Hansen         redfish::time_utils::getDateTimeUintMs(entry.UpdateTimestamp);
1459262dcc1cSAlexander Hansen     if (entry.Path != nullptr)
1460898f2aa2SEd Tanous     {
1461898f2aa2SEd Tanous         objectToFillOut["AdditionalDataURI"] = boost::urls::format(
1462898f2aa2SEd Tanous             "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}/attachment",
1463262dcc1cSAlexander Hansen             BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(entry.Id));
1464898f2aa2SEd Tanous     }
1465898f2aa2SEd Tanous }
1466898f2aa2SEd Tanous 
1467b729096dSEd Tanous inline void afterLogEntriesGetManagedObjects(
1468b729096dSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1469b729096dSEd Tanous     const boost::system::error_code& ec,
1470b729096dSEd Tanous     const dbus::utility::ManagedObjectType& resp)
1471b729096dSEd Tanous {
1472b729096dSEd Tanous     if (ec)
1473b729096dSEd Tanous     {
1474b729096dSEd Tanous         // TODO Handle for specific error code
1475b729096dSEd Tanous         BMCWEB_LOG_ERROR("getLogEntriesIfaceData resp_handler got error {}",
1476b729096dSEd Tanous                          ec);
1477b729096dSEd Tanous         messages::internalError(asyncResp->res);
1478b729096dSEd Tanous         return;
1479b729096dSEd Tanous     }
1480b729096dSEd Tanous     nlohmann::json::array_t entriesArray;
1481b729096dSEd Tanous     for (const auto& objectPath : resp)
1482b729096dSEd Tanous     {
1483898f2aa2SEd Tanous         dbus::utility::DBusPropertiesMap propsFlattened;
1484bd79bce8SPatrick Williams         auto isEntry =
1485bd79bce8SPatrick Williams             std::ranges::find_if(objectPath.second, [](const auto& object) {
1486898f2aa2SEd Tanous                 return object.first == "xyz.openbmc_project.Logging.Entry";
1487898f2aa2SEd Tanous             });
1488898f2aa2SEd Tanous         if (isEntry == objectPath.second.end())
1489b729096dSEd Tanous         {
1490b729096dSEd Tanous             continue;
1491b729096dSEd Tanous         }
1492898f2aa2SEd Tanous         for (const auto& interfaceMap : objectPath.second)
1493b729096dSEd Tanous         {
1494898f2aa2SEd Tanous             for (const auto& propertyMap : interfaceMap.second)
1495b729096dSEd Tanous             {
1496898f2aa2SEd Tanous                 propsFlattened.emplace_back(propertyMap.first,
1497898f2aa2SEd Tanous                                             propertyMap.second);
1498b729096dSEd Tanous             }
1499b729096dSEd Tanous         }
1500898f2aa2SEd Tanous         fillEventLogLogEntryFromPropertyMap(asyncResp, propsFlattened,
1501898f2aa2SEd Tanous                                             entriesArray.emplace_back());
1502b729096dSEd Tanous     }
1503898f2aa2SEd Tanous 
1504b729096dSEd Tanous     std::ranges::sort(entriesArray, [](const nlohmann::json& left,
1505b729096dSEd Tanous                                        const nlohmann::json& right) {
1506b729096dSEd Tanous         return (left["Id"] <= right["Id"]);
1507b729096dSEd Tanous     });
1508b729096dSEd Tanous     asyncResp->res.jsonValue["Members@odata.count"] = entriesArray.size();
1509b729096dSEd Tanous     asyncResp->res.jsonValue["Members"] = std::move(entriesArray);
1510b729096dSEd Tanous }
1511b729096dSEd Tanous 
1512599b9af3SAlexander Hansen inline void handleSystemsLogServiceEventLogLogEntryCollection(
1513599b9af3SAlexander Hansen     App& app, const crow::Request& req,
151422d268cbSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1515599b9af3SAlexander Hansen     const std::string& systemName)
1516599b9af3SAlexander Hansen {
1517c937d2bfSEd Tanous     query_param::QueryCapabilities capabilities = {
1518c937d2bfSEd Tanous         .canDelegateTop = true,
1519c937d2bfSEd Tanous         .canDelegateSkip = true,
1520c937d2bfSEd Tanous     };
1521c937d2bfSEd Tanous     query_param::Query delegatedQuery;
1522599b9af3SAlexander Hansen     if (!redfish::setUpRedfishRouteWithDelegation(app, req, asyncResp,
1523599b9af3SAlexander Hansen                                                   delegatedQuery, capabilities))
1524c4bf6374SJason M. Bills     {
1525c4bf6374SJason M. Bills         return;
1526c4bf6374SJason M. Bills     }
152725b54dbaSEd Tanous     if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
15287f3e84a1SEd Tanous     {
15297f3e84a1SEd Tanous         // Option currently returns no systems.  TBD
15307f3e84a1SEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
15317f3e84a1SEd Tanous                                    systemName);
15327f3e84a1SEd Tanous         return;
15337f3e84a1SEd Tanous     }
1534253f11b8SEd Tanous     if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
153522d268cbSEd Tanous     {
153622d268cbSEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
153722d268cbSEd Tanous                                    systemName);
153822d268cbSEd Tanous         return;
153922d268cbSEd Tanous     }
154022d268cbSEd Tanous 
15415143f7a5SJiaqing Zhao     size_t top = delegatedQuery.top.value_or(query_param::Query::maxTop);
15423648c8beSEd Tanous     size_t skip = delegatedQuery.skip.value_or(0);
15433648c8beSEd Tanous 
15447e860f15SJohn Edward Broadbent     // Collections don't include the static data added by SubRoute
15457e860f15SJohn Edward Broadbent     // because it has a duplicate entry for members
1546c4bf6374SJason M. Bills     asyncResp->res.jsonValue["@odata.type"] =
1547c4bf6374SJason M. Bills         "#LogEntryCollection.LogEntryCollection";
1548c4bf6374SJason M. Bills     asyncResp->res.jsonValue["@odata.id"] =
1549253f11b8SEd Tanous         std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
1550253f11b8SEd Tanous                     BMCWEB_REDFISH_SYSTEM_URI_NAME);
1551c4bf6374SJason M. Bills     asyncResp->res.jsonValue["Name"] = "System Event Log Entries";
1552c4bf6374SJason M. Bills     asyncResp->res.jsonValue["Description"] =
1553c4bf6374SJason M. Bills         "Collection of System Event Log Entries";
1554cb92c03bSAndrew Geissler 
15554978b63fSJason M. Bills     nlohmann::json& logEntryArray = asyncResp->res.jsonValue["Members"];
1556c4bf6374SJason M. Bills     logEntryArray = nlohmann::json::array();
15577e860f15SJohn Edward Broadbent     // Go through the log files and create a unique ID for each
15587e860f15SJohn Edward Broadbent     // entry
155995820184SJason M. Bills     std::vector<std::filesystem::path> redfishLogFiles;
156095820184SJason M. Bills     getRedfishLogFiles(redfishLogFiles);
1561b01bf299SEd Tanous     uint64_t entryCount = 0;
1562cd225da8SJason M. Bills     std::string logEntry;
156395820184SJason M. Bills 
15647e860f15SJohn Edward Broadbent     // Oldest logs are in the last file, so start there and loop
15657e860f15SJohn Edward Broadbent     // backwards
1566599b9af3SAlexander Hansen     for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend(); it++)
1567c4bf6374SJason M. Bills     {
1568cd225da8SJason M. Bills         std::ifstream logStream(*it);
156995820184SJason M. Bills         if (!logStream.is_open())
1570c4bf6374SJason M. Bills         {
1571c4bf6374SJason M. Bills             continue;
1572c4bf6374SJason M. Bills         }
1573c4bf6374SJason M. Bills 
1574e85d6b16SJason M. Bills         // Reset the unique ID on the first entry
1575e85d6b16SJason M. Bills         bool firstEntry = true;
157695820184SJason M. Bills         while (std::getline(logStream, logEntry))
157795820184SJason M. Bills         {
1578c4bf6374SJason M. Bills             std::string idStr;
1579e85d6b16SJason M. Bills             if (!getUniqueEntryID(logEntry, idStr, firstEntry))
1580c4bf6374SJason M. Bills             {
1581c4bf6374SJason M. Bills                 continue;
1582c4bf6374SJason M. Bills             }
1583e85d6b16SJason M. Bills             firstEntry = false;
1584e85d6b16SJason M. Bills 
1585de703c5dSJason M. Bills             nlohmann::json::object_t bmcLogEntry;
1586bd79bce8SPatrick Williams             LogParseError status =
1587bd79bce8SPatrick Williams                 fillEventLogEntryJson(idStr, logEntry, bmcLogEntry);
1588ac992cdeSJason M. Bills             if (status == LogParseError::messageIdNotInRegistry)
1589ac992cdeSJason M. Bills             {
1590ac992cdeSJason M. Bills                 continue;
1591ac992cdeSJason M. Bills             }
1592ac992cdeSJason M. Bills             if (status != LogParseError::success)
1593c4bf6374SJason M. Bills             {
1594c4bf6374SJason M. Bills                 messages::internalError(asyncResp->res);
1595c4bf6374SJason M. Bills                 return;
1596c4bf6374SJason M. Bills             }
1597de703c5dSJason M. Bills 
1598de703c5dSJason M. Bills             entryCount++;
1599de703c5dSJason M. Bills             // Handle paging using skip (number of entries to skip from the
1600de703c5dSJason M. Bills             // start) and top (number of entries to display)
16013648c8beSEd Tanous             if (entryCount <= skip || entryCount > skip + top)
1602de703c5dSJason M. Bills             {
1603de703c5dSJason M. Bills                 continue;
1604de703c5dSJason M. Bills             }
1605de703c5dSJason M. Bills 
1606b2ba3072SPatrick Williams             logEntryArray.emplace_back(std::move(bmcLogEntry));
1607c4bf6374SJason M. Bills         }
160895820184SJason M. Bills     }
1609c4bf6374SJason M. Bills     asyncResp->res.jsonValue["Members@odata.count"] = entryCount;
16103648c8beSEd Tanous     if (skip + top < entryCount)
1611c4bf6374SJason M. Bills     {
1612599b9af3SAlexander Hansen         asyncResp->res.jsonValue["Members@odata.nextLink"] =
1613599b9af3SAlexander Hansen             boost::urls::format(
1614253f11b8SEd Tanous                 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries?$skip={}",
1615253f11b8SEd Tanous                 BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(skip + top));
1616c4bf6374SJason M. Bills     }
1617897967deSJason M. Bills }
1618897967deSJason M. Bills 
1619599b9af3SAlexander Hansen inline void requestRoutesJournalEventLogEntryCollection(App& app)
1620897967deSJason M. Bills {
1621599b9af3SAlexander Hansen     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/")
1622599b9af3SAlexander Hansen         .privileges(redfish::privileges::getLogEntryCollection)
1623599b9af3SAlexander Hansen         .methods(boost::beast::http::verb::get)(std::bind_front(
1624599b9af3SAlexander Hansen             handleSystemsLogServiceEventLogLogEntryCollection, std::ref(app)));
1625599b9af3SAlexander Hansen }
1626599b9af3SAlexander Hansen 
1627599b9af3SAlexander Hansen inline void handleSystemsLogServiceEventLogEntriesGet(
1628599b9af3SAlexander Hansen     App& app, const crow::Request& req,
16297e860f15SJohn Edward Broadbent     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1630599b9af3SAlexander Hansen     const std::string& systemName, const std::string& param)
1631599b9af3SAlexander Hansen {
16323ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
163345ca1b86SEd Tanous     {
163445ca1b86SEd Tanous         return;
163545ca1b86SEd Tanous     }
163625b54dbaSEd Tanous     if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
16377f3e84a1SEd Tanous     {
16387f3e84a1SEd Tanous         // Option currently returns no systems.  TBD
16397f3e84a1SEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
16407f3e84a1SEd Tanous                                    systemName);
16417f3e84a1SEd Tanous         return;
16427f3e84a1SEd Tanous     }
164322d268cbSEd Tanous 
1644253f11b8SEd Tanous     if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
164522d268cbSEd Tanous     {
164622d268cbSEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
164722d268cbSEd Tanous                                    systemName);
164822d268cbSEd Tanous         return;
164922d268cbSEd Tanous     }
165022d268cbSEd Tanous 
16517e860f15SJohn Edward Broadbent     const std::string& targetID = param;
16528d1b46d7Szhanghch05 
16537e860f15SJohn Edward Broadbent     // Go through the log files and check the unique ID for each
16547e860f15SJohn Edward Broadbent     // entry to find the target entry
1655897967deSJason M. Bills     std::vector<std::filesystem::path> redfishLogFiles;
1656897967deSJason M. Bills     getRedfishLogFiles(redfishLogFiles);
1657897967deSJason M. Bills     std::string logEntry;
1658897967deSJason M. Bills 
16597e860f15SJohn Edward Broadbent     // Oldest logs are in the last file, so start there and loop
16607e860f15SJohn Edward Broadbent     // backwards
1661599b9af3SAlexander Hansen     for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend(); it++)
1662897967deSJason M. Bills     {
1663897967deSJason M. Bills         std::ifstream logStream(*it);
1664897967deSJason M. Bills         if (!logStream.is_open())
1665897967deSJason M. Bills         {
1666897967deSJason M. Bills             continue;
1667897967deSJason M. Bills         }
1668897967deSJason M. Bills 
1669897967deSJason M. Bills         // Reset the unique ID on the first entry
1670897967deSJason M. Bills         bool firstEntry = true;
1671897967deSJason M. Bills         while (std::getline(logStream, logEntry))
1672897967deSJason M. Bills         {
1673897967deSJason M. Bills             std::string idStr;
1674897967deSJason M. Bills             if (!getUniqueEntryID(logEntry, idStr, firstEntry))
1675897967deSJason M. Bills             {
1676897967deSJason M. Bills                 continue;
1677897967deSJason M. Bills             }
1678897967deSJason M. Bills             firstEntry = false;
1679897967deSJason M. Bills 
1680897967deSJason M. Bills             if (idStr == targetID)
1681897967deSJason M. Bills             {
1682de703c5dSJason M. Bills                 nlohmann::json::object_t bmcLogEntry;
1683bd79bce8SPatrick Williams                 LogParseError status =
1684bd79bce8SPatrick Williams                     fillEventLogEntryJson(idStr, logEntry, bmcLogEntry);
1685ac992cdeSJason M. Bills                 if (status != LogParseError::success)
1686897967deSJason M. Bills                 {
1687897967deSJason M. Bills                     messages::internalError(asyncResp->res);
1688897967deSJason M. Bills                     return;
1689897967deSJason M. Bills                 }
1690d405bb51SJason M. Bills                 asyncResp->res.jsonValue.update(bmcLogEntry);
1691897967deSJason M. Bills                 return;
1692897967deSJason M. Bills             }
1693897967deSJason M. Bills         }
1694897967deSJason M. Bills     }
1695897967deSJason M. Bills     // Requested ID was not found
16969db4ba25SJiaqing Zhao     messages::resourceNotFound(asyncResp->res, "LogEntry", targetID);
1697599b9af3SAlexander Hansen }
1698599b9af3SAlexander Hansen 
1699599b9af3SAlexander Hansen inline void requestRoutesJournalEventLogEntry(App& app)
1700599b9af3SAlexander Hansen {
1701599b9af3SAlexander Hansen     BMCWEB_ROUTE(
1702599b9af3SAlexander Hansen         app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
1703599b9af3SAlexander Hansen         .privileges(redfish::privileges::getLogEntry)
1704599b9af3SAlexander Hansen         .methods(boost::beast::http::verb::get)(std::bind_front(
1705599b9af3SAlexander Hansen             handleSystemsLogServiceEventLogEntriesGet, std::ref(app)));
1706599b9af3SAlexander Hansen }
1707599b9af3SAlexander Hansen 
1708599b9af3SAlexander Hansen inline void dBusEventLogEntryCollection(
1709599b9af3SAlexander Hansen     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1710599b9af3SAlexander Hansen {
1711599b9af3SAlexander Hansen     // Collections don't include the static data added by SubRoute
1712599b9af3SAlexander Hansen     // because it has a duplicate entry for members
1713599b9af3SAlexander Hansen     asyncResp->res.jsonValue["@odata.type"] =
1714599b9af3SAlexander Hansen         "#LogEntryCollection.LogEntryCollection";
1715599b9af3SAlexander Hansen     asyncResp->res.jsonValue["@odata.id"] =
1716599b9af3SAlexander Hansen         std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
1717599b9af3SAlexander Hansen                     BMCWEB_REDFISH_SYSTEM_URI_NAME);
1718599b9af3SAlexander Hansen     asyncResp->res.jsonValue["Name"] = "System Event Log Entries";
1719599b9af3SAlexander Hansen     asyncResp->res.jsonValue["Description"] =
1720599b9af3SAlexander Hansen         "Collection of System Event Log Entries";
1721599b9af3SAlexander Hansen 
1722599b9af3SAlexander Hansen     // DBus implementation of EventLog/Entries
1723599b9af3SAlexander Hansen     // Make call to Logging Service to find all log entry objects
1724599b9af3SAlexander Hansen     sdbusplus::message::object_path path("/xyz/openbmc_project/logging");
1725599b9af3SAlexander Hansen     dbus::utility::getManagedObjects(
1726599b9af3SAlexander Hansen         "xyz.openbmc_project.Logging", path,
1727599b9af3SAlexander Hansen         [asyncResp](const boost::system::error_code& ec,
1728599b9af3SAlexander Hansen                     const dbus::utility::ManagedObjectType& resp) {
1729b729096dSEd Tanous             afterLogEntriesGetManagedObjects(asyncResp, ec, resp);
17307e860f15SJohn Edward Broadbent         });
173108a4e4b5SAnthony Wilson }
173208a4e4b5SAnthony Wilson 
17337e860f15SJohn Edward Broadbent inline void requestRoutesDBusEventLogEntryCollection(App& app)
173408a4e4b5SAnthony Wilson {
173522d268cbSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/")
1736ed398213SEd Tanous         .privileges(redfish::privileges::getLogEntryCollection)
1737002d39b4SEd Tanous         .methods(boost::beast::http::verb::get)(
1738002d39b4SEd Tanous             [&app](const crow::Request& req,
173922d268cbSEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
174022d268cbSEd Tanous                    const std::string& systemName) {
17413ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
174245ca1b86SEd Tanous                 {
174345ca1b86SEd Tanous                     return;
174445ca1b86SEd Tanous                 }
174525b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
17467f3e84a1SEd Tanous                 {
17477f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
17487f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
17497f3e84a1SEd Tanous                                                systemName);
17507f3e84a1SEd Tanous                     return;
17517f3e84a1SEd Tanous                 }
1752253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
175322d268cbSEd Tanous                 {
175422d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
175522d268cbSEd Tanous                                                systemName);
175622d268cbSEd Tanous                     return;
175722d268cbSEd Tanous                 }
1758599b9af3SAlexander Hansen                 dBusEventLogEntryCollection(asyncResp);
1759599b9af3SAlexander Hansen             });
1760599b9af3SAlexander Hansen }
176122d268cbSEd Tanous 
1762bd79bce8SPatrick Williams inline void dBusEventLogEntryGet(
1763bd79bce8SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID)
1764599b9af3SAlexander Hansen {
1765599b9af3SAlexander Hansen     dbus::utility::escapePathForDbus(entryID);
176608a4e4b5SAnthony Wilson 
1767cb92c03bSAndrew Geissler     // DBus implementation of EventLog/Entries
1768cb92c03bSAndrew Geissler     // Make call to Logging Service to find all log entry objects
1769599b9af3SAlexander Hansen     sdbusplus::asio::getAllProperties(
1770599b9af3SAlexander Hansen         *crow::connections::systemBus, "xyz.openbmc_project.Logging",
1771599b9af3SAlexander Hansen         "/xyz/openbmc_project/logging/entry/" + entryID, "",
1772599b9af3SAlexander Hansen         [asyncResp, entryID](const boost::system::error_code& ec,
1773599b9af3SAlexander Hansen                              const dbus::utility::DBusPropertiesMap& resp) {
1774599b9af3SAlexander Hansen             if (ec.value() == EBADR)
1775599b9af3SAlexander Hansen             {
1776599b9af3SAlexander Hansen                 messages::resourceNotFound(asyncResp->res, "EventLogEntry",
1777599b9af3SAlexander Hansen                                            entryID);
1778599b9af3SAlexander Hansen                 return;
1779599b9af3SAlexander Hansen             }
1780cb92c03bSAndrew Geissler             if (ec)
1781cb92c03bSAndrew Geissler             {
1782bd79bce8SPatrick Williams                 BMCWEB_LOG_ERROR(
1783bd79bce8SPatrick Williams                     "EventLogEntry (DBus) resp_handler got error {}", ec);
1784cb92c03bSAndrew Geissler                 messages::internalError(asyncResp->res);
1785cb92c03bSAndrew Geissler                 return;
1786cb92c03bSAndrew Geissler             }
17879017faf2SAbhishek Patel 
1788898f2aa2SEd Tanous             fillEventLogLogEntryFromPropertyMap(asyncResp, resp,
1789898f2aa2SEd Tanous                                                 asyncResp->res.jsonValue);
1790599b9af3SAlexander Hansen         });
17917e860f15SJohn Edward Broadbent }
1792599b9af3SAlexander Hansen 
1793599b9af3SAlexander Hansen inline void
1794599b9af3SAlexander Hansen     dBusEventLogEntryPatch(const crow::Request& req,
1795599b9af3SAlexander Hansen                            const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1796599b9af3SAlexander Hansen                            const std::string& entryId)
1797599b9af3SAlexander Hansen {
1798599b9af3SAlexander Hansen     std::optional<bool> resolved;
1799599b9af3SAlexander Hansen 
1800599b9af3SAlexander Hansen     if (!json_util::readJsonPatch(req, asyncResp->res, "Resolved", resolved))
1801599b9af3SAlexander Hansen     {
1802599b9af3SAlexander Hansen         return;
1803599b9af3SAlexander Hansen     }
1804599b9af3SAlexander Hansen     BMCWEB_LOG_DEBUG("Set Resolved");
1805599b9af3SAlexander Hansen 
1806599b9af3SAlexander Hansen     setDbusProperty(asyncResp, "Resolved", "xyz.openbmc_project.Logging",
1807599b9af3SAlexander Hansen                     "/xyz/openbmc_project/logging/entry/" + entryId,
1808599b9af3SAlexander Hansen                     "xyz.openbmc_project.Logging.Entry", "Resolved",
1809599b9af3SAlexander Hansen                     resolved.value_or(false));
1810599b9af3SAlexander Hansen }
1811599b9af3SAlexander Hansen 
1812bd79bce8SPatrick Williams inline void dBusEventLogEntryDelete(
1813bd79bce8SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID)
1814599b9af3SAlexander Hansen {
1815599b9af3SAlexander Hansen     BMCWEB_LOG_DEBUG("Do delete single event entries.");
1816599b9af3SAlexander Hansen 
1817599b9af3SAlexander Hansen     dbus::utility::escapePathForDbus(entryID);
1818599b9af3SAlexander Hansen 
1819599b9af3SAlexander Hansen     // Process response from Logging service.
1820599b9af3SAlexander Hansen     auto respHandler = [asyncResp,
1821599b9af3SAlexander Hansen                         entryID](const boost::system::error_code& ec) {
1822599b9af3SAlexander Hansen         BMCWEB_LOG_DEBUG("EventLogEntry (DBus) doDelete callback: Done");
1823599b9af3SAlexander Hansen         if (ec)
1824599b9af3SAlexander Hansen         {
1825599b9af3SAlexander Hansen             if (ec.value() == EBADR)
1826599b9af3SAlexander Hansen             {
1827599b9af3SAlexander Hansen                 messages::resourceNotFound(asyncResp->res, "LogEntry", entryID);
1828599b9af3SAlexander Hansen                 return;
1829599b9af3SAlexander Hansen             }
1830599b9af3SAlexander Hansen             // TODO Handle for specific error code
1831599b9af3SAlexander Hansen             BMCWEB_LOG_ERROR(
1832599b9af3SAlexander Hansen                 "EventLogEntry (DBus) doDelete respHandler got error {}", ec);
1833599b9af3SAlexander Hansen             asyncResp->res.result(
1834599b9af3SAlexander Hansen                 boost::beast::http::status::internal_server_error);
1835599b9af3SAlexander Hansen             return;
1836599b9af3SAlexander Hansen         }
1837599b9af3SAlexander Hansen 
1838599b9af3SAlexander Hansen         asyncResp->res.result(boost::beast::http::status::ok);
1839599b9af3SAlexander Hansen     };
1840599b9af3SAlexander Hansen 
1841599b9af3SAlexander Hansen     // Make call to Logging service to request Delete Log
1842599b9af3SAlexander Hansen     crow::connections::systemBus->async_method_call(
1843599b9af3SAlexander Hansen         respHandler, "xyz.openbmc_project.Logging",
1844599b9af3SAlexander Hansen         "/xyz/openbmc_project/logging/entry/" + entryID,
1845599b9af3SAlexander Hansen         "xyz.openbmc_project.Object.Delete", "Delete");
18467e860f15SJohn Edward Broadbent }
18477e860f15SJohn Edward Broadbent 
18487e860f15SJohn Edward Broadbent inline void requestRoutesDBusEventLogEntry(App& app)
18497e860f15SJohn Edward Broadbent {
18507e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
185122d268cbSEd Tanous         app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
1852ed398213SEd Tanous         .privileges(redfish::privileges::getLogEntry)
1853002d39b4SEd Tanous         .methods(boost::beast::http::verb::get)(
1854002d39b4SEd Tanous             [&app](const crow::Request& req,
18557e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1856898f2aa2SEd Tanous                    const std::string& systemName, const std::string& entryId) {
18573ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
18587e860f15SJohn Edward Broadbent                 {
185945ca1b86SEd Tanous                     return;
186045ca1b86SEd Tanous                 }
186125b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
18627f3e84a1SEd Tanous                 {
18637f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
18647f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
18657f3e84a1SEd Tanous                                                systemName);
18667f3e84a1SEd Tanous                     return;
18677f3e84a1SEd Tanous                 }
1868253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
186922d268cbSEd Tanous                 {
187022d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
187122d268cbSEd Tanous                                                systemName);
187222d268cbSEd Tanous                     return;
187322d268cbSEd Tanous                 }
187422d268cbSEd Tanous 
1875898f2aa2SEd Tanous                 dBusEventLogEntryGet(asyncResp, entryId);
18767e860f15SJohn Edward Broadbent             });
1877336e96c6SChicago Duan 
18787e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
187922d268cbSEd Tanous         app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
1880ed398213SEd Tanous         .privileges(redfish::privileges::patchLogEntry)
18817e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::patch)(
188245ca1b86SEd Tanous             [&app](const crow::Request& req,
18837e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
188422d268cbSEd Tanous                    const std::string& systemName, const std::string& entryId) {
18853ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
188645ca1b86SEd Tanous                 {
188745ca1b86SEd Tanous                     return;
188845ca1b86SEd Tanous                 }
188925b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
18907f3e84a1SEd Tanous                 {
18917f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
18927f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
18937f3e84a1SEd Tanous                                                systemName);
18947f3e84a1SEd Tanous                     return;
18957f3e84a1SEd Tanous                 }
1896253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
189722d268cbSEd Tanous                 {
189822d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
189922d268cbSEd Tanous                                                systemName);
190022d268cbSEd Tanous                     return;
190122d268cbSEd Tanous                 }
190275710de2SXiaochao Ma 
1903599b9af3SAlexander Hansen                 dBusEventLogEntryPatch(req, asyncResp, entryId);
19047e860f15SJohn Edward Broadbent             });
190575710de2SXiaochao Ma 
19067e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
190722d268cbSEd Tanous         app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
1908ed398213SEd Tanous         .privileges(redfish::privileges::deleteLogEntry)
1909ed398213SEd Tanous 
1910002d39b4SEd Tanous         .methods(boost::beast::http::verb::delete_)(
1911002d39b4SEd Tanous             [&app](const crow::Request& req,
1912002d39b4SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
191322d268cbSEd Tanous                    const std::string& systemName, const std::string& param) {
19143ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1915336e96c6SChicago Duan                 {
191645ca1b86SEd Tanous                     return;
191745ca1b86SEd Tanous                 }
191825b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
19197f3e84a1SEd Tanous                 {
19207f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
19217f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
19227f3e84a1SEd Tanous                                                systemName);
19237f3e84a1SEd Tanous                     return;
19247f3e84a1SEd Tanous                 }
1925253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
192622d268cbSEd Tanous                 {
192722d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
192822d268cbSEd Tanous                                                systemName);
192922d268cbSEd Tanous                     return;
193022d268cbSEd Tanous                 }
1931599b9af3SAlexander Hansen                 dBusEventLogEntryDelete(asyncResp, param);
19327e860f15SJohn Edward Broadbent             });
1933400fd1fbSAdriana Kobylak }
1934400fd1fbSAdriana Kobylak 
1935b7028ebfSSpencer Ku constexpr const char* hostLoggerFolderPath = "/var/log/console";
1936b7028ebfSSpencer Ku 
1937b7028ebfSSpencer Ku inline bool
1938b7028ebfSSpencer Ku     getHostLoggerFiles(const std::string& hostLoggerFilePath,
1939b7028ebfSSpencer Ku                        std::vector<std::filesystem::path>& hostLoggerFiles)
1940b7028ebfSSpencer Ku {
1941b7028ebfSSpencer Ku     std::error_code ec;
1942b7028ebfSSpencer Ku     std::filesystem::directory_iterator logPath(hostLoggerFilePath, ec);
1943b7028ebfSSpencer Ku     if (ec)
1944b7028ebfSSpencer Ku     {
1945bf2ddedeSCarson Labrado         BMCWEB_LOG_WARNING("{}", ec.message());
1946b7028ebfSSpencer Ku         return false;
1947b7028ebfSSpencer Ku     }
1948b7028ebfSSpencer Ku     for (const std::filesystem::directory_entry& it : logPath)
1949b7028ebfSSpencer Ku     {
1950b7028ebfSSpencer Ku         std::string filename = it.path().filename();
1951b7028ebfSSpencer Ku         // Prefix of each log files is "log". Find the file and save the
1952b7028ebfSSpencer Ku         // path
195311ba3979SEd Tanous         if (filename.starts_with("log"))
1954b7028ebfSSpencer Ku         {
1955b7028ebfSSpencer Ku             hostLoggerFiles.emplace_back(it.path());
1956b7028ebfSSpencer Ku         }
1957b7028ebfSSpencer Ku     }
1958b7028ebfSSpencer Ku     // As the log files rotate, they are appended with a ".#" that is higher for
1959b7028ebfSSpencer Ku     // the older logs. Since we start from oldest logs, sort the name in
1960b7028ebfSSpencer Ku     // descending order.
1961b7028ebfSSpencer Ku     std::sort(hostLoggerFiles.rbegin(), hostLoggerFiles.rend(),
1962b7028ebfSSpencer Ku               AlphanumLess<std::string>());
1963b7028ebfSSpencer Ku 
1964b7028ebfSSpencer Ku     return true;
1965b7028ebfSSpencer Ku }
1966b7028ebfSSpencer Ku 
196702cad96eSEd Tanous inline bool getHostLoggerEntries(
196802cad96eSEd Tanous     const std::vector<std::filesystem::path>& hostLoggerFiles, uint64_t skip,
196902cad96eSEd Tanous     uint64_t top, std::vector<std::string>& logEntries, size_t& logCount)
1970b7028ebfSSpencer Ku {
1971b7028ebfSSpencer Ku     GzFileReader logFile;
1972b7028ebfSSpencer Ku 
1973b7028ebfSSpencer Ku     // Go though all log files and expose host logs.
1974b7028ebfSSpencer Ku     for (const std::filesystem::path& it : hostLoggerFiles)
1975b7028ebfSSpencer Ku     {
1976b7028ebfSSpencer Ku         if (!logFile.gzGetLines(it.string(), skip, top, logEntries, logCount))
1977b7028ebfSSpencer Ku         {
197862598e31SEd Tanous             BMCWEB_LOG_ERROR("fail to expose host logs");
1979b7028ebfSSpencer Ku             return false;
1980b7028ebfSSpencer Ku         }
1981b7028ebfSSpencer Ku     }
1982b7028ebfSSpencer Ku     // Get lastMessage from constructor by getter
1983b7028ebfSSpencer Ku     std::string lastMessage = logFile.getLastMessage();
1984b7028ebfSSpencer Ku     if (!lastMessage.empty())
1985b7028ebfSSpencer Ku     {
1986b7028ebfSSpencer Ku         logCount++;
1987b7028ebfSSpencer Ku         if (logCount > skip && logCount <= (skip + top))
1988b7028ebfSSpencer Ku         {
1989b7028ebfSSpencer Ku             logEntries.push_back(lastMessage);
1990b7028ebfSSpencer Ku         }
1991b7028ebfSSpencer Ku     }
1992b7028ebfSSpencer Ku     return true;
1993b7028ebfSSpencer Ku }
1994b7028ebfSSpencer Ku 
1995dd72e87bSClaire Weinan inline void handleBMCLogServicesCollectionGet(
1996fdd26906SClaire Weinan     crow::App& app, const crow::Request& req,
1997253f11b8SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1998253f11b8SEd Tanous     const std::string& managerId)
19991da66f75SEd Tanous {
20003ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
200145ca1b86SEd Tanous     {
200245ca1b86SEd Tanous         return;
200345ca1b86SEd Tanous     }
2004253f11b8SEd Tanous 
2005253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2006253f11b8SEd Tanous     {
2007253f11b8SEd Tanous         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2008253f11b8SEd Tanous         return;
2009253f11b8SEd Tanous     }
2010253f11b8SEd Tanous 
20117e860f15SJohn Edward Broadbent     // Collections don't include the static data added by SubRoute
20127e860f15SJohn Edward Broadbent     // because it has a duplicate entry for members
2013e1f26343SJason M. Bills     asyncResp->res.jsonValue["@odata.type"] =
20141da66f75SEd Tanous         "#LogServiceCollection.LogServiceCollection";
2015253f11b8SEd Tanous     asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
2016253f11b8SEd Tanous         "/redfish/v1/Managers/{}/LogServices", BMCWEB_REDFISH_MANAGER_URI_NAME);
2017002d39b4SEd Tanous     asyncResp->res.jsonValue["Name"] = "Open BMC Log Services Collection";
2018e1f26343SJason M. Bills     asyncResp->res.jsonValue["Description"] =
20191da66f75SEd Tanous         "Collection of LogServices for this Manager";
2020002d39b4SEd Tanous     nlohmann::json& logServiceArray = asyncResp->res.jsonValue["Members"];
2021c4bf6374SJason M. Bills     logServiceArray = nlohmann::json::array();
2022fdd26906SClaire Weinan 
202325b54dbaSEd Tanous     if constexpr (BMCWEB_REDFISH_BMC_JOURNAL)
202425b54dbaSEd Tanous     {
2025613dabeaSEd Tanous         nlohmann::json::object_t journal;
2026253f11b8SEd Tanous         journal["@odata.id"] =
2027253f11b8SEd Tanous             boost::urls::format("/redfish/v1/Managers/{}/LogServices/Journal",
2028253f11b8SEd Tanous                                 BMCWEB_REDFISH_MANAGER_URI_NAME);
2029b2ba3072SPatrick Williams         logServiceArray.emplace_back(std::move(journal));
203025b54dbaSEd Tanous     }
2031fdd26906SClaire Weinan 
2032fdd26906SClaire Weinan     asyncResp->res.jsonValue["Members@odata.count"] = logServiceArray.size();
2033fdd26906SClaire Weinan 
203425b54dbaSEd Tanous     if constexpr (BMCWEB_REDFISH_DUMP_LOG)
203525b54dbaSEd Tanous     {
203615912159SGeorge Liu         constexpr std::array<std::string_view, 1> interfaces = {
20377a1dbc48SGeorge Liu             "xyz.openbmc_project.Collection.DeleteAll"};
20387a1dbc48SGeorge Liu         dbus::utility::getSubTreePaths(
20397a1dbc48SGeorge Liu             "/xyz/openbmc_project/dump", 0, interfaces,
204025b54dbaSEd Tanous             [asyncResp](const boost::system::error_code& ec,
204125b54dbaSEd Tanous                         const dbus::utility::MapperGetSubTreePathsResponse&
204225b54dbaSEd Tanous                             subTreePaths) {
2043fdd26906SClaire Weinan                 if (ec)
2044fdd26906SClaire Weinan                 {
204562598e31SEd Tanous                     BMCWEB_LOG_ERROR(
204662598e31SEd Tanous                         "handleBMCLogServicesCollectionGet respHandler got error {}",
204762598e31SEd Tanous                         ec);
2048bd79bce8SPatrick Williams                     // Assume that getting an error simply means there are no
2049bd79bce8SPatrick Williams                     // dump LogServices. Return without adding any error
2050bd79bce8SPatrick Williams                     // response.
2051fdd26906SClaire Weinan                     return;
2052fdd26906SClaire Weinan                 }
2053fdd26906SClaire Weinan 
2054fdd26906SClaire Weinan                 nlohmann::json& logServiceArrayLocal =
2055fdd26906SClaire Weinan                     asyncResp->res.jsonValue["Members"];
2056fdd26906SClaire Weinan 
2057fdd26906SClaire Weinan                 for (const std::string& path : subTreePaths)
2058fdd26906SClaire Weinan                 {
2059fdd26906SClaire Weinan                     if (path == "/xyz/openbmc_project/dump/bmc")
2060fdd26906SClaire Weinan                     {
2061613dabeaSEd Tanous                         nlohmann::json::object_t member;
2062253f11b8SEd Tanous                         member["@odata.id"] = boost::urls::format(
2063253f11b8SEd Tanous                             "/redfish/v1/Managers/{}/LogServices/Dump",
2064253f11b8SEd Tanous                             BMCWEB_REDFISH_MANAGER_URI_NAME);
2065b2ba3072SPatrick Williams                         logServiceArrayLocal.emplace_back(std::move(member));
2066fdd26906SClaire Weinan                     }
2067fdd26906SClaire Weinan                     else if (path == "/xyz/openbmc_project/dump/faultlog")
2068fdd26906SClaire Weinan                     {
2069613dabeaSEd Tanous                         nlohmann::json::object_t member;
2070253f11b8SEd Tanous                         member["@odata.id"] = boost::urls::format(
2071253f11b8SEd Tanous                             "/redfish/v1/Managers/{}/LogServices/FaultLog",
2072253f11b8SEd Tanous                             BMCWEB_REDFISH_MANAGER_URI_NAME);
2073b2ba3072SPatrick Williams                         logServiceArrayLocal.emplace_back(std::move(member));
2074fdd26906SClaire Weinan                     }
2075fdd26906SClaire Weinan                 }
2076fdd26906SClaire Weinan 
2077e1f26343SJason M. Bills                 asyncResp->res.jsonValue["Members@odata.count"] =
2078fdd26906SClaire Weinan                     logServiceArrayLocal.size();
20797a1dbc48SGeorge Liu             });
208025b54dbaSEd Tanous     }
2081fdd26906SClaire Weinan }
2082fdd26906SClaire Weinan 
2083fdd26906SClaire Weinan inline void requestRoutesBMCLogServiceCollection(App& app)
2084fdd26906SClaire Weinan {
2085253f11b8SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/")
2086fdd26906SClaire Weinan         .privileges(redfish::privileges::getLogServiceCollection)
2087fdd26906SClaire Weinan         .methods(boost::beast::http::verb::get)(
2088dd72e87bSClaire Weinan             std::bind_front(handleBMCLogServicesCollectionGet, std::ref(app)));
2089e1f26343SJason M. Bills }
2090e1f26343SJason M. Bills 
2091fdd26906SClaire Weinan inline void
2092fdd26906SClaire Weinan     getDumpServiceInfo(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2093fdd26906SClaire Weinan                        const std::string& dumpType)
2094c9bb6861Sraviteja-b {
2095fdd26906SClaire Weinan     std::string dumpPath;
2096539d8c6bSEd Tanous     log_service::OverWritePolicy overWritePolicy =
2097539d8c6bSEd Tanous         log_service::OverWritePolicy::Invalid;
2098fdd26906SClaire Weinan     bool collectDiagnosticDataSupported = false;
2099fdd26906SClaire Weinan 
2100fdd26906SClaire Weinan     if (dumpType == "BMC")
210145ca1b86SEd Tanous     {
2102253f11b8SEd Tanous         dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/Dump",
2103253f11b8SEd Tanous                                BMCWEB_REDFISH_MANAGER_URI_NAME);
2104539d8c6bSEd Tanous         overWritePolicy = log_service::OverWritePolicy::WrapsWhenFull;
2105fdd26906SClaire Weinan         collectDiagnosticDataSupported = true;
2106fdd26906SClaire Weinan     }
2107fdd26906SClaire Weinan     else if (dumpType == "FaultLog")
2108fdd26906SClaire Weinan     {
2109253f11b8SEd Tanous         dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/FaultLog",
2110253f11b8SEd Tanous                                BMCWEB_REDFISH_MANAGER_URI_NAME);
2111539d8c6bSEd Tanous         overWritePolicy = log_service::OverWritePolicy::Unknown;
2112fdd26906SClaire Weinan         collectDiagnosticDataSupported = false;
2113fdd26906SClaire Weinan     }
2114fdd26906SClaire Weinan     else if (dumpType == "System")
2115fdd26906SClaire Weinan     {
2116253f11b8SEd Tanous         dumpPath = std::format("/redfish/v1/Systems/{}/LogServices/Dump",
2117253f11b8SEd Tanous                                BMCWEB_REDFISH_SYSTEM_URI_NAME);
2118539d8c6bSEd Tanous         overWritePolicy = log_service::OverWritePolicy::WrapsWhenFull;
2119fdd26906SClaire Weinan         collectDiagnosticDataSupported = true;
2120fdd26906SClaire Weinan     }
2121fdd26906SClaire Weinan     else
2122fdd26906SClaire Weinan     {
212362598e31SEd Tanous         BMCWEB_LOG_ERROR("getDumpServiceInfo() invalid dump type: {}",
212462598e31SEd Tanous                          dumpType);
2125fdd26906SClaire Weinan         messages::internalError(asyncResp->res);
212645ca1b86SEd Tanous         return;
212745ca1b86SEd Tanous     }
2128fdd26906SClaire Weinan 
2129fdd26906SClaire Weinan     asyncResp->res.jsonValue["@odata.id"] = dumpPath;
2130fdd26906SClaire Weinan     asyncResp->res.jsonValue["@odata.type"] = "#LogService.v1_2_0.LogService";
2131c9bb6861Sraviteja-b     asyncResp->res.jsonValue["Name"] = "Dump LogService";
2132fdd26906SClaire Weinan     asyncResp->res.jsonValue["Description"] = dumpType + " Dump LogService";
2133fdd26906SClaire Weinan     asyncResp->res.jsonValue["Id"] = std::filesystem::path(dumpPath).filename();
2134539d8c6bSEd Tanous     asyncResp->res.jsonValue["OverWritePolicy"] = overWritePolicy;
21357c8c4058STejas Patil 
21367c8c4058STejas Patil     std::pair<std::string, std::string> redfishDateTimeOffset =
21372b82937eSEd Tanous         redfish::time_utils::getDateTimeOffsetNow();
21380fda0f12SGeorge Liu     asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
21397c8c4058STejas Patil     asyncResp->res.jsonValue["DateTimeLocalOffset"] =
21407c8c4058STejas Patil         redfishDateTimeOffset.second;
21417c8c4058STejas Patil 
2142fdd26906SClaire Weinan     asyncResp->res.jsonValue["Entries"]["@odata.id"] = dumpPath + "/Entries";
2143fdd26906SClaire Weinan 
2144fdd26906SClaire Weinan     if (collectDiagnosticDataSupported)
2145fdd26906SClaire Weinan     {
2146002d39b4SEd Tanous         asyncResp->res.jsonValue["Actions"]["#LogService.CollectDiagnosticData"]
21471476687dSEd Tanous                                 ["target"] =
2148fdd26906SClaire Weinan             dumpPath + "/Actions/LogService.CollectDiagnosticData";
2149fdd26906SClaire Weinan     }
21500d946211SClaire Weinan 
21510d946211SClaire Weinan     constexpr std::array<std::string_view, 1> interfaces = {deleteAllInterface};
21520d946211SClaire Weinan     dbus::utility::getSubTreePaths(
21530d946211SClaire Weinan         "/xyz/openbmc_project/dump", 0, interfaces,
21540d946211SClaire Weinan         [asyncResp, dumpType, dumpPath](
21550d946211SClaire Weinan             const boost::system::error_code& ec,
21560d946211SClaire Weinan             const dbus::utility::MapperGetSubTreePathsResponse& subTreePaths) {
21570d946211SClaire Weinan             if (ec)
21580d946211SClaire Weinan             {
2159bd79bce8SPatrick Williams                 BMCWEB_LOG_ERROR("getDumpServiceInfo respHandler got error {}",
2160bd79bce8SPatrick Williams                                  ec);
21610d946211SClaire Weinan                 // Assume that getting an error simply means there are no dump
21620d946211SClaire Weinan                 // LogServices. Return without adding any error response.
21630d946211SClaire Weinan                 return;
21640d946211SClaire Weinan             }
216518f8f608SEd Tanous             std::string dbusDumpPath = getDumpPath(dumpType);
21660d946211SClaire Weinan             for (const std::string& path : subTreePaths)
21670d946211SClaire Weinan             {
21680d946211SClaire Weinan                 if (path == dbusDumpPath)
21690d946211SClaire Weinan                 {
2170bd79bce8SPatrick Williams                     asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"]
2171bd79bce8SPatrick Williams                                             ["target"] =
21720d946211SClaire Weinan                         dumpPath + "/Actions/LogService.ClearLog";
21730d946211SClaire Weinan                     break;
21740d946211SClaire Weinan                 }
21750d946211SClaire Weinan             }
21760d946211SClaire Weinan         });
2177c9bb6861Sraviteja-b }
2178c9bb6861Sraviteja-b 
2179fdd26906SClaire Weinan inline void handleLogServicesDumpServiceGet(
2180fdd26906SClaire Weinan     crow::App& app, const std::string& dumpType, const crow::Request& req,
2181253f11b8SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2182253f11b8SEd Tanous     const std::string& managerId)
21837e860f15SJohn Edward Broadbent {
21843ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
218545ca1b86SEd Tanous     {
218645ca1b86SEd Tanous         return;
218745ca1b86SEd Tanous     }
2188253f11b8SEd Tanous 
2189253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2190253f11b8SEd Tanous     {
2191253f11b8SEd Tanous         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2192253f11b8SEd Tanous         return;
2193253f11b8SEd Tanous     }
2194253f11b8SEd Tanous 
2195fdd26906SClaire Weinan     getDumpServiceInfo(asyncResp, dumpType);
2196fdd26906SClaire Weinan }
2197c9bb6861Sraviteja-b 
219822d268cbSEd Tanous inline void handleLogServicesDumpServiceComputerSystemGet(
219922d268cbSEd Tanous     crow::App& app, const crow::Request& req,
220022d268cbSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
220122d268cbSEd Tanous     const std::string& chassisId)
220222d268cbSEd Tanous {
220322d268cbSEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
220422d268cbSEd Tanous     {
220522d268cbSEd Tanous         return;
220622d268cbSEd Tanous     }
2207253f11b8SEd Tanous     if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
220822d268cbSEd Tanous     {
220922d268cbSEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
221022d268cbSEd Tanous         return;
221122d268cbSEd Tanous     }
221222d268cbSEd Tanous     getDumpServiceInfo(asyncResp, "System");
221322d268cbSEd Tanous }
221422d268cbSEd Tanous 
2215fdd26906SClaire Weinan inline void handleLogServicesDumpEntriesCollectionGet(
2216fdd26906SClaire Weinan     crow::App& app, const std::string& dumpType, const crow::Request& req,
2217253f11b8SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2218253f11b8SEd Tanous     const std::string& managerId)
2219fdd26906SClaire Weinan {
2220fdd26906SClaire Weinan     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2221fdd26906SClaire Weinan     {
2222fdd26906SClaire Weinan         return;
2223fdd26906SClaire Weinan     }
2224253f11b8SEd Tanous 
2225253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2226253f11b8SEd Tanous     {
2227253f11b8SEd Tanous         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2228253f11b8SEd Tanous         return;
2229253f11b8SEd Tanous     }
2230fdd26906SClaire Weinan     getDumpEntryCollection(asyncResp, dumpType);
2231fdd26906SClaire Weinan }
2232fdd26906SClaire Weinan 
223322d268cbSEd Tanous inline void handleLogServicesDumpEntriesCollectionComputerSystemGet(
223422d268cbSEd Tanous     crow::App& app, const crow::Request& req,
223522d268cbSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
223622d268cbSEd Tanous     const std::string& chassisId)
223722d268cbSEd Tanous {
223822d268cbSEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
223922d268cbSEd Tanous     {
224022d268cbSEd Tanous         return;
224122d268cbSEd Tanous     }
2242253f11b8SEd Tanous     if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
224322d268cbSEd Tanous     {
224422d268cbSEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
224522d268cbSEd Tanous         return;
224622d268cbSEd Tanous     }
224722d268cbSEd Tanous     getDumpEntryCollection(asyncResp, "System");
224822d268cbSEd Tanous }
224922d268cbSEd Tanous 
2250fdd26906SClaire Weinan inline void handleLogServicesDumpEntryGet(
2251fdd26906SClaire Weinan     crow::App& app, const std::string& dumpType, const crow::Request& req,
2252fdd26906SClaire Weinan     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2253253f11b8SEd Tanous     const std::string& managerId, const std::string& dumpId)
2254fdd26906SClaire Weinan {
2255fdd26906SClaire Weinan     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2256fdd26906SClaire Weinan     {
2257fdd26906SClaire Weinan         return;
2258fdd26906SClaire Weinan     }
2259253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2260253f11b8SEd Tanous     {
2261253f11b8SEd Tanous         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2262253f11b8SEd Tanous         return;
2263253f11b8SEd Tanous     }
2264fdd26906SClaire Weinan     getDumpEntryById(asyncResp, dumpId, dumpType);
2265fdd26906SClaire Weinan }
2266168d1b1aSCarson Labrado 
226722d268cbSEd Tanous inline void handleLogServicesDumpEntryComputerSystemGet(
226822d268cbSEd Tanous     crow::App& app, const crow::Request& req,
226922d268cbSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
227022d268cbSEd Tanous     const std::string& chassisId, const std::string& dumpId)
227122d268cbSEd Tanous {
227222d268cbSEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
227322d268cbSEd Tanous     {
227422d268cbSEd Tanous         return;
227522d268cbSEd Tanous     }
2276253f11b8SEd Tanous     if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
227722d268cbSEd Tanous     {
227822d268cbSEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
227922d268cbSEd Tanous         return;
228022d268cbSEd Tanous     }
228122d268cbSEd Tanous     getDumpEntryById(asyncResp, dumpId, "System");
228222d268cbSEd Tanous }
2283fdd26906SClaire Weinan 
2284fdd26906SClaire Weinan inline void handleLogServicesDumpEntryDelete(
2285fdd26906SClaire Weinan     crow::App& app, const std::string& dumpType, const crow::Request& req,
2286fdd26906SClaire Weinan     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2287253f11b8SEd Tanous     const std::string& managerId, const std::string& dumpId)
2288fdd26906SClaire Weinan {
2289fdd26906SClaire Weinan     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2290fdd26906SClaire Weinan     {
2291fdd26906SClaire Weinan         return;
2292fdd26906SClaire Weinan     }
2293253f11b8SEd Tanous 
2294253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2295253f11b8SEd Tanous     {
2296253f11b8SEd Tanous         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2297253f11b8SEd Tanous         return;
2298253f11b8SEd Tanous     }
2299fdd26906SClaire Weinan     deleteDumpEntry(asyncResp, dumpId, dumpType);
2300fdd26906SClaire Weinan }
2301fdd26906SClaire Weinan 
230222d268cbSEd Tanous inline void handleLogServicesDumpEntryComputerSystemDelete(
230322d268cbSEd Tanous     crow::App& app, const crow::Request& req,
230422d268cbSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
230522d268cbSEd Tanous     const std::string& chassisId, const std::string& dumpId)
230622d268cbSEd Tanous {
230722d268cbSEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
230822d268cbSEd Tanous     {
230922d268cbSEd Tanous         return;
231022d268cbSEd Tanous     }
2311253f11b8SEd Tanous     if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
231222d268cbSEd Tanous     {
231322d268cbSEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
231422d268cbSEd Tanous         return;
231522d268cbSEd Tanous     }
231622d268cbSEd Tanous     deleteDumpEntry(asyncResp, dumpId, "System");
231722d268cbSEd Tanous }
231822d268cbSEd Tanous 
2319168d1b1aSCarson Labrado inline void handleLogServicesDumpEntryDownloadGet(
2320168d1b1aSCarson Labrado     crow::App& app, const std::string& dumpType, const crow::Request& req,
2321168d1b1aSCarson Labrado     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2322253f11b8SEd Tanous     const std::string& managerId, const std::string& dumpId)
2323168d1b1aSCarson Labrado {
2324168d1b1aSCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2325168d1b1aSCarson Labrado     {
2326168d1b1aSCarson Labrado         return;
2327168d1b1aSCarson Labrado     }
2328253f11b8SEd Tanous 
2329253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2330253f11b8SEd Tanous     {
2331253f11b8SEd Tanous         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2332253f11b8SEd Tanous         return;
2333253f11b8SEd Tanous     }
2334168d1b1aSCarson Labrado     downloadDumpEntry(asyncResp, dumpId, dumpType);
2335168d1b1aSCarson Labrado }
2336168d1b1aSCarson Labrado 
2337168d1b1aSCarson Labrado inline void handleDBusEventLogEntryDownloadGet(
2338168d1b1aSCarson Labrado     crow::App& app, const std::string& dumpType, const crow::Request& req,
2339168d1b1aSCarson Labrado     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2340168d1b1aSCarson Labrado     const std::string& systemName, const std::string& entryID)
2341168d1b1aSCarson Labrado {
2342168d1b1aSCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2343168d1b1aSCarson Labrado     {
2344168d1b1aSCarson Labrado         return;
2345168d1b1aSCarson Labrado     }
2346168d1b1aSCarson Labrado     if (!http_helpers::isContentTypeAllowed(
2347168d1b1aSCarson Labrado             req.getHeaderValue("Accept"),
2348168d1b1aSCarson Labrado             http_helpers::ContentType::OctetStream, true))
2349168d1b1aSCarson Labrado     {
2350168d1b1aSCarson Labrado         asyncResp->res.result(boost::beast::http::status::bad_request);
2351168d1b1aSCarson Labrado         return;
2352168d1b1aSCarson Labrado     }
2353168d1b1aSCarson Labrado     downloadEventLogEntry(asyncResp, systemName, entryID, dumpType);
2354168d1b1aSCarson Labrado }
2355168d1b1aSCarson Labrado 
2356fdd26906SClaire Weinan inline void handleLogServicesDumpCollectDiagnosticDataPost(
2357fdd26906SClaire Weinan     crow::App& app, const std::string& dumpType, const crow::Request& req,
2358253f11b8SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2359253f11b8SEd Tanous     const std::string& managerId)
2360fdd26906SClaire Weinan {
2361fdd26906SClaire Weinan     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2362fdd26906SClaire Weinan     {
2363fdd26906SClaire Weinan         return;
2364fdd26906SClaire Weinan     }
2365253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2366253f11b8SEd Tanous     {
2367253f11b8SEd Tanous         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2368253f11b8SEd Tanous         return;
2369253f11b8SEd Tanous     }
2370253f11b8SEd Tanous 
2371fdd26906SClaire Weinan     createDump(asyncResp, req, dumpType);
2372fdd26906SClaire Weinan }
2373fdd26906SClaire Weinan 
237422d268cbSEd Tanous inline void handleLogServicesDumpCollectDiagnosticDataComputerSystemPost(
237522d268cbSEd Tanous     crow::App& app, const crow::Request& req,
237622d268cbSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
23777f3e84a1SEd Tanous     const std::string& systemName)
237822d268cbSEd Tanous {
237922d268cbSEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
238022d268cbSEd Tanous     {
238122d268cbSEd Tanous         return;
238222d268cbSEd Tanous     }
23837f3e84a1SEd Tanous 
238425b54dbaSEd Tanous     if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
238522d268cbSEd Tanous     {
23867f3e84a1SEd Tanous         // Option currently returns no systems.  TBD
23877f3e84a1SEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
23887f3e84a1SEd Tanous                                    systemName);
23897f3e84a1SEd Tanous         return;
23907f3e84a1SEd Tanous     }
2391253f11b8SEd Tanous     if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
23927f3e84a1SEd Tanous     {
23937f3e84a1SEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
23947f3e84a1SEd Tanous                                    systemName);
239522d268cbSEd Tanous         return;
239622d268cbSEd Tanous     }
239722d268cbSEd Tanous     createDump(asyncResp, req, "System");
239822d268cbSEd Tanous }
239922d268cbSEd Tanous 
2400fdd26906SClaire Weinan inline void handleLogServicesDumpClearLogPost(
2401fdd26906SClaire Weinan     crow::App& app, const std::string& dumpType, const crow::Request& req,
2402253f11b8SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2403253f11b8SEd Tanous     const std::string& managerId)
2404fdd26906SClaire Weinan {
2405fdd26906SClaire Weinan     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2406fdd26906SClaire Weinan     {
2407fdd26906SClaire Weinan         return;
2408fdd26906SClaire Weinan     }
2409253f11b8SEd Tanous 
2410253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2411253f11b8SEd Tanous     {
2412253f11b8SEd Tanous         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2413253f11b8SEd Tanous         return;
2414253f11b8SEd Tanous     }
2415fdd26906SClaire Weinan     clearDump(asyncResp, dumpType);
2416fdd26906SClaire Weinan }
2417fdd26906SClaire Weinan 
241822d268cbSEd Tanous inline void handleLogServicesDumpClearLogComputerSystemPost(
241922d268cbSEd Tanous     crow::App& app, const crow::Request& req,
242022d268cbSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
24217f3e84a1SEd Tanous     const std::string& systemName)
242222d268cbSEd Tanous {
242322d268cbSEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
242422d268cbSEd Tanous     {
242522d268cbSEd Tanous         return;
242622d268cbSEd Tanous     }
242725b54dbaSEd Tanous     if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
242822d268cbSEd Tanous     {
24297f3e84a1SEd Tanous         // Option currently returns no systems.  TBD
24307f3e84a1SEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
24317f3e84a1SEd Tanous                                    systemName);
24327f3e84a1SEd Tanous         return;
24337f3e84a1SEd Tanous     }
2434253f11b8SEd Tanous     if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
24357f3e84a1SEd Tanous     {
24367f3e84a1SEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
24377f3e84a1SEd Tanous                                    systemName);
243822d268cbSEd Tanous         return;
243922d268cbSEd Tanous     }
244022d268cbSEd Tanous     clearDump(asyncResp, "System");
244122d268cbSEd Tanous }
244222d268cbSEd Tanous 
2443fdd26906SClaire Weinan inline void requestRoutesBMCDumpService(App& app)
2444fdd26906SClaire Weinan {
2445253f11b8SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/Dump/")
2446fdd26906SClaire Weinan         .privileges(redfish::privileges::getLogService)
2447fdd26906SClaire Weinan         .methods(boost::beast::http::verb::get)(std::bind_front(
2448fdd26906SClaire Weinan             handleLogServicesDumpServiceGet, std::ref(app), "BMC"));
2449fdd26906SClaire Weinan }
2450fdd26906SClaire Weinan 
2451fdd26906SClaire Weinan inline void requestRoutesBMCDumpEntryCollection(App& app)
2452fdd26906SClaire Weinan {
2453253f11b8SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/")
2454fdd26906SClaire Weinan         .privileges(redfish::privileges::getLogEntryCollection)
2455fdd26906SClaire Weinan         .methods(boost::beast::http::verb::get)(std::bind_front(
2456fdd26906SClaire Weinan             handleLogServicesDumpEntriesCollectionGet, std::ref(app), "BMC"));
2457c9bb6861Sraviteja-b }
2458c9bb6861Sraviteja-b 
24597e860f15SJohn Edward Broadbent inline void requestRoutesBMCDumpEntry(App& app)
2460c9bb6861Sraviteja-b {
24617e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
2462253f11b8SEd Tanous                  "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/")
2463ed398213SEd Tanous         .privileges(redfish::privileges::getLogEntry)
2464fdd26906SClaire Weinan         .methods(boost::beast::http::verb::get)(std::bind_front(
2465fdd26906SClaire Weinan             handleLogServicesDumpEntryGet, std::ref(app), "BMC"));
2466fdd26906SClaire Weinan 
24677e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
2468253f11b8SEd Tanous                  "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/")
2469ed398213SEd Tanous         .privileges(redfish::privileges::deleteLogEntry)
2470fdd26906SClaire Weinan         .methods(boost::beast::http::verb::delete_)(std::bind_front(
2471fdd26906SClaire Weinan             handleLogServicesDumpEntryDelete, std::ref(app), "BMC"));
2472c9bb6861Sraviteja-b }
2473c9bb6861Sraviteja-b 
2474168d1b1aSCarson Labrado inline void requestRoutesBMCDumpEntryDownload(App& app)
2475168d1b1aSCarson Labrado {
2476168d1b1aSCarson Labrado     BMCWEB_ROUTE(
2477168d1b1aSCarson Labrado         app,
2478253f11b8SEd Tanous         "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/attachment/")
2479168d1b1aSCarson Labrado         .privileges(redfish::privileges::getLogEntry)
2480168d1b1aSCarson Labrado         .methods(boost::beast::http::verb::get)(std::bind_front(
2481168d1b1aSCarson Labrado             handleLogServicesDumpEntryDownloadGet, std::ref(app), "BMC"));
2482168d1b1aSCarson Labrado }
2483168d1b1aSCarson Labrado 
24847e860f15SJohn Edward Broadbent inline void requestRoutesBMCDumpCreate(App& app)
2485c9bb6861Sraviteja-b {
24860fda0f12SGeorge Liu     BMCWEB_ROUTE(
24870fda0f12SGeorge Liu         app,
2488253f11b8SEd Tanous         "/redfish/v1/Managers/<str>/LogServices/Dump/Actions/LogService.CollectDiagnosticData/")
2489ed398213SEd Tanous         .privileges(redfish::privileges::postLogService)
24907e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
2491fdd26906SClaire Weinan             std::bind_front(handleLogServicesDumpCollectDiagnosticDataPost,
2492fdd26906SClaire Weinan                             std::ref(app), "BMC"));
2493a43be80fSAsmitha Karunanithi }
2494a43be80fSAsmitha Karunanithi 
24957e860f15SJohn Edward Broadbent inline void requestRoutesBMCDumpClear(App& app)
249680319af1SAsmitha Karunanithi {
24970fda0f12SGeorge Liu     BMCWEB_ROUTE(
24980fda0f12SGeorge Liu         app,
2499253f11b8SEd Tanous         "/redfish/v1/Managers/<str>/LogServices/Dump/Actions/LogService.ClearLog/")
2500ed398213SEd Tanous         .privileges(redfish::privileges::postLogService)
2501fdd26906SClaire Weinan         .methods(boost::beast::http::verb::post)(std::bind_front(
2502fdd26906SClaire Weinan             handleLogServicesDumpClearLogPost, std::ref(app), "BMC"));
250345ca1b86SEd Tanous }
2504fdd26906SClaire Weinan 
2505168d1b1aSCarson Labrado inline void requestRoutesDBusEventLogEntryDownload(App& app)
2506168d1b1aSCarson Labrado {
2507168d1b1aSCarson Labrado     BMCWEB_ROUTE(
2508168d1b1aSCarson Labrado         app,
25099e9d99daSRavi Teja         "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/attachment/")
2510168d1b1aSCarson Labrado         .privileges(redfish::privileges::getLogEntry)
2511168d1b1aSCarson Labrado         .methods(boost::beast::http::verb::get)(std::bind_front(
2512168d1b1aSCarson Labrado             handleDBusEventLogEntryDownloadGet, std::ref(app), "System"));
2513168d1b1aSCarson Labrado }
2514168d1b1aSCarson Labrado 
2515fdd26906SClaire Weinan inline void requestRoutesFaultLogDumpService(App& app)
2516fdd26906SClaire Weinan {
2517253f11b8SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/")
2518fdd26906SClaire Weinan         .privileges(redfish::privileges::getLogService)
2519fdd26906SClaire Weinan         .methods(boost::beast::http::verb::get)(std::bind_front(
2520fdd26906SClaire Weinan             handleLogServicesDumpServiceGet, std::ref(app), "FaultLog"));
2521fdd26906SClaire Weinan }
2522fdd26906SClaire Weinan 
2523fdd26906SClaire Weinan inline void requestRoutesFaultLogDumpEntryCollection(App& app)
2524fdd26906SClaire Weinan {
2525253f11b8SEd Tanous     BMCWEB_ROUTE(app,
2526253f11b8SEd Tanous                  "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/")
2527fdd26906SClaire Weinan         .privileges(redfish::privileges::getLogEntryCollection)
2528fdd26906SClaire Weinan         .methods(boost::beast::http::verb::get)(
2529fdd26906SClaire Weinan             std::bind_front(handleLogServicesDumpEntriesCollectionGet,
2530fdd26906SClaire Weinan                             std::ref(app), "FaultLog"));
2531fdd26906SClaire Weinan }
2532fdd26906SClaire Weinan 
2533fdd26906SClaire Weinan inline void requestRoutesFaultLogDumpEntry(App& app)
2534fdd26906SClaire Weinan {
2535253f11b8SEd Tanous     BMCWEB_ROUTE(
2536253f11b8SEd Tanous         app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/<str>/")
2537fdd26906SClaire Weinan         .privileges(redfish::privileges::getLogEntry)
2538fdd26906SClaire Weinan         .methods(boost::beast::http::verb::get)(std::bind_front(
2539fdd26906SClaire Weinan             handleLogServicesDumpEntryGet, std::ref(app), "FaultLog"));
2540fdd26906SClaire Weinan 
2541253f11b8SEd Tanous     BMCWEB_ROUTE(
2542253f11b8SEd Tanous         app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/<str>/")
2543fdd26906SClaire Weinan         .privileges(redfish::privileges::deleteLogEntry)
2544fdd26906SClaire Weinan         .methods(boost::beast::http::verb::delete_)(std::bind_front(
2545fdd26906SClaire Weinan             handleLogServicesDumpEntryDelete, std::ref(app), "FaultLog"));
2546fdd26906SClaire Weinan }
2547fdd26906SClaire Weinan 
2548fdd26906SClaire Weinan inline void requestRoutesFaultLogDumpClear(App& app)
2549fdd26906SClaire Weinan {
2550fdd26906SClaire Weinan     BMCWEB_ROUTE(
2551fdd26906SClaire Weinan         app,
2552253f11b8SEd Tanous         "/redfish/v1/Managers/<str>/LogServices/FaultLog/Actions/LogService.ClearLog/")
2553fdd26906SClaire Weinan         .privileges(redfish::privileges::postLogService)
2554fdd26906SClaire Weinan         .methods(boost::beast::http::verb::post)(std::bind_front(
2555fdd26906SClaire Weinan             handleLogServicesDumpClearLogPost, std::ref(app), "FaultLog"));
25565cb1dd27SAsmitha Karunanithi }
25575cb1dd27SAsmitha Karunanithi 
25587e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpService(App& app)
25595cb1dd27SAsmitha Karunanithi {
256022d268cbSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Dump/")
2561ed398213SEd Tanous         .privileges(redfish::privileges::getLogService)
25626ab9ad54SClaire Weinan         .methods(boost::beast::http::verb::get)(std::bind_front(
256322d268cbSEd Tanous             handleLogServicesDumpServiceComputerSystemGet, std::ref(app)));
25645cb1dd27SAsmitha Karunanithi }
25655cb1dd27SAsmitha Karunanithi 
25667e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpEntryCollection(App& app)
25677e860f15SJohn Edward Broadbent {
256822d268cbSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/")
2569ed398213SEd Tanous         .privileges(redfish::privileges::getLogEntryCollection)
257022d268cbSEd Tanous         .methods(boost::beast::http::verb::get)(std::bind_front(
257122d268cbSEd Tanous             handleLogServicesDumpEntriesCollectionComputerSystemGet,
257222d268cbSEd Tanous             std::ref(app)));
25735cb1dd27SAsmitha Karunanithi }
25745cb1dd27SAsmitha Karunanithi 
25757e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpEntry(App& app)
25765cb1dd27SAsmitha Karunanithi {
25777e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
257822d268cbSEd Tanous                  "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/<str>/")
2579ed398213SEd Tanous         .privileges(redfish::privileges::getLogEntry)
25806ab9ad54SClaire Weinan         .methods(boost::beast::http::verb::get)(std::bind_front(
258122d268cbSEd Tanous             handleLogServicesDumpEntryComputerSystemGet, std::ref(app)));
25828d1b46d7Szhanghch05 
25837e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
258422d268cbSEd Tanous                  "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/<str>/")
2585ed398213SEd Tanous         .privileges(redfish::privileges::deleteLogEntry)
25866ab9ad54SClaire Weinan         .methods(boost::beast::http::verb::delete_)(std::bind_front(
258722d268cbSEd Tanous             handleLogServicesDumpEntryComputerSystemDelete, std::ref(app)));
25885cb1dd27SAsmitha Karunanithi }
2589c9bb6861Sraviteja-b 
25907e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpCreate(App& app)
2591c9bb6861Sraviteja-b {
25920fda0f12SGeorge Liu     BMCWEB_ROUTE(
25930fda0f12SGeorge Liu         app,
259422d268cbSEd Tanous         "/redfish/v1/Systems/<str>/LogServices/Dump/Actions/LogService.CollectDiagnosticData/")
2595ed398213SEd Tanous         .privileges(redfish::privileges::postLogService)
259622d268cbSEd Tanous         .methods(boost::beast::http::verb::post)(std::bind_front(
259722d268cbSEd Tanous             handleLogServicesDumpCollectDiagnosticDataComputerSystemPost,
259822d268cbSEd Tanous             std::ref(app)));
2599a43be80fSAsmitha Karunanithi }
2600a43be80fSAsmitha Karunanithi 
26017e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpClear(App& app)
2602a43be80fSAsmitha Karunanithi {
26030fda0f12SGeorge Liu     BMCWEB_ROUTE(
26040fda0f12SGeorge Liu         app,
260522d268cbSEd Tanous         "/redfish/v1/Systems/<str>/LogServices/Dump/Actions/LogService.ClearLog/")
2606ed398213SEd Tanous         .privileges(redfish::privileges::postLogService)
26076ab9ad54SClaire Weinan         .methods(boost::beast::http::verb::post)(std::bind_front(
260822d268cbSEd Tanous             handleLogServicesDumpClearLogComputerSystemPost, std::ref(app)));
2609013487e5Sraviteja-b }
2610013487e5Sraviteja-b 
26117e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpService(App& app)
26121da66f75SEd Tanous {
26133946028dSAppaRao Puli     // Note: Deviated from redfish privilege registry for GET & HEAD
26143946028dSAppaRao Puli     // method for security reasons.
26151da66f75SEd Tanous     /**
26161da66f75SEd Tanous      * Functions triggers appropriate requests on DBus
26171da66f75SEd Tanous      */
261822d268cbSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Crashdump/")
2619ed398213SEd Tanous         // This is incorrect, should be:
2620ed398213SEd Tanous         //.privileges(redfish::privileges::getLogService)
2621432a890cSEd Tanous         .privileges({{"ConfigureManager"}})
2622bd79bce8SPatrick Williams         .methods(
2623bd79bce8SPatrick Williams             boost::beast::http::verb::
2624bd79bce8SPatrick Williams                 get)([&app](const crow::Request& req,
262522d268cbSEd Tanous                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
262622d268cbSEd Tanous                             const std::string& systemName) {
26273ba00073SCarson Labrado             if (!redfish::setUpRedfishRoute(app, req, asyncResp))
262845ca1b86SEd Tanous             {
262945ca1b86SEd Tanous                 return;
263045ca1b86SEd Tanous             }
263125b54dbaSEd Tanous             if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
26327f3e84a1SEd Tanous             {
26337f3e84a1SEd Tanous                 // Option currently returns no systems.  TBD
26347f3e84a1SEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
26357f3e84a1SEd Tanous                                            systemName);
26367f3e84a1SEd Tanous                 return;
26377f3e84a1SEd Tanous             }
2638253f11b8SEd Tanous             if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
263922d268cbSEd Tanous             {
264022d268cbSEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
264122d268cbSEd Tanous                                            systemName);
264222d268cbSEd Tanous                 return;
264322d268cbSEd Tanous             }
264422d268cbSEd Tanous 
26457e860f15SJohn Edward Broadbent             // Copy over the static data to include the entries added by
26467e860f15SJohn Edward Broadbent             // SubRoute
26470f74e643SEd Tanous             asyncResp->res.jsonValue["@odata.id"] =
2648253f11b8SEd Tanous                 std::format("/redfish/v1/Systems/{}/LogServices/Crashdump",
2649253f11b8SEd Tanous                             BMCWEB_REDFISH_SYSTEM_URI_NAME);
2650e1f26343SJason M. Bills             asyncResp->res.jsonValue["@odata.type"] =
26518e6c099aSJason M. Bills                 "#LogService.v1_2_0.LogService";
26524f50ae4bSGunnar Mills             asyncResp->res.jsonValue["Name"] = "Open BMC Oem Crashdump Service";
26534f50ae4bSGunnar Mills             asyncResp->res.jsonValue["Description"] = "Oem Crashdump Service";
265415b89725SV-Sanjana             asyncResp->res.jsonValue["Id"] = "Crashdump";
2655539d8c6bSEd Tanous             asyncResp->res.jsonValue["OverWritePolicy"] =
2656539d8c6bSEd Tanous                 log_service::OverWritePolicy::WrapsWhenFull;
2657e1f26343SJason M. Bills             asyncResp->res.jsonValue["MaxNumberOfRecords"] = 3;
26587c8c4058STejas Patil 
26597c8c4058STejas Patil             std::pair<std::string, std::string> redfishDateTimeOffset =
26602b82937eSEd Tanous                 redfish::time_utils::getDateTimeOffsetNow();
26617c8c4058STejas Patil             asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
26627c8c4058STejas Patil             asyncResp->res.jsonValue["DateTimeLocalOffset"] =
26637c8c4058STejas Patil                 redfishDateTimeOffset.second;
26647c8c4058STejas Patil 
2665bd79bce8SPatrick Williams             asyncResp->res.jsonValue["Entries"]["@odata.id"] = std::format(
2666bd79bce8SPatrick Williams                 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries",
2667253f11b8SEd Tanous                 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2668253f11b8SEd Tanous             asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"]
2669253f11b8SEd Tanous                                     ["target"] = std::format(
2670253f11b8SEd Tanous                 "/redfish/v1/Systems/{}/LogServices/Crashdump/Actions/LogService.ClearLog",
2671253f11b8SEd Tanous                 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2672bd79bce8SPatrick Williams             asyncResp->res
2673bd79bce8SPatrick Williams                 .jsonValue["Actions"]["#LogService.CollectDiagnosticData"]
2674253f11b8SEd Tanous                           ["target"] = std::format(
2675253f11b8SEd Tanous                 "/redfish/v1/Systems/{}/LogServices/Crashdump/Actions/LogService.CollectDiagnosticData",
2676253f11b8SEd Tanous                 BMCWEB_REDFISH_SYSTEM_URI_NAME);
26777e860f15SJohn Edward Broadbent         });
26781da66f75SEd Tanous }
26791da66f75SEd Tanous 
26807e860f15SJohn Edward Broadbent void inline requestRoutesCrashdumpClear(App& app)
26815b61b5e8SJason M. Bills {
26820fda0f12SGeorge Liu     BMCWEB_ROUTE(
26830fda0f12SGeorge Liu         app,
268422d268cbSEd Tanous         "/redfish/v1/Systems/<str>/LogServices/Crashdump/Actions/LogService.ClearLog/")
2685ed398213SEd Tanous         // This is incorrect, should be:
2686ed398213SEd Tanous         //.privileges(redfish::privileges::postLogService)
2687432a890cSEd Tanous         .privileges({{"ConfigureComponents"}})
26887e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
268945ca1b86SEd Tanous             [&app](const crow::Request& req,
269022d268cbSEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
269122d268cbSEd Tanous                    const std::string& systemName) {
26923ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
269345ca1b86SEd Tanous                 {
269445ca1b86SEd Tanous                     return;
269545ca1b86SEd Tanous                 }
269625b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
26977f3e84a1SEd Tanous                 {
26987f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
26997f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
27007f3e84a1SEd Tanous                                                systemName);
27017f3e84a1SEd Tanous                     return;
27027f3e84a1SEd Tanous                 }
2703253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
270422d268cbSEd Tanous                 {
270522d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
270622d268cbSEd Tanous                                                systemName);
270722d268cbSEd Tanous                     return;
270822d268cbSEd Tanous                 }
27095b61b5e8SJason M. Bills                 crow::connections::systemBus->async_method_call(
27105e7e2dc5SEd Tanous                     [asyncResp](const boost::system::error_code& ec,
2711cb13a392SEd Tanous                                 const std::string&) {
27125b61b5e8SJason M. Bills                         if (ec)
27135b61b5e8SJason M. Bills                         {
27145b61b5e8SJason M. Bills                             messages::internalError(asyncResp->res);
27155b61b5e8SJason M. Bills                             return;
27165b61b5e8SJason M. Bills                         }
27175b61b5e8SJason M. Bills                         messages::success(asyncResp->res);
27185b61b5e8SJason M. Bills                     },
2719bd79bce8SPatrick Williams                     crashdumpObject, crashdumpPath, deleteAllInterface,
2720bd79bce8SPatrick Williams                     "DeleteAll");
27217e860f15SJohn Edward Broadbent             });
27225b61b5e8SJason M. Bills }
27235b61b5e8SJason M. Bills 
27244ff0f1f4SEd Tanous inline void
27258d1b46d7Szhanghch05     logCrashdumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
27268d1b46d7Szhanghch05                       const std::string& logID, nlohmann::json& logEntryJson)
2727e855dd28SJason M. Bills {
2728043a0536SJohnathan Mantey     auto getStoredLogCallback =
2729b9d36b47SEd Tanous         [asyncResp, logID,
27305e7e2dc5SEd Tanous          &logEntryJson](const boost::system::error_code& ec,
2731b9d36b47SEd Tanous                         const dbus::utility::DBusPropertiesMap& params) {
2732e855dd28SJason M. Bills             if (ec)
2733e855dd28SJason M. Bills             {
273462598e31SEd Tanous                 BMCWEB_LOG_DEBUG("failed to get log ec: {}", ec.message());
27351ddcf01aSJason M. Bills                 if (ec.value() ==
27361ddcf01aSJason M. Bills                     boost::system::linux_error::bad_request_descriptor)
27371ddcf01aSJason M. Bills                 {
2738bd79bce8SPatrick Williams                     messages::resourceNotFound(asyncResp->res, "LogEntry",
2739bd79bce8SPatrick Williams                                                logID);
27401ddcf01aSJason M. Bills                 }
27411ddcf01aSJason M. Bills                 else
27421ddcf01aSJason M. Bills                 {
2743e855dd28SJason M. Bills                     messages::internalError(asyncResp->res);
27441ddcf01aSJason M. Bills                 }
2745e855dd28SJason M. Bills                 return;
2746e855dd28SJason M. Bills             }
2747043a0536SJohnathan Mantey 
2748043a0536SJohnathan Mantey             std::string timestamp{};
2749043a0536SJohnathan Mantey             std::string filename{};
2750043a0536SJohnathan Mantey             std::string logfile{};
27512c70f800SEd Tanous             parseCrashdumpParameters(params, filename, timestamp, logfile);
2752043a0536SJohnathan Mantey 
2753043a0536SJohnathan Mantey             if (filename.empty() || timestamp.empty())
2754e855dd28SJason M. Bills             {
27559db4ba25SJiaqing Zhao                 messages::resourceNotFound(asyncResp->res, "LogEntry", logID);
2756e855dd28SJason M. Bills                 return;
2757e855dd28SJason M. Bills             }
2758e855dd28SJason M. Bills 
2759043a0536SJohnathan Mantey             std::string crashdumpURI =
2760bd79bce8SPatrick Williams                 std::format(
2761bd79bce8SPatrick Williams                     "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries/",
2762253f11b8SEd Tanous                     BMCWEB_REDFISH_SYSTEM_URI_NAME) +
2763043a0536SJohnathan Mantey                 logID + "/" + filename;
276484afc48bSJason M. Bills             nlohmann::json::object_t logEntry;
27659c11a172SVijay Lobo             logEntry["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
2766ef4c65b7SEd Tanous             logEntry["@odata.id"] = boost::urls::format(
2767253f11b8SEd Tanous                 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries/{}",
2768253f11b8SEd Tanous                 BMCWEB_REDFISH_SYSTEM_URI_NAME, logID);
276984afc48bSJason M. Bills             logEntry["Name"] = "CPU Crashdump";
277084afc48bSJason M. Bills             logEntry["Id"] = logID;
2771539d8c6bSEd Tanous             logEntry["EntryType"] = log_entry::LogEntryType::Oem;
277284afc48bSJason M. Bills             logEntry["AdditionalDataURI"] = std::move(crashdumpURI);
277384afc48bSJason M. Bills             logEntry["DiagnosticDataType"] = "OEM";
277484afc48bSJason M. Bills             logEntry["OEMDiagnosticDataType"] = "PECICrashdump";
277584afc48bSJason M. Bills             logEntry["Created"] = std::move(timestamp);
27762b20ef6eSJason M. Bills 
27772b20ef6eSJason M. Bills             // If logEntryJson references an array of LogEntry resources
27782b20ef6eSJason M. Bills             // ('Members' list), then push this as a new entry, otherwise set it
27792b20ef6eSJason M. Bills             // directly
27802b20ef6eSJason M. Bills             if (logEntryJson.is_array())
27812b20ef6eSJason M. Bills             {
27822b20ef6eSJason M. Bills                 logEntryJson.push_back(logEntry);
27832b20ef6eSJason M. Bills                 asyncResp->res.jsonValue["Members@odata.count"] =
27842b20ef6eSJason M. Bills                     logEntryJson.size();
27852b20ef6eSJason M. Bills             }
27862b20ef6eSJason M. Bills             else
27872b20ef6eSJason M. Bills             {
2788d405bb51SJason M. Bills                 logEntryJson.update(logEntry);
27892b20ef6eSJason M. Bills             }
2790e855dd28SJason M. Bills         };
2791d1bde9e5SKrzysztof Grobelny     sdbusplus::asio::getAllProperties(
2792d1bde9e5SKrzysztof Grobelny         *crow::connections::systemBus, crashdumpObject,
2793d1bde9e5SKrzysztof Grobelny         crashdumpPath + std::string("/") + logID, crashdumpInterface,
2794d1bde9e5SKrzysztof Grobelny         std::move(getStoredLogCallback));
2795e855dd28SJason M. Bills }
2796e855dd28SJason M. Bills 
27977e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpEntryCollection(App& app)
27981da66f75SEd Tanous {
27993946028dSAppaRao Puli     // Note: Deviated from redfish privilege registry for GET & HEAD
28003946028dSAppaRao Puli     // method for security reasons.
28011da66f75SEd Tanous     /**
28021da66f75SEd Tanous      * Functions triggers appropriate requests on DBus
28031da66f75SEd Tanous      */
28047e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
280522d268cbSEd Tanous                  "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/")
2806ed398213SEd Tanous         // This is incorrect, should be.
2807ed398213SEd Tanous         //.privileges(redfish::privileges::postLogEntryCollection)
2808432a890cSEd Tanous         .privileges({{"ConfigureComponents"}})
2809bd79bce8SPatrick Williams         .methods(
2810bd79bce8SPatrick Williams             boost::beast::http::verb::
2811bd79bce8SPatrick Williams                 get)([&app](const crow::Request& req,
281222d268cbSEd Tanous                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
281322d268cbSEd Tanous                             const std::string& systemName) {
28143ba00073SCarson Labrado             if (!redfish::setUpRedfishRoute(app, req, asyncResp))
281545ca1b86SEd Tanous             {
281645ca1b86SEd Tanous                 return;
281745ca1b86SEd Tanous             }
281825b54dbaSEd Tanous             if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
28197f3e84a1SEd Tanous             {
28207f3e84a1SEd Tanous                 // Option currently returns no systems.  TBD
28217f3e84a1SEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
28227f3e84a1SEd Tanous                                            systemName);
28237f3e84a1SEd Tanous                 return;
28247f3e84a1SEd Tanous             }
2825253f11b8SEd Tanous             if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
282622d268cbSEd Tanous             {
282722d268cbSEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
282822d268cbSEd Tanous                                            systemName);
282922d268cbSEd Tanous                 return;
283022d268cbSEd Tanous             }
283122d268cbSEd Tanous 
28327a1dbc48SGeorge Liu             constexpr std::array<std::string_view, 1> interfaces = {
28337a1dbc48SGeorge Liu                 crashdumpInterface};
28347a1dbc48SGeorge Liu             dbus::utility::getSubTreePaths(
28357a1dbc48SGeorge Liu                 "/", 0, interfaces,
28367a1dbc48SGeorge Liu                 [asyncResp](const boost::system::error_code& ec,
28372b20ef6eSJason M. Bills                             const std::vector<std::string>& resp) {
28381da66f75SEd Tanous                     if (ec)
28391da66f75SEd Tanous                     {
28401da66f75SEd Tanous                         if (ec.value() !=
28411da66f75SEd Tanous                             boost::system::errc::no_such_file_or_directory)
28421da66f75SEd Tanous                         {
284362598e31SEd Tanous                             BMCWEB_LOG_DEBUG("failed to get entries ec: {}",
284462598e31SEd Tanous                                              ec.message());
2845f12894f8SJason M. Bills                             messages::internalError(asyncResp->res);
28461da66f75SEd Tanous                             return;
28471da66f75SEd Tanous                         }
28481da66f75SEd Tanous                     }
2849e1f26343SJason M. Bills                     asyncResp->res.jsonValue["@odata.type"] =
28501da66f75SEd Tanous                         "#LogEntryCollection.LogEntryCollection";
2851253f11b8SEd Tanous                     asyncResp->res.jsonValue["@odata.id"] = std::format(
2852253f11b8SEd Tanous                         "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries",
2853253f11b8SEd Tanous                         BMCWEB_REDFISH_SYSTEM_URI_NAME);
2854bd79bce8SPatrick Williams                     asyncResp->res.jsonValue["Name"] =
2855bd79bce8SPatrick Williams                         "Open BMC Crashdump Entries";
2856e1f26343SJason M. Bills                     asyncResp->res.jsonValue["Description"] =
2857424c4176SJason M. Bills                         "Collection of Crashdump Entries";
2858bd79bce8SPatrick Williams                     asyncResp->res.jsonValue["Members"] =
2859bd79bce8SPatrick Williams                         nlohmann::json::array();
2860a2dd60a6SBrandon Kim                     asyncResp->res.jsonValue["Members@odata.count"] = 0;
28612b20ef6eSJason M. Bills 
28622b20ef6eSJason M. Bills                     for (const std::string& path : resp)
28631da66f75SEd Tanous                     {
28642b20ef6eSJason M. Bills                         const sdbusplus::message::object_path objPath(path);
2865e855dd28SJason M. Bills                         // Get the log ID
28662b20ef6eSJason M. Bills                         std::string logID = objPath.filename();
28672b20ef6eSJason M. Bills                         if (logID.empty())
28681da66f75SEd Tanous                         {
2869e855dd28SJason M. Bills                             continue;
28701da66f75SEd Tanous                         }
2871e855dd28SJason M. Bills                         // Add the log entry to the array
28722b20ef6eSJason M. Bills                         logCrashdumpEntry(asyncResp, logID,
28732b20ef6eSJason M. Bills                                           asyncResp->res.jsonValue["Members"]);
28741da66f75SEd Tanous                     }
28757a1dbc48SGeorge Liu                 });
28767e860f15SJohn Edward Broadbent         });
28771da66f75SEd Tanous }
28781da66f75SEd Tanous 
28797e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpEntry(App& app)
28801da66f75SEd Tanous {
28813946028dSAppaRao Puli     // Note: Deviated from redfish privilege registry for GET & HEAD
28823946028dSAppaRao Puli     // method for security reasons.
28831da66f75SEd Tanous 
28847e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
288522d268cbSEd Tanous         app, "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/<str>/")
2886ed398213SEd Tanous         // this is incorrect, should be
2887ed398213SEd Tanous         // .privileges(redfish::privileges::getLogEntry)
2888432a890cSEd Tanous         .privileges({{"ConfigureComponents"}})
28897e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
289045ca1b86SEd Tanous             [&app](const crow::Request& req,
28917e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
289222d268cbSEd Tanous                    const std::string& systemName, const std::string& param) {
28933ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
289445ca1b86SEd Tanous                 {
289545ca1b86SEd Tanous                     return;
289645ca1b86SEd Tanous                 }
289725b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
28987f3e84a1SEd Tanous                 {
28997f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
29007f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
29017f3e84a1SEd Tanous                                                systemName);
29027f3e84a1SEd Tanous                     return;
29037f3e84a1SEd Tanous                 }
2904253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
290522d268cbSEd Tanous                 {
290622d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
290722d268cbSEd Tanous                                                systemName);
290822d268cbSEd Tanous                     return;
290922d268cbSEd Tanous                 }
29107e860f15SJohn Edward Broadbent                 const std::string& logID = param;
2911e855dd28SJason M. Bills                 logCrashdumpEntry(asyncResp, logID, asyncResp->res.jsonValue);
29127e860f15SJohn Edward Broadbent             });
2913e855dd28SJason M. Bills }
2914e855dd28SJason M. Bills 
29157e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpFile(App& app)
2916e855dd28SJason M. Bills {
29173946028dSAppaRao Puli     // Note: Deviated from redfish privilege registry for GET & HEAD
29183946028dSAppaRao Puli     // method for security reasons.
29197e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
29207e860f15SJohn Edward Broadbent         app,
292122d268cbSEd Tanous         "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/<str>/<str>/")
2922ed398213SEd Tanous         .privileges(redfish::privileges::getLogEntry)
29237e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
2924a4ce114aSNan Zhou             [](const crow::Request& req,
29257e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
292622d268cbSEd Tanous                const std::string& systemName, const std::string& logID,
292722d268cbSEd Tanous                const std::string& fileName) {
2928bd79bce8SPatrick Williams                 // Do not call getRedfishRoute here since the crashdump file is
2929bd79bce8SPatrick Williams                 // not a Redfish resource.
293022d268cbSEd Tanous 
293125b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
29327f3e84a1SEd Tanous                 {
29337f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
29347f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
29357f3e84a1SEd Tanous                                                systemName);
29367f3e84a1SEd Tanous                     return;
29377f3e84a1SEd Tanous                 }
2938253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
293922d268cbSEd Tanous                 {
294022d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
294122d268cbSEd Tanous                                                systemName);
294222d268cbSEd Tanous                     return;
294322d268cbSEd Tanous                 }
294422d268cbSEd Tanous 
2945043a0536SJohnathan Mantey                 auto getStoredLogCallback =
2946bd79bce8SPatrick Williams                     [asyncResp, logID, fileName,
2947bd79bce8SPatrick Williams                      url(boost::urls::url(req.url()))](
29485e7e2dc5SEd Tanous                         const boost::system::error_code& ec,
2949bd79bce8SPatrick Williams                         const std::vector<std::pair<
2950bd79bce8SPatrick Williams                             std::string, dbus::utility::DbusVariantType>>&
29517e860f15SJohn Edward Broadbent                             resp) {
29521da66f75SEd Tanous                         if (ec)
29531da66f75SEd Tanous                         {
2954bd79bce8SPatrick Williams                             BMCWEB_LOG_DEBUG("failed to get log ec: {}",
2955bd79bce8SPatrick Williams                                              ec.message());
2956f12894f8SJason M. Bills                             messages::internalError(asyncResp->res);
29571da66f75SEd Tanous                             return;
29581da66f75SEd Tanous                         }
2959e855dd28SJason M. Bills 
2960043a0536SJohnathan Mantey                         std::string dbusFilename{};
2961043a0536SJohnathan Mantey                         std::string dbusTimestamp{};
2962043a0536SJohnathan Mantey                         std::string dbusFilepath{};
2963043a0536SJohnathan Mantey 
2964bd79bce8SPatrick Williams                         parseCrashdumpParameters(resp, dbusFilename,
2965bd79bce8SPatrick Williams                                                  dbusTimestamp, dbusFilepath);
2966043a0536SJohnathan Mantey 
2967043a0536SJohnathan Mantey                         if (dbusFilename.empty() || dbusTimestamp.empty() ||
2968043a0536SJohnathan Mantey                             dbusFilepath.empty())
29691da66f75SEd Tanous                         {
2970bd79bce8SPatrick Williams                             messages::resourceNotFound(asyncResp->res,
2971bd79bce8SPatrick Williams                                                        "LogEntry", logID);
29721da66f75SEd Tanous                             return;
29731da66f75SEd Tanous                         }
2974e855dd28SJason M. Bills 
2975043a0536SJohnathan Mantey                         // Verify the file name parameter is correct
2976043a0536SJohnathan Mantey                         if (fileName != dbusFilename)
2977043a0536SJohnathan Mantey                         {
2978bd79bce8SPatrick Williams                             messages::resourceNotFound(asyncResp->res,
2979bd79bce8SPatrick Williams                                                        "LogEntry", logID);
2980043a0536SJohnathan Mantey                             return;
2981043a0536SJohnathan Mantey                         }
2982043a0536SJohnathan Mantey 
2983d51c61b4SMyung Bae                         if (asyncResp->res.openFile(dbusFilepath) !=
2984d51c61b4SMyung Bae                             crow::OpenCode::Success)
2985043a0536SJohnathan Mantey                         {
2986bd79bce8SPatrick Williams                             messages::resourceNotFound(asyncResp->res,
2987bd79bce8SPatrick Williams                                                        "LogEntry", logID);
2988043a0536SJohnathan Mantey                             return;
2989043a0536SJohnathan Mantey                         }
2990043a0536SJohnathan Mantey 
29917e860f15SJohn Edward Broadbent                         // Configure this to be a file download when accessed
29927e860f15SJohn Edward Broadbent                         // from a browser
2993d9f6c621SEd Tanous                         asyncResp->res.addHeader(
2994bd79bce8SPatrick Williams                             boost::beast::http::field::content_disposition,
2995bd79bce8SPatrick Williams                             "attachment");
29961da66f75SEd Tanous                     };
2997d1bde9e5SKrzysztof Grobelny                 sdbusplus::asio::getAllProperties(
2998d1bde9e5SKrzysztof Grobelny                     *crow::connections::systemBus, crashdumpObject,
2999bd79bce8SPatrick Williams                     crashdumpPath + std::string("/") + logID,
3000bd79bce8SPatrick Williams                     crashdumpInterface, std::move(getStoredLogCallback));
30017e860f15SJohn Edward Broadbent             });
30021da66f75SEd Tanous }
30031da66f75SEd Tanous 
3004c5a4c82aSJason M. Bills enum class OEMDiagnosticType
3005c5a4c82aSJason M. Bills {
3006c5a4c82aSJason M. Bills     onDemand,
3007c5a4c82aSJason M. Bills     telemetry,
3008c5a4c82aSJason M. Bills     invalid,
3009c5a4c82aSJason M. Bills };
3010c5a4c82aSJason M. Bills 
301126ccae32SEd Tanous inline OEMDiagnosticType getOEMDiagnosticType(std::string_view oemDiagStr)
3012c5a4c82aSJason M. Bills {
3013c5a4c82aSJason M. Bills     if (oemDiagStr == "OnDemand")
3014c5a4c82aSJason M. Bills     {
3015c5a4c82aSJason M. Bills         return OEMDiagnosticType::onDemand;
3016c5a4c82aSJason M. Bills     }
3017c5a4c82aSJason M. Bills     if (oemDiagStr == "Telemetry")
3018c5a4c82aSJason M. Bills     {
3019c5a4c82aSJason M. Bills         return OEMDiagnosticType::telemetry;
3020c5a4c82aSJason M. Bills     }
3021c5a4c82aSJason M. Bills 
3022c5a4c82aSJason M. Bills     return OEMDiagnosticType::invalid;
3023c5a4c82aSJason M. Bills }
3024c5a4c82aSJason M. Bills 
30257e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpCollect(App& app)
30261da66f75SEd Tanous {
30273946028dSAppaRao Puli     // Note: Deviated from redfish privilege registry for GET & HEAD
30283946028dSAppaRao Puli     // method for security reasons.
30290fda0f12SGeorge Liu     BMCWEB_ROUTE(
30300fda0f12SGeorge Liu         app,
303122d268cbSEd Tanous         "/redfish/v1/Systems/<str>/LogServices/Crashdump/Actions/LogService.CollectDiagnosticData/")
3032ed398213SEd Tanous         // The below is incorrect;  Should be ConfigureManager
3033ed398213SEd Tanous         //.privileges(redfish::privileges::postLogService)
3034432a890cSEd Tanous         .privileges({{"ConfigureComponents"}})
3035002d39b4SEd Tanous         .methods(boost::beast::http::verb::post)(
3036002d39b4SEd Tanous             [&app](const crow::Request& req,
303722d268cbSEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
303822d268cbSEd Tanous                    const std::string& systemName) {
30393ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
304045ca1b86SEd Tanous                 {
304145ca1b86SEd Tanous                     return;
304245ca1b86SEd Tanous                 }
304322d268cbSEd Tanous 
304425b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
30457f3e84a1SEd Tanous                 {
30467f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
30477f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
30487f3e84a1SEd Tanous                                                systemName);
30497f3e84a1SEd Tanous                     return;
30507f3e84a1SEd Tanous                 }
3051253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
305222d268cbSEd Tanous                 {
305322d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
305422d268cbSEd Tanous                                                systemName);
305522d268cbSEd Tanous                     return;
305622d268cbSEd Tanous                 }
305722d268cbSEd Tanous 
30588e6c099aSJason M. Bills                 std::string diagnosticDataType;
30598e6c099aSJason M. Bills                 std::string oemDiagnosticDataType;
3060*afc474aeSMyung Bae                 if (!redfish::json_util::readJsonAction( //
3061*afc474aeSMyung Bae                         req, asyncResp->res, //
3062*afc474aeSMyung Bae                         "DiagnosticDataType", diagnosticDataType, //
3063*afc474aeSMyung Bae                         "OEMDiagnosticDataType", oemDiagnosticDataType //
3064*afc474aeSMyung Bae                         ))
30658e6c099aSJason M. Bills                 {
30668e6c099aSJason M. Bills                     return;
30678e6c099aSJason M. Bills                 }
30688e6c099aSJason M. Bills 
30698e6c099aSJason M. Bills                 if (diagnosticDataType != "OEM")
30708e6c099aSJason M. Bills                 {
307162598e31SEd Tanous                     BMCWEB_LOG_ERROR(
307262598e31SEd Tanous                         "Only OEM DiagnosticDataType supported for Crashdump");
30738e6c099aSJason M. Bills                     messages::actionParameterValueFormatError(
3074bd79bce8SPatrick Williams                         asyncResp->res, diagnosticDataType,
3075bd79bce8SPatrick Williams                         "DiagnosticDataType", "CollectDiagnosticData");
30768e6c099aSJason M. Bills                     return;
30778e6c099aSJason M. Bills                 }
30788e6c099aSJason M. Bills 
3079c5a4c82aSJason M. Bills                 OEMDiagnosticType oemDiagType =
3080c5a4c82aSJason M. Bills                     getOEMDiagnosticType(oemDiagnosticDataType);
3081c5a4c82aSJason M. Bills 
3082c5a4c82aSJason M. Bills                 std::string iface;
3083c5a4c82aSJason M. Bills                 std::string method;
3084c5a4c82aSJason M. Bills                 std::string taskMatchStr;
3085c5a4c82aSJason M. Bills                 if (oemDiagType == OEMDiagnosticType::onDemand)
3086c5a4c82aSJason M. Bills                 {
3087c5a4c82aSJason M. Bills                     iface = crashdumpOnDemandInterface;
3088c5a4c82aSJason M. Bills                     method = "GenerateOnDemandLog";
3089bd79bce8SPatrick Williams                     taskMatchStr =
3090bd79bce8SPatrick Williams                         "type='signal',"
3091c5a4c82aSJason M. Bills                         "interface='org.freedesktop.DBus.Properties',"
3092c5a4c82aSJason M. Bills                         "member='PropertiesChanged',"
3093c5a4c82aSJason M. Bills                         "arg0namespace='com.intel.crashdump'";
3094c5a4c82aSJason M. Bills                 }
3095c5a4c82aSJason M. Bills                 else if (oemDiagType == OEMDiagnosticType::telemetry)
3096c5a4c82aSJason M. Bills                 {
3097c5a4c82aSJason M. Bills                     iface = crashdumpTelemetryInterface;
3098c5a4c82aSJason M. Bills                     method = "GenerateTelemetryLog";
3099bd79bce8SPatrick Williams                     taskMatchStr =
3100bd79bce8SPatrick Williams                         "type='signal',"
3101c5a4c82aSJason M. Bills                         "interface='org.freedesktop.DBus.Properties',"
3102c5a4c82aSJason M. Bills                         "member='PropertiesChanged',"
3103c5a4c82aSJason M. Bills                         "arg0namespace='com.intel.crashdump'";
3104c5a4c82aSJason M. Bills                 }
3105c5a4c82aSJason M. Bills                 else
3106c5a4c82aSJason M. Bills                 {
310762598e31SEd Tanous                     BMCWEB_LOG_ERROR("Unsupported OEMDiagnosticDataType: {}",
310862598e31SEd Tanous                                      oemDiagnosticDataType);
3109c5a4c82aSJason M. Bills                     messages::actionParameterValueFormatError(
3110bd79bce8SPatrick Williams                         asyncResp->res, oemDiagnosticDataType,
3111bd79bce8SPatrick Williams                         "OEMDiagnosticDataType", "CollectDiagnosticData");
3112c5a4c82aSJason M. Bills                     return;
3113c5a4c82aSJason M. Bills                 }
3114c5a4c82aSJason M. Bills 
3115c5a4c82aSJason M. Bills                 auto collectCrashdumpCallback =
3116c5a4c82aSJason M. Bills                     [asyncResp, payload(task::Payload(req)),
31175e7e2dc5SEd Tanous                      taskMatchStr](const boost::system::error_code& ec,
311898be3e39SEd Tanous                                    const std::string&) mutable {
31191da66f75SEd Tanous                         if (ec)
31201da66f75SEd Tanous                         {
3121bd79bce8SPatrick Williams                             if (ec.value() ==
3122bd79bce8SPatrick Williams                                 boost::system::errc::operation_not_supported)
31231da66f75SEd Tanous                             {
3124f12894f8SJason M. Bills                                 messages::resourceInStandby(asyncResp->res);
31251da66f75SEd Tanous                             }
3126bd79bce8SPatrick Williams                             else if (ec.value() == boost::system::errc::
3127bd79bce8SPatrick Williams                                                        device_or_resource_busy)
31284363d3b2SJason M. Bills                             {
3129bd79bce8SPatrick Williams                                 messages::serviceTemporarilyUnavailable(
3130bd79bce8SPatrick Williams                                     asyncResp->res, "60");
31314363d3b2SJason M. Bills                             }
31321da66f75SEd Tanous                             else
31331da66f75SEd Tanous                             {
3134f12894f8SJason M. Bills                                 messages::internalError(asyncResp->res);
31351da66f75SEd Tanous                             }
31361da66f75SEd Tanous                             return;
31371da66f75SEd Tanous                         }
3138bd79bce8SPatrick Williams                         std::shared_ptr<task::TaskData> task =
3139bd79bce8SPatrick Williams                             task::TaskData::createTask(
3140bd79bce8SPatrick Williams                                 [](const boost::system::error_code& ec2,
3141bd79bce8SPatrick Williams                                    sdbusplus::message_t&,
3142bd79bce8SPatrick Williams                                    const std::shared_ptr<task::TaskData>&
3143bd79bce8SPatrick Williams                                        taskData) {
31448b24275dSEd Tanous                                     if (!ec2)
314566afe4faSJames Feist                                     {
3146bd79bce8SPatrick Williams                                         taskData->messages.emplace_back(
3147bd79bce8SPatrick Williams                                             messages::taskCompletedOK(
3148bd79bce8SPatrick Williams                                                 std::to_string(
3149bd79bce8SPatrick Williams                                                     taskData->index)));
3150831d6b09SJames Feist                                         taskData->state = "Completed";
315166afe4faSJames Feist                                     }
315232898ceaSJames Feist                                     return task::completed;
315366afe4faSJames Feist                                 },
3154c5a4c82aSJason M. Bills                                 taskMatchStr);
3155c5a4c82aSJason M. Bills 
315646229577SJames Feist                         task->startTimer(std::chrono::minutes(5));
315746229577SJames Feist                         task->populateResp(asyncResp->res);
315898be3e39SEd Tanous                         task->payload.emplace(std::move(payload));
31591da66f75SEd Tanous                     };
31608e6c099aSJason M. Bills 
31611da66f75SEd Tanous                 crow::connections::systemBus->async_method_call(
3162bd79bce8SPatrick Williams                     std::move(collectCrashdumpCallback), crashdumpObject,
3163bd79bce8SPatrick Williams                     crashdumpPath, iface, method);
31647e860f15SJohn Edward Broadbent             });
31656eda7685SKenny L. Ku }
31666eda7685SKenny L. Ku 
3167599b9af3SAlexander Hansen inline void dBusLogServiceActionsClear(
3168599b9af3SAlexander Hansen     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
3169599b9af3SAlexander Hansen {
3170599b9af3SAlexander Hansen     BMCWEB_LOG_DEBUG("Do delete all entries.");
3171599b9af3SAlexander Hansen 
3172599b9af3SAlexander Hansen     // Process response from Logging service.
3173599b9af3SAlexander Hansen     auto respHandler = [asyncResp](const boost::system::error_code& ec) {
3174599b9af3SAlexander Hansen         BMCWEB_LOG_DEBUG("doClearLog resp_handler callback: Done");
3175599b9af3SAlexander Hansen         if (ec)
3176599b9af3SAlexander Hansen         {
3177599b9af3SAlexander Hansen             // TODO Handle for specific error code
3178599b9af3SAlexander Hansen             BMCWEB_LOG_ERROR("doClearLog resp_handler got error {}", ec);
3179599b9af3SAlexander Hansen             asyncResp->res.result(
3180599b9af3SAlexander Hansen                 boost::beast::http::status::internal_server_error);
3181599b9af3SAlexander Hansen             return;
3182599b9af3SAlexander Hansen         }
3183599b9af3SAlexander Hansen 
3184599b9af3SAlexander Hansen         asyncResp->res.result(boost::beast::http::status::no_content);
3185599b9af3SAlexander Hansen     };
3186599b9af3SAlexander Hansen 
3187599b9af3SAlexander Hansen     // Make call to Logging service to request Clear Log
3188599b9af3SAlexander Hansen     crow::connections::systemBus->async_method_call(
3189599b9af3SAlexander Hansen         respHandler, "xyz.openbmc_project.Logging",
3190599b9af3SAlexander Hansen         "/xyz/openbmc_project/logging",
3191599b9af3SAlexander Hansen         "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
3192599b9af3SAlexander Hansen }
3193599b9af3SAlexander Hansen 
3194cb92c03bSAndrew Geissler /**
3195cb92c03bSAndrew Geissler  * DBusLogServiceActionsClear class supports POST method for ClearLog action.
3196cb92c03bSAndrew Geissler  */
31977e860f15SJohn Edward Broadbent inline void requestRoutesDBusLogServiceActionsClear(App& app)
3198cb92c03bSAndrew Geissler {
3199cb92c03bSAndrew Geissler     /**
3200cb92c03bSAndrew Geissler      * Function handles POST method request.
3201cb92c03bSAndrew Geissler      * The Clear Log actions does not require any parameter.The action deletes
3202cb92c03bSAndrew Geissler      * all entries found in the Entries collection for this Log Service.
3203cb92c03bSAndrew Geissler      */
32047e860f15SJohn Edward Broadbent 
32050fda0f12SGeorge Liu     BMCWEB_ROUTE(
32060fda0f12SGeorge Liu         app,
320722d268cbSEd Tanous         "/redfish/v1/Systems/<str>/LogServices/EventLog/Actions/LogService.ClearLog/")
3208ed398213SEd Tanous         .privileges(redfish::privileges::postLogService)
32097e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
321045ca1b86SEd Tanous             [&app](const crow::Request& req,
321122d268cbSEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
321222d268cbSEd Tanous                    const std::string& systemName) {
32133ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
321445ca1b86SEd Tanous                 {
321545ca1b86SEd Tanous                     return;
321645ca1b86SEd Tanous                 }
321725b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
32187f3e84a1SEd Tanous                 {
32197f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
32207f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
32217f3e84a1SEd Tanous                                                systemName);
32227f3e84a1SEd Tanous                     return;
32237f3e84a1SEd Tanous                 }
3224253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
322522d268cbSEd Tanous                 {
322622d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
322722d268cbSEd Tanous                                                systemName);
322822d268cbSEd Tanous                     return;
322922d268cbSEd Tanous                 }
3230599b9af3SAlexander Hansen                 dBusLogServiceActionsClear(asyncResp);
32317e860f15SJohn Edward Broadbent             });
3232cb92c03bSAndrew Geissler }
3233a3316fc6SZhikuiRen 
32341da66f75SEd Tanous } // namespace redfish
3235