xref: /openbmc/bmcweb/features/redfish/lib/log_services.hpp (revision 262dcc1ca87af630218644204fc6948f7f592b9f)
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"
33*262dcc1cSAlexander 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 
94415ed6780SWilly Tu     if (!redfish::json_util::readJsonAction(
945a43be80fSAsmitha Karunanithi             req, asyncResp->res, "DiagnosticDataType", diagnosticDataType,
946a43be80fSAsmitha Karunanithi             "OEMDiagnosticDataType", oemDiagnosticDataType))
947a43be80fSAsmitha Karunanithi     {
948a43be80fSAsmitha Karunanithi         return;
949a43be80fSAsmitha Karunanithi     }
950a43be80fSAsmitha Karunanithi 
951a43be80fSAsmitha Karunanithi     if (dumpType == "System")
952a43be80fSAsmitha Karunanithi     {
953a43be80fSAsmitha Karunanithi         if (!oemDiagnosticDataType || !diagnosticDataType)
954a43be80fSAsmitha Karunanithi         {
95562598e31SEd Tanous             BMCWEB_LOG_ERROR(
95662598e31SEd Tanous                 "CreateDump action parameter 'DiagnosticDataType'/'OEMDiagnosticDataType' value not found!");
957a43be80fSAsmitha Karunanithi             messages::actionParameterMissing(
958a43be80fSAsmitha Karunanithi                 asyncResp->res, "CollectDiagnosticData",
959a43be80fSAsmitha Karunanithi                 "DiagnosticDataType & OEMDiagnosticDataType");
960a43be80fSAsmitha Karunanithi             return;
961a43be80fSAsmitha Karunanithi         }
9623174e4dfSEd Tanous         if ((*oemDiagnosticDataType != "System") ||
963a43be80fSAsmitha Karunanithi             (*diagnosticDataType != "OEM"))
964a43be80fSAsmitha Karunanithi         {
96562598e31SEd Tanous             BMCWEB_LOG_ERROR("Wrong parameter values passed");
966ace85d60SEd Tanous             messages::internalError(asyncResp->res);
967a43be80fSAsmitha Karunanithi             return;
968a43be80fSAsmitha Karunanithi         }
969253f11b8SEd Tanous         dumpPath = std::format("/redfish/v1/Systems/{}/LogServices/Dump/",
970253f11b8SEd Tanous                                BMCWEB_REDFISH_SYSTEM_URI_NAME);
971a43be80fSAsmitha Karunanithi     }
972a43be80fSAsmitha Karunanithi     else if (dumpType == "BMC")
973a43be80fSAsmitha Karunanithi     {
974a43be80fSAsmitha Karunanithi         if (!diagnosticDataType)
975a43be80fSAsmitha Karunanithi         {
97662598e31SEd Tanous             BMCWEB_LOG_ERROR(
97762598e31SEd Tanous                 "CreateDump action parameter 'DiagnosticDataType' not found!");
978a43be80fSAsmitha Karunanithi             messages::actionParameterMissing(
979a43be80fSAsmitha Karunanithi                 asyncResp->res, "CollectDiagnosticData", "DiagnosticDataType");
980a43be80fSAsmitha Karunanithi             return;
981a43be80fSAsmitha Karunanithi         }
9823174e4dfSEd Tanous         if (*diagnosticDataType != "Manager")
983a43be80fSAsmitha Karunanithi         {
98462598e31SEd Tanous             BMCWEB_LOG_ERROR(
98562598e31SEd Tanous                 "Wrong parameter value passed for 'DiagnosticDataType'");
986ace85d60SEd Tanous             messages::internalError(asyncResp->res);
987a43be80fSAsmitha Karunanithi             return;
988a43be80fSAsmitha Karunanithi         }
989253f11b8SEd Tanous         dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/Dump/",
990253f11b8SEd Tanous                                BMCWEB_REDFISH_MANAGER_URI_NAME);
9915907571dSAsmitha Karunanithi     }
9925907571dSAsmitha Karunanithi     else
9935907571dSAsmitha Karunanithi     {
99462598e31SEd Tanous         BMCWEB_LOG_ERROR("CreateDump failed. Unknown dump type");
9955907571dSAsmitha Karunanithi         messages::internalError(asyncResp->res);
9965907571dSAsmitha Karunanithi         return;
997a43be80fSAsmitha Karunanithi     }
998a43be80fSAsmitha Karunanithi 
9998e31778eSAsmitha Karunanithi     std::vector<std::pair<std::string, std::variant<std::string, uint64_t>>>
10008e31778eSAsmitha Karunanithi         createDumpParamVec;
10018e31778eSAsmitha Karunanithi 
1002f574a8e1SCarson Labrado     if (req.session != nullptr)
1003f574a8e1SCarson Labrado     {
100468dd075aSAsmitha Karunanithi         createDumpParamVec.emplace_back(
100568dd075aSAsmitha Karunanithi             "xyz.openbmc_project.Dump.Create.CreateParameters.OriginatorId",
100668dd075aSAsmitha Karunanithi             req.session->clientIp);
100768dd075aSAsmitha Karunanithi         createDumpParamVec.emplace_back(
100868dd075aSAsmitha Karunanithi             "xyz.openbmc_project.Dump.Create.CreateParameters.OriginatorType",
100968dd075aSAsmitha Karunanithi             "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Client");
1010f574a8e1SCarson Labrado     }
101168dd075aSAsmitha Karunanithi 
1012a43be80fSAsmitha Karunanithi     crow::connections::systemBus->async_method_call(
10135e7e2dc5SEd Tanous         [asyncResp, payload(task::Payload(req)),
10145e7e2dc5SEd Tanous          dumpPath](const boost::system::error_code& ec,
10155e7e2dc5SEd Tanous                    const sdbusplus::message_t& msg,
10168e31778eSAsmitha Karunanithi                    const sdbusplus::message::object_path& objPath) mutable {
1017a43be80fSAsmitha Karunanithi             if (ec)
1018a43be80fSAsmitha Karunanithi             {
101962598e31SEd Tanous                 BMCWEB_LOG_ERROR("CreateDump resp_handler got error {}", ec);
10205907571dSAsmitha Karunanithi                 const sd_bus_error* dbusError = msg.get_error();
10215907571dSAsmitha Karunanithi                 if (dbusError == nullptr)
10225907571dSAsmitha Karunanithi                 {
10235907571dSAsmitha Karunanithi                     messages::internalError(asyncResp->res);
10245907571dSAsmitha Karunanithi                     return;
10255907571dSAsmitha Karunanithi                 }
10265907571dSAsmitha Karunanithi 
102762598e31SEd Tanous                 BMCWEB_LOG_ERROR("CreateDump DBus error: {} and error msg: {}",
102862598e31SEd Tanous                                  dbusError->name, dbusError->message);
10295907571dSAsmitha Karunanithi                 if (std::string_view(
10305907571dSAsmitha Karunanithi                         "xyz.openbmc_project.Common.Error.NotAllowed") ==
10315907571dSAsmitha Karunanithi                     dbusError->name)
10325907571dSAsmitha Karunanithi                 {
10335907571dSAsmitha Karunanithi                     messages::resourceInStandby(asyncResp->res);
10345907571dSAsmitha Karunanithi                     return;
10355907571dSAsmitha Karunanithi                 }
10365907571dSAsmitha Karunanithi                 if (std::string_view(
10375907571dSAsmitha Karunanithi                         "xyz.openbmc_project.Dump.Create.Error.Disabled") ==
10385907571dSAsmitha Karunanithi                     dbusError->name)
10395907571dSAsmitha Karunanithi                 {
10405907571dSAsmitha Karunanithi                     messages::serviceDisabled(asyncResp->res, dumpPath);
10415907571dSAsmitha Karunanithi                     return;
10425907571dSAsmitha Karunanithi                 }
10435907571dSAsmitha Karunanithi                 if (std::string_view(
10445907571dSAsmitha Karunanithi                         "xyz.openbmc_project.Common.Error.Unavailable") ==
10455907571dSAsmitha Karunanithi                     dbusError->name)
10465907571dSAsmitha Karunanithi                 {
10475907571dSAsmitha Karunanithi                     messages::resourceInUse(asyncResp->res);
10485907571dSAsmitha Karunanithi                     return;
10495907571dSAsmitha Karunanithi                 }
10505907571dSAsmitha Karunanithi                 // Other Dbus errors such as:
10515907571dSAsmitha Karunanithi                 // xyz.openbmc_project.Common.Error.InvalidArgument &
10525907571dSAsmitha Karunanithi                 // org.freedesktop.DBus.Error.InvalidArgs are all related to
10535907571dSAsmitha Karunanithi                 // the dbus call that is made here in the bmcweb
10545907571dSAsmitha Karunanithi                 // implementation and has nothing to do with the client's
10555907571dSAsmitha Karunanithi                 // input in the request. Hence, returning internal error
10565907571dSAsmitha Karunanithi                 // back to the client.
1057a43be80fSAsmitha Karunanithi                 messages::internalError(asyncResp->res);
1058a43be80fSAsmitha Karunanithi                 return;
1059a43be80fSAsmitha Karunanithi             }
106062598e31SEd Tanous             BMCWEB_LOG_DEBUG("Dump Created. Path: {}", objPath.str);
10618e31778eSAsmitha Karunanithi             createDumpTaskCallback(std::move(payload), asyncResp, objPath);
1062a43be80fSAsmitha Karunanithi         },
106318f8f608SEd Tanous         "xyz.openbmc_project.Dump.Manager", getDumpPath(dumpType),
10648e31778eSAsmitha Karunanithi         "xyz.openbmc_project.Dump.Create", "CreateDump", createDumpParamVec);
1065a43be80fSAsmitha Karunanithi }
1066a43be80fSAsmitha Karunanithi 
10678d1b46d7Szhanghch05 inline void clearDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
10688d1b46d7Szhanghch05                       const std::string& dumpType)
106980319af1SAsmitha Karunanithi {
10700d946211SClaire Weinan     crow::connections::systemBus->async_method_call(
10710d946211SClaire Weinan         [asyncResp](const boost::system::error_code& ec) {
107280319af1SAsmitha Karunanithi             if (ec)
107380319af1SAsmitha Karunanithi             {
107462598e31SEd Tanous                 BMCWEB_LOG_ERROR("clearDump resp_handler got error {}", ec);
107580319af1SAsmitha Karunanithi                 messages::internalError(asyncResp->res);
107680319af1SAsmitha Karunanithi                 return;
107780319af1SAsmitha Karunanithi             }
10780d946211SClaire Weinan         },
107918f8f608SEd Tanous         "xyz.openbmc_project.Dump.Manager", getDumpPath(dumpType),
10800d946211SClaire Weinan         "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
108180319af1SAsmitha Karunanithi }
108280319af1SAsmitha Karunanithi 
1083bd79bce8SPatrick Williams inline void parseCrashdumpParameters(
1084bd79bce8SPatrick Williams     const dbus::utility::DBusPropertiesMap& params, std::string& filename,
1085bd79bce8SPatrick Williams     std::string& timestamp, std::string& logfile)
1086043a0536SJohnathan Mantey {
1087d1bde9e5SKrzysztof Grobelny     const std::string* filenamePtr = nullptr;
1088d1bde9e5SKrzysztof Grobelny     const std::string* timestampPtr = nullptr;
1089d1bde9e5SKrzysztof Grobelny     const std::string* logfilePtr = nullptr;
1090d1bde9e5SKrzysztof Grobelny 
1091d1bde9e5SKrzysztof Grobelny     const bool success = sdbusplus::unpackPropertiesNoThrow(
1092d1bde9e5SKrzysztof Grobelny         dbus_utils::UnpackErrorPrinter(), params, "Timestamp", timestampPtr,
1093d1bde9e5SKrzysztof Grobelny         "Filename", filenamePtr, "Log", logfilePtr);
1094d1bde9e5SKrzysztof Grobelny 
1095d1bde9e5SKrzysztof Grobelny     if (!success)
1096043a0536SJohnathan Mantey     {
1097d1bde9e5SKrzysztof Grobelny         return;
1098043a0536SJohnathan Mantey     }
1099d1bde9e5SKrzysztof Grobelny 
1100d1bde9e5SKrzysztof Grobelny     if (filenamePtr != nullptr)
1101043a0536SJohnathan Mantey     {
1102d1bde9e5SKrzysztof Grobelny         filename = *filenamePtr;
1103d1bde9e5SKrzysztof Grobelny     }
1104d1bde9e5SKrzysztof Grobelny 
1105d1bde9e5SKrzysztof Grobelny     if (timestampPtr != nullptr)
1106043a0536SJohnathan Mantey     {
1107d1bde9e5SKrzysztof Grobelny         timestamp = *timestampPtr;
1108043a0536SJohnathan Mantey     }
1109d1bde9e5SKrzysztof Grobelny 
1110d1bde9e5SKrzysztof Grobelny     if (logfilePtr != nullptr)
1111043a0536SJohnathan Mantey     {
1112d1bde9e5SKrzysztof Grobelny         logfile = *logfilePtr;
1113043a0536SJohnathan Mantey     }
1114043a0536SJohnathan Mantey }
1115043a0536SJohnathan Mantey 
11167e860f15SJohn Edward Broadbent inline void requestRoutesSystemLogServiceCollection(App& app)
11171da66f75SEd Tanous {
1118c4bf6374SJason M. Bills     /**
1119c4bf6374SJason M. Bills      * Functions triggers appropriate requests on DBus
1120c4bf6374SJason M. Bills      */
112122d268cbSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/")
1122ed398213SEd Tanous         .privileges(redfish::privileges::getLogServiceCollection)
1123bd79bce8SPatrick Williams         .methods(
1124bd79bce8SPatrick Williams             boost::beast::http::verb::
1125bd79bce8SPatrick Williams                 get)([&app](const crow::Request& req,
112622d268cbSEd Tanous                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
112722d268cbSEd Tanous                             const std::string& systemName) {
11283ba00073SCarson Labrado             if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1129c4bf6374SJason M. Bills             {
113045ca1b86SEd Tanous                 return;
113145ca1b86SEd Tanous             }
113225b54dbaSEd Tanous             if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
11337f3e84a1SEd Tanous             {
11347f3e84a1SEd Tanous                 // Option currently returns no systems.  TBD
11357f3e84a1SEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
11367f3e84a1SEd Tanous                                            systemName);
11377f3e84a1SEd Tanous                 return;
11387f3e84a1SEd Tanous             }
1139253f11b8SEd Tanous             if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
114022d268cbSEd Tanous             {
114122d268cbSEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
114222d268cbSEd Tanous                                            systemName);
114322d268cbSEd Tanous                 return;
114422d268cbSEd Tanous             }
114522d268cbSEd Tanous 
11467e860f15SJohn Edward Broadbent             // Collections don't include the static data added by SubRoute
11477e860f15SJohn Edward Broadbent             // because it has a duplicate entry for members
1148c4bf6374SJason M. Bills             asyncResp->res.jsonValue["@odata.type"] =
1149c4bf6374SJason M. Bills                 "#LogServiceCollection.LogServiceCollection";
1150c4bf6374SJason M. Bills             asyncResp->res.jsonValue["@odata.id"] =
1151253f11b8SEd Tanous                 std::format("/redfish/v1/Systems/{}/LogServices",
1152253f11b8SEd Tanous                             BMCWEB_REDFISH_SYSTEM_URI_NAME);
115345ca1b86SEd Tanous             asyncResp->res.jsonValue["Name"] = "System Log Services Collection";
1154c4bf6374SJason M. Bills             asyncResp->res.jsonValue["Description"] =
1155c4bf6374SJason M. Bills                 "Collection of LogServices for this Computer System";
1156bd79bce8SPatrick Williams             nlohmann::json& logServiceArray =
1157bd79bce8SPatrick Williams                 asyncResp->res.jsonValue["Members"];
1158c4bf6374SJason M. Bills             logServiceArray = nlohmann::json::array();
11591476687dSEd Tanous             nlohmann::json::object_t eventLog;
11601476687dSEd Tanous             eventLog["@odata.id"] =
1161253f11b8SEd Tanous                 std::format("/redfish/v1/Systems/{}/LogServices/EventLog",
1162253f11b8SEd Tanous                             BMCWEB_REDFISH_SYSTEM_URI_NAME);
1163b2ba3072SPatrick Williams             logServiceArray.emplace_back(std::move(eventLog));
116425b54dbaSEd Tanous             if constexpr (BMCWEB_REDFISH_DUMP_LOG)
116525b54dbaSEd Tanous             {
11661476687dSEd Tanous                 nlohmann::json::object_t dumpLog;
116725b54dbaSEd Tanous                 dumpLog["@odata.id"] =
1168253f11b8SEd Tanous                     std::format("/redfish/v1/Systems/{}/LogServices/Dump",
1169253f11b8SEd Tanous                                 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1170b2ba3072SPatrick Williams                 logServiceArray.emplace_back(std::move(dumpLog));
117125b54dbaSEd Tanous             }
1172c9bb6861Sraviteja-b 
11735ffd11f2SGunnar Mills             if constexpr (BMCWEB_REDFISH_CPU_LOG)
117425b54dbaSEd Tanous             {
11751476687dSEd Tanous                 nlohmann::json::object_t crashdump;
11761476687dSEd Tanous                 crashdump["@odata.id"] =
1177253f11b8SEd Tanous                     std::format("/redfish/v1/Systems/{}/LogServices/Crashdump",
1178253f11b8SEd Tanous                                 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1179b2ba3072SPatrick Williams                 logServiceArray.emplace_back(std::move(crashdump));
118025b54dbaSEd Tanous             }
1181b7028ebfSSpencer Ku 
118225b54dbaSEd Tanous             if constexpr (BMCWEB_REDFISH_HOST_LOGGER)
118325b54dbaSEd Tanous             {
11841476687dSEd Tanous                 nlohmann::json::object_t hostlogger;
11851476687dSEd Tanous                 hostlogger["@odata.id"] =
1186253f11b8SEd Tanous                     std::format("/redfish/v1/Systems/{}/LogServices/HostLogger",
1187253f11b8SEd Tanous                                 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1188b2ba3072SPatrick Williams                 logServiceArray.emplace_back(std::move(hostlogger));
118925b54dbaSEd Tanous             }
1190c4bf6374SJason M. Bills             asyncResp->res.jsonValue["Members@odata.count"] =
1191c4bf6374SJason M. Bills                 logServiceArray.size();
1192a3316fc6SZhikuiRen 
11937a1dbc48SGeorge Liu             constexpr std::array<std::string_view, 1> interfaces = {
11947a1dbc48SGeorge Liu                 "xyz.openbmc_project.State.Boot.PostCode"};
11957a1dbc48SGeorge Liu             dbus::utility::getSubTreePaths(
11967a1dbc48SGeorge Liu                 "/", 0, interfaces,
11977a1dbc48SGeorge Liu                 [asyncResp](const boost::system::error_code& ec,
1198b9d36b47SEd Tanous                             const dbus::utility::MapperGetSubTreePathsResponse&
1199b9d36b47SEd Tanous                                 subtreePath) {
1200a3316fc6SZhikuiRen                     if (ec)
1201a3316fc6SZhikuiRen                     {
120262598e31SEd Tanous                         BMCWEB_LOG_ERROR("{}", ec);
1203a3316fc6SZhikuiRen                         return;
1204a3316fc6SZhikuiRen                     }
1205a3316fc6SZhikuiRen 
120655f79e6fSEd Tanous                     for (const auto& pathStr : subtreePath)
1207a3316fc6SZhikuiRen                     {
1208a3316fc6SZhikuiRen                         if (pathStr.find("PostCode") != std::string::npos)
1209a3316fc6SZhikuiRen                         {
121023a21a1cSEd Tanous                             nlohmann::json& logServiceArrayLocal =
1211a3316fc6SZhikuiRen                                 asyncResp->res.jsonValue["Members"];
1212613dabeaSEd Tanous                             nlohmann::json::object_t member;
1213253f11b8SEd Tanous                             member["@odata.id"] = std::format(
1214253f11b8SEd Tanous                                 "/redfish/v1/Systems/{}/LogServices/PostCodes",
1215253f11b8SEd Tanous                                 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1216613dabeaSEd Tanous 
1217bd79bce8SPatrick Williams                             logServiceArrayLocal.emplace_back(
1218bd79bce8SPatrick Williams                                 std::move(member));
1219613dabeaSEd Tanous 
122045ca1b86SEd Tanous                             asyncResp->res.jsonValue["Members@odata.count"] =
122123a21a1cSEd Tanous                                 logServiceArrayLocal.size();
1222a3316fc6SZhikuiRen                             return;
1223a3316fc6SZhikuiRen                         }
1224a3316fc6SZhikuiRen                     }
12257a1dbc48SGeorge Liu                 });
12267e860f15SJohn Edward Broadbent         });
1227c4bf6374SJason M. Bills }
1228c4bf6374SJason M. Bills 
12297e860f15SJohn Edward Broadbent inline void requestRoutesEventLogService(App& app)
1230c4bf6374SJason M. Bills {
123122d268cbSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/")
1232ed398213SEd Tanous         .privileges(redfish::privileges::getLogService)
1233bd79bce8SPatrick Williams         .methods(
1234bd79bce8SPatrick Williams             boost::beast::http::verb::
1235bd79bce8SPatrick Williams                 get)([&app](const crow::Request& req,
123622d268cbSEd Tanous                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
123722d268cbSEd Tanous                             const std::string& systemName) {
12383ba00073SCarson Labrado             if (!redfish::setUpRedfishRoute(app, req, asyncResp))
123945ca1b86SEd Tanous             {
124045ca1b86SEd Tanous                 return;
124145ca1b86SEd Tanous             }
1242253f11b8SEd Tanous             if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
124322d268cbSEd Tanous             {
124422d268cbSEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
124522d268cbSEd Tanous                                            systemName);
124622d268cbSEd Tanous                 return;
124722d268cbSEd Tanous             }
1248c4bf6374SJason M. Bills             asyncResp->res.jsonValue["@odata.id"] =
1249253f11b8SEd Tanous                 std::format("/redfish/v1/Systems/{}/LogServices/EventLog",
1250253f11b8SEd Tanous                             BMCWEB_REDFISH_SYSTEM_URI_NAME);
1251c4bf6374SJason M. Bills             asyncResp->res.jsonValue["@odata.type"] =
1252b25644a1SJanet Adkins                 "#LogService.v1_2_0.LogService";
1253c4bf6374SJason M. Bills             asyncResp->res.jsonValue["Name"] = "Event Log Service";
1254bd79bce8SPatrick Williams             asyncResp->res.jsonValue["Description"] =
1255bd79bce8SPatrick Williams                 "System Event Log Service";
1256c4bf6374SJason M. Bills             asyncResp->res.jsonValue["Id"] = "EventLog";
1257539d8c6bSEd Tanous             asyncResp->res.jsonValue["OverWritePolicy"] =
1258539d8c6bSEd Tanous                 log_service::OverWritePolicy::WrapsWhenFull;
12597c8c4058STejas Patil 
12607c8c4058STejas Patil             std::pair<std::string, std::string> redfishDateTimeOffset =
12612b82937eSEd Tanous                 redfish::time_utils::getDateTimeOffsetNow();
12627c8c4058STejas Patil 
12637c8c4058STejas Patil             asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
12647c8c4058STejas Patil             asyncResp->res.jsonValue["DateTimeLocalOffset"] =
12657c8c4058STejas Patil                 redfishDateTimeOffset.second;
12667c8c4058STejas Patil 
1267bd79bce8SPatrick Williams             asyncResp->res.jsonValue["Entries"]["@odata.id"] = std::format(
1268bd79bce8SPatrick Williams                 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
1269253f11b8SEd Tanous                 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1270bd79bce8SPatrick Williams             asyncResp->res
1271bd79bce8SPatrick Williams                 .jsonValue["Actions"]["#LogService.ClearLog"]["target"]
1272e7d6c8b2SGunnar Mills 
127320fa6a2cSEd Tanous                 = std::format(
1274253f11b8SEd Tanous                     "/redfish/v1/Systems/{}/LogServices/EventLog/Actions/LogService.ClearLog",
127520fa6a2cSEd Tanous                     BMCWEB_REDFISH_SYSTEM_URI_NAME);
12767e860f15SJohn Edward Broadbent         });
1277489640c6SJason M. Bills }
1278489640c6SJason M. Bills 
1279599b9af3SAlexander Hansen inline void handleSystemsLogServicesEventLogActionsClearPost(
1280599b9af3SAlexander Hansen     App& app, const crow::Request& req,
128122d268cbSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1282599b9af3SAlexander Hansen     const std::string& systemName)
1283599b9af3SAlexander Hansen {
12843ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
128545ca1b86SEd Tanous     {
128645ca1b86SEd Tanous         return;
128745ca1b86SEd Tanous     }
1288253f11b8SEd Tanous     if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
128922d268cbSEd Tanous     {
129022d268cbSEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
129122d268cbSEd Tanous                                    systemName);
129222d268cbSEd Tanous         return;
129322d268cbSEd Tanous     }
1294599b9af3SAlexander Hansen 
1295489640c6SJason M. Bills     // Clear the EventLog by deleting the log files
1296489640c6SJason M. Bills     std::vector<std::filesystem::path> redfishLogFiles;
1297489640c6SJason M. Bills     if (getRedfishLogFiles(redfishLogFiles))
1298489640c6SJason M. Bills     {
1299489640c6SJason M. Bills         for (const std::filesystem::path& file : redfishLogFiles)
1300489640c6SJason M. Bills         {
1301489640c6SJason M. Bills             std::error_code ec;
1302489640c6SJason M. Bills             std::filesystem::remove(file, ec);
1303489640c6SJason M. Bills         }
1304489640c6SJason M. Bills     }
1305489640c6SJason M. Bills 
1306489640c6SJason M. Bills     // Reload rsyslog so it knows to start new log files
1307489640c6SJason M. Bills     crow::connections::systemBus->async_method_call(
13085e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
1309489640c6SJason M. Bills             if (ec)
1310489640c6SJason M. Bills             {
131162598e31SEd Tanous                 BMCWEB_LOG_ERROR("Failed to reload rsyslog: {}", ec);
1312489640c6SJason M. Bills                 messages::internalError(asyncResp->res);
1313489640c6SJason M. Bills                 return;
1314489640c6SJason M. Bills             }
1315489640c6SJason M. Bills 
1316489640c6SJason M. Bills             messages::success(asyncResp->res);
1317489640c6SJason M. Bills         },
1318489640c6SJason M. Bills         "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
1319002d39b4SEd Tanous         "org.freedesktop.systemd1.Manager", "ReloadUnit", "rsyslog.service",
1320002d39b4SEd Tanous         "replace");
1321599b9af3SAlexander Hansen }
1322599b9af3SAlexander Hansen 
1323599b9af3SAlexander Hansen inline void requestRoutesJournalEventLogClear(App& app)
1324599b9af3SAlexander Hansen {
1325599b9af3SAlexander Hansen     BMCWEB_ROUTE(
1326599b9af3SAlexander Hansen         app,
1327599b9af3SAlexander Hansen         "/redfish/v1/Systems/<str>/LogServices/EventLog/Actions/LogService.ClearLog/")
1328599b9af3SAlexander Hansen         .privileges({{"ConfigureComponents"}})
1329599b9af3SAlexander Hansen         .methods(boost::beast::http::verb::post)(std::bind_front(
1330599b9af3SAlexander Hansen             handleSystemsLogServicesEventLogActionsClearPost, std::ref(app)));
1331c4bf6374SJason M. Bills }
1332c4bf6374SJason M. Bills 
1333ac992cdeSJason M. Bills enum class LogParseError
1334ac992cdeSJason M. Bills {
1335ac992cdeSJason M. Bills     success,
1336ac992cdeSJason M. Bills     parseFailed,
1337ac992cdeSJason M. Bills     messageIdNotInRegistry,
1338ac992cdeSJason M. Bills };
1339ac992cdeSJason M. Bills 
1340bd79bce8SPatrick Williams static LogParseError fillEventLogEntryJson(
1341bd79bce8SPatrick Williams     const std::string& logEntryID, const std::string& logEntry,
1342de703c5dSJason M. Bills     nlohmann::json::object_t& logEntryJson)
1343c4bf6374SJason M. Bills {
134495820184SJason M. Bills     // The redfish log format is "<Timestamp> <MessageId>,<MessageArgs>"
1345cd225da8SJason M. Bills     // First get the Timestamp
1346f23b7296SEd Tanous     size_t space = logEntry.find_first_of(' ');
1347cd225da8SJason M. Bills     if (space == std::string::npos)
134895820184SJason M. Bills     {
1349ac992cdeSJason M. Bills         return LogParseError::parseFailed;
135095820184SJason M. Bills     }
1351cd225da8SJason M. Bills     std::string timestamp = logEntry.substr(0, space);
1352cd225da8SJason M. Bills     // Then get the log contents
1353f23b7296SEd Tanous     size_t entryStart = logEntry.find_first_not_of(' ', space);
1354cd225da8SJason M. Bills     if (entryStart == std::string::npos)
1355cd225da8SJason M. Bills     {
1356ac992cdeSJason M. Bills         return LogParseError::parseFailed;
1357cd225da8SJason M. Bills     }
1358cd225da8SJason M. Bills     std::string_view entry(logEntry);
1359cd225da8SJason M. Bills     entry.remove_prefix(entryStart);
1360cd225da8SJason M. Bills     // Use split to separate the entry into its fields
1361cd225da8SJason M. Bills     std::vector<std::string> logEntryFields;
136250ebd4afSEd Tanous     bmcweb::split(logEntryFields, entry, ',');
1363cd225da8SJason M. Bills     // We need at least a MessageId to be valid
13641e6deaf6SEd Tanous     auto logEntryIter = logEntryFields.begin();
13651e6deaf6SEd Tanous     if (logEntryIter == logEntryFields.end())
1366cd225da8SJason M. Bills     {
1367ac992cdeSJason M. Bills         return LogParseError::parseFailed;
1368cd225da8SJason M. Bills     }
13691e6deaf6SEd Tanous     std::string& messageID = *logEntryIter;
13704851d45dSJason M. Bills     // Get the Message from the MessageRegistry
1371fffb8c1fSEd Tanous     const registries::Message* message = registries::getMessage(messageID);
1372c4bf6374SJason M. Bills 
13731e6deaf6SEd Tanous     logEntryIter++;
137454417b02SSui Chen     if (message == nullptr)
1375c4bf6374SJason M. Bills     {
137662598e31SEd Tanous         BMCWEB_LOG_WARNING("Log entry not found in registry: {}", logEntry);
1377ac992cdeSJason M. Bills         return LogParseError::messageIdNotInRegistry;
1378c4bf6374SJason M. Bills     }
1379c4bf6374SJason M. Bills 
13801e6deaf6SEd Tanous     std::vector<std::string_view> messageArgs(logEntryIter,
13811e6deaf6SEd Tanous                                               logEntryFields.end());
1382c05bba45SEd Tanous     messageArgs.resize(message->numberOfArgs);
1383c05bba45SEd Tanous 
1384bd79bce8SPatrick Williams     std::string msg =
1385bd79bce8SPatrick Williams         redfish::registries::fillMessageArgs(messageArgs, message->message);
13861e6deaf6SEd Tanous     if (msg.empty())
138715a86ff6SJason M. Bills     {
13881e6deaf6SEd Tanous         return LogParseError::parseFailed;
138915a86ff6SJason M. Bills     }
13904851d45dSJason M. Bills 
139195820184SJason M. Bills     // Get the Created time from the timestamp. The log timestamp is in RFC3339
139295820184SJason M. Bills     // format which matches the Redfish format except for the fractional seconds
139395820184SJason M. Bills     // between the '.' and the '+', so just remove them.
1394f23b7296SEd Tanous     std::size_t dot = timestamp.find_first_of('.');
1395f23b7296SEd Tanous     std::size_t plus = timestamp.find_first_of('+');
139695820184SJason M. Bills     if (dot != std::string::npos && plus != std::string::npos)
1397c4bf6374SJason M. Bills     {
139895820184SJason M. Bills         timestamp.erase(dot, plus - dot);
1399c4bf6374SJason M. Bills     }
1400c4bf6374SJason M. Bills 
1401c4bf6374SJason M. Bills     // Fill in the log entry with the gathered data
14029c11a172SVijay Lobo     logEntryJson["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
1403ef4c65b7SEd Tanous     logEntryJson["@odata.id"] = boost::urls::format(
1404253f11b8SEd Tanous         "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}",
1405253f11b8SEd Tanous         BMCWEB_REDFISH_SYSTEM_URI_NAME, logEntryID);
140684afc48bSJason M. Bills     logEntryJson["Name"] = "System Event Log Entry";
140784afc48bSJason M. Bills     logEntryJson["Id"] = logEntryID;
140884afc48bSJason M. Bills     logEntryJson["Message"] = std::move(msg);
140984afc48bSJason M. Bills     logEntryJson["MessageId"] = std::move(messageID);
141084afc48bSJason M. Bills     logEntryJson["MessageArgs"] = messageArgs;
141184afc48bSJason M. Bills     logEntryJson["EntryType"] = "Event";
141284afc48bSJason M. Bills     logEntryJson["Severity"] = message->messageSeverity;
141384afc48bSJason M. Bills     logEntryJson["Created"] = std::move(timestamp);
1414ac992cdeSJason M. Bills     return LogParseError::success;
1415c4bf6374SJason M. Bills }
1416c4bf6374SJason M. Bills 
1417898f2aa2SEd Tanous inline void fillEventLogLogEntryFromPropertyMap(
1418898f2aa2SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1419898f2aa2SEd Tanous     const dbus::utility::DBusPropertiesMap& resp,
1420898f2aa2SEd Tanous     nlohmann::json& objectToFillOut)
1421898f2aa2SEd Tanous {
1422*262dcc1cSAlexander Hansen     std::optional<DbusEventLogEntry> optEntry =
1423*262dcc1cSAlexander Hansen         fillDbusEventLogEntryFromPropertyMap(resp);
1424898f2aa2SEd Tanous 
1425*262dcc1cSAlexander Hansen     if (!optEntry.has_value())
1426898f2aa2SEd Tanous     {
1427898f2aa2SEd Tanous         messages::internalError(asyncResp->res);
1428898f2aa2SEd Tanous         return;
1429898f2aa2SEd Tanous     }
1430*262dcc1cSAlexander Hansen     DbusEventLogEntry entry = optEntry.value();
1431898f2aa2SEd Tanous 
1432898f2aa2SEd Tanous     objectToFillOut["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
1433898f2aa2SEd Tanous     objectToFillOut["@odata.id"] = boost::urls::format(
1434898f2aa2SEd Tanous         "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}",
1435*262dcc1cSAlexander Hansen         BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(entry.Id));
1436898f2aa2SEd Tanous     objectToFillOut["Name"] = "System Event Log Entry";
1437*262dcc1cSAlexander Hansen     objectToFillOut["Id"] = std::to_string(entry.Id);
1438*262dcc1cSAlexander Hansen     objectToFillOut["Message"] = entry.Message;
1439*262dcc1cSAlexander Hansen     objectToFillOut["Resolved"] = entry.Resolved;
1440*262dcc1cSAlexander Hansen     std::optional<bool> notifyAction =
1441*262dcc1cSAlexander Hansen         getProviderNotifyAction(entry.ServiceProviderNotify);
1442898f2aa2SEd Tanous     if (notifyAction)
1443898f2aa2SEd Tanous     {
1444898f2aa2SEd Tanous         objectToFillOut["ServiceProviderNotified"] = *notifyAction;
1445898f2aa2SEd Tanous     }
1446*262dcc1cSAlexander Hansen     if ((entry.Resolution != nullptr) && !entry.Resolution->empty())
1447898f2aa2SEd Tanous     {
1448*262dcc1cSAlexander Hansen         objectToFillOut["Resolution"] = *entry.Resolution;
1449898f2aa2SEd Tanous     }
1450898f2aa2SEd Tanous     objectToFillOut["EntryType"] = "Event";
1451*262dcc1cSAlexander Hansen     objectToFillOut["Severity"] =
1452*262dcc1cSAlexander Hansen         translateSeverityDbusToRedfish(entry.Severity);
1453898f2aa2SEd Tanous     objectToFillOut["Created"] =
1454*262dcc1cSAlexander Hansen         redfish::time_utils::getDateTimeUintMs(entry.Timestamp);
1455898f2aa2SEd Tanous     objectToFillOut["Modified"] =
1456*262dcc1cSAlexander Hansen         redfish::time_utils::getDateTimeUintMs(entry.UpdateTimestamp);
1457*262dcc1cSAlexander Hansen     if (entry.Path != nullptr)
1458898f2aa2SEd Tanous     {
1459898f2aa2SEd Tanous         objectToFillOut["AdditionalDataURI"] = boost::urls::format(
1460898f2aa2SEd Tanous             "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}/attachment",
1461*262dcc1cSAlexander Hansen             BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(entry.Id));
1462898f2aa2SEd Tanous     }
1463898f2aa2SEd Tanous }
1464898f2aa2SEd Tanous 
1465b729096dSEd Tanous inline void afterLogEntriesGetManagedObjects(
1466b729096dSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1467b729096dSEd Tanous     const boost::system::error_code& ec,
1468b729096dSEd Tanous     const dbus::utility::ManagedObjectType& resp)
1469b729096dSEd Tanous {
1470b729096dSEd Tanous     if (ec)
1471b729096dSEd Tanous     {
1472b729096dSEd Tanous         // TODO Handle for specific error code
1473b729096dSEd Tanous         BMCWEB_LOG_ERROR("getLogEntriesIfaceData resp_handler got error {}",
1474b729096dSEd Tanous                          ec);
1475b729096dSEd Tanous         messages::internalError(asyncResp->res);
1476b729096dSEd Tanous         return;
1477b729096dSEd Tanous     }
1478b729096dSEd Tanous     nlohmann::json::array_t entriesArray;
1479b729096dSEd Tanous     for (const auto& objectPath : resp)
1480b729096dSEd Tanous     {
1481898f2aa2SEd Tanous         dbus::utility::DBusPropertiesMap propsFlattened;
1482bd79bce8SPatrick Williams         auto isEntry =
1483bd79bce8SPatrick Williams             std::ranges::find_if(objectPath.second, [](const auto& object) {
1484898f2aa2SEd Tanous                 return object.first == "xyz.openbmc_project.Logging.Entry";
1485898f2aa2SEd Tanous             });
1486898f2aa2SEd Tanous         if (isEntry == objectPath.second.end())
1487b729096dSEd Tanous         {
1488b729096dSEd Tanous             continue;
1489b729096dSEd Tanous         }
1490898f2aa2SEd Tanous         for (const auto& interfaceMap : objectPath.second)
1491b729096dSEd Tanous         {
1492898f2aa2SEd Tanous             for (const auto& propertyMap : interfaceMap.second)
1493b729096dSEd Tanous             {
1494898f2aa2SEd Tanous                 propsFlattened.emplace_back(propertyMap.first,
1495898f2aa2SEd Tanous                                             propertyMap.second);
1496b729096dSEd Tanous             }
1497b729096dSEd Tanous         }
1498898f2aa2SEd Tanous         fillEventLogLogEntryFromPropertyMap(asyncResp, propsFlattened,
1499898f2aa2SEd Tanous                                             entriesArray.emplace_back());
1500b729096dSEd Tanous     }
1501898f2aa2SEd Tanous 
1502b729096dSEd Tanous     std::ranges::sort(entriesArray, [](const nlohmann::json& left,
1503b729096dSEd Tanous                                        const nlohmann::json& right) {
1504b729096dSEd Tanous         return (left["Id"] <= right["Id"]);
1505b729096dSEd Tanous     });
1506b729096dSEd Tanous     asyncResp->res.jsonValue["Members@odata.count"] = entriesArray.size();
1507b729096dSEd Tanous     asyncResp->res.jsonValue["Members"] = std::move(entriesArray);
1508b729096dSEd Tanous }
1509b729096dSEd Tanous 
1510599b9af3SAlexander Hansen inline void handleSystemsLogServiceEventLogLogEntryCollection(
1511599b9af3SAlexander Hansen     App& app, const crow::Request& req,
151222d268cbSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1513599b9af3SAlexander Hansen     const std::string& systemName)
1514599b9af3SAlexander Hansen {
1515c937d2bfSEd Tanous     query_param::QueryCapabilities capabilities = {
1516c937d2bfSEd Tanous         .canDelegateTop = true,
1517c937d2bfSEd Tanous         .canDelegateSkip = true,
1518c937d2bfSEd Tanous     };
1519c937d2bfSEd Tanous     query_param::Query delegatedQuery;
1520599b9af3SAlexander Hansen     if (!redfish::setUpRedfishRouteWithDelegation(app, req, asyncResp,
1521599b9af3SAlexander Hansen                                                   delegatedQuery, capabilities))
1522c4bf6374SJason M. Bills     {
1523c4bf6374SJason M. Bills         return;
1524c4bf6374SJason M. Bills     }
152525b54dbaSEd Tanous     if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
15267f3e84a1SEd Tanous     {
15277f3e84a1SEd Tanous         // Option currently returns no systems.  TBD
15287f3e84a1SEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
15297f3e84a1SEd Tanous                                    systemName);
15307f3e84a1SEd Tanous         return;
15317f3e84a1SEd Tanous     }
1532253f11b8SEd Tanous     if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
153322d268cbSEd Tanous     {
153422d268cbSEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
153522d268cbSEd Tanous                                    systemName);
153622d268cbSEd Tanous         return;
153722d268cbSEd Tanous     }
153822d268cbSEd Tanous 
15395143f7a5SJiaqing Zhao     size_t top = delegatedQuery.top.value_or(query_param::Query::maxTop);
15403648c8beSEd Tanous     size_t skip = delegatedQuery.skip.value_or(0);
15413648c8beSEd Tanous 
15427e860f15SJohn Edward Broadbent     // Collections don't include the static data added by SubRoute
15437e860f15SJohn Edward Broadbent     // because it has a duplicate entry for members
1544c4bf6374SJason M. Bills     asyncResp->res.jsonValue["@odata.type"] =
1545c4bf6374SJason M. Bills         "#LogEntryCollection.LogEntryCollection";
1546c4bf6374SJason M. Bills     asyncResp->res.jsonValue["@odata.id"] =
1547253f11b8SEd Tanous         std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
1548253f11b8SEd Tanous                     BMCWEB_REDFISH_SYSTEM_URI_NAME);
1549c4bf6374SJason M. Bills     asyncResp->res.jsonValue["Name"] = "System Event Log Entries";
1550c4bf6374SJason M. Bills     asyncResp->res.jsonValue["Description"] =
1551c4bf6374SJason M. Bills         "Collection of System Event Log Entries";
1552cb92c03bSAndrew Geissler 
15534978b63fSJason M. Bills     nlohmann::json& logEntryArray = asyncResp->res.jsonValue["Members"];
1554c4bf6374SJason M. Bills     logEntryArray = nlohmann::json::array();
15557e860f15SJohn Edward Broadbent     // Go through the log files and create a unique ID for each
15567e860f15SJohn Edward Broadbent     // entry
155795820184SJason M. Bills     std::vector<std::filesystem::path> redfishLogFiles;
155895820184SJason M. Bills     getRedfishLogFiles(redfishLogFiles);
1559b01bf299SEd Tanous     uint64_t entryCount = 0;
1560cd225da8SJason M. Bills     std::string logEntry;
156195820184SJason M. Bills 
15627e860f15SJohn Edward Broadbent     // Oldest logs are in the last file, so start there and loop
15637e860f15SJohn Edward Broadbent     // backwards
1564599b9af3SAlexander Hansen     for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend(); it++)
1565c4bf6374SJason M. Bills     {
1566cd225da8SJason M. Bills         std::ifstream logStream(*it);
156795820184SJason M. Bills         if (!logStream.is_open())
1568c4bf6374SJason M. Bills         {
1569c4bf6374SJason M. Bills             continue;
1570c4bf6374SJason M. Bills         }
1571c4bf6374SJason M. Bills 
1572e85d6b16SJason M. Bills         // Reset the unique ID on the first entry
1573e85d6b16SJason M. Bills         bool firstEntry = true;
157495820184SJason M. Bills         while (std::getline(logStream, logEntry))
157595820184SJason M. Bills         {
1576c4bf6374SJason M. Bills             std::string idStr;
1577e85d6b16SJason M. Bills             if (!getUniqueEntryID(logEntry, idStr, firstEntry))
1578c4bf6374SJason M. Bills             {
1579c4bf6374SJason M. Bills                 continue;
1580c4bf6374SJason M. Bills             }
1581e85d6b16SJason M. Bills             firstEntry = false;
1582e85d6b16SJason M. Bills 
1583de703c5dSJason M. Bills             nlohmann::json::object_t bmcLogEntry;
1584bd79bce8SPatrick Williams             LogParseError status =
1585bd79bce8SPatrick Williams                 fillEventLogEntryJson(idStr, logEntry, bmcLogEntry);
1586ac992cdeSJason M. Bills             if (status == LogParseError::messageIdNotInRegistry)
1587ac992cdeSJason M. Bills             {
1588ac992cdeSJason M. Bills                 continue;
1589ac992cdeSJason M. Bills             }
1590ac992cdeSJason M. Bills             if (status != LogParseError::success)
1591c4bf6374SJason M. Bills             {
1592c4bf6374SJason M. Bills                 messages::internalError(asyncResp->res);
1593c4bf6374SJason M. Bills                 return;
1594c4bf6374SJason M. Bills             }
1595de703c5dSJason M. Bills 
1596de703c5dSJason M. Bills             entryCount++;
1597de703c5dSJason M. Bills             // Handle paging using skip (number of entries to skip from the
1598de703c5dSJason M. Bills             // start) and top (number of entries to display)
15993648c8beSEd Tanous             if (entryCount <= skip || entryCount > skip + top)
1600de703c5dSJason M. Bills             {
1601de703c5dSJason M. Bills                 continue;
1602de703c5dSJason M. Bills             }
1603de703c5dSJason M. Bills 
1604b2ba3072SPatrick Williams             logEntryArray.emplace_back(std::move(bmcLogEntry));
1605c4bf6374SJason M. Bills         }
160695820184SJason M. Bills     }
1607c4bf6374SJason M. Bills     asyncResp->res.jsonValue["Members@odata.count"] = entryCount;
16083648c8beSEd Tanous     if (skip + top < entryCount)
1609c4bf6374SJason M. Bills     {
1610599b9af3SAlexander Hansen         asyncResp->res.jsonValue["Members@odata.nextLink"] =
1611599b9af3SAlexander Hansen             boost::urls::format(
1612253f11b8SEd Tanous                 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries?$skip={}",
1613253f11b8SEd Tanous                 BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(skip + top));
1614c4bf6374SJason M. Bills     }
1615897967deSJason M. Bills }
1616897967deSJason M. Bills 
1617599b9af3SAlexander Hansen inline void requestRoutesJournalEventLogEntryCollection(App& app)
1618897967deSJason M. Bills {
1619599b9af3SAlexander Hansen     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/")
1620599b9af3SAlexander Hansen         .privileges(redfish::privileges::getLogEntryCollection)
1621599b9af3SAlexander Hansen         .methods(boost::beast::http::verb::get)(std::bind_front(
1622599b9af3SAlexander Hansen             handleSystemsLogServiceEventLogLogEntryCollection, std::ref(app)));
1623599b9af3SAlexander Hansen }
1624599b9af3SAlexander Hansen 
1625599b9af3SAlexander Hansen inline void handleSystemsLogServiceEventLogEntriesGet(
1626599b9af3SAlexander Hansen     App& app, const crow::Request& req,
16277e860f15SJohn Edward Broadbent     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1628599b9af3SAlexander Hansen     const std::string& systemName, const std::string& param)
1629599b9af3SAlexander Hansen {
16303ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
163145ca1b86SEd Tanous     {
163245ca1b86SEd Tanous         return;
163345ca1b86SEd Tanous     }
163425b54dbaSEd Tanous     if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
16357f3e84a1SEd Tanous     {
16367f3e84a1SEd Tanous         // Option currently returns no systems.  TBD
16377f3e84a1SEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
16387f3e84a1SEd Tanous                                    systemName);
16397f3e84a1SEd Tanous         return;
16407f3e84a1SEd Tanous     }
164122d268cbSEd Tanous 
1642253f11b8SEd Tanous     if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
164322d268cbSEd Tanous     {
164422d268cbSEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
164522d268cbSEd Tanous                                    systemName);
164622d268cbSEd Tanous         return;
164722d268cbSEd Tanous     }
164822d268cbSEd Tanous 
16497e860f15SJohn Edward Broadbent     const std::string& targetID = param;
16508d1b46d7Szhanghch05 
16517e860f15SJohn Edward Broadbent     // Go through the log files and check the unique ID for each
16527e860f15SJohn Edward Broadbent     // entry to find the target entry
1653897967deSJason M. Bills     std::vector<std::filesystem::path> redfishLogFiles;
1654897967deSJason M. Bills     getRedfishLogFiles(redfishLogFiles);
1655897967deSJason M. Bills     std::string logEntry;
1656897967deSJason M. Bills 
16577e860f15SJohn Edward Broadbent     // Oldest logs are in the last file, so start there and loop
16587e860f15SJohn Edward Broadbent     // backwards
1659599b9af3SAlexander Hansen     for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend(); it++)
1660897967deSJason M. Bills     {
1661897967deSJason M. Bills         std::ifstream logStream(*it);
1662897967deSJason M. Bills         if (!logStream.is_open())
1663897967deSJason M. Bills         {
1664897967deSJason M. Bills             continue;
1665897967deSJason M. Bills         }
1666897967deSJason M. Bills 
1667897967deSJason M. Bills         // Reset the unique ID on the first entry
1668897967deSJason M. Bills         bool firstEntry = true;
1669897967deSJason M. Bills         while (std::getline(logStream, logEntry))
1670897967deSJason M. Bills         {
1671897967deSJason M. Bills             std::string idStr;
1672897967deSJason M. Bills             if (!getUniqueEntryID(logEntry, idStr, firstEntry))
1673897967deSJason M. Bills             {
1674897967deSJason M. Bills                 continue;
1675897967deSJason M. Bills             }
1676897967deSJason M. Bills             firstEntry = false;
1677897967deSJason M. Bills 
1678897967deSJason M. Bills             if (idStr == targetID)
1679897967deSJason M. Bills             {
1680de703c5dSJason M. Bills                 nlohmann::json::object_t bmcLogEntry;
1681bd79bce8SPatrick Williams                 LogParseError status =
1682bd79bce8SPatrick Williams                     fillEventLogEntryJson(idStr, logEntry, bmcLogEntry);
1683ac992cdeSJason M. Bills                 if (status != LogParseError::success)
1684897967deSJason M. Bills                 {
1685897967deSJason M. Bills                     messages::internalError(asyncResp->res);
1686897967deSJason M. Bills                     return;
1687897967deSJason M. Bills                 }
1688d405bb51SJason M. Bills                 asyncResp->res.jsonValue.update(bmcLogEntry);
1689897967deSJason M. Bills                 return;
1690897967deSJason M. Bills             }
1691897967deSJason M. Bills         }
1692897967deSJason M. Bills     }
1693897967deSJason M. Bills     // Requested ID was not found
16949db4ba25SJiaqing Zhao     messages::resourceNotFound(asyncResp->res, "LogEntry", targetID);
1695599b9af3SAlexander Hansen }
1696599b9af3SAlexander Hansen 
1697599b9af3SAlexander Hansen inline void requestRoutesJournalEventLogEntry(App& app)
1698599b9af3SAlexander Hansen {
1699599b9af3SAlexander Hansen     BMCWEB_ROUTE(
1700599b9af3SAlexander Hansen         app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
1701599b9af3SAlexander Hansen         .privileges(redfish::privileges::getLogEntry)
1702599b9af3SAlexander Hansen         .methods(boost::beast::http::verb::get)(std::bind_front(
1703599b9af3SAlexander Hansen             handleSystemsLogServiceEventLogEntriesGet, std::ref(app)));
1704599b9af3SAlexander Hansen }
1705599b9af3SAlexander Hansen 
1706599b9af3SAlexander Hansen inline void dBusEventLogEntryCollection(
1707599b9af3SAlexander Hansen     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1708599b9af3SAlexander Hansen {
1709599b9af3SAlexander Hansen     // Collections don't include the static data added by SubRoute
1710599b9af3SAlexander Hansen     // because it has a duplicate entry for members
1711599b9af3SAlexander Hansen     asyncResp->res.jsonValue["@odata.type"] =
1712599b9af3SAlexander Hansen         "#LogEntryCollection.LogEntryCollection";
1713599b9af3SAlexander Hansen     asyncResp->res.jsonValue["@odata.id"] =
1714599b9af3SAlexander Hansen         std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
1715599b9af3SAlexander Hansen                     BMCWEB_REDFISH_SYSTEM_URI_NAME);
1716599b9af3SAlexander Hansen     asyncResp->res.jsonValue["Name"] = "System Event Log Entries";
1717599b9af3SAlexander Hansen     asyncResp->res.jsonValue["Description"] =
1718599b9af3SAlexander Hansen         "Collection of System Event Log Entries";
1719599b9af3SAlexander Hansen 
1720599b9af3SAlexander Hansen     // DBus implementation of EventLog/Entries
1721599b9af3SAlexander Hansen     // Make call to Logging Service to find all log entry objects
1722599b9af3SAlexander Hansen     sdbusplus::message::object_path path("/xyz/openbmc_project/logging");
1723599b9af3SAlexander Hansen     dbus::utility::getManagedObjects(
1724599b9af3SAlexander Hansen         "xyz.openbmc_project.Logging", path,
1725599b9af3SAlexander Hansen         [asyncResp](const boost::system::error_code& ec,
1726599b9af3SAlexander Hansen                     const dbus::utility::ManagedObjectType& resp) {
1727b729096dSEd Tanous             afterLogEntriesGetManagedObjects(asyncResp, ec, resp);
17287e860f15SJohn Edward Broadbent         });
172908a4e4b5SAnthony Wilson }
173008a4e4b5SAnthony Wilson 
17317e860f15SJohn Edward Broadbent inline void requestRoutesDBusEventLogEntryCollection(App& app)
173208a4e4b5SAnthony Wilson {
173322d268cbSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/")
1734ed398213SEd Tanous         .privileges(redfish::privileges::getLogEntryCollection)
1735002d39b4SEd Tanous         .methods(boost::beast::http::verb::get)(
1736002d39b4SEd Tanous             [&app](const crow::Request& req,
173722d268cbSEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
173822d268cbSEd Tanous                    const std::string& systemName) {
17393ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
174045ca1b86SEd Tanous                 {
174145ca1b86SEd Tanous                     return;
174245ca1b86SEd Tanous                 }
174325b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
17447f3e84a1SEd Tanous                 {
17457f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
17467f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
17477f3e84a1SEd Tanous                                                systemName);
17487f3e84a1SEd Tanous                     return;
17497f3e84a1SEd Tanous                 }
1750253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
175122d268cbSEd Tanous                 {
175222d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
175322d268cbSEd Tanous                                                systemName);
175422d268cbSEd Tanous                     return;
175522d268cbSEd Tanous                 }
1756599b9af3SAlexander Hansen                 dBusEventLogEntryCollection(asyncResp);
1757599b9af3SAlexander Hansen             });
1758599b9af3SAlexander Hansen }
175922d268cbSEd Tanous 
1760bd79bce8SPatrick Williams inline void dBusEventLogEntryGet(
1761bd79bce8SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID)
1762599b9af3SAlexander Hansen {
1763599b9af3SAlexander Hansen     dbus::utility::escapePathForDbus(entryID);
176408a4e4b5SAnthony Wilson 
1765cb92c03bSAndrew Geissler     // DBus implementation of EventLog/Entries
1766cb92c03bSAndrew Geissler     // Make call to Logging Service to find all log entry objects
1767599b9af3SAlexander Hansen     sdbusplus::asio::getAllProperties(
1768599b9af3SAlexander Hansen         *crow::connections::systemBus, "xyz.openbmc_project.Logging",
1769599b9af3SAlexander Hansen         "/xyz/openbmc_project/logging/entry/" + entryID, "",
1770599b9af3SAlexander Hansen         [asyncResp, entryID](const boost::system::error_code& ec,
1771599b9af3SAlexander Hansen                              const dbus::utility::DBusPropertiesMap& resp) {
1772599b9af3SAlexander Hansen             if (ec.value() == EBADR)
1773599b9af3SAlexander Hansen             {
1774599b9af3SAlexander Hansen                 messages::resourceNotFound(asyncResp->res, "EventLogEntry",
1775599b9af3SAlexander Hansen                                            entryID);
1776599b9af3SAlexander Hansen                 return;
1777599b9af3SAlexander Hansen             }
1778cb92c03bSAndrew Geissler             if (ec)
1779cb92c03bSAndrew Geissler             {
1780bd79bce8SPatrick Williams                 BMCWEB_LOG_ERROR(
1781bd79bce8SPatrick Williams                     "EventLogEntry (DBus) resp_handler got error {}", ec);
1782cb92c03bSAndrew Geissler                 messages::internalError(asyncResp->res);
1783cb92c03bSAndrew Geissler                 return;
1784cb92c03bSAndrew Geissler             }
17859017faf2SAbhishek Patel 
1786898f2aa2SEd Tanous             fillEventLogLogEntryFromPropertyMap(asyncResp, resp,
1787898f2aa2SEd Tanous                                                 asyncResp->res.jsonValue);
1788599b9af3SAlexander Hansen         });
17897e860f15SJohn Edward Broadbent }
1790599b9af3SAlexander Hansen 
1791599b9af3SAlexander Hansen inline void
1792599b9af3SAlexander Hansen     dBusEventLogEntryPatch(const crow::Request& req,
1793599b9af3SAlexander Hansen                            const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1794599b9af3SAlexander Hansen                            const std::string& entryId)
1795599b9af3SAlexander Hansen {
1796599b9af3SAlexander Hansen     std::optional<bool> resolved;
1797599b9af3SAlexander Hansen 
1798599b9af3SAlexander Hansen     if (!json_util::readJsonPatch(req, asyncResp->res, "Resolved", resolved))
1799599b9af3SAlexander Hansen     {
1800599b9af3SAlexander Hansen         return;
1801599b9af3SAlexander Hansen     }
1802599b9af3SAlexander Hansen     BMCWEB_LOG_DEBUG("Set Resolved");
1803599b9af3SAlexander Hansen 
1804599b9af3SAlexander Hansen     setDbusProperty(asyncResp, "Resolved", "xyz.openbmc_project.Logging",
1805599b9af3SAlexander Hansen                     "/xyz/openbmc_project/logging/entry/" + entryId,
1806599b9af3SAlexander Hansen                     "xyz.openbmc_project.Logging.Entry", "Resolved",
1807599b9af3SAlexander Hansen                     resolved.value_or(false));
1808599b9af3SAlexander Hansen }
1809599b9af3SAlexander Hansen 
1810bd79bce8SPatrick Williams inline void dBusEventLogEntryDelete(
1811bd79bce8SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID)
1812599b9af3SAlexander Hansen {
1813599b9af3SAlexander Hansen     BMCWEB_LOG_DEBUG("Do delete single event entries.");
1814599b9af3SAlexander Hansen 
1815599b9af3SAlexander Hansen     dbus::utility::escapePathForDbus(entryID);
1816599b9af3SAlexander Hansen 
1817599b9af3SAlexander Hansen     // Process response from Logging service.
1818599b9af3SAlexander Hansen     auto respHandler = [asyncResp,
1819599b9af3SAlexander Hansen                         entryID](const boost::system::error_code& ec) {
1820599b9af3SAlexander Hansen         BMCWEB_LOG_DEBUG("EventLogEntry (DBus) doDelete callback: Done");
1821599b9af3SAlexander Hansen         if (ec)
1822599b9af3SAlexander Hansen         {
1823599b9af3SAlexander Hansen             if (ec.value() == EBADR)
1824599b9af3SAlexander Hansen             {
1825599b9af3SAlexander Hansen                 messages::resourceNotFound(asyncResp->res, "LogEntry", entryID);
1826599b9af3SAlexander Hansen                 return;
1827599b9af3SAlexander Hansen             }
1828599b9af3SAlexander Hansen             // TODO Handle for specific error code
1829599b9af3SAlexander Hansen             BMCWEB_LOG_ERROR(
1830599b9af3SAlexander Hansen                 "EventLogEntry (DBus) doDelete respHandler got error {}", ec);
1831599b9af3SAlexander Hansen             asyncResp->res.result(
1832599b9af3SAlexander Hansen                 boost::beast::http::status::internal_server_error);
1833599b9af3SAlexander Hansen             return;
1834599b9af3SAlexander Hansen         }
1835599b9af3SAlexander Hansen 
1836599b9af3SAlexander Hansen         asyncResp->res.result(boost::beast::http::status::ok);
1837599b9af3SAlexander Hansen     };
1838599b9af3SAlexander Hansen 
1839599b9af3SAlexander Hansen     // Make call to Logging service to request Delete Log
1840599b9af3SAlexander Hansen     crow::connections::systemBus->async_method_call(
1841599b9af3SAlexander Hansen         respHandler, "xyz.openbmc_project.Logging",
1842599b9af3SAlexander Hansen         "/xyz/openbmc_project/logging/entry/" + entryID,
1843599b9af3SAlexander Hansen         "xyz.openbmc_project.Object.Delete", "Delete");
18447e860f15SJohn Edward Broadbent }
18457e860f15SJohn Edward Broadbent 
18467e860f15SJohn Edward Broadbent inline void requestRoutesDBusEventLogEntry(App& app)
18477e860f15SJohn Edward Broadbent {
18487e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
184922d268cbSEd Tanous         app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
1850ed398213SEd Tanous         .privileges(redfish::privileges::getLogEntry)
1851002d39b4SEd Tanous         .methods(boost::beast::http::verb::get)(
1852002d39b4SEd Tanous             [&app](const crow::Request& req,
18537e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1854898f2aa2SEd Tanous                    const std::string& systemName, const std::string& entryId) {
18553ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
18567e860f15SJohn Edward Broadbent                 {
185745ca1b86SEd Tanous                     return;
185845ca1b86SEd Tanous                 }
185925b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
18607f3e84a1SEd Tanous                 {
18617f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
18627f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
18637f3e84a1SEd Tanous                                                systemName);
18647f3e84a1SEd Tanous                     return;
18657f3e84a1SEd Tanous                 }
1866253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
186722d268cbSEd Tanous                 {
186822d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
186922d268cbSEd Tanous                                                systemName);
187022d268cbSEd Tanous                     return;
187122d268cbSEd Tanous                 }
187222d268cbSEd Tanous 
1873898f2aa2SEd Tanous                 dBusEventLogEntryGet(asyncResp, entryId);
18747e860f15SJohn Edward Broadbent             });
1875336e96c6SChicago Duan 
18767e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
187722d268cbSEd Tanous         app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
1878ed398213SEd Tanous         .privileges(redfish::privileges::patchLogEntry)
18797e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::patch)(
188045ca1b86SEd Tanous             [&app](const crow::Request& req,
18817e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
188222d268cbSEd Tanous                    const std::string& systemName, const std::string& entryId) {
18833ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
188445ca1b86SEd Tanous                 {
188545ca1b86SEd Tanous                     return;
188645ca1b86SEd Tanous                 }
188725b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
18887f3e84a1SEd Tanous                 {
18897f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
18907f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
18917f3e84a1SEd Tanous                                                systemName);
18927f3e84a1SEd Tanous                     return;
18937f3e84a1SEd Tanous                 }
1894253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
189522d268cbSEd Tanous                 {
189622d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
189722d268cbSEd Tanous                                                systemName);
189822d268cbSEd Tanous                     return;
189922d268cbSEd Tanous                 }
190075710de2SXiaochao Ma 
1901599b9af3SAlexander Hansen                 dBusEventLogEntryPatch(req, asyncResp, entryId);
19027e860f15SJohn Edward Broadbent             });
190375710de2SXiaochao Ma 
19047e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
190522d268cbSEd Tanous         app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
1906ed398213SEd Tanous         .privileges(redfish::privileges::deleteLogEntry)
1907ed398213SEd Tanous 
1908002d39b4SEd Tanous         .methods(boost::beast::http::verb::delete_)(
1909002d39b4SEd Tanous             [&app](const crow::Request& req,
1910002d39b4SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
191122d268cbSEd Tanous                    const std::string& systemName, const std::string& param) {
19123ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1913336e96c6SChicago Duan                 {
191445ca1b86SEd Tanous                     return;
191545ca1b86SEd Tanous                 }
191625b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
19177f3e84a1SEd Tanous                 {
19187f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
19197f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
19207f3e84a1SEd Tanous                                                systemName);
19217f3e84a1SEd Tanous                     return;
19227f3e84a1SEd Tanous                 }
1923253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
192422d268cbSEd Tanous                 {
192522d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
192622d268cbSEd Tanous                                                systemName);
192722d268cbSEd Tanous                     return;
192822d268cbSEd Tanous                 }
1929599b9af3SAlexander Hansen                 dBusEventLogEntryDelete(asyncResp, param);
19307e860f15SJohn Edward Broadbent             });
1931400fd1fbSAdriana Kobylak }
1932400fd1fbSAdriana Kobylak 
1933b7028ebfSSpencer Ku constexpr const char* hostLoggerFolderPath = "/var/log/console";
1934b7028ebfSSpencer Ku 
1935b7028ebfSSpencer Ku inline bool
1936b7028ebfSSpencer Ku     getHostLoggerFiles(const std::string& hostLoggerFilePath,
1937b7028ebfSSpencer Ku                        std::vector<std::filesystem::path>& hostLoggerFiles)
1938b7028ebfSSpencer Ku {
1939b7028ebfSSpencer Ku     std::error_code ec;
1940b7028ebfSSpencer Ku     std::filesystem::directory_iterator logPath(hostLoggerFilePath, ec);
1941b7028ebfSSpencer Ku     if (ec)
1942b7028ebfSSpencer Ku     {
1943bf2ddedeSCarson Labrado         BMCWEB_LOG_WARNING("{}", ec.message());
1944b7028ebfSSpencer Ku         return false;
1945b7028ebfSSpencer Ku     }
1946b7028ebfSSpencer Ku     for (const std::filesystem::directory_entry& it : logPath)
1947b7028ebfSSpencer Ku     {
1948b7028ebfSSpencer Ku         std::string filename = it.path().filename();
1949b7028ebfSSpencer Ku         // Prefix of each log files is "log". Find the file and save the
1950b7028ebfSSpencer Ku         // path
195111ba3979SEd Tanous         if (filename.starts_with("log"))
1952b7028ebfSSpencer Ku         {
1953b7028ebfSSpencer Ku             hostLoggerFiles.emplace_back(it.path());
1954b7028ebfSSpencer Ku         }
1955b7028ebfSSpencer Ku     }
1956b7028ebfSSpencer Ku     // As the log files rotate, they are appended with a ".#" that is higher for
1957b7028ebfSSpencer Ku     // the older logs. Since we start from oldest logs, sort the name in
1958b7028ebfSSpencer Ku     // descending order.
1959b7028ebfSSpencer Ku     std::sort(hostLoggerFiles.rbegin(), hostLoggerFiles.rend(),
1960b7028ebfSSpencer Ku               AlphanumLess<std::string>());
1961b7028ebfSSpencer Ku 
1962b7028ebfSSpencer Ku     return true;
1963b7028ebfSSpencer Ku }
1964b7028ebfSSpencer Ku 
196502cad96eSEd Tanous inline bool getHostLoggerEntries(
196602cad96eSEd Tanous     const std::vector<std::filesystem::path>& hostLoggerFiles, uint64_t skip,
196702cad96eSEd Tanous     uint64_t top, std::vector<std::string>& logEntries, size_t& logCount)
1968b7028ebfSSpencer Ku {
1969b7028ebfSSpencer Ku     GzFileReader logFile;
1970b7028ebfSSpencer Ku 
1971b7028ebfSSpencer Ku     // Go though all log files and expose host logs.
1972b7028ebfSSpencer Ku     for (const std::filesystem::path& it : hostLoggerFiles)
1973b7028ebfSSpencer Ku     {
1974b7028ebfSSpencer Ku         if (!logFile.gzGetLines(it.string(), skip, top, logEntries, logCount))
1975b7028ebfSSpencer Ku         {
197662598e31SEd Tanous             BMCWEB_LOG_ERROR("fail to expose host logs");
1977b7028ebfSSpencer Ku             return false;
1978b7028ebfSSpencer Ku         }
1979b7028ebfSSpencer Ku     }
1980b7028ebfSSpencer Ku     // Get lastMessage from constructor by getter
1981b7028ebfSSpencer Ku     std::string lastMessage = logFile.getLastMessage();
1982b7028ebfSSpencer Ku     if (!lastMessage.empty())
1983b7028ebfSSpencer Ku     {
1984b7028ebfSSpencer Ku         logCount++;
1985b7028ebfSSpencer Ku         if (logCount > skip && logCount <= (skip + top))
1986b7028ebfSSpencer Ku         {
1987b7028ebfSSpencer Ku             logEntries.push_back(lastMessage);
1988b7028ebfSSpencer Ku         }
1989b7028ebfSSpencer Ku     }
1990b7028ebfSSpencer Ku     return true;
1991b7028ebfSSpencer Ku }
1992b7028ebfSSpencer Ku 
1993dd72e87bSClaire Weinan inline void handleBMCLogServicesCollectionGet(
1994fdd26906SClaire Weinan     crow::App& app, const crow::Request& req,
1995253f11b8SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1996253f11b8SEd Tanous     const std::string& managerId)
19971da66f75SEd Tanous {
19983ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
199945ca1b86SEd Tanous     {
200045ca1b86SEd Tanous         return;
200145ca1b86SEd Tanous     }
2002253f11b8SEd Tanous 
2003253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2004253f11b8SEd Tanous     {
2005253f11b8SEd Tanous         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2006253f11b8SEd Tanous         return;
2007253f11b8SEd Tanous     }
2008253f11b8SEd Tanous 
20097e860f15SJohn Edward Broadbent     // Collections don't include the static data added by SubRoute
20107e860f15SJohn Edward Broadbent     // because it has a duplicate entry for members
2011e1f26343SJason M. Bills     asyncResp->res.jsonValue["@odata.type"] =
20121da66f75SEd Tanous         "#LogServiceCollection.LogServiceCollection";
2013253f11b8SEd Tanous     asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
2014253f11b8SEd Tanous         "/redfish/v1/Managers/{}/LogServices", BMCWEB_REDFISH_MANAGER_URI_NAME);
2015002d39b4SEd Tanous     asyncResp->res.jsonValue["Name"] = "Open BMC Log Services Collection";
2016e1f26343SJason M. Bills     asyncResp->res.jsonValue["Description"] =
20171da66f75SEd Tanous         "Collection of LogServices for this Manager";
2018002d39b4SEd Tanous     nlohmann::json& logServiceArray = asyncResp->res.jsonValue["Members"];
2019c4bf6374SJason M. Bills     logServiceArray = nlohmann::json::array();
2020fdd26906SClaire Weinan 
202125b54dbaSEd Tanous     if constexpr (BMCWEB_REDFISH_BMC_JOURNAL)
202225b54dbaSEd Tanous     {
2023613dabeaSEd Tanous         nlohmann::json::object_t journal;
2024253f11b8SEd Tanous         journal["@odata.id"] =
2025253f11b8SEd Tanous             boost::urls::format("/redfish/v1/Managers/{}/LogServices/Journal",
2026253f11b8SEd Tanous                                 BMCWEB_REDFISH_MANAGER_URI_NAME);
2027b2ba3072SPatrick Williams         logServiceArray.emplace_back(std::move(journal));
202825b54dbaSEd Tanous     }
2029fdd26906SClaire Weinan 
2030fdd26906SClaire Weinan     asyncResp->res.jsonValue["Members@odata.count"] = logServiceArray.size();
2031fdd26906SClaire Weinan 
203225b54dbaSEd Tanous     if constexpr (BMCWEB_REDFISH_DUMP_LOG)
203325b54dbaSEd Tanous     {
203415912159SGeorge Liu         constexpr std::array<std::string_view, 1> interfaces = {
20357a1dbc48SGeorge Liu             "xyz.openbmc_project.Collection.DeleteAll"};
20367a1dbc48SGeorge Liu         dbus::utility::getSubTreePaths(
20377a1dbc48SGeorge Liu             "/xyz/openbmc_project/dump", 0, interfaces,
203825b54dbaSEd Tanous             [asyncResp](const boost::system::error_code& ec,
203925b54dbaSEd Tanous                         const dbus::utility::MapperGetSubTreePathsResponse&
204025b54dbaSEd Tanous                             subTreePaths) {
2041fdd26906SClaire Weinan                 if (ec)
2042fdd26906SClaire Weinan                 {
204362598e31SEd Tanous                     BMCWEB_LOG_ERROR(
204462598e31SEd Tanous                         "handleBMCLogServicesCollectionGet respHandler got error {}",
204562598e31SEd Tanous                         ec);
2046bd79bce8SPatrick Williams                     // Assume that getting an error simply means there are no
2047bd79bce8SPatrick Williams                     // dump LogServices. Return without adding any error
2048bd79bce8SPatrick Williams                     // response.
2049fdd26906SClaire Weinan                     return;
2050fdd26906SClaire Weinan                 }
2051fdd26906SClaire Weinan 
2052fdd26906SClaire Weinan                 nlohmann::json& logServiceArrayLocal =
2053fdd26906SClaire Weinan                     asyncResp->res.jsonValue["Members"];
2054fdd26906SClaire Weinan 
2055fdd26906SClaire Weinan                 for (const std::string& path : subTreePaths)
2056fdd26906SClaire Weinan                 {
2057fdd26906SClaire Weinan                     if (path == "/xyz/openbmc_project/dump/bmc")
2058fdd26906SClaire Weinan                     {
2059613dabeaSEd Tanous                         nlohmann::json::object_t member;
2060253f11b8SEd Tanous                         member["@odata.id"] = boost::urls::format(
2061253f11b8SEd Tanous                             "/redfish/v1/Managers/{}/LogServices/Dump",
2062253f11b8SEd Tanous                             BMCWEB_REDFISH_MANAGER_URI_NAME);
2063b2ba3072SPatrick Williams                         logServiceArrayLocal.emplace_back(std::move(member));
2064fdd26906SClaire Weinan                     }
2065fdd26906SClaire Weinan                     else if (path == "/xyz/openbmc_project/dump/faultlog")
2066fdd26906SClaire Weinan                     {
2067613dabeaSEd Tanous                         nlohmann::json::object_t member;
2068253f11b8SEd Tanous                         member["@odata.id"] = boost::urls::format(
2069253f11b8SEd Tanous                             "/redfish/v1/Managers/{}/LogServices/FaultLog",
2070253f11b8SEd Tanous                             BMCWEB_REDFISH_MANAGER_URI_NAME);
2071b2ba3072SPatrick Williams                         logServiceArrayLocal.emplace_back(std::move(member));
2072fdd26906SClaire Weinan                     }
2073fdd26906SClaire Weinan                 }
2074fdd26906SClaire Weinan 
2075e1f26343SJason M. Bills                 asyncResp->res.jsonValue["Members@odata.count"] =
2076fdd26906SClaire Weinan                     logServiceArrayLocal.size();
20777a1dbc48SGeorge Liu             });
207825b54dbaSEd Tanous     }
2079fdd26906SClaire Weinan }
2080fdd26906SClaire Weinan 
2081fdd26906SClaire Weinan inline void requestRoutesBMCLogServiceCollection(App& app)
2082fdd26906SClaire Weinan {
2083253f11b8SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/")
2084fdd26906SClaire Weinan         .privileges(redfish::privileges::getLogServiceCollection)
2085fdd26906SClaire Weinan         .methods(boost::beast::http::verb::get)(
2086dd72e87bSClaire Weinan             std::bind_front(handleBMCLogServicesCollectionGet, std::ref(app)));
2087e1f26343SJason M. Bills }
2088e1f26343SJason M. Bills 
2089fdd26906SClaire Weinan inline void
2090fdd26906SClaire Weinan     getDumpServiceInfo(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2091fdd26906SClaire Weinan                        const std::string& dumpType)
2092c9bb6861Sraviteja-b {
2093fdd26906SClaire Weinan     std::string dumpPath;
2094539d8c6bSEd Tanous     log_service::OverWritePolicy overWritePolicy =
2095539d8c6bSEd Tanous         log_service::OverWritePolicy::Invalid;
2096fdd26906SClaire Weinan     bool collectDiagnosticDataSupported = false;
2097fdd26906SClaire Weinan 
2098fdd26906SClaire Weinan     if (dumpType == "BMC")
209945ca1b86SEd Tanous     {
2100253f11b8SEd Tanous         dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/Dump",
2101253f11b8SEd Tanous                                BMCWEB_REDFISH_MANAGER_URI_NAME);
2102539d8c6bSEd Tanous         overWritePolicy = log_service::OverWritePolicy::WrapsWhenFull;
2103fdd26906SClaire Weinan         collectDiagnosticDataSupported = true;
2104fdd26906SClaire Weinan     }
2105fdd26906SClaire Weinan     else if (dumpType == "FaultLog")
2106fdd26906SClaire Weinan     {
2107253f11b8SEd Tanous         dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/FaultLog",
2108253f11b8SEd Tanous                                BMCWEB_REDFISH_MANAGER_URI_NAME);
2109539d8c6bSEd Tanous         overWritePolicy = log_service::OverWritePolicy::Unknown;
2110fdd26906SClaire Weinan         collectDiagnosticDataSupported = false;
2111fdd26906SClaire Weinan     }
2112fdd26906SClaire Weinan     else if (dumpType == "System")
2113fdd26906SClaire Weinan     {
2114253f11b8SEd Tanous         dumpPath = std::format("/redfish/v1/Systems/{}/LogServices/Dump",
2115253f11b8SEd Tanous                                BMCWEB_REDFISH_SYSTEM_URI_NAME);
2116539d8c6bSEd Tanous         overWritePolicy = log_service::OverWritePolicy::WrapsWhenFull;
2117fdd26906SClaire Weinan         collectDiagnosticDataSupported = true;
2118fdd26906SClaire Weinan     }
2119fdd26906SClaire Weinan     else
2120fdd26906SClaire Weinan     {
212162598e31SEd Tanous         BMCWEB_LOG_ERROR("getDumpServiceInfo() invalid dump type: {}",
212262598e31SEd Tanous                          dumpType);
2123fdd26906SClaire Weinan         messages::internalError(asyncResp->res);
212445ca1b86SEd Tanous         return;
212545ca1b86SEd Tanous     }
2126fdd26906SClaire Weinan 
2127fdd26906SClaire Weinan     asyncResp->res.jsonValue["@odata.id"] = dumpPath;
2128fdd26906SClaire Weinan     asyncResp->res.jsonValue["@odata.type"] = "#LogService.v1_2_0.LogService";
2129c9bb6861Sraviteja-b     asyncResp->res.jsonValue["Name"] = "Dump LogService";
2130fdd26906SClaire Weinan     asyncResp->res.jsonValue["Description"] = dumpType + " Dump LogService";
2131fdd26906SClaire Weinan     asyncResp->res.jsonValue["Id"] = std::filesystem::path(dumpPath).filename();
2132539d8c6bSEd Tanous     asyncResp->res.jsonValue["OverWritePolicy"] = overWritePolicy;
21337c8c4058STejas Patil 
21347c8c4058STejas Patil     std::pair<std::string, std::string> redfishDateTimeOffset =
21352b82937eSEd Tanous         redfish::time_utils::getDateTimeOffsetNow();
21360fda0f12SGeorge Liu     asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
21377c8c4058STejas Patil     asyncResp->res.jsonValue["DateTimeLocalOffset"] =
21387c8c4058STejas Patil         redfishDateTimeOffset.second;
21397c8c4058STejas Patil 
2140fdd26906SClaire Weinan     asyncResp->res.jsonValue["Entries"]["@odata.id"] = dumpPath + "/Entries";
2141fdd26906SClaire Weinan 
2142fdd26906SClaire Weinan     if (collectDiagnosticDataSupported)
2143fdd26906SClaire Weinan     {
2144002d39b4SEd Tanous         asyncResp->res.jsonValue["Actions"]["#LogService.CollectDiagnosticData"]
21451476687dSEd Tanous                                 ["target"] =
2146fdd26906SClaire Weinan             dumpPath + "/Actions/LogService.CollectDiagnosticData";
2147fdd26906SClaire Weinan     }
21480d946211SClaire Weinan 
21490d946211SClaire Weinan     constexpr std::array<std::string_view, 1> interfaces = {deleteAllInterface};
21500d946211SClaire Weinan     dbus::utility::getSubTreePaths(
21510d946211SClaire Weinan         "/xyz/openbmc_project/dump", 0, interfaces,
21520d946211SClaire Weinan         [asyncResp, dumpType, dumpPath](
21530d946211SClaire Weinan             const boost::system::error_code& ec,
21540d946211SClaire Weinan             const dbus::utility::MapperGetSubTreePathsResponse& subTreePaths) {
21550d946211SClaire Weinan             if (ec)
21560d946211SClaire Weinan             {
2157bd79bce8SPatrick Williams                 BMCWEB_LOG_ERROR("getDumpServiceInfo respHandler got error {}",
2158bd79bce8SPatrick Williams                                  ec);
21590d946211SClaire Weinan                 // Assume that getting an error simply means there are no dump
21600d946211SClaire Weinan                 // LogServices. Return without adding any error response.
21610d946211SClaire Weinan                 return;
21620d946211SClaire Weinan             }
216318f8f608SEd Tanous             std::string dbusDumpPath = getDumpPath(dumpType);
21640d946211SClaire Weinan             for (const std::string& path : subTreePaths)
21650d946211SClaire Weinan             {
21660d946211SClaire Weinan                 if (path == dbusDumpPath)
21670d946211SClaire Weinan                 {
2168bd79bce8SPatrick Williams                     asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"]
2169bd79bce8SPatrick Williams                                             ["target"] =
21700d946211SClaire Weinan                         dumpPath + "/Actions/LogService.ClearLog";
21710d946211SClaire Weinan                     break;
21720d946211SClaire Weinan                 }
21730d946211SClaire Weinan             }
21740d946211SClaire Weinan         });
2175c9bb6861Sraviteja-b }
2176c9bb6861Sraviteja-b 
2177fdd26906SClaire Weinan inline void handleLogServicesDumpServiceGet(
2178fdd26906SClaire Weinan     crow::App& app, const std::string& dumpType, const crow::Request& req,
2179253f11b8SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2180253f11b8SEd Tanous     const std::string& managerId)
21817e860f15SJohn Edward Broadbent {
21823ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
218345ca1b86SEd Tanous     {
218445ca1b86SEd Tanous         return;
218545ca1b86SEd Tanous     }
2186253f11b8SEd Tanous 
2187253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2188253f11b8SEd Tanous     {
2189253f11b8SEd Tanous         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2190253f11b8SEd Tanous         return;
2191253f11b8SEd Tanous     }
2192253f11b8SEd Tanous 
2193fdd26906SClaire Weinan     getDumpServiceInfo(asyncResp, dumpType);
2194fdd26906SClaire Weinan }
2195c9bb6861Sraviteja-b 
219622d268cbSEd Tanous inline void handleLogServicesDumpServiceComputerSystemGet(
219722d268cbSEd Tanous     crow::App& app, const crow::Request& req,
219822d268cbSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
219922d268cbSEd Tanous     const std::string& chassisId)
220022d268cbSEd Tanous {
220122d268cbSEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
220222d268cbSEd Tanous     {
220322d268cbSEd Tanous         return;
220422d268cbSEd Tanous     }
2205253f11b8SEd Tanous     if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
220622d268cbSEd Tanous     {
220722d268cbSEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
220822d268cbSEd Tanous         return;
220922d268cbSEd Tanous     }
221022d268cbSEd Tanous     getDumpServiceInfo(asyncResp, "System");
221122d268cbSEd Tanous }
221222d268cbSEd Tanous 
2213fdd26906SClaire Weinan inline void handleLogServicesDumpEntriesCollectionGet(
2214fdd26906SClaire Weinan     crow::App& app, const std::string& dumpType, const crow::Request& req,
2215253f11b8SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2216253f11b8SEd Tanous     const std::string& managerId)
2217fdd26906SClaire Weinan {
2218fdd26906SClaire Weinan     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2219fdd26906SClaire Weinan     {
2220fdd26906SClaire Weinan         return;
2221fdd26906SClaire Weinan     }
2222253f11b8SEd Tanous 
2223253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2224253f11b8SEd Tanous     {
2225253f11b8SEd Tanous         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2226253f11b8SEd Tanous         return;
2227253f11b8SEd Tanous     }
2228fdd26906SClaire Weinan     getDumpEntryCollection(asyncResp, dumpType);
2229fdd26906SClaire Weinan }
2230fdd26906SClaire Weinan 
223122d268cbSEd Tanous inline void handleLogServicesDumpEntriesCollectionComputerSystemGet(
223222d268cbSEd Tanous     crow::App& app, const crow::Request& req,
223322d268cbSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
223422d268cbSEd Tanous     const std::string& chassisId)
223522d268cbSEd Tanous {
223622d268cbSEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
223722d268cbSEd Tanous     {
223822d268cbSEd Tanous         return;
223922d268cbSEd Tanous     }
2240253f11b8SEd Tanous     if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
224122d268cbSEd Tanous     {
224222d268cbSEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
224322d268cbSEd Tanous         return;
224422d268cbSEd Tanous     }
224522d268cbSEd Tanous     getDumpEntryCollection(asyncResp, "System");
224622d268cbSEd Tanous }
224722d268cbSEd Tanous 
2248fdd26906SClaire Weinan inline void handleLogServicesDumpEntryGet(
2249fdd26906SClaire Weinan     crow::App& app, const std::string& dumpType, const crow::Request& req,
2250fdd26906SClaire Weinan     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2251253f11b8SEd Tanous     const std::string& managerId, const std::string& dumpId)
2252fdd26906SClaire Weinan {
2253fdd26906SClaire Weinan     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2254fdd26906SClaire Weinan     {
2255fdd26906SClaire Weinan         return;
2256fdd26906SClaire Weinan     }
2257253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2258253f11b8SEd Tanous     {
2259253f11b8SEd Tanous         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2260253f11b8SEd Tanous         return;
2261253f11b8SEd Tanous     }
2262fdd26906SClaire Weinan     getDumpEntryById(asyncResp, dumpId, dumpType);
2263fdd26906SClaire Weinan }
2264168d1b1aSCarson Labrado 
226522d268cbSEd Tanous inline void handleLogServicesDumpEntryComputerSystemGet(
226622d268cbSEd Tanous     crow::App& app, const crow::Request& req,
226722d268cbSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
226822d268cbSEd Tanous     const std::string& chassisId, const std::string& dumpId)
226922d268cbSEd Tanous {
227022d268cbSEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
227122d268cbSEd Tanous     {
227222d268cbSEd Tanous         return;
227322d268cbSEd Tanous     }
2274253f11b8SEd Tanous     if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
227522d268cbSEd Tanous     {
227622d268cbSEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
227722d268cbSEd Tanous         return;
227822d268cbSEd Tanous     }
227922d268cbSEd Tanous     getDumpEntryById(asyncResp, dumpId, "System");
228022d268cbSEd Tanous }
2281fdd26906SClaire Weinan 
2282fdd26906SClaire Weinan inline void handleLogServicesDumpEntryDelete(
2283fdd26906SClaire Weinan     crow::App& app, const std::string& dumpType, const crow::Request& req,
2284fdd26906SClaire Weinan     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2285253f11b8SEd Tanous     const std::string& managerId, const std::string& dumpId)
2286fdd26906SClaire Weinan {
2287fdd26906SClaire Weinan     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2288fdd26906SClaire Weinan     {
2289fdd26906SClaire Weinan         return;
2290fdd26906SClaire Weinan     }
2291253f11b8SEd Tanous 
2292253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2293253f11b8SEd Tanous     {
2294253f11b8SEd Tanous         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2295253f11b8SEd Tanous         return;
2296253f11b8SEd Tanous     }
2297fdd26906SClaire Weinan     deleteDumpEntry(asyncResp, dumpId, dumpType);
2298fdd26906SClaire Weinan }
2299fdd26906SClaire Weinan 
230022d268cbSEd Tanous inline void handleLogServicesDumpEntryComputerSystemDelete(
230122d268cbSEd Tanous     crow::App& app, const crow::Request& req,
230222d268cbSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
230322d268cbSEd Tanous     const std::string& chassisId, const std::string& dumpId)
230422d268cbSEd Tanous {
230522d268cbSEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
230622d268cbSEd Tanous     {
230722d268cbSEd Tanous         return;
230822d268cbSEd Tanous     }
2309253f11b8SEd Tanous     if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
231022d268cbSEd Tanous     {
231122d268cbSEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
231222d268cbSEd Tanous         return;
231322d268cbSEd Tanous     }
231422d268cbSEd Tanous     deleteDumpEntry(asyncResp, dumpId, "System");
231522d268cbSEd Tanous }
231622d268cbSEd Tanous 
2317168d1b1aSCarson Labrado inline void handleLogServicesDumpEntryDownloadGet(
2318168d1b1aSCarson Labrado     crow::App& app, const std::string& dumpType, const crow::Request& req,
2319168d1b1aSCarson Labrado     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2320253f11b8SEd Tanous     const std::string& managerId, const std::string& dumpId)
2321168d1b1aSCarson Labrado {
2322168d1b1aSCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2323168d1b1aSCarson Labrado     {
2324168d1b1aSCarson Labrado         return;
2325168d1b1aSCarson Labrado     }
2326253f11b8SEd Tanous 
2327253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2328253f11b8SEd Tanous     {
2329253f11b8SEd Tanous         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2330253f11b8SEd Tanous         return;
2331253f11b8SEd Tanous     }
2332168d1b1aSCarson Labrado     downloadDumpEntry(asyncResp, dumpId, dumpType);
2333168d1b1aSCarson Labrado }
2334168d1b1aSCarson Labrado 
2335168d1b1aSCarson Labrado inline void handleDBusEventLogEntryDownloadGet(
2336168d1b1aSCarson Labrado     crow::App& app, const std::string& dumpType, const crow::Request& req,
2337168d1b1aSCarson Labrado     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2338168d1b1aSCarson Labrado     const std::string& systemName, const std::string& entryID)
2339168d1b1aSCarson Labrado {
2340168d1b1aSCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2341168d1b1aSCarson Labrado     {
2342168d1b1aSCarson Labrado         return;
2343168d1b1aSCarson Labrado     }
2344168d1b1aSCarson Labrado     if (!http_helpers::isContentTypeAllowed(
2345168d1b1aSCarson Labrado             req.getHeaderValue("Accept"),
2346168d1b1aSCarson Labrado             http_helpers::ContentType::OctetStream, true))
2347168d1b1aSCarson Labrado     {
2348168d1b1aSCarson Labrado         asyncResp->res.result(boost::beast::http::status::bad_request);
2349168d1b1aSCarson Labrado         return;
2350168d1b1aSCarson Labrado     }
2351168d1b1aSCarson Labrado     downloadEventLogEntry(asyncResp, systemName, entryID, dumpType);
2352168d1b1aSCarson Labrado }
2353168d1b1aSCarson Labrado 
2354fdd26906SClaire Weinan inline void handleLogServicesDumpCollectDiagnosticDataPost(
2355fdd26906SClaire Weinan     crow::App& app, const std::string& dumpType, const crow::Request& req,
2356253f11b8SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2357253f11b8SEd Tanous     const std::string& managerId)
2358fdd26906SClaire Weinan {
2359fdd26906SClaire Weinan     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2360fdd26906SClaire Weinan     {
2361fdd26906SClaire Weinan         return;
2362fdd26906SClaire Weinan     }
2363253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2364253f11b8SEd Tanous     {
2365253f11b8SEd Tanous         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2366253f11b8SEd Tanous         return;
2367253f11b8SEd Tanous     }
2368253f11b8SEd Tanous 
2369fdd26906SClaire Weinan     createDump(asyncResp, req, dumpType);
2370fdd26906SClaire Weinan }
2371fdd26906SClaire Weinan 
237222d268cbSEd Tanous inline void handleLogServicesDumpCollectDiagnosticDataComputerSystemPost(
237322d268cbSEd Tanous     crow::App& app, const crow::Request& req,
237422d268cbSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
23757f3e84a1SEd Tanous     const std::string& systemName)
237622d268cbSEd Tanous {
237722d268cbSEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
237822d268cbSEd Tanous     {
237922d268cbSEd Tanous         return;
238022d268cbSEd Tanous     }
23817f3e84a1SEd Tanous 
238225b54dbaSEd Tanous     if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
238322d268cbSEd Tanous     {
23847f3e84a1SEd Tanous         // Option currently returns no systems.  TBD
23857f3e84a1SEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
23867f3e84a1SEd Tanous                                    systemName);
23877f3e84a1SEd Tanous         return;
23887f3e84a1SEd Tanous     }
2389253f11b8SEd Tanous     if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
23907f3e84a1SEd Tanous     {
23917f3e84a1SEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
23927f3e84a1SEd Tanous                                    systemName);
239322d268cbSEd Tanous         return;
239422d268cbSEd Tanous     }
239522d268cbSEd Tanous     createDump(asyncResp, req, "System");
239622d268cbSEd Tanous }
239722d268cbSEd Tanous 
2398fdd26906SClaire Weinan inline void handleLogServicesDumpClearLogPost(
2399fdd26906SClaire Weinan     crow::App& app, const std::string& dumpType, const crow::Request& req,
2400253f11b8SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2401253f11b8SEd Tanous     const std::string& managerId)
2402fdd26906SClaire Weinan {
2403fdd26906SClaire Weinan     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2404fdd26906SClaire Weinan     {
2405fdd26906SClaire Weinan         return;
2406fdd26906SClaire Weinan     }
2407253f11b8SEd Tanous 
2408253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2409253f11b8SEd Tanous     {
2410253f11b8SEd Tanous         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2411253f11b8SEd Tanous         return;
2412253f11b8SEd Tanous     }
2413fdd26906SClaire Weinan     clearDump(asyncResp, dumpType);
2414fdd26906SClaire Weinan }
2415fdd26906SClaire Weinan 
241622d268cbSEd Tanous inline void handleLogServicesDumpClearLogComputerSystemPost(
241722d268cbSEd Tanous     crow::App& app, const crow::Request& req,
241822d268cbSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
24197f3e84a1SEd Tanous     const std::string& systemName)
242022d268cbSEd Tanous {
242122d268cbSEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
242222d268cbSEd Tanous     {
242322d268cbSEd Tanous         return;
242422d268cbSEd Tanous     }
242525b54dbaSEd Tanous     if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
242622d268cbSEd Tanous     {
24277f3e84a1SEd Tanous         // Option currently returns no systems.  TBD
24287f3e84a1SEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
24297f3e84a1SEd Tanous                                    systemName);
24307f3e84a1SEd Tanous         return;
24317f3e84a1SEd Tanous     }
2432253f11b8SEd Tanous     if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
24337f3e84a1SEd Tanous     {
24347f3e84a1SEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
24357f3e84a1SEd Tanous                                    systemName);
243622d268cbSEd Tanous         return;
243722d268cbSEd Tanous     }
243822d268cbSEd Tanous     clearDump(asyncResp, "System");
243922d268cbSEd Tanous }
244022d268cbSEd Tanous 
2441fdd26906SClaire Weinan inline void requestRoutesBMCDumpService(App& app)
2442fdd26906SClaire Weinan {
2443253f11b8SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/Dump/")
2444fdd26906SClaire Weinan         .privileges(redfish::privileges::getLogService)
2445fdd26906SClaire Weinan         .methods(boost::beast::http::verb::get)(std::bind_front(
2446fdd26906SClaire Weinan             handleLogServicesDumpServiceGet, std::ref(app), "BMC"));
2447fdd26906SClaire Weinan }
2448fdd26906SClaire Weinan 
2449fdd26906SClaire Weinan inline void requestRoutesBMCDumpEntryCollection(App& app)
2450fdd26906SClaire Weinan {
2451253f11b8SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/")
2452fdd26906SClaire Weinan         .privileges(redfish::privileges::getLogEntryCollection)
2453fdd26906SClaire Weinan         .methods(boost::beast::http::verb::get)(std::bind_front(
2454fdd26906SClaire Weinan             handleLogServicesDumpEntriesCollectionGet, std::ref(app), "BMC"));
2455c9bb6861Sraviteja-b }
2456c9bb6861Sraviteja-b 
24577e860f15SJohn Edward Broadbent inline void requestRoutesBMCDumpEntry(App& app)
2458c9bb6861Sraviteja-b {
24597e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
2460253f11b8SEd Tanous                  "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/")
2461ed398213SEd Tanous         .privileges(redfish::privileges::getLogEntry)
2462fdd26906SClaire Weinan         .methods(boost::beast::http::verb::get)(std::bind_front(
2463fdd26906SClaire Weinan             handleLogServicesDumpEntryGet, std::ref(app), "BMC"));
2464fdd26906SClaire Weinan 
24657e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
2466253f11b8SEd Tanous                  "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/")
2467ed398213SEd Tanous         .privileges(redfish::privileges::deleteLogEntry)
2468fdd26906SClaire Weinan         .methods(boost::beast::http::verb::delete_)(std::bind_front(
2469fdd26906SClaire Weinan             handleLogServicesDumpEntryDelete, std::ref(app), "BMC"));
2470c9bb6861Sraviteja-b }
2471c9bb6861Sraviteja-b 
2472168d1b1aSCarson Labrado inline void requestRoutesBMCDumpEntryDownload(App& app)
2473168d1b1aSCarson Labrado {
2474168d1b1aSCarson Labrado     BMCWEB_ROUTE(
2475168d1b1aSCarson Labrado         app,
2476253f11b8SEd Tanous         "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/attachment/")
2477168d1b1aSCarson Labrado         .privileges(redfish::privileges::getLogEntry)
2478168d1b1aSCarson Labrado         .methods(boost::beast::http::verb::get)(std::bind_front(
2479168d1b1aSCarson Labrado             handleLogServicesDumpEntryDownloadGet, std::ref(app), "BMC"));
2480168d1b1aSCarson Labrado }
2481168d1b1aSCarson Labrado 
24827e860f15SJohn Edward Broadbent inline void requestRoutesBMCDumpCreate(App& app)
2483c9bb6861Sraviteja-b {
24840fda0f12SGeorge Liu     BMCWEB_ROUTE(
24850fda0f12SGeorge Liu         app,
2486253f11b8SEd Tanous         "/redfish/v1/Managers/<str>/LogServices/Dump/Actions/LogService.CollectDiagnosticData/")
2487ed398213SEd Tanous         .privileges(redfish::privileges::postLogService)
24887e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
2489fdd26906SClaire Weinan             std::bind_front(handleLogServicesDumpCollectDiagnosticDataPost,
2490fdd26906SClaire Weinan                             std::ref(app), "BMC"));
2491a43be80fSAsmitha Karunanithi }
2492a43be80fSAsmitha Karunanithi 
24937e860f15SJohn Edward Broadbent inline void requestRoutesBMCDumpClear(App& app)
249480319af1SAsmitha Karunanithi {
24950fda0f12SGeorge Liu     BMCWEB_ROUTE(
24960fda0f12SGeorge Liu         app,
2497253f11b8SEd Tanous         "/redfish/v1/Managers/<str>/LogServices/Dump/Actions/LogService.ClearLog/")
2498ed398213SEd Tanous         .privileges(redfish::privileges::postLogService)
2499fdd26906SClaire Weinan         .methods(boost::beast::http::verb::post)(std::bind_front(
2500fdd26906SClaire Weinan             handleLogServicesDumpClearLogPost, std::ref(app), "BMC"));
250145ca1b86SEd Tanous }
2502fdd26906SClaire Weinan 
2503168d1b1aSCarson Labrado inline void requestRoutesDBusEventLogEntryDownload(App& app)
2504168d1b1aSCarson Labrado {
2505168d1b1aSCarson Labrado     BMCWEB_ROUTE(
2506168d1b1aSCarson Labrado         app,
25079e9d99daSRavi Teja         "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/attachment/")
2508168d1b1aSCarson Labrado         .privileges(redfish::privileges::getLogEntry)
2509168d1b1aSCarson Labrado         .methods(boost::beast::http::verb::get)(std::bind_front(
2510168d1b1aSCarson Labrado             handleDBusEventLogEntryDownloadGet, std::ref(app), "System"));
2511168d1b1aSCarson Labrado }
2512168d1b1aSCarson Labrado 
2513fdd26906SClaire Weinan inline void requestRoutesFaultLogDumpService(App& app)
2514fdd26906SClaire Weinan {
2515253f11b8SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/")
2516fdd26906SClaire Weinan         .privileges(redfish::privileges::getLogService)
2517fdd26906SClaire Weinan         .methods(boost::beast::http::verb::get)(std::bind_front(
2518fdd26906SClaire Weinan             handleLogServicesDumpServiceGet, std::ref(app), "FaultLog"));
2519fdd26906SClaire Weinan }
2520fdd26906SClaire Weinan 
2521fdd26906SClaire Weinan inline void requestRoutesFaultLogDumpEntryCollection(App& app)
2522fdd26906SClaire Weinan {
2523253f11b8SEd Tanous     BMCWEB_ROUTE(app,
2524253f11b8SEd Tanous                  "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/")
2525fdd26906SClaire Weinan         .privileges(redfish::privileges::getLogEntryCollection)
2526fdd26906SClaire Weinan         .methods(boost::beast::http::verb::get)(
2527fdd26906SClaire Weinan             std::bind_front(handleLogServicesDumpEntriesCollectionGet,
2528fdd26906SClaire Weinan                             std::ref(app), "FaultLog"));
2529fdd26906SClaire Weinan }
2530fdd26906SClaire Weinan 
2531fdd26906SClaire Weinan inline void requestRoutesFaultLogDumpEntry(App& app)
2532fdd26906SClaire Weinan {
2533253f11b8SEd Tanous     BMCWEB_ROUTE(
2534253f11b8SEd Tanous         app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/<str>/")
2535fdd26906SClaire Weinan         .privileges(redfish::privileges::getLogEntry)
2536fdd26906SClaire Weinan         .methods(boost::beast::http::verb::get)(std::bind_front(
2537fdd26906SClaire Weinan             handleLogServicesDumpEntryGet, std::ref(app), "FaultLog"));
2538fdd26906SClaire Weinan 
2539253f11b8SEd Tanous     BMCWEB_ROUTE(
2540253f11b8SEd Tanous         app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/<str>/")
2541fdd26906SClaire Weinan         .privileges(redfish::privileges::deleteLogEntry)
2542fdd26906SClaire Weinan         .methods(boost::beast::http::verb::delete_)(std::bind_front(
2543fdd26906SClaire Weinan             handleLogServicesDumpEntryDelete, std::ref(app), "FaultLog"));
2544fdd26906SClaire Weinan }
2545fdd26906SClaire Weinan 
2546fdd26906SClaire Weinan inline void requestRoutesFaultLogDumpClear(App& app)
2547fdd26906SClaire Weinan {
2548fdd26906SClaire Weinan     BMCWEB_ROUTE(
2549fdd26906SClaire Weinan         app,
2550253f11b8SEd Tanous         "/redfish/v1/Managers/<str>/LogServices/FaultLog/Actions/LogService.ClearLog/")
2551fdd26906SClaire Weinan         .privileges(redfish::privileges::postLogService)
2552fdd26906SClaire Weinan         .methods(boost::beast::http::verb::post)(std::bind_front(
2553fdd26906SClaire Weinan             handleLogServicesDumpClearLogPost, std::ref(app), "FaultLog"));
25545cb1dd27SAsmitha Karunanithi }
25555cb1dd27SAsmitha Karunanithi 
25567e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpService(App& app)
25575cb1dd27SAsmitha Karunanithi {
255822d268cbSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Dump/")
2559ed398213SEd Tanous         .privileges(redfish::privileges::getLogService)
25606ab9ad54SClaire Weinan         .methods(boost::beast::http::verb::get)(std::bind_front(
256122d268cbSEd Tanous             handleLogServicesDumpServiceComputerSystemGet, std::ref(app)));
25625cb1dd27SAsmitha Karunanithi }
25635cb1dd27SAsmitha Karunanithi 
25647e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpEntryCollection(App& app)
25657e860f15SJohn Edward Broadbent {
256622d268cbSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/")
2567ed398213SEd Tanous         .privileges(redfish::privileges::getLogEntryCollection)
256822d268cbSEd Tanous         .methods(boost::beast::http::verb::get)(std::bind_front(
256922d268cbSEd Tanous             handleLogServicesDumpEntriesCollectionComputerSystemGet,
257022d268cbSEd Tanous             std::ref(app)));
25715cb1dd27SAsmitha Karunanithi }
25725cb1dd27SAsmitha Karunanithi 
25737e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpEntry(App& app)
25745cb1dd27SAsmitha Karunanithi {
25757e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
257622d268cbSEd Tanous                  "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/<str>/")
2577ed398213SEd Tanous         .privileges(redfish::privileges::getLogEntry)
25786ab9ad54SClaire Weinan         .methods(boost::beast::http::verb::get)(std::bind_front(
257922d268cbSEd Tanous             handleLogServicesDumpEntryComputerSystemGet, std::ref(app)));
25808d1b46d7Szhanghch05 
25817e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
258222d268cbSEd Tanous                  "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/<str>/")
2583ed398213SEd Tanous         .privileges(redfish::privileges::deleteLogEntry)
25846ab9ad54SClaire Weinan         .methods(boost::beast::http::verb::delete_)(std::bind_front(
258522d268cbSEd Tanous             handleLogServicesDumpEntryComputerSystemDelete, std::ref(app)));
25865cb1dd27SAsmitha Karunanithi }
2587c9bb6861Sraviteja-b 
25887e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpCreate(App& app)
2589c9bb6861Sraviteja-b {
25900fda0f12SGeorge Liu     BMCWEB_ROUTE(
25910fda0f12SGeorge Liu         app,
259222d268cbSEd Tanous         "/redfish/v1/Systems/<str>/LogServices/Dump/Actions/LogService.CollectDiagnosticData/")
2593ed398213SEd Tanous         .privileges(redfish::privileges::postLogService)
259422d268cbSEd Tanous         .methods(boost::beast::http::verb::post)(std::bind_front(
259522d268cbSEd Tanous             handleLogServicesDumpCollectDiagnosticDataComputerSystemPost,
259622d268cbSEd Tanous             std::ref(app)));
2597a43be80fSAsmitha Karunanithi }
2598a43be80fSAsmitha Karunanithi 
25997e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpClear(App& app)
2600a43be80fSAsmitha Karunanithi {
26010fda0f12SGeorge Liu     BMCWEB_ROUTE(
26020fda0f12SGeorge Liu         app,
260322d268cbSEd Tanous         "/redfish/v1/Systems/<str>/LogServices/Dump/Actions/LogService.ClearLog/")
2604ed398213SEd Tanous         .privileges(redfish::privileges::postLogService)
26056ab9ad54SClaire Weinan         .methods(boost::beast::http::verb::post)(std::bind_front(
260622d268cbSEd Tanous             handleLogServicesDumpClearLogComputerSystemPost, std::ref(app)));
2607013487e5Sraviteja-b }
2608013487e5Sraviteja-b 
26097e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpService(App& app)
26101da66f75SEd Tanous {
26113946028dSAppaRao Puli     // Note: Deviated from redfish privilege registry for GET & HEAD
26123946028dSAppaRao Puli     // method for security reasons.
26131da66f75SEd Tanous     /**
26141da66f75SEd Tanous      * Functions triggers appropriate requests on DBus
26151da66f75SEd Tanous      */
261622d268cbSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Crashdump/")
2617ed398213SEd Tanous         // This is incorrect, should be:
2618ed398213SEd Tanous         //.privileges(redfish::privileges::getLogService)
2619432a890cSEd Tanous         .privileges({{"ConfigureManager"}})
2620bd79bce8SPatrick Williams         .methods(
2621bd79bce8SPatrick Williams             boost::beast::http::verb::
2622bd79bce8SPatrick Williams                 get)([&app](const crow::Request& req,
262322d268cbSEd Tanous                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
262422d268cbSEd Tanous                             const std::string& systemName) {
26253ba00073SCarson Labrado             if (!redfish::setUpRedfishRoute(app, req, asyncResp))
262645ca1b86SEd Tanous             {
262745ca1b86SEd Tanous                 return;
262845ca1b86SEd Tanous             }
262925b54dbaSEd Tanous             if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
26307f3e84a1SEd Tanous             {
26317f3e84a1SEd Tanous                 // Option currently returns no systems.  TBD
26327f3e84a1SEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
26337f3e84a1SEd Tanous                                            systemName);
26347f3e84a1SEd Tanous                 return;
26357f3e84a1SEd Tanous             }
2636253f11b8SEd Tanous             if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
263722d268cbSEd Tanous             {
263822d268cbSEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
263922d268cbSEd Tanous                                            systemName);
264022d268cbSEd Tanous                 return;
264122d268cbSEd Tanous             }
264222d268cbSEd Tanous 
26437e860f15SJohn Edward Broadbent             // Copy over the static data to include the entries added by
26447e860f15SJohn Edward Broadbent             // SubRoute
26450f74e643SEd Tanous             asyncResp->res.jsonValue["@odata.id"] =
2646253f11b8SEd Tanous                 std::format("/redfish/v1/Systems/{}/LogServices/Crashdump",
2647253f11b8SEd Tanous                             BMCWEB_REDFISH_SYSTEM_URI_NAME);
2648e1f26343SJason M. Bills             asyncResp->res.jsonValue["@odata.type"] =
26498e6c099aSJason M. Bills                 "#LogService.v1_2_0.LogService";
26504f50ae4bSGunnar Mills             asyncResp->res.jsonValue["Name"] = "Open BMC Oem Crashdump Service";
26514f50ae4bSGunnar Mills             asyncResp->res.jsonValue["Description"] = "Oem Crashdump Service";
265215b89725SV-Sanjana             asyncResp->res.jsonValue["Id"] = "Crashdump";
2653539d8c6bSEd Tanous             asyncResp->res.jsonValue["OverWritePolicy"] =
2654539d8c6bSEd Tanous                 log_service::OverWritePolicy::WrapsWhenFull;
2655e1f26343SJason M. Bills             asyncResp->res.jsonValue["MaxNumberOfRecords"] = 3;
26567c8c4058STejas Patil 
26577c8c4058STejas Patil             std::pair<std::string, std::string> redfishDateTimeOffset =
26582b82937eSEd Tanous                 redfish::time_utils::getDateTimeOffsetNow();
26597c8c4058STejas Patil             asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
26607c8c4058STejas Patil             asyncResp->res.jsonValue["DateTimeLocalOffset"] =
26617c8c4058STejas Patil                 redfishDateTimeOffset.second;
26627c8c4058STejas Patil 
2663bd79bce8SPatrick Williams             asyncResp->res.jsonValue["Entries"]["@odata.id"] = std::format(
2664bd79bce8SPatrick Williams                 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries",
2665253f11b8SEd Tanous                 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2666253f11b8SEd Tanous             asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"]
2667253f11b8SEd Tanous                                     ["target"] = std::format(
2668253f11b8SEd Tanous                 "/redfish/v1/Systems/{}/LogServices/Crashdump/Actions/LogService.ClearLog",
2669253f11b8SEd Tanous                 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2670bd79bce8SPatrick Williams             asyncResp->res
2671bd79bce8SPatrick Williams                 .jsonValue["Actions"]["#LogService.CollectDiagnosticData"]
2672253f11b8SEd Tanous                           ["target"] = std::format(
2673253f11b8SEd Tanous                 "/redfish/v1/Systems/{}/LogServices/Crashdump/Actions/LogService.CollectDiagnosticData",
2674253f11b8SEd Tanous                 BMCWEB_REDFISH_SYSTEM_URI_NAME);
26757e860f15SJohn Edward Broadbent         });
26761da66f75SEd Tanous }
26771da66f75SEd Tanous 
26787e860f15SJohn Edward Broadbent void inline requestRoutesCrashdumpClear(App& app)
26795b61b5e8SJason M. Bills {
26800fda0f12SGeorge Liu     BMCWEB_ROUTE(
26810fda0f12SGeorge Liu         app,
268222d268cbSEd Tanous         "/redfish/v1/Systems/<str>/LogServices/Crashdump/Actions/LogService.ClearLog/")
2683ed398213SEd Tanous         // This is incorrect, should be:
2684ed398213SEd Tanous         //.privileges(redfish::privileges::postLogService)
2685432a890cSEd Tanous         .privileges({{"ConfigureComponents"}})
26867e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
268745ca1b86SEd Tanous             [&app](const crow::Request& req,
268822d268cbSEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
268922d268cbSEd Tanous                    const std::string& systemName) {
26903ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
269145ca1b86SEd Tanous                 {
269245ca1b86SEd Tanous                     return;
269345ca1b86SEd Tanous                 }
269425b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
26957f3e84a1SEd Tanous                 {
26967f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
26977f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
26987f3e84a1SEd Tanous                                                systemName);
26997f3e84a1SEd Tanous                     return;
27007f3e84a1SEd Tanous                 }
2701253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
270222d268cbSEd Tanous                 {
270322d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
270422d268cbSEd Tanous                                                systemName);
270522d268cbSEd Tanous                     return;
270622d268cbSEd Tanous                 }
27075b61b5e8SJason M. Bills                 crow::connections::systemBus->async_method_call(
27085e7e2dc5SEd Tanous                     [asyncResp](const boost::system::error_code& ec,
2709cb13a392SEd Tanous                                 const std::string&) {
27105b61b5e8SJason M. Bills                         if (ec)
27115b61b5e8SJason M. Bills                         {
27125b61b5e8SJason M. Bills                             messages::internalError(asyncResp->res);
27135b61b5e8SJason M. Bills                             return;
27145b61b5e8SJason M. Bills                         }
27155b61b5e8SJason M. Bills                         messages::success(asyncResp->res);
27165b61b5e8SJason M. Bills                     },
2717bd79bce8SPatrick Williams                     crashdumpObject, crashdumpPath, deleteAllInterface,
2718bd79bce8SPatrick Williams                     "DeleteAll");
27197e860f15SJohn Edward Broadbent             });
27205b61b5e8SJason M. Bills }
27215b61b5e8SJason M. Bills 
27224ff0f1f4SEd Tanous inline void
27238d1b46d7Szhanghch05     logCrashdumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
27248d1b46d7Szhanghch05                       const std::string& logID, nlohmann::json& logEntryJson)
2725e855dd28SJason M. Bills {
2726043a0536SJohnathan Mantey     auto getStoredLogCallback =
2727b9d36b47SEd Tanous         [asyncResp, logID,
27285e7e2dc5SEd Tanous          &logEntryJson](const boost::system::error_code& ec,
2729b9d36b47SEd Tanous                         const dbus::utility::DBusPropertiesMap& params) {
2730e855dd28SJason M. Bills             if (ec)
2731e855dd28SJason M. Bills             {
273262598e31SEd Tanous                 BMCWEB_LOG_DEBUG("failed to get log ec: {}", ec.message());
27331ddcf01aSJason M. Bills                 if (ec.value() ==
27341ddcf01aSJason M. Bills                     boost::system::linux_error::bad_request_descriptor)
27351ddcf01aSJason M. Bills                 {
2736bd79bce8SPatrick Williams                     messages::resourceNotFound(asyncResp->res, "LogEntry",
2737bd79bce8SPatrick Williams                                                logID);
27381ddcf01aSJason M. Bills                 }
27391ddcf01aSJason M. Bills                 else
27401ddcf01aSJason M. Bills                 {
2741e855dd28SJason M. Bills                     messages::internalError(asyncResp->res);
27421ddcf01aSJason M. Bills                 }
2743e855dd28SJason M. Bills                 return;
2744e855dd28SJason M. Bills             }
2745043a0536SJohnathan Mantey 
2746043a0536SJohnathan Mantey             std::string timestamp{};
2747043a0536SJohnathan Mantey             std::string filename{};
2748043a0536SJohnathan Mantey             std::string logfile{};
27492c70f800SEd Tanous             parseCrashdumpParameters(params, filename, timestamp, logfile);
2750043a0536SJohnathan Mantey 
2751043a0536SJohnathan Mantey             if (filename.empty() || timestamp.empty())
2752e855dd28SJason M. Bills             {
27539db4ba25SJiaqing Zhao                 messages::resourceNotFound(asyncResp->res, "LogEntry", logID);
2754e855dd28SJason M. Bills                 return;
2755e855dd28SJason M. Bills             }
2756e855dd28SJason M. Bills 
2757043a0536SJohnathan Mantey             std::string crashdumpURI =
2758bd79bce8SPatrick Williams                 std::format(
2759bd79bce8SPatrick Williams                     "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries/",
2760253f11b8SEd Tanous                     BMCWEB_REDFISH_SYSTEM_URI_NAME) +
2761043a0536SJohnathan Mantey                 logID + "/" + filename;
276284afc48bSJason M. Bills             nlohmann::json::object_t logEntry;
27639c11a172SVijay Lobo             logEntry["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
2764ef4c65b7SEd Tanous             logEntry["@odata.id"] = boost::urls::format(
2765253f11b8SEd Tanous                 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries/{}",
2766253f11b8SEd Tanous                 BMCWEB_REDFISH_SYSTEM_URI_NAME, logID);
276784afc48bSJason M. Bills             logEntry["Name"] = "CPU Crashdump";
276884afc48bSJason M. Bills             logEntry["Id"] = logID;
2769539d8c6bSEd Tanous             logEntry["EntryType"] = log_entry::LogEntryType::Oem;
277084afc48bSJason M. Bills             logEntry["AdditionalDataURI"] = std::move(crashdumpURI);
277184afc48bSJason M. Bills             logEntry["DiagnosticDataType"] = "OEM";
277284afc48bSJason M. Bills             logEntry["OEMDiagnosticDataType"] = "PECICrashdump";
277384afc48bSJason M. Bills             logEntry["Created"] = std::move(timestamp);
27742b20ef6eSJason M. Bills 
27752b20ef6eSJason M. Bills             // If logEntryJson references an array of LogEntry resources
27762b20ef6eSJason M. Bills             // ('Members' list), then push this as a new entry, otherwise set it
27772b20ef6eSJason M. Bills             // directly
27782b20ef6eSJason M. Bills             if (logEntryJson.is_array())
27792b20ef6eSJason M. Bills             {
27802b20ef6eSJason M. Bills                 logEntryJson.push_back(logEntry);
27812b20ef6eSJason M. Bills                 asyncResp->res.jsonValue["Members@odata.count"] =
27822b20ef6eSJason M. Bills                     logEntryJson.size();
27832b20ef6eSJason M. Bills             }
27842b20ef6eSJason M. Bills             else
27852b20ef6eSJason M. Bills             {
2786d405bb51SJason M. Bills                 logEntryJson.update(logEntry);
27872b20ef6eSJason M. Bills             }
2788e855dd28SJason M. Bills         };
2789d1bde9e5SKrzysztof Grobelny     sdbusplus::asio::getAllProperties(
2790d1bde9e5SKrzysztof Grobelny         *crow::connections::systemBus, crashdumpObject,
2791d1bde9e5SKrzysztof Grobelny         crashdumpPath + std::string("/") + logID, crashdumpInterface,
2792d1bde9e5SKrzysztof Grobelny         std::move(getStoredLogCallback));
2793e855dd28SJason M. Bills }
2794e855dd28SJason M. Bills 
27957e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpEntryCollection(App& app)
27961da66f75SEd Tanous {
27973946028dSAppaRao Puli     // Note: Deviated from redfish privilege registry for GET & HEAD
27983946028dSAppaRao Puli     // method for security reasons.
27991da66f75SEd Tanous     /**
28001da66f75SEd Tanous      * Functions triggers appropriate requests on DBus
28011da66f75SEd Tanous      */
28027e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
280322d268cbSEd Tanous                  "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/")
2804ed398213SEd Tanous         // This is incorrect, should be.
2805ed398213SEd Tanous         //.privileges(redfish::privileges::postLogEntryCollection)
2806432a890cSEd Tanous         .privileges({{"ConfigureComponents"}})
2807bd79bce8SPatrick Williams         .methods(
2808bd79bce8SPatrick Williams             boost::beast::http::verb::
2809bd79bce8SPatrick Williams                 get)([&app](const crow::Request& req,
281022d268cbSEd Tanous                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
281122d268cbSEd Tanous                             const std::string& systemName) {
28123ba00073SCarson Labrado             if (!redfish::setUpRedfishRoute(app, req, asyncResp))
281345ca1b86SEd Tanous             {
281445ca1b86SEd Tanous                 return;
281545ca1b86SEd Tanous             }
281625b54dbaSEd Tanous             if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
28177f3e84a1SEd Tanous             {
28187f3e84a1SEd Tanous                 // Option currently returns no systems.  TBD
28197f3e84a1SEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
28207f3e84a1SEd Tanous                                            systemName);
28217f3e84a1SEd Tanous                 return;
28227f3e84a1SEd Tanous             }
2823253f11b8SEd Tanous             if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
282422d268cbSEd Tanous             {
282522d268cbSEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
282622d268cbSEd Tanous                                            systemName);
282722d268cbSEd Tanous                 return;
282822d268cbSEd Tanous             }
282922d268cbSEd Tanous 
28307a1dbc48SGeorge Liu             constexpr std::array<std::string_view, 1> interfaces = {
28317a1dbc48SGeorge Liu                 crashdumpInterface};
28327a1dbc48SGeorge Liu             dbus::utility::getSubTreePaths(
28337a1dbc48SGeorge Liu                 "/", 0, interfaces,
28347a1dbc48SGeorge Liu                 [asyncResp](const boost::system::error_code& ec,
28352b20ef6eSJason M. Bills                             const std::vector<std::string>& resp) {
28361da66f75SEd Tanous                     if (ec)
28371da66f75SEd Tanous                     {
28381da66f75SEd Tanous                         if (ec.value() !=
28391da66f75SEd Tanous                             boost::system::errc::no_such_file_or_directory)
28401da66f75SEd Tanous                         {
284162598e31SEd Tanous                             BMCWEB_LOG_DEBUG("failed to get entries ec: {}",
284262598e31SEd Tanous                                              ec.message());
2843f12894f8SJason M. Bills                             messages::internalError(asyncResp->res);
28441da66f75SEd Tanous                             return;
28451da66f75SEd Tanous                         }
28461da66f75SEd Tanous                     }
2847e1f26343SJason M. Bills                     asyncResp->res.jsonValue["@odata.type"] =
28481da66f75SEd Tanous                         "#LogEntryCollection.LogEntryCollection";
2849253f11b8SEd Tanous                     asyncResp->res.jsonValue["@odata.id"] = std::format(
2850253f11b8SEd Tanous                         "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries",
2851253f11b8SEd Tanous                         BMCWEB_REDFISH_SYSTEM_URI_NAME);
2852bd79bce8SPatrick Williams                     asyncResp->res.jsonValue["Name"] =
2853bd79bce8SPatrick Williams                         "Open BMC Crashdump Entries";
2854e1f26343SJason M. Bills                     asyncResp->res.jsonValue["Description"] =
2855424c4176SJason M. Bills                         "Collection of Crashdump Entries";
2856bd79bce8SPatrick Williams                     asyncResp->res.jsonValue["Members"] =
2857bd79bce8SPatrick Williams                         nlohmann::json::array();
2858a2dd60a6SBrandon Kim                     asyncResp->res.jsonValue["Members@odata.count"] = 0;
28592b20ef6eSJason M. Bills 
28602b20ef6eSJason M. Bills                     for (const std::string& path : resp)
28611da66f75SEd Tanous                     {
28622b20ef6eSJason M. Bills                         const sdbusplus::message::object_path objPath(path);
2863e855dd28SJason M. Bills                         // Get the log ID
28642b20ef6eSJason M. Bills                         std::string logID = objPath.filename();
28652b20ef6eSJason M. Bills                         if (logID.empty())
28661da66f75SEd Tanous                         {
2867e855dd28SJason M. Bills                             continue;
28681da66f75SEd Tanous                         }
2869e855dd28SJason M. Bills                         // Add the log entry to the array
28702b20ef6eSJason M. Bills                         logCrashdumpEntry(asyncResp, logID,
28712b20ef6eSJason M. Bills                                           asyncResp->res.jsonValue["Members"]);
28721da66f75SEd Tanous                     }
28737a1dbc48SGeorge Liu                 });
28747e860f15SJohn Edward Broadbent         });
28751da66f75SEd Tanous }
28761da66f75SEd Tanous 
28777e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpEntry(App& app)
28781da66f75SEd Tanous {
28793946028dSAppaRao Puli     // Note: Deviated from redfish privilege registry for GET & HEAD
28803946028dSAppaRao Puli     // method for security reasons.
28811da66f75SEd Tanous 
28827e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
288322d268cbSEd Tanous         app, "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/<str>/")
2884ed398213SEd Tanous         // this is incorrect, should be
2885ed398213SEd Tanous         // .privileges(redfish::privileges::getLogEntry)
2886432a890cSEd Tanous         .privileges({{"ConfigureComponents"}})
28877e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
288845ca1b86SEd Tanous             [&app](const crow::Request& req,
28897e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
289022d268cbSEd Tanous                    const std::string& systemName, const std::string& param) {
28913ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
289245ca1b86SEd Tanous                 {
289345ca1b86SEd Tanous                     return;
289445ca1b86SEd Tanous                 }
289525b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
28967f3e84a1SEd Tanous                 {
28977f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
28987f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
28997f3e84a1SEd Tanous                                                systemName);
29007f3e84a1SEd Tanous                     return;
29017f3e84a1SEd Tanous                 }
2902253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
290322d268cbSEd Tanous                 {
290422d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
290522d268cbSEd Tanous                                                systemName);
290622d268cbSEd Tanous                     return;
290722d268cbSEd Tanous                 }
29087e860f15SJohn Edward Broadbent                 const std::string& logID = param;
2909e855dd28SJason M. Bills                 logCrashdumpEntry(asyncResp, logID, asyncResp->res.jsonValue);
29107e860f15SJohn Edward Broadbent             });
2911e855dd28SJason M. Bills }
2912e855dd28SJason M. Bills 
29137e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpFile(App& app)
2914e855dd28SJason M. Bills {
29153946028dSAppaRao Puli     // Note: Deviated from redfish privilege registry for GET & HEAD
29163946028dSAppaRao Puli     // method for security reasons.
29177e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
29187e860f15SJohn Edward Broadbent         app,
291922d268cbSEd Tanous         "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/<str>/<str>/")
2920ed398213SEd Tanous         .privileges(redfish::privileges::getLogEntry)
29217e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
2922a4ce114aSNan Zhou             [](const crow::Request& req,
29237e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
292422d268cbSEd Tanous                const std::string& systemName, const std::string& logID,
292522d268cbSEd Tanous                const std::string& fileName) {
2926bd79bce8SPatrick Williams                 // Do not call getRedfishRoute here since the crashdump file is
2927bd79bce8SPatrick Williams                 // not a Redfish resource.
292822d268cbSEd Tanous 
292925b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
29307f3e84a1SEd Tanous                 {
29317f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
29327f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
29337f3e84a1SEd Tanous                                                systemName);
29347f3e84a1SEd Tanous                     return;
29357f3e84a1SEd Tanous                 }
2936253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
293722d268cbSEd Tanous                 {
293822d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
293922d268cbSEd Tanous                                                systemName);
294022d268cbSEd Tanous                     return;
294122d268cbSEd Tanous                 }
294222d268cbSEd Tanous 
2943043a0536SJohnathan Mantey                 auto getStoredLogCallback =
2944bd79bce8SPatrick Williams                     [asyncResp, logID, fileName,
2945bd79bce8SPatrick Williams                      url(boost::urls::url(req.url()))](
29465e7e2dc5SEd Tanous                         const boost::system::error_code& ec,
2947bd79bce8SPatrick Williams                         const std::vector<std::pair<
2948bd79bce8SPatrick Williams                             std::string, dbus::utility::DbusVariantType>>&
29497e860f15SJohn Edward Broadbent                             resp) {
29501da66f75SEd Tanous                         if (ec)
29511da66f75SEd Tanous                         {
2952bd79bce8SPatrick Williams                             BMCWEB_LOG_DEBUG("failed to get log ec: {}",
2953bd79bce8SPatrick Williams                                              ec.message());
2954f12894f8SJason M. Bills                             messages::internalError(asyncResp->res);
29551da66f75SEd Tanous                             return;
29561da66f75SEd Tanous                         }
2957e855dd28SJason M. Bills 
2958043a0536SJohnathan Mantey                         std::string dbusFilename{};
2959043a0536SJohnathan Mantey                         std::string dbusTimestamp{};
2960043a0536SJohnathan Mantey                         std::string dbusFilepath{};
2961043a0536SJohnathan Mantey 
2962bd79bce8SPatrick Williams                         parseCrashdumpParameters(resp, dbusFilename,
2963bd79bce8SPatrick Williams                                                  dbusTimestamp, dbusFilepath);
2964043a0536SJohnathan Mantey 
2965043a0536SJohnathan Mantey                         if (dbusFilename.empty() || dbusTimestamp.empty() ||
2966043a0536SJohnathan Mantey                             dbusFilepath.empty())
29671da66f75SEd Tanous                         {
2968bd79bce8SPatrick Williams                             messages::resourceNotFound(asyncResp->res,
2969bd79bce8SPatrick Williams                                                        "LogEntry", logID);
29701da66f75SEd Tanous                             return;
29711da66f75SEd Tanous                         }
2972e855dd28SJason M. Bills 
2973043a0536SJohnathan Mantey                         // Verify the file name parameter is correct
2974043a0536SJohnathan Mantey                         if (fileName != dbusFilename)
2975043a0536SJohnathan Mantey                         {
2976bd79bce8SPatrick Williams                             messages::resourceNotFound(asyncResp->res,
2977bd79bce8SPatrick Williams                                                        "LogEntry", logID);
2978043a0536SJohnathan Mantey                             return;
2979043a0536SJohnathan Mantey                         }
2980043a0536SJohnathan Mantey 
2981d51c61b4SMyung Bae                         if (asyncResp->res.openFile(dbusFilepath) !=
2982d51c61b4SMyung Bae                             crow::OpenCode::Success)
2983043a0536SJohnathan Mantey                         {
2984bd79bce8SPatrick Williams                             messages::resourceNotFound(asyncResp->res,
2985bd79bce8SPatrick Williams                                                        "LogEntry", logID);
2986043a0536SJohnathan Mantey                             return;
2987043a0536SJohnathan Mantey                         }
2988043a0536SJohnathan Mantey 
29897e860f15SJohn Edward Broadbent                         // Configure this to be a file download when accessed
29907e860f15SJohn Edward Broadbent                         // from a browser
2991d9f6c621SEd Tanous                         asyncResp->res.addHeader(
2992bd79bce8SPatrick Williams                             boost::beast::http::field::content_disposition,
2993bd79bce8SPatrick Williams                             "attachment");
29941da66f75SEd Tanous                     };
2995d1bde9e5SKrzysztof Grobelny                 sdbusplus::asio::getAllProperties(
2996d1bde9e5SKrzysztof Grobelny                     *crow::connections::systemBus, crashdumpObject,
2997bd79bce8SPatrick Williams                     crashdumpPath + std::string("/") + logID,
2998bd79bce8SPatrick Williams                     crashdumpInterface, std::move(getStoredLogCallback));
29997e860f15SJohn Edward Broadbent             });
30001da66f75SEd Tanous }
30011da66f75SEd Tanous 
3002c5a4c82aSJason M. Bills enum class OEMDiagnosticType
3003c5a4c82aSJason M. Bills {
3004c5a4c82aSJason M. Bills     onDemand,
3005c5a4c82aSJason M. Bills     telemetry,
3006c5a4c82aSJason M. Bills     invalid,
3007c5a4c82aSJason M. Bills };
3008c5a4c82aSJason M. Bills 
300926ccae32SEd Tanous inline OEMDiagnosticType getOEMDiagnosticType(std::string_view oemDiagStr)
3010c5a4c82aSJason M. Bills {
3011c5a4c82aSJason M. Bills     if (oemDiagStr == "OnDemand")
3012c5a4c82aSJason M. Bills     {
3013c5a4c82aSJason M. Bills         return OEMDiagnosticType::onDemand;
3014c5a4c82aSJason M. Bills     }
3015c5a4c82aSJason M. Bills     if (oemDiagStr == "Telemetry")
3016c5a4c82aSJason M. Bills     {
3017c5a4c82aSJason M. Bills         return OEMDiagnosticType::telemetry;
3018c5a4c82aSJason M. Bills     }
3019c5a4c82aSJason M. Bills 
3020c5a4c82aSJason M. Bills     return OEMDiagnosticType::invalid;
3021c5a4c82aSJason M. Bills }
3022c5a4c82aSJason M. Bills 
30237e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpCollect(App& app)
30241da66f75SEd Tanous {
30253946028dSAppaRao Puli     // Note: Deviated from redfish privilege registry for GET & HEAD
30263946028dSAppaRao Puli     // method for security reasons.
30270fda0f12SGeorge Liu     BMCWEB_ROUTE(
30280fda0f12SGeorge Liu         app,
302922d268cbSEd Tanous         "/redfish/v1/Systems/<str>/LogServices/Crashdump/Actions/LogService.CollectDiagnosticData/")
3030ed398213SEd Tanous         // The below is incorrect;  Should be ConfigureManager
3031ed398213SEd Tanous         //.privileges(redfish::privileges::postLogService)
3032432a890cSEd Tanous         .privileges({{"ConfigureComponents"}})
3033002d39b4SEd Tanous         .methods(boost::beast::http::verb::post)(
3034002d39b4SEd Tanous             [&app](const crow::Request& req,
303522d268cbSEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
303622d268cbSEd Tanous                    const std::string& systemName) {
30373ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
303845ca1b86SEd Tanous                 {
303945ca1b86SEd Tanous                     return;
304045ca1b86SEd Tanous                 }
304122d268cbSEd Tanous 
304225b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
30437f3e84a1SEd Tanous                 {
30447f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
30457f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
30467f3e84a1SEd Tanous                                                systemName);
30477f3e84a1SEd Tanous                     return;
30487f3e84a1SEd Tanous                 }
3049253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
305022d268cbSEd Tanous                 {
305122d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
305222d268cbSEd Tanous                                                systemName);
305322d268cbSEd Tanous                     return;
305422d268cbSEd Tanous                 }
305522d268cbSEd Tanous 
30568e6c099aSJason M. Bills                 std::string diagnosticDataType;
30578e6c099aSJason M. Bills                 std::string oemDiagnosticDataType;
305815ed6780SWilly Tu                 if (!redfish::json_util::readJsonAction(
3059bd79bce8SPatrick Williams                         req, asyncResp->res, "DiagnosticDataType",
3060bd79bce8SPatrick Williams                         diagnosticDataType, "OEMDiagnosticDataType",
3061bd79bce8SPatrick Williams                         oemDiagnosticDataType))
30628e6c099aSJason M. Bills                 {
30638e6c099aSJason M. Bills                     return;
30648e6c099aSJason M. Bills                 }
30658e6c099aSJason M. Bills 
30668e6c099aSJason M. Bills                 if (diagnosticDataType != "OEM")
30678e6c099aSJason M. Bills                 {
306862598e31SEd Tanous                     BMCWEB_LOG_ERROR(
306962598e31SEd Tanous                         "Only OEM DiagnosticDataType supported for Crashdump");
30708e6c099aSJason M. Bills                     messages::actionParameterValueFormatError(
3071bd79bce8SPatrick Williams                         asyncResp->res, diagnosticDataType,
3072bd79bce8SPatrick Williams                         "DiagnosticDataType", "CollectDiagnosticData");
30738e6c099aSJason M. Bills                     return;
30748e6c099aSJason M. Bills                 }
30758e6c099aSJason M. Bills 
3076c5a4c82aSJason M. Bills                 OEMDiagnosticType oemDiagType =
3077c5a4c82aSJason M. Bills                     getOEMDiagnosticType(oemDiagnosticDataType);
3078c5a4c82aSJason M. Bills 
3079c5a4c82aSJason M. Bills                 std::string iface;
3080c5a4c82aSJason M. Bills                 std::string method;
3081c5a4c82aSJason M. Bills                 std::string taskMatchStr;
3082c5a4c82aSJason M. Bills                 if (oemDiagType == OEMDiagnosticType::onDemand)
3083c5a4c82aSJason M. Bills                 {
3084c5a4c82aSJason M. Bills                     iface = crashdumpOnDemandInterface;
3085c5a4c82aSJason M. Bills                     method = "GenerateOnDemandLog";
3086bd79bce8SPatrick Williams                     taskMatchStr =
3087bd79bce8SPatrick Williams                         "type='signal',"
3088c5a4c82aSJason M. Bills                         "interface='org.freedesktop.DBus.Properties',"
3089c5a4c82aSJason M. Bills                         "member='PropertiesChanged',"
3090c5a4c82aSJason M. Bills                         "arg0namespace='com.intel.crashdump'";
3091c5a4c82aSJason M. Bills                 }
3092c5a4c82aSJason M. Bills                 else if (oemDiagType == OEMDiagnosticType::telemetry)
3093c5a4c82aSJason M. Bills                 {
3094c5a4c82aSJason M. Bills                     iface = crashdumpTelemetryInterface;
3095c5a4c82aSJason M. Bills                     method = "GenerateTelemetryLog";
3096bd79bce8SPatrick Williams                     taskMatchStr =
3097bd79bce8SPatrick Williams                         "type='signal',"
3098c5a4c82aSJason M. Bills                         "interface='org.freedesktop.DBus.Properties',"
3099c5a4c82aSJason M. Bills                         "member='PropertiesChanged',"
3100c5a4c82aSJason M. Bills                         "arg0namespace='com.intel.crashdump'";
3101c5a4c82aSJason M. Bills                 }
3102c5a4c82aSJason M. Bills                 else
3103c5a4c82aSJason M. Bills                 {
310462598e31SEd Tanous                     BMCWEB_LOG_ERROR("Unsupported OEMDiagnosticDataType: {}",
310562598e31SEd Tanous                                      oemDiagnosticDataType);
3106c5a4c82aSJason M. Bills                     messages::actionParameterValueFormatError(
3107bd79bce8SPatrick Williams                         asyncResp->res, oemDiagnosticDataType,
3108bd79bce8SPatrick Williams                         "OEMDiagnosticDataType", "CollectDiagnosticData");
3109c5a4c82aSJason M. Bills                     return;
3110c5a4c82aSJason M. Bills                 }
3111c5a4c82aSJason M. Bills 
3112c5a4c82aSJason M. Bills                 auto collectCrashdumpCallback =
3113c5a4c82aSJason M. Bills                     [asyncResp, payload(task::Payload(req)),
31145e7e2dc5SEd Tanous                      taskMatchStr](const boost::system::error_code& ec,
311598be3e39SEd Tanous                                    const std::string&) mutable {
31161da66f75SEd Tanous                         if (ec)
31171da66f75SEd Tanous                         {
3118bd79bce8SPatrick Williams                             if (ec.value() ==
3119bd79bce8SPatrick Williams                                 boost::system::errc::operation_not_supported)
31201da66f75SEd Tanous                             {
3121f12894f8SJason M. Bills                                 messages::resourceInStandby(asyncResp->res);
31221da66f75SEd Tanous                             }
3123bd79bce8SPatrick Williams                             else if (ec.value() == boost::system::errc::
3124bd79bce8SPatrick Williams                                                        device_or_resource_busy)
31254363d3b2SJason M. Bills                             {
3126bd79bce8SPatrick Williams                                 messages::serviceTemporarilyUnavailable(
3127bd79bce8SPatrick Williams                                     asyncResp->res, "60");
31284363d3b2SJason M. Bills                             }
31291da66f75SEd Tanous                             else
31301da66f75SEd Tanous                             {
3131f12894f8SJason M. Bills                                 messages::internalError(asyncResp->res);
31321da66f75SEd Tanous                             }
31331da66f75SEd Tanous                             return;
31341da66f75SEd Tanous                         }
3135bd79bce8SPatrick Williams                         std::shared_ptr<task::TaskData> task =
3136bd79bce8SPatrick Williams                             task::TaskData::createTask(
3137bd79bce8SPatrick Williams                                 [](const boost::system::error_code& ec2,
3138bd79bce8SPatrick Williams                                    sdbusplus::message_t&,
3139bd79bce8SPatrick Williams                                    const std::shared_ptr<task::TaskData>&
3140bd79bce8SPatrick Williams                                        taskData) {
31418b24275dSEd Tanous                                     if (!ec2)
314266afe4faSJames Feist                                     {
3143bd79bce8SPatrick Williams                                         taskData->messages.emplace_back(
3144bd79bce8SPatrick Williams                                             messages::taskCompletedOK(
3145bd79bce8SPatrick Williams                                                 std::to_string(
3146bd79bce8SPatrick Williams                                                     taskData->index)));
3147831d6b09SJames Feist                                         taskData->state = "Completed";
314866afe4faSJames Feist                                     }
314932898ceaSJames Feist                                     return task::completed;
315066afe4faSJames Feist                                 },
3151c5a4c82aSJason M. Bills                                 taskMatchStr);
3152c5a4c82aSJason M. Bills 
315346229577SJames Feist                         task->startTimer(std::chrono::minutes(5));
315446229577SJames Feist                         task->populateResp(asyncResp->res);
315598be3e39SEd Tanous                         task->payload.emplace(std::move(payload));
31561da66f75SEd Tanous                     };
31578e6c099aSJason M. Bills 
31581da66f75SEd Tanous                 crow::connections::systemBus->async_method_call(
3159bd79bce8SPatrick Williams                     std::move(collectCrashdumpCallback), crashdumpObject,
3160bd79bce8SPatrick Williams                     crashdumpPath, iface, method);
31617e860f15SJohn Edward Broadbent             });
31626eda7685SKenny L. Ku }
31636eda7685SKenny L. Ku 
3164599b9af3SAlexander Hansen inline void dBusLogServiceActionsClear(
3165599b9af3SAlexander Hansen     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
3166599b9af3SAlexander Hansen {
3167599b9af3SAlexander Hansen     BMCWEB_LOG_DEBUG("Do delete all entries.");
3168599b9af3SAlexander Hansen 
3169599b9af3SAlexander Hansen     // Process response from Logging service.
3170599b9af3SAlexander Hansen     auto respHandler = [asyncResp](const boost::system::error_code& ec) {
3171599b9af3SAlexander Hansen         BMCWEB_LOG_DEBUG("doClearLog resp_handler callback: Done");
3172599b9af3SAlexander Hansen         if (ec)
3173599b9af3SAlexander Hansen         {
3174599b9af3SAlexander Hansen             // TODO Handle for specific error code
3175599b9af3SAlexander Hansen             BMCWEB_LOG_ERROR("doClearLog resp_handler got error {}", ec);
3176599b9af3SAlexander Hansen             asyncResp->res.result(
3177599b9af3SAlexander Hansen                 boost::beast::http::status::internal_server_error);
3178599b9af3SAlexander Hansen             return;
3179599b9af3SAlexander Hansen         }
3180599b9af3SAlexander Hansen 
3181599b9af3SAlexander Hansen         asyncResp->res.result(boost::beast::http::status::no_content);
3182599b9af3SAlexander Hansen     };
3183599b9af3SAlexander Hansen 
3184599b9af3SAlexander Hansen     // Make call to Logging service to request Clear Log
3185599b9af3SAlexander Hansen     crow::connections::systemBus->async_method_call(
3186599b9af3SAlexander Hansen         respHandler, "xyz.openbmc_project.Logging",
3187599b9af3SAlexander Hansen         "/xyz/openbmc_project/logging",
3188599b9af3SAlexander Hansen         "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
3189599b9af3SAlexander Hansen }
3190599b9af3SAlexander Hansen 
3191cb92c03bSAndrew Geissler /**
3192cb92c03bSAndrew Geissler  * DBusLogServiceActionsClear class supports POST method for ClearLog action.
3193cb92c03bSAndrew Geissler  */
31947e860f15SJohn Edward Broadbent inline void requestRoutesDBusLogServiceActionsClear(App& app)
3195cb92c03bSAndrew Geissler {
3196cb92c03bSAndrew Geissler     /**
3197cb92c03bSAndrew Geissler      * Function handles POST method request.
3198cb92c03bSAndrew Geissler      * The Clear Log actions does not require any parameter.The action deletes
3199cb92c03bSAndrew Geissler      * all entries found in the Entries collection for this Log Service.
3200cb92c03bSAndrew Geissler      */
32017e860f15SJohn Edward Broadbent 
32020fda0f12SGeorge Liu     BMCWEB_ROUTE(
32030fda0f12SGeorge Liu         app,
320422d268cbSEd Tanous         "/redfish/v1/Systems/<str>/LogServices/EventLog/Actions/LogService.ClearLog/")
3205ed398213SEd Tanous         .privileges(redfish::privileges::postLogService)
32067e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
320745ca1b86SEd Tanous             [&app](const crow::Request& req,
320822d268cbSEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
320922d268cbSEd Tanous                    const std::string& systemName) {
32103ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
321145ca1b86SEd Tanous                 {
321245ca1b86SEd Tanous                     return;
321345ca1b86SEd Tanous                 }
321425b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
32157f3e84a1SEd Tanous                 {
32167f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
32177f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
32187f3e84a1SEd Tanous                                                systemName);
32197f3e84a1SEd Tanous                     return;
32207f3e84a1SEd Tanous                 }
3221253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
322222d268cbSEd Tanous                 {
322322d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
322422d268cbSEd Tanous                                                systemName);
322522d268cbSEd Tanous                     return;
322622d268cbSEd Tanous                 }
3227599b9af3SAlexander Hansen                 dBusLogServiceActionsClear(asyncResp);
32287e860f15SJohn Edward Broadbent             });
3229cb92c03bSAndrew Geissler }
3230a3316fc6SZhikuiRen 
32311da66f75SEd Tanous } // namespace redfish
3232