xref: /openbmc/bmcweb/features/redfish/lib/log_services.hpp (revision 29e2bdd7b4418dc7d6c48ca701eb2a3832aab090)
140e9b92eSEd Tanous // SPDX-License-Identifier: Apache-2.0
240e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright OpenBMC Authors
340e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright 2018 Intel Corporation
41da66f75SEd Tanous #pragma once
51da66f75SEd Tanous 
6d7857201SEd Tanous #include "bmcweb_config.h"
7d7857201SEd Tanous 
83ccb3adbSEd Tanous #include "app.hpp"
9d7857201SEd Tanous #include "async_resp.hpp"
10d7857201SEd Tanous #include "dbus_singleton.hpp"
117a1dbc48SGeorge Liu #include "dbus_utility.hpp"
123ccb3adbSEd Tanous #include "error_messages.hpp"
1368dd075aSAsmitha Karunanithi #include "generated/enums/log_entry.hpp"
14539d8c6bSEd Tanous #include "generated/enums/log_service.hpp"
15d7857201SEd Tanous #include "http_body.hpp"
16d7857201SEd Tanous #include "http_request.hpp"
17d7857201SEd Tanous #include "http_response.hpp"
18647b3cdcSGeorge Liu #include "http_utility.hpp"
19b7028ebfSSpencer Ku #include "human_sort.hpp"
20d7857201SEd Tanous #include "logging.hpp"
213ccb3adbSEd Tanous #include "query.hpp"
224851d45dSJason M. Bills #include "registries.hpp"
233ccb3adbSEd Tanous #include "registries/privilege_registry.hpp"
24d7857201SEd Tanous #include "str_utility.hpp"
2546229577SJames Feist #include "task.hpp"
265b90429aSEd Tanous #include "task_messages.hpp"
27262dcc1cSAlexander Hansen #include "utils/dbus_event_log_entry.hpp"
283ccb3adbSEd Tanous #include "utils/dbus_utils.hpp"
295b90429aSEd Tanous #include "utils/json_utils.hpp"
30d7857201SEd Tanous #include "utils/query_param.hpp"
313ccb3adbSEd Tanous #include "utils/time_utils.hpp"
321da66f75SEd Tanous 
33d7857201SEd Tanous #include <asm-generic/errno.h>
34d7857201SEd Tanous #include <systemd/sd-bus.h>
358e31778eSAsmitha Karunanithi #include <tinyxml2.h>
36400fd1fbSAdriana Kobylak #include <unistd.h>
37e1f26343SJason M. Bills 
38d7857201SEd Tanous #include <boost/beast/http/field.hpp>
39d7857201SEd Tanous #include <boost/beast/http/status.hpp>
4007c8c20dSEd Tanous #include <boost/beast/http/verb.hpp>
411ddcf01aSJason M. Bills #include <boost/system/linux_error.hpp>
42ef4c65b7SEd Tanous #include <boost/url/format.hpp>
43d7857201SEd Tanous #include <boost/url/url.hpp>
44d7857201SEd Tanous #include <sdbusplus/message.hpp>
45d7857201SEd Tanous #include <sdbusplus/message/native_types.hpp>
46d1bde9e5SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp>
471214b7e7SGunnar Mills 
48d7857201SEd Tanous #include <algorithm>
497a1dbc48SGeorge Liu #include <array>
50d7857201SEd Tanous #include <chrono>
51b5f288d2SAbhilash Raju #include <cstddef>
52d7857201SEd Tanous #include <cstdint>
53d7857201SEd Tanous #include <cstdio>
54d7857201SEd Tanous #include <ctime>
554418c7f0SJames Feist #include <filesystem>
56d7857201SEd Tanous #include <format>
57d7857201SEd Tanous #include <fstream>
58d7857201SEd Tanous #include <functional>
59d7857201SEd Tanous #include <iomanip>
6018f8f608SEd Tanous #include <iterator>
61d7857201SEd Tanous #include <memory>
6275710de2SXiaochao Ma #include <optional>
633544d2a7SEd Tanous #include <ranges>
6426702d01SEd Tanous #include <span>
65d7857201SEd Tanous #include <sstream>
6618f8f608SEd Tanous #include <string>
67cd225da8SJason M. Bills #include <string_view>
68d7857201SEd Tanous #include <system_error>
69d7857201SEd Tanous #include <utility>
70abf2add6SEd Tanous #include <variant>
71d7857201SEd Tanous #include <vector>
721da66f75SEd Tanous 
731da66f75SEd Tanous namespace redfish
741da66f75SEd Tanous {
751da66f75SEd Tanous 
7689492a15SPatrick Williams constexpr const char* crashdumpObject = "com.intel.crashdump";
7789492a15SPatrick Williams constexpr const char* crashdumpPath = "/com/intel/crashdump";
7889492a15SPatrick Williams constexpr const char* crashdumpInterface = "com.intel.crashdump";
7989492a15SPatrick Williams constexpr const char* deleteAllInterface =
805b61b5e8SJason M. Bills     "xyz.openbmc_project.Collection.DeleteAll";
8189492a15SPatrick Williams constexpr const char* crashdumpOnDemandInterface =
82424c4176SJason M. Bills     "com.intel.crashdump.OnDemand";
8389492a15SPatrick Williams constexpr const char* crashdumpTelemetryInterface =
846eda7685SKenny L. Ku     "com.intel.crashdump.Telemetry";
851da66f75SEd Tanous 
868e31778eSAsmitha Karunanithi enum class DumpCreationProgress
878e31778eSAsmitha Karunanithi {
888e31778eSAsmitha Karunanithi     DUMP_CREATE_SUCCESS,
898e31778eSAsmitha Karunanithi     DUMP_CREATE_FAILED,
908e31778eSAsmitha Karunanithi     DUMP_CREATE_INPROGRESS
918e31778eSAsmitha Karunanithi };
928e31778eSAsmitha Karunanithi 
93cb92c03bSAndrew Geissler inline std::string translateSeverityDbusToRedfish(const std::string& s)
94cb92c03bSAndrew Geissler {
95d4d25793SEd Tanous     if ((s == "xyz.openbmc_project.Logging.Entry.Level.Alert") ||
96d4d25793SEd Tanous         (s == "xyz.openbmc_project.Logging.Entry.Level.Critical") ||
97d4d25793SEd Tanous         (s == "xyz.openbmc_project.Logging.Entry.Level.Emergency") ||
98d4d25793SEd Tanous         (s == "xyz.openbmc_project.Logging.Entry.Level.Error"))
99cb92c03bSAndrew Geissler     {
100cb92c03bSAndrew Geissler         return "Critical";
101cb92c03bSAndrew Geissler     }
1023174e4dfSEd Tanous     if ((s == "xyz.openbmc_project.Logging.Entry.Level.Debug") ||
103d4d25793SEd Tanous         (s == "xyz.openbmc_project.Logging.Entry.Level.Informational") ||
104d4d25793SEd Tanous         (s == "xyz.openbmc_project.Logging.Entry.Level.Notice"))
105cb92c03bSAndrew Geissler     {
106cb92c03bSAndrew Geissler         return "OK";
107cb92c03bSAndrew Geissler     }
1083174e4dfSEd Tanous     if (s == "xyz.openbmc_project.Logging.Entry.Level.Warning")
109cb92c03bSAndrew Geissler     {
110cb92c03bSAndrew Geissler         return "Warning";
111cb92c03bSAndrew Geissler     }
112cb92c03bSAndrew Geissler     return "";
113cb92c03bSAndrew Geissler }
114cb92c03bSAndrew Geissler 
1159017faf2SAbhishek Patel inline std::optional<bool> getProviderNotifyAction(const std::string& notify)
1169017faf2SAbhishek Patel {
1179017faf2SAbhishek Patel     std::optional<bool> notifyAction;
1189017faf2SAbhishek Patel     if (notify == "xyz.openbmc_project.Logging.Entry.Notify.Notify")
1199017faf2SAbhishek Patel     {
1209017faf2SAbhishek Patel         notifyAction = true;
1219017faf2SAbhishek Patel     }
1229017faf2SAbhishek Patel     else if (notify == "xyz.openbmc_project.Logging.Entry.Notify.Inhibit")
1239017faf2SAbhishek Patel     {
1249017faf2SAbhishek Patel         notifyAction = false;
1259017faf2SAbhishek Patel     }
1269017faf2SAbhishek Patel 
1279017faf2SAbhishek Patel     return notifyAction;
1289017faf2SAbhishek Patel }
1299017faf2SAbhishek Patel 
13018f8f608SEd Tanous inline std::string getDumpPath(std::string_view dumpType)
13118f8f608SEd Tanous {
13218f8f608SEd Tanous     std::string dbusDumpPath = "/xyz/openbmc_project/dump/";
13318f8f608SEd Tanous     std::ranges::transform(dumpType, std::back_inserter(dbusDumpPath),
13418f8f608SEd Tanous                            bmcweb::asciiToLower);
13518f8f608SEd Tanous 
13618f8f608SEd Tanous     return dbusDumpPath;
13718f8f608SEd Tanous }
13818f8f608SEd Tanous 
139055713e4SEd Tanous inline bool getUniqueEntryID(const std::string& logEntry, std::string& entryID,
140e85d6b16SJason M. Bills                              const bool firstEntry = true)
14195820184SJason M. Bills {
142271584abSEd Tanous     static time_t prevTs = 0;
14395820184SJason M. Bills     static int index = 0;
144e85d6b16SJason M. Bills     if (firstEntry)
145e85d6b16SJason M. Bills     {
146e85d6b16SJason M. Bills         prevTs = 0;
147e85d6b16SJason M. Bills     }
148e85d6b16SJason M. Bills 
14995820184SJason M. Bills     // Get the entry timestamp
150271584abSEd Tanous     std::time_t curTs = 0;
15195820184SJason M. Bills     std::tm timeStruct = {};
15295820184SJason M. Bills     std::istringstream entryStream(logEntry);
15395820184SJason M. Bills     if (entryStream >> std::get_time(&timeStruct, "%Y-%m-%dT%H:%M:%S"))
15495820184SJason M. Bills     {
15595820184SJason M. Bills         curTs = std::mktime(&timeStruct);
15695820184SJason M. Bills     }
15795820184SJason M. Bills     // If the timestamp isn't unique, increment the index
15895820184SJason M. Bills     if (curTs == prevTs)
15995820184SJason M. Bills     {
16095820184SJason M. Bills         index++;
16195820184SJason M. Bills     }
16295820184SJason M. Bills     else
16395820184SJason M. Bills     {
16495820184SJason M. Bills         // Otherwise, reset it
16595820184SJason M. Bills         index = 0;
16695820184SJason M. Bills     }
16795820184SJason M. Bills     // Save the timestamp
16895820184SJason M. Bills     prevTs = curTs;
16995820184SJason M. Bills 
17095820184SJason M. Bills     entryID = std::to_string(curTs);
17195820184SJason M. Bills     if (index > 0)
17295820184SJason M. Bills     {
17395820184SJason M. Bills         entryID += "_" + std::to_string(index);
17495820184SJason M. Bills     }
17595820184SJason M. Bills     return true;
17695820184SJason M. Bills }
17795820184SJason M. Bills 
178504af5a0SPatrick Williams inline bool getRedfishLogFiles(
179504af5a0SPatrick Williams     std::vector<std::filesystem::path>& redfishLogFiles)
18095820184SJason M. Bills {
18195820184SJason M. Bills     static const std::filesystem::path redfishLogDir = "/var/log";
18295820184SJason M. Bills     static const std::string redfishLogFilename = "redfish";
18395820184SJason M. Bills 
18495820184SJason M. Bills     // Loop through the directory looking for redfish log files
18595820184SJason M. Bills     for (const std::filesystem::directory_entry& dirEnt :
18695820184SJason M. Bills          std::filesystem::directory_iterator(redfishLogDir))
18795820184SJason M. Bills     {
18895820184SJason M. Bills         // If we find a redfish log file, save the path
18995820184SJason M. Bills         std::string filename = dirEnt.path().filename();
19011ba3979SEd Tanous         if (filename.starts_with(redfishLogFilename))
19195820184SJason M. Bills         {
19295820184SJason M. Bills             redfishLogFiles.emplace_back(redfishLogDir / filename);
19395820184SJason M. Bills         }
19495820184SJason M. Bills     }
19595820184SJason M. Bills     // As the log files rotate, they are appended with a ".#" that is higher for
19695820184SJason M. Bills     // the older logs. Since we don't expect more than 10 log files, we
19795820184SJason M. Bills     // can just sort the list to get them in order from newest to oldest
1983544d2a7SEd Tanous     std::ranges::sort(redfishLogFiles);
19995820184SJason M. Bills 
20095820184SJason M. Bills     return !redfishLogFiles.empty();
20195820184SJason M. Bills }
20295820184SJason M. Bills 
203504af5a0SPatrick Williams inline log_entry::OriginatorTypes mapDbusOriginatorTypeToRedfish(
204504af5a0SPatrick Williams     const std::string& originatorType)
20568dd075aSAsmitha Karunanithi {
20668dd075aSAsmitha Karunanithi     if (originatorType ==
20768dd075aSAsmitha Karunanithi         "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Client")
20868dd075aSAsmitha Karunanithi     {
20968dd075aSAsmitha Karunanithi         return log_entry::OriginatorTypes::Client;
21068dd075aSAsmitha Karunanithi     }
21168dd075aSAsmitha Karunanithi     if (originatorType ==
21268dd075aSAsmitha Karunanithi         "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Internal")
21368dd075aSAsmitha Karunanithi     {
21468dd075aSAsmitha Karunanithi         return log_entry::OriginatorTypes::Internal;
21568dd075aSAsmitha Karunanithi     }
21668dd075aSAsmitha Karunanithi     if (originatorType ==
21768dd075aSAsmitha Karunanithi         "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.SupportingService")
21868dd075aSAsmitha Karunanithi     {
21968dd075aSAsmitha Karunanithi         return log_entry::OriginatorTypes::SupportingService;
22068dd075aSAsmitha Karunanithi     }
22168dd075aSAsmitha Karunanithi     return log_entry::OriginatorTypes::Invalid;
22268dd075aSAsmitha Karunanithi }
22368dd075aSAsmitha Karunanithi 
224aefe3786SClaire Weinan inline void parseDumpEntryFromDbusObject(
2252d613eb6SJiaqing Zhao     const dbus::utility::ManagedObjectType::value_type& object,
226c6fecdabSClaire Weinan     std::string& dumpStatus, uint64_t& size, uint64_t& timestampUs,
22768dd075aSAsmitha Karunanithi     std::string& originatorId, log_entry::OriginatorTypes& originatorType,
228aefe3786SClaire Weinan     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
229aefe3786SClaire Weinan {
230aefe3786SClaire Weinan     for (const auto& interfaceMap : object.second)
231aefe3786SClaire Weinan     {
232aefe3786SClaire Weinan         if (interfaceMap.first == "xyz.openbmc_project.Common.Progress")
233aefe3786SClaire Weinan         {
234aefe3786SClaire Weinan             for (const auto& propertyMap : interfaceMap.second)
235aefe3786SClaire Weinan             {
236aefe3786SClaire Weinan                 if (propertyMap.first == "Status")
237aefe3786SClaire Weinan                 {
238aefe3786SClaire Weinan                     const auto* status =
239aefe3786SClaire Weinan                         std::get_if<std::string>(&propertyMap.second);
240aefe3786SClaire Weinan                     if (status == nullptr)
241aefe3786SClaire Weinan                     {
242aefe3786SClaire Weinan                         messages::internalError(asyncResp->res);
243aefe3786SClaire Weinan                         break;
244aefe3786SClaire Weinan                     }
245aefe3786SClaire Weinan                     dumpStatus = *status;
246aefe3786SClaire Weinan                 }
247aefe3786SClaire Weinan             }
248aefe3786SClaire Weinan         }
249aefe3786SClaire Weinan         else if (interfaceMap.first == "xyz.openbmc_project.Dump.Entry")
250aefe3786SClaire Weinan         {
251aefe3786SClaire Weinan             for (const auto& propertyMap : interfaceMap.second)
252aefe3786SClaire Weinan             {
253aefe3786SClaire Weinan                 if (propertyMap.first == "Size")
254aefe3786SClaire Weinan                 {
255aefe3786SClaire Weinan                     const auto* sizePtr =
256aefe3786SClaire Weinan                         std::get_if<uint64_t>(&propertyMap.second);
257aefe3786SClaire Weinan                     if (sizePtr == nullptr)
258aefe3786SClaire Weinan                     {
259aefe3786SClaire Weinan                         messages::internalError(asyncResp->res);
260aefe3786SClaire Weinan                         break;
261aefe3786SClaire Weinan                     }
262aefe3786SClaire Weinan                     size = *sizePtr;
263aefe3786SClaire Weinan                     break;
264aefe3786SClaire Weinan                 }
265aefe3786SClaire Weinan             }
266aefe3786SClaire Weinan         }
267aefe3786SClaire Weinan         else if (interfaceMap.first == "xyz.openbmc_project.Time.EpochTime")
268aefe3786SClaire Weinan         {
269aefe3786SClaire Weinan             for (const auto& propertyMap : interfaceMap.second)
270aefe3786SClaire Weinan             {
271aefe3786SClaire Weinan                 if (propertyMap.first == "Elapsed")
272aefe3786SClaire Weinan                 {
273aefe3786SClaire Weinan                     const uint64_t* usecsTimeStamp =
274aefe3786SClaire Weinan                         std::get_if<uint64_t>(&propertyMap.second);
275aefe3786SClaire Weinan                     if (usecsTimeStamp == nullptr)
276aefe3786SClaire Weinan                     {
277aefe3786SClaire Weinan                         messages::internalError(asyncResp->res);
278aefe3786SClaire Weinan                         break;
279aefe3786SClaire Weinan                     }
280c6fecdabSClaire Weinan                     timestampUs = *usecsTimeStamp;
281aefe3786SClaire Weinan                     break;
282aefe3786SClaire Weinan                 }
283aefe3786SClaire Weinan             }
284aefe3786SClaire Weinan         }
28568dd075aSAsmitha Karunanithi         else if (interfaceMap.first ==
28668dd075aSAsmitha Karunanithi                  "xyz.openbmc_project.Common.OriginatedBy")
28768dd075aSAsmitha Karunanithi         {
28868dd075aSAsmitha Karunanithi             for (const auto& propertyMap : interfaceMap.second)
28968dd075aSAsmitha Karunanithi             {
29068dd075aSAsmitha Karunanithi                 if (propertyMap.first == "OriginatorId")
29168dd075aSAsmitha Karunanithi                 {
29268dd075aSAsmitha Karunanithi                     const std::string* id =
29368dd075aSAsmitha Karunanithi                         std::get_if<std::string>(&propertyMap.second);
29468dd075aSAsmitha Karunanithi                     if (id == nullptr)
29568dd075aSAsmitha Karunanithi                     {
29668dd075aSAsmitha Karunanithi                         messages::internalError(asyncResp->res);
29768dd075aSAsmitha Karunanithi                         break;
29868dd075aSAsmitha Karunanithi                     }
29968dd075aSAsmitha Karunanithi                     originatorId = *id;
30068dd075aSAsmitha Karunanithi                 }
30168dd075aSAsmitha Karunanithi 
30268dd075aSAsmitha Karunanithi                 if (propertyMap.first == "OriginatorType")
30368dd075aSAsmitha Karunanithi                 {
30468dd075aSAsmitha Karunanithi                     const std::string* type =
30568dd075aSAsmitha Karunanithi                         std::get_if<std::string>(&propertyMap.second);
30668dd075aSAsmitha Karunanithi                     if (type == nullptr)
30768dd075aSAsmitha Karunanithi                     {
30868dd075aSAsmitha Karunanithi                         messages::internalError(asyncResp->res);
30968dd075aSAsmitha Karunanithi                         break;
31068dd075aSAsmitha Karunanithi                     }
31168dd075aSAsmitha Karunanithi 
31268dd075aSAsmitha Karunanithi                     originatorType = mapDbusOriginatorTypeToRedfish(*type);
31368dd075aSAsmitha Karunanithi                     if (originatorType == log_entry::OriginatorTypes::Invalid)
31468dd075aSAsmitha Karunanithi                     {
31568dd075aSAsmitha Karunanithi                         messages::internalError(asyncResp->res);
31668dd075aSAsmitha Karunanithi                         break;
31768dd075aSAsmitha Karunanithi                     }
31868dd075aSAsmitha Karunanithi                 }
31968dd075aSAsmitha Karunanithi             }
32068dd075aSAsmitha Karunanithi         }
321aefe3786SClaire Weinan     }
322aefe3786SClaire Weinan }
323aefe3786SClaire Weinan 
32421ab404cSNan Zhou static std::string getDumpEntriesPath(const std::string& dumpType)
325fdd26906SClaire Weinan {
326fdd26906SClaire Weinan     std::string entriesPath;
327fdd26906SClaire Weinan 
328fdd26906SClaire Weinan     if (dumpType == "BMC")
329fdd26906SClaire Weinan     {
330253f11b8SEd Tanous         entriesPath =
331253f11b8SEd Tanous             std::format("/redfish/v1/Managers/{}/LogServices/Dump/Entries/",
332253f11b8SEd Tanous                         BMCWEB_REDFISH_MANAGER_URI_NAME);
333fdd26906SClaire Weinan     }
334fdd26906SClaire Weinan     else if (dumpType == "FaultLog")
335fdd26906SClaire Weinan     {
336253f11b8SEd Tanous         entriesPath =
337253f11b8SEd Tanous             std::format("/redfish/v1/Managers/{}/LogServices/FaultLog/Entries/",
338253f11b8SEd Tanous                         BMCWEB_REDFISH_MANAGER_URI_NAME);
339fdd26906SClaire Weinan     }
340fdd26906SClaire Weinan     else if (dumpType == "System")
341fdd26906SClaire Weinan     {
342253f11b8SEd Tanous         entriesPath =
343253f11b8SEd Tanous             std::format("/redfish/v1/Systems/{}/LogServices/Dump/Entries/",
344253f11b8SEd Tanous                         BMCWEB_REDFISH_SYSTEM_URI_NAME);
345fdd26906SClaire Weinan     }
346fdd26906SClaire Weinan     else
347fdd26906SClaire Weinan     {
34862598e31SEd Tanous         BMCWEB_LOG_ERROR("getDumpEntriesPath() invalid dump type: {}",
34962598e31SEd Tanous                          dumpType);
350fdd26906SClaire Weinan     }
351fdd26906SClaire Weinan 
352fdd26906SClaire Weinan     // Returns empty string on error
353fdd26906SClaire Weinan     return entriesPath;
354fdd26906SClaire Weinan }
355fdd26906SClaire Weinan 
356504af5a0SPatrick Williams inline void getDumpEntryCollection(
357504af5a0SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3585cb1dd27SAsmitha Karunanithi     const std::string& dumpType)
3595cb1dd27SAsmitha Karunanithi {
360fdd26906SClaire Weinan     std::string entriesPath = getDumpEntriesPath(dumpType);
361fdd26906SClaire Weinan     if (entriesPath.empty())
3625cb1dd27SAsmitha Karunanithi     {
3635cb1dd27SAsmitha Karunanithi         messages::internalError(asyncResp->res);
3645cb1dd27SAsmitha Karunanithi         return;
3655cb1dd27SAsmitha Karunanithi     }
3665cb1dd27SAsmitha Karunanithi 
3675eb468daSGeorge Liu     sdbusplus::message::object_path path("/xyz/openbmc_project/dump");
3685eb468daSGeorge Liu     dbus::utility::getManagedObjects(
3695eb468daSGeorge Liu         "xyz.openbmc_project.Dump.Manager", path,
370fdd26906SClaire Weinan         [asyncResp, entriesPath,
3715e7e2dc5SEd Tanous          dumpType](const boost::system::error_code& ec,
3725eb468daSGeorge Liu                    const dbus::utility::ManagedObjectType& objects) {
3735cb1dd27SAsmitha Karunanithi             if (ec)
3745cb1dd27SAsmitha Karunanithi             {
37562598e31SEd Tanous                 BMCWEB_LOG_ERROR("DumpEntry resp_handler got error {}", ec);
3765cb1dd27SAsmitha Karunanithi                 messages::internalError(asyncResp->res);
3775cb1dd27SAsmitha Karunanithi                 return;
3785cb1dd27SAsmitha Karunanithi             }
3795cb1dd27SAsmitha Karunanithi 
380fdd26906SClaire Weinan             // Remove ending slash
381fdd26906SClaire Weinan             std::string odataIdStr = entriesPath;
382fdd26906SClaire Weinan             if (!odataIdStr.empty())
383fdd26906SClaire Weinan             {
384fdd26906SClaire Weinan                 odataIdStr.pop_back();
385fdd26906SClaire Weinan             }
386fdd26906SClaire Weinan 
387fdd26906SClaire Weinan             asyncResp->res.jsonValue["@odata.type"] =
388fdd26906SClaire Weinan                 "#LogEntryCollection.LogEntryCollection";
389fdd26906SClaire Weinan             asyncResp->res.jsonValue["@odata.id"] = std::move(odataIdStr);
390fdd26906SClaire Weinan             asyncResp->res.jsonValue["Name"] = dumpType + " Dump Entries";
391bd79bce8SPatrick Williams             asyncResp->res.jsonValue["Description"] =
392bd79bce8SPatrick Williams                 "Collection of " + dumpType + " Dump Entries";
393fdd26906SClaire Weinan 
3943544d2a7SEd Tanous             nlohmann::json::array_t entriesArray;
39518f8f608SEd Tanous             std::string dumpEntryPath = getDumpPath(dumpType) + "/entry/";
3965cb1dd27SAsmitha Karunanithi 
3975eb468daSGeorge Liu             dbus::utility::ManagedObjectType resp(objects);
3983544d2a7SEd Tanous             std::ranges::sort(resp, [](const auto& l, const auto& r) {
399002d39b4SEd Tanous                 return AlphanumLess<std::string>()(l.first.filename(),
400002d39b4SEd Tanous                                                    r.first.filename());
401565dfb6fSClaire Weinan             });
402565dfb6fSClaire Weinan 
4035cb1dd27SAsmitha Karunanithi             for (auto& object : resp)
4045cb1dd27SAsmitha Karunanithi             {
405b47452b2SAsmitha Karunanithi                 if (object.first.str.find(dumpEntryPath) == std::string::npos)
4065cb1dd27SAsmitha Karunanithi                 {
4075cb1dd27SAsmitha Karunanithi                     continue;
4085cb1dd27SAsmitha Karunanithi                 }
409c6fecdabSClaire Weinan                 uint64_t timestampUs = 0;
4105cb1dd27SAsmitha Karunanithi                 uint64_t size = 0;
41135440d18SAsmitha Karunanithi                 std::string dumpStatus;
41268dd075aSAsmitha Karunanithi                 std::string originatorId;
41368dd075aSAsmitha Karunanithi                 log_entry::OriginatorTypes originatorType =
41468dd075aSAsmitha Karunanithi                     log_entry::OriginatorTypes::Internal;
415433b68b4SJason M. Bills                 nlohmann::json::object_t thisEntry;
4162dfd18efSEd Tanous 
4172dfd18efSEd Tanous                 std::string entryID = object.first.filename();
4182dfd18efSEd Tanous                 if (entryID.empty())
4195cb1dd27SAsmitha Karunanithi                 {
4205cb1dd27SAsmitha Karunanithi                     continue;
4215cb1dd27SAsmitha Karunanithi                 }
4225cb1dd27SAsmitha Karunanithi 
423bd79bce8SPatrick Williams                 parseDumpEntryFromDbusObject(object, dumpStatus, size,
424bd79bce8SPatrick Williams                                              timestampUs, originatorId,
425bd79bce8SPatrick Williams                                              originatorType, asyncResp);
4265cb1dd27SAsmitha Karunanithi 
4270fda0f12SGeorge Liu                 if (dumpStatus !=
4280fda0f12SGeorge Liu                         "xyz.openbmc_project.Common.Progress.OperationStatus.Completed" &&
42935440d18SAsmitha Karunanithi                     !dumpStatus.empty())
43035440d18SAsmitha Karunanithi                 {
43135440d18SAsmitha Karunanithi                     // Dump status is not Complete, no need to enumerate
43235440d18SAsmitha Karunanithi                     continue;
43335440d18SAsmitha Karunanithi                 }
43435440d18SAsmitha Karunanithi 
43568dd075aSAsmitha Karunanithi                 thisEntry["@odata.type"] = "#LogEntry.v1_11_0.LogEntry";
436fdd26906SClaire Weinan                 thisEntry["@odata.id"] = entriesPath + entryID;
4375cb1dd27SAsmitha Karunanithi                 thisEntry["Id"] = entryID;
4385cb1dd27SAsmitha Karunanithi                 thisEntry["EntryType"] = "Event";
4395cb1dd27SAsmitha Karunanithi                 thisEntry["Name"] = dumpType + " Dump Entry";
440bbd80db8SClaire Weinan                 thisEntry["Created"] =
441bbd80db8SClaire Weinan                     redfish::time_utils::getDateTimeUintUs(timestampUs);
4425cb1dd27SAsmitha Karunanithi 
44368dd075aSAsmitha Karunanithi                 if (!originatorId.empty())
44468dd075aSAsmitha Karunanithi                 {
44568dd075aSAsmitha Karunanithi                     thisEntry["Originator"] = originatorId;
44668dd075aSAsmitha Karunanithi                     thisEntry["OriginatorType"] = originatorType;
44768dd075aSAsmitha Karunanithi                 }
44868dd075aSAsmitha Karunanithi 
4495cb1dd27SAsmitha Karunanithi                 if (dumpType == "BMC")
4505cb1dd27SAsmitha Karunanithi                 {
451d337bb72SAsmitha Karunanithi                     thisEntry["DiagnosticDataType"] = "Manager";
452bd79bce8SPatrick Williams                     thisEntry["AdditionalDataURI"] =
453bd79bce8SPatrick Williams                         entriesPath + entryID + "/attachment";
454fdd26906SClaire Weinan                     thisEntry["AdditionalDataSizeBytes"] = size;
4555cb1dd27SAsmitha Karunanithi                 }
4565cb1dd27SAsmitha Karunanithi                 else if (dumpType == "System")
4575cb1dd27SAsmitha Karunanithi                 {
458d337bb72SAsmitha Karunanithi                     thisEntry["DiagnosticDataType"] = "OEM";
459d337bb72SAsmitha Karunanithi                     thisEntry["OEMDiagnosticDataType"] = "System";
460bd79bce8SPatrick Williams                     thisEntry["AdditionalDataURI"] =
461bd79bce8SPatrick Williams                         entriesPath + entryID + "/attachment";
462fdd26906SClaire Weinan                     thisEntry["AdditionalDataSizeBytes"] = size;
4635cb1dd27SAsmitha Karunanithi                 }
464b2ba3072SPatrick Williams                 entriesArray.emplace_back(std::move(thisEntry));
4655cb1dd27SAsmitha Karunanithi             }
466bd79bce8SPatrick Williams             asyncResp->res.jsonValue["Members@odata.count"] =
467bd79bce8SPatrick Williams                 entriesArray.size();
4683544d2a7SEd Tanous             asyncResp->res.jsonValue["Members"] = std::move(entriesArray);
4695eb468daSGeorge Liu         });
4705cb1dd27SAsmitha Karunanithi }
4715cb1dd27SAsmitha Karunanithi 
472504af5a0SPatrick Williams inline void getDumpEntryById(
473504af5a0SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
4748d1b46d7Szhanghch05     const std::string& entryID, const std::string& dumpType)
4755cb1dd27SAsmitha Karunanithi {
476fdd26906SClaire Weinan     std::string entriesPath = getDumpEntriesPath(dumpType);
477fdd26906SClaire Weinan     if (entriesPath.empty())
4785cb1dd27SAsmitha Karunanithi     {
4795cb1dd27SAsmitha Karunanithi         messages::internalError(asyncResp->res);
4805cb1dd27SAsmitha Karunanithi         return;
4815cb1dd27SAsmitha Karunanithi     }
4825cb1dd27SAsmitha Karunanithi 
4835eb468daSGeorge Liu     sdbusplus::message::object_path path("/xyz/openbmc_project/dump");
4845eb468daSGeorge Liu     dbus::utility::getManagedObjects(
4855eb468daSGeorge Liu         "xyz.openbmc_project.Dump.Manager", path,
486fdd26906SClaire Weinan         [asyncResp, entryID, dumpType,
4875e7e2dc5SEd Tanous          entriesPath](const boost::system::error_code& ec,
48802cad96eSEd Tanous                       const dbus::utility::ManagedObjectType& resp) {
4895cb1dd27SAsmitha Karunanithi             if (ec)
4905cb1dd27SAsmitha Karunanithi             {
49162598e31SEd Tanous                 BMCWEB_LOG_ERROR("DumpEntry resp_handler got error {}", ec);
4925cb1dd27SAsmitha Karunanithi                 messages::internalError(asyncResp->res);
4935cb1dd27SAsmitha Karunanithi                 return;
4945cb1dd27SAsmitha Karunanithi             }
4955cb1dd27SAsmitha Karunanithi 
496b47452b2SAsmitha Karunanithi             bool foundDumpEntry = false;
49718f8f608SEd Tanous             std::string dumpEntryPath = getDumpPath(dumpType) + "/entry/";
498b47452b2SAsmitha Karunanithi 
4999eb808c1SEd Tanous             for (const auto& objectPath : resp)
5005cb1dd27SAsmitha Karunanithi             {
501b47452b2SAsmitha Karunanithi                 if (objectPath.first.str != dumpEntryPath + entryID)
5025cb1dd27SAsmitha Karunanithi                 {
5035cb1dd27SAsmitha Karunanithi                     continue;
5045cb1dd27SAsmitha Karunanithi                 }
5055cb1dd27SAsmitha Karunanithi 
5065cb1dd27SAsmitha Karunanithi                 foundDumpEntry = true;
507c6fecdabSClaire Weinan                 uint64_t timestampUs = 0;
5085cb1dd27SAsmitha Karunanithi                 uint64_t size = 0;
50935440d18SAsmitha Karunanithi                 std::string dumpStatus;
51068dd075aSAsmitha Karunanithi                 std::string originatorId;
51168dd075aSAsmitha Karunanithi                 log_entry::OriginatorTypes originatorType =
51268dd075aSAsmitha Karunanithi                     log_entry::OriginatorTypes::Internal;
5135cb1dd27SAsmitha Karunanithi 
514aefe3786SClaire Weinan                 parseDumpEntryFromDbusObject(objectPath, dumpStatus, size,
51568dd075aSAsmitha Karunanithi                                              timestampUs, originatorId,
51668dd075aSAsmitha Karunanithi                                              originatorType, asyncResp);
5175cb1dd27SAsmitha Karunanithi 
5180fda0f12SGeorge Liu                 if (dumpStatus !=
5190fda0f12SGeorge Liu                         "xyz.openbmc_project.Common.Progress.OperationStatus.Completed" &&
52035440d18SAsmitha Karunanithi                     !dumpStatus.empty())
52135440d18SAsmitha Karunanithi                 {
52235440d18SAsmitha Karunanithi                     // Dump status is not Complete
52335440d18SAsmitha Karunanithi                     // return not found until status is changed to Completed
524bd79bce8SPatrick Williams                     messages::resourceNotFound(asyncResp->res,
525bd79bce8SPatrick Williams                                                dumpType + " dump", entryID);
52635440d18SAsmitha Karunanithi                     return;
52735440d18SAsmitha Karunanithi                 }
52835440d18SAsmitha Karunanithi 
5295cb1dd27SAsmitha Karunanithi                 asyncResp->res.jsonValue["@odata.type"] =
53068dd075aSAsmitha Karunanithi                     "#LogEntry.v1_11_0.LogEntry";
531fdd26906SClaire Weinan                 asyncResp->res.jsonValue["@odata.id"] = entriesPath + entryID;
5325cb1dd27SAsmitha Karunanithi                 asyncResp->res.jsonValue["Id"] = entryID;
5335cb1dd27SAsmitha Karunanithi                 asyncResp->res.jsonValue["EntryType"] = "Event";
5345cb1dd27SAsmitha Karunanithi                 asyncResp->res.jsonValue["Name"] = dumpType + " Dump Entry";
535bbd80db8SClaire Weinan                 asyncResp->res.jsonValue["Created"] =
536bbd80db8SClaire Weinan                     redfish::time_utils::getDateTimeUintUs(timestampUs);
5375cb1dd27SAsmitha Karunanithi 
53868dd075aSAsmitha Karunanithi                 if (!originatorId.empty())
53968dd075aSAsmitha Karunanithi                 {
54068dd075aSAsmitha Karunanithi                     asyncResp->res.jsonValue["Originator"] = originatorId;
54168dd075aSAsmitha Karunanithi                     asyncResp->res.jsonValue["OriginatorType"] = originatorType;
54268dd075aSAsmitha Karunanithi                 }
54368dd075aSAsmitha Karunanithi 
5445cb1dd27SAsmitha Karunanithi                 if (dumpType == "BMC")
5455cb1dd27SAsmitha Karunanithi                 {
546d337bb72SAsmitha Karunanithi                     asyncResp->res.jsonValue["DiagnosticDataType"] = "Manager";
547d337bb72SAsmitha Karunanithi                     asyncResp->res.jsonValue["AdditionalDataURI"] =
548fdd26906SClaire Weinan                         entriesPath + entryID + "/attachment";
549fdd26906SClaire Weinan                     asyncResp->res.jsonValue["AdditionalDataSizeBytes"] = size;
5505cb1dd27SAsmitha Karunanithi                 }
5515cb1dd27SAsmitha Karunanithi                 else if (dumpType == "System")
5525cb1dd27SAsmitha Karunanithi                 {
553d337bb72SAsmitha Karunanithi                     asyncResp->res.jsonValue["DiagnosticDataType"] = "OEM";
554bd79bce8SPatrick Williams                     asyncResp->res.jsonValue["OEMDiagnosticDataType"] =
555bd79bce8SPatrick Williams                         "System";
556d337bb72SAsmitha Karunanithi                     asyncResp->res.jsonValue["AdditionalDataURI"] =
557fdd26906SClaire Weinan                         entriesPath + entryID + "/attachment";
558fdd26906SClaire Weinan                     asyncResp->res.jsonValue["AdditionalDataSizeBytes"] = size;
5595cb1dd27SAsmitha Karunanithi                 }
5605cb1dd27SAsmitha Karunanithi             }
561e05aec50SEd Tanous             if (!foundDumpEntry)
562b47452b2SAsmitha Karunanithi             {
56362598e31SEd Tanous                 BMCWEB_LOG_WARNING("Can't find Dump Entry {}", entryID);
564b90d14f2SMyung Bae                 messages::resourceNotFound(asyncResp->res, dumpType + " dump",
565b90d14f2SMyung Bae                                            entryID);
566b47452b2SAsmitha Karunanithi                 return;
567b47452b2SAsmitha Karunanithi             }
5685eb468daSGeorge Liu         });
5695cb1dd27SAsmitha Karunanithi }
5705cb1dd27SAsmitha Karunanithi 
5718d1b46d7Szhanghch05 inline void deleteDumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
5729878256fSStanley Chu                             const std::string& entryID,
573b47452b2SAsmitha Karunanithi                             const std::string& dumpType)
5745cb1dd27SAsmitha Karunanithi {
5755a39f77aSPatrick Williams     auto respHandler = [asyncResp,
5765a39f77aSPatrick Williams                         entryID](const boost::system::error_code& ec) {
57762598e31SEd Tanous         BMCWEB_LOG_DEBUG("Dump Entry doDelete callback: Done");
5785cb1dd27SAsmitha Karunanithi         if (ec)
5795cb1dd27SAsmitha Karunanithi         {
5803de8d8baSGeorge Liu             if (ec.value() == EBADR)
5813de8d8baSGeorge Liu             {
5823de8d8baSGeorge Liu                 messages::resourceNotFound(asyncResp->res, "LogEntry", entryID);
5833de8d8baSGeorge Liu                 return;
5843de8d8baSGeorge Liu             }
58562598e31SEd Tanous             BMCWEB_LOG_ERROR(
58662598e31SEd Tanous                 "Dump (DBus) doDelete respHandler got error {} entryID={}", ec,
58762598e31SEd Tanous                 entryID);
5885cb1dd27SAsmitha Karunanithi             messages::internalError(asyncResp->res);
5895cb1dd27SAsmitha Karunanithi             return;
5905cb1dd27SAsmitha Karunanithi         }
5915cb1dd27SAsmitha Karunanithi     };
59218f8f608SEd Tanous 
593177612aaSEd Tanous     dbus::utility::async_method_call(
594177612aaSEd Tanous         asyncResp, respHandler, "xyz.openbmc_project.Dump.Manager",
59518f8f608SEd Tanous         std::format("{}/entry/{}", getDumpPath(dumpType), entryID),
5965cb1dd27SAsmitha Karunanithi         "xyz.openbmc_project.Object.Delete", "Delete");
5975cb1dd27SAsmitha Karunanithi }
598b5f288d2SAbhilash Raju inline bool checkSizeLimit(int fd, crow::Response& res)
599b5f288d2SAbhilash Raju {
600b5f288d2SAbhilash Raju     long long int size = lseek(fd, 0, SEEK_END);
601b5f288d2SAbhilash Raju     if (size <= 0)
602b5f288d2SAbhilash Raju     {
603b5f288d2SAbhilash Raju         BMCWEB_LOG_ERROR("Failed to get size of file, lseek() returned {}",
604b5f288d2SAbhilash Raju                          size);
605b5f288d2SAbhilash Raju         messages::internalError(res);
606b5f288d2SAbhilash Raju         return false;
607b5f288d2SAbhilash Raju     }
6085cb1dd27SAsmitha Karunanithi 
609b5f288d2SAbhilash Raju     // Arbitrary max size of 20MB to accommodate BMC dumps
610b5f288d2SAbhilash Raju     constexpr long long int maxFileSize = 20LL * 1024LL * 1024LL;
611b5f288d2SAbhilash Raju     if (size > maxFileSize)
612b5f288d2SAbhilash Raju     {
613b5f288d2SAbhilash Raju         BMCWEB_LOG_ERROR("File size {} exceeds maximum allowed size of {}",
614b5f288d2SAbhilash Raju                          size, maxFileSize);
615b5f288d2SAbhilash Raju         messages::internalError(res);
616b5f288d2SAbhilash Raju         return false;
617b5f288d2SAbhilash Raju     }
618b5f288d2SAbhilash Raju     off_t rc = lseek(fd, 0, SEEK_SET);
619b5f288d2SAbhilash Raju     if (rc < 0)
620b5f288d2SAbhilash Raju     {
621b5f288d2SAbhilash Raju         BMCWEB_LOG_ERROR("Failed to reset file offset to 0");
622b5f288d2SAbhilash Raju         messages::internalError(res);
623b5f288d2SAbhilash Raju         return false;
624b5f288d2SAbhilash Raju     }
625b5f288d2SAbhilash Raju     return true;
626b5f288d2SAbhilash Raju }
627bd79bce8SPatrick Williams inline void downloadEntryCallback(
628bd79bce8SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
629bd79bce8SPatrick Williams     const std::string& entryID, const std::string& downloadEntryType,
630168d1b1aSCarson Labrado     const boost::system::error_code& ec,
631168d1b1aSCarson Labrado     const sdbusplus::message::unix_fd& unixfd)
632168d1b1aSCarson Labrado {
633168d1b1aSCarson Labrado     if (ec.value() == EBADR)
634168d1b1aSCarson Labrado     {
635168d1b1aSCarson Labrado         messages::resourceNotFound(asyncResp->res, "EntryAttachment", entryID);
636168d1b1aSCarson Labrado         return;
637168d1b1aSCarson Labrado     }
638168d1b1aSCarson Labrado     if (ec)
639168d1b1aSCarson Labrado     {
640168d1b1aSCarson Labrado         BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
641168d1b1aSCarson Labrado         messages::internalError(asyncResp->res);
642168d1b1aSCarson Labrado         return;
643168d1b1aSCarson Labrado     }
644168d1b1aSCarson Labrado 
645168d1b1aSCarson Labrado     // Make sure we know how to process the retrieved entry attachment
646168d1b1aSCarson Labrado     if ((downloadEntryType != "BMC") && (downloadEntryType != "System"))
647168d1b1aSCarson Labrado     {
648168d1b1aSCarson Labrado         BMCWEB_LOG_ERROR("downloadEntryCallback() invalid entry type: {}",
649168d1b1aSCarson Labrado                          downloadEntryType);
650168d1b1aSCarson Labrado         messages::internalError(asyncResp->res);
651168d1b1aSCarson Labrado     }
652168d1b1aSCarson Labrado 
653168d1b1aSCarson Labrado     int fd = -1;
654168d1b1aSCarson Labrado     fd = dup(unixfd);
655168d1b1aSCarson Labrado     if (fd < 0)
656168d1b1aSCarson Labrado     {
657168d1b1aSCarson Labrado         BMCWEB_LOG_ERROR("Failed to open file");
658168d1b1aSCarson Labrado         messages::internalError(asyncResp->res);
659168d1b1aSCarson Labrado         return;
660168d1b1aSCarson Labrado     }
661b5f288d2SAbhilash Raju     if (!checkSizeLimit(fd, asyncResp->res))
662168d1b1aSCarson Labrado     {
663168d1b1aSCarson Labrado         close(fd);
664168d1b1aSCarson Labrado         return;
665168d1b1aSCarson Labrado     }
666168d1b1aSCarson Labrado     if (downloadEntryType == "System")
667168d1b1aSCarson Labrado     {
668b5f288d2SAbhilash Raju         if (!asyncResp->res.openFd(fd, bmcweb::EncodingType::Base64))
669b5f288d2SAbhilash Raju         {
670b5f288d2SAbhilash Raju             messages::internalError(asyncResp->res);
671b5f288d2SAbhilash Raju             close(fd);
672b5f288d2SAbhilash Raju             return;
673b5f288d2SAbhilash Raju         }
674168d1b1aSCarson Labrado         asyncResp->res.addHeader(
675168d1b1aSCarson Labrado             boost::beast::http::field::content_transfer_encoding, "Base64");
676b5f288d2SAbhilash Raju         return;
677168d1b1aSCarson Labrado     }
678b5f288d2SAbhilash Raju     if (!asyncResp->res.openFd(fd))
67927b0cf90SEd Tanous     {
680b5f288d2SAbhilash Raju         messages::internalError(asyncResp->res);
681b5f288d2SAbhilash Raju         close(fd);
682b5f288d2SAbhilash Raju         return;
68327b0cf90SEd Tanous     }
684168d1b1aSCarson Labrado     asyncResp->res.addHeader(boost::beast::http::field::content_type,
685168d1b1aSCarson Labrado                              "application/octet-stream");
686168d1b1aSCarson Labrado }
687168d1b1aSCarson Labrado 
688504af5a0SPatrick Williams inline void downloadDumpEntry(
689504af5a0SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
690168d1b1aSCarson Labrado     const std::string& entryID, const std::string& dumpType)
691168d1b1aSCarson Labrado {
692168d1b1aSCarson Labrado     if (dumpType != "BMC")
693168d1b1aSCarson Labrado     {
694168d1b1aSCarson Labrado         BMCWEB_LOG_WARNING("Can't find Dump Entry {}", entryID);
695168d1b1aSCarson Labrado         messages::resourceNotFound(asyncResp->res, dumpType + " dump", entryID);
696168d1b1aSCarson Labrado         return;
697168d1b1aSCarson Labrado     }
698168d1b1aSCarson Labrado 
699bd79bce8SPatrick Williams     std::string dumpEntryPath =
700bd79bce8SPatrick Williams         std::format("{}/entry/{}", getDumpPath(dumpType), entryID);
701168d1b1aSCarson Labrado 
702168d1b1aSCarson Labrado     auto downloadDumpEntryHandler =
703168d1b1aSCarson Labrado         [asyncResp, entryID,
704168d1b1aSCarson Labrado          dumpType](const boost::system::error_code& ec,
705168d1b1aSCarson Labrado                    const sdbusplus::message::unix_fd& unixfd) {
706168d1b1aSCarson Labrado             downloadEntryCallback(asyncResp, entryID, dumpType, ec, unixfd);
707168d1b1aSCarson Labrado         };
708168d1b1aSCarson Labrado 
709177612aaSEd Tanous     dbus::utility::async_method_call(
710177612aaSEd Tanous         asyncResp, std::move(downloadDumpEntryHandler),
711177612aaSEd Tanous         "xyz.openbmc_project.Dump.Manager", dumpEntryPath,
712177612aaSEd Tanous         "xyz.openbmc_project.Dump.Entry", "GetFileHandle");
713168d1b1aSCarson Labrado }
714168d1b1aSCarson Labrado 
715bd79bce8SPatrick Williams inline void downloadEventLogEntry(
716bd79bce8SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
717bd79bce8SPatrick Williams     const std::string& systemName, const std::string& entryID,
718168d1b1aSCarson Labrado     const std::string& dumpType)
719168d1b1aSCarson Labrado {
72025b54dbaSEd Tanous     if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
721168d1b1aSCarson Labrado     {
722168d1b1aSCarson Labrado         // Option currently returns no systems.  TBD
723168d1b1aSCarson Labrado         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
724168d1b1aSCarson Labrado                                    systemName);
725168d1b1aSCarson Labrado         return;
726168d1b1aSCarson Labrado     }
727253f11b8SEd Tanous     if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
728168d1b1aSCarson Labrado     {
729168d1b1aSCarson Labrado         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
730168d1b1aSCarson Labrado                                    systemName);
731168d1b1aSCarson Labrado         return;
732168d1b1aSCarson Labrado     }
733168d1b1aSCarson Labrado 
734168d1b1aSCarson Labrado     std::string entryPath =
735168d1b1aSCarson Labrado         sdbusplus::message::object_path("/xyz/openbmc_project/logging/entry") /
736168d1b1aSCarson Labrado         entryID;
737168d1b1aSCarson Labrado 
738168d1b1aSCarson Labrado     auto downloadEventLogEntryHandler =
739168d1b1aSCarson Labrado         [asyncResp, entryID,
740168d1b1aSCarson Labrado          dumpType](const boost::system::error_code& ec,
741168d1b1aSCarson Labrado                    const sdbusplus::message::unix_fd& unixfd) {
742168d1b1aSCarson Labrado             downloadEntryCallback(asyncResp, entryID, dumpType, ec, unixfd);
743168d1b1aSCarson Labrado         };
744168d1b1aSCarson Labrado 
745177612aaSEd Tanous     dbus::utility::async_method_call(
746177612aaSEd Tanous         asyncResp, std::move(downloadEventLogEntryHandler),
747177612aaSEd Tanous         "xyz.openbmc_project.Logging", entryPath,
748177612aaSEd Tanous         "xyz.openbmc_project.Logging.Entry", "GetEntry");
749168d1b1aSCarson Labrado }
750168d1b1aSCarson Labrado 
751504af5a0SPatrick Williams inline DumpCreationProgress mapDbusStatusToDumpProgress(
752504af5a0SPatrick Williams     const std::string& status)
753a43be80fSAsmitha Karunanithi {
7548e31778eSAsmitha Karunanithi     if (status ==
7558e31778eSAsmitha Karunanithi             "xyz.openbmc_project.Common.Progress.OperationStatus.Failed" ||
7568e31778eSAsmitha Karunanithi         status == "xyz.openbmc_project.Common.Progress.OperationStatus.Aborted")
7578e31778eSAsmitha Karunanithi     {
7588e31778eSAsmitha Karunanithi         return DumpCreationProgress::DUMP_CREATE_FAILED;
7598e31778eSAsmitha Karunanithi     }
7608e31778eSAsmitha Karunanithi     if (status ==
7618e31778eSAsmitha Karunanithi         "xyz.openbmc_project.Common.Progress.OperationStatus.Completed")
7628e31778eSAsmitha Karunanithi     {
7638e31778eSAsmitha Karunanithi         return DumpCreationProgress::DUMP_CREATE_SUCCESS;
7648e31778eSAsmitha Karunanithi     }
7658e31778eSAsmitha Karunanithi     return DumpCreationProgress::DUMP_CREATE_INPROGRESS;
7668e31778eSAsmitha Karunanithi }
7678e31778eSAsmitha Karunanithi 
768504af5a0SPatrick Williams inline DumpCreationProgress getDumpCompletionStatus(
769504af5a0SPatrick Williams     const dbus::utility::DBusPropertiesMap& values)
7708e31778eSAsmitha Karunanithi {
7718e31778eSAsmitha Karunanithi     for (const auto& [key, val] : values)
7728e31778eSAsmitha Karunanithi     {
7738e31778eSAsmitha Karunanithi         if (key == "Status")
7748e31778eSAsmitha Karunanithi         {
7758e31778eSAsmitha Karunanithi             const std::string* value = std::get_if<std::string>(&val);
7768e31778eSAsmitha Karunanithi             if (value == nullptr)
7778e31778eSAsmitha Karunanithi             {
77862598e31SEd Tanous                 BMCWEB_LOG_ERROR("Status property value is null");
7798e31778eSAsmitha Karunanithi                 return DumpCreationProgress::DUMP_CREATE_FAILED;
7808e31778eSAsmitha Karunanithi             }
7818e31778eSAsmitha Karunanithi             return mapDbusStatusToDumpProgress(*value);
7828e31778eSAsmitha Karunanithi         }
7838e31778eSAsmitha Karunanithi     }
7848e31778eSAsmitha Karunanithi     return DumpCreationProgress::DUMP_CREATE_INPROGRESS;
7858e31778eSAsmitha Karunanithi }
7868e31778eSAsmitha Karunanithi 
7878e31778eSAsmitha Karunanithi inline std::string getDumpEntryPath(const std::string& dumpPath)
7888e31778eSAsmitha Karunanithi {
7898e31778eSAsmitha Karunanithi     if (dumpPath == "/xyz/openbmc_project/dump/bmc/entry")
7908e31778eSAsmitha Karunanithi     {
791253f11b8SEd Tanous         return std::format("/redfish/v1/Managers/{}/LogServices/Dump/Entries/",
7929f565090SEd Tanous                            BMCWEB_REDFISH_MANAGER_URI_NAME);
7938e31778eSAsmitha Karunanithi     }
7948e31778eSAsmitha Karunanithi     if (dumpPath == "/xyz/openbmc_project/dump/system/entry")
7958e31778eSAsmitha Karunanithi     {
796253f11b8SEd Tanous         return std::format("/redfish/v1/Systems/{}/LogServices/Dump/Entries/",
797253f11b8SEd Tanous                            BMCWEB_REDFISH_SYSTEM_URI_NAME);
7988e31778eSAsmitha Karunanithi     }
7998e31778eSAsmitha Karunanithi     return "";
8008e31778eSAsmitha Karunanithi }
8018e31778eSAsmitha Karunanithi 
8028e31778eSAsmitha Karunanithi inline void createDumpTaskCallback(
8038e31778eSAsmitha Karunanithi     task::Payload&& payload,
8048e31778eSAsmitha Karunanithi     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
8058e31778eSAsmitha Karunanithi     const sdbusplus::message::object_path& createdObjPath)
8068e31778eSAsmitha Karunanithi {
8078e31778eSAsmitha Karunanithi     const std::string dumpPath = createdObjPath.parent_path().str;
8088e31778eSAsmitha Karunanithi     const std::string dumpId = createdObjPath.filename();
8098e31778eSAsmitha Karunanithi 
8108e31778eSAsmitha Karunanithi     std::string dumpEntryPath = getDumpEntryPath(dumpPath);
8118e31778eSAsmitha Karunanithi 
8128e31778eSAsmitha Karunanithi     if (dumpEntryPath.empty())
8138e31778eSAsmitha Karunanithi     {
81462598e31SEd Tanous         BMCWEB_LOG_ERROR("Invalid dump type received");
8158e31778eSAsmitha Karunanithi         messages::internalError(asyncResp->res);
8168e31778eSAsmitha Karunanithi         return;
8178e31778eSAsmitha Karunanithi     }
8188e31778eSAsmitha Karunanithi 
819177612aaSEd Tanous     dbus::utility::async_method_call(
820177612aaSEd Tanous         asyncResp,
8218cb2c024SEd Tanous         [asyncResp, payload = std::move(payload), createdObjPath,
8228e31778eSAsmitha Karunanithi          dumpEntryPath{std::move(dumpEntryPath)},
8235e7e2dc5SEd Tanous          dumpId](const boost::system::error_code& ec,
8248e31778eSAsmitha Karunanithi                  const std::string& introspectXml) {
8258e31778eSAsmitha Karunanithi             if (ec)
8268e31778eSAsmitha Karunanithi             {
82762598e31SEd Tanous                 BMCWEB_LOG_ERROR("Introspect call failed with error: {}",
82862598e31SEd Tanous                                  ec.message());
8298e31778eSAsmitha Karunanithi                 messages::internalError(asyncResp->res);
8308e31778eSAsmitha Karunanithi                 return;
8318e31778eSAsmitha Karunanithi             }
8328e31778eSAsmitha Karunanithi 
8338e31778eSAsmitha Karunanithi             // Check if the created dump object has implemented Progress
8348e31778eSAsmitha Karunanithi             // interface to track dump completion. If yes, fetch the "Status"
8358e31778eSAsmitha Karunanithi             // property of the interface, modify the task state accordingly.
8368e31778eSAsmitha Karunanithi             // Else, return task completed.
8378e31778eSAsmitha Karunanithi             tinyxml2::XMLDocument doc;
8388e31778eSAsmitha Karunanithi 
8398e31778eSAsmitha Karunanithi             doc.Parse(introspectXml.data(), introspectXml.size());
8408e31778eSAsmitha Karunanithi             tinyxml2::XMLNode* pRoot = doc.FirstChildElement("node");
8418e31778eSAsmitha Karunanithi             if (pRoot == nullptr)
8428e31778eSAsmitha Karunanithi             {
84362598e31SEd Tanous                 BMCWEB_LOG_ERROR("XML document failed to parse");
8448e31778eSAsmitha Karunanithi                 messages::internalError(asyncResp->res);
8458e31778eSAsmitha Karunanithi                 return;
8468e31778eSAsmitha Karunanithi             }
8478e31778eSAsmitha Karunanithi             tinyxml2::XMLElement* interfaceNode =
8488e31778eSAsmitha Karunanithi                 pRoot->FirstChildElement("interface");
8498e31778eSAsmitha Karunanithi 
8508e31778eSAsmitha Karunanithi             bool isProgressIntfPresent = false;
8518e31778eSAsmitha Karunanithi             while (interfaceNode != nullptr)
8528e31778eSAsmitha Karunanithi             {
853bd79bce8SPatrick Williams                 const char* thisInterfaceName =
854bd79bce8SPatrick Williams                     interfaceNode->Attribute("name");
8558e31778eSAsmitha Karunanithi                 if (thisInterfaceName != nullptr)
8568e31778eSAsmitha Karunanithi                 {
8578e31778eSAsmitha Karunanithi                     if (thisInterfaceName ==
8588e31778eSAsmitha Karunanithi                         std::string_view("xyz.openbmc_project.Common.Progress"))
8598e31778eSAsmitha Karunanithi                     {
8608e31778eSAsmitha Karunanithi                         interfaceNode =
8618e31778eSAsmitha Karunanithi                             interfaceNode->NextSiblingElement("interface");
8628e31778eSAsmitha Karunanithi                         continue;
8638e31778eSAsmitha Karunanithi                     }
8648e31778eSAsmitha Karunanithi                     isProgressIntfPresent = true;
8658e31778eSAsmitha Karunanithi                     break;
8668e31778eSAsmitha Karunanithi                 }
8678e31778eSAsmitha Karunanithi                 interfaceNode = interfaceNode->NextSiblingElement("interface");
8688e31778eSAsmitha Karunanithi             }
8698e31778eSAsmitha Karunanithi 
870a43be80fSAsmitha Karunanithi             std::shared_ptr<task::TaskData> task = task::TaskData::createTask(
8718e31778eSAsmitha Karunanithi                 [createdObjPath, dumpEntryPath, dumpId, isProgressIntfPresent](
872bd79bce8SPatrick Williams                     const boost::system::error_code& ec2,
873bd79bce8SPatrick Williams                     sdbusplus::message_t& msg,
874a43be80fSAsmitha Karunanithi                     const std::shared_ptr<task::TaskData>& taskData) {
8758b24275dSEd Tanous                     if (ec2)
876cb13a392SEd Tanous                     {
87762598e31SEd Tanous                         BMCWEB_LOG_ERROR("{}: Error in creating dump",
87862598e31SEd Tanous                                          createdObjPath.str);
879bd79bce8SPatrick Williams                         taskData->messages.emplace_back(
880bd79bce8SPatrick Williams                             messages::internalError());
8816145ed6fSAsmitha Karunanithi                         taskData->state = "Cancelled";
8826145ed6fSAsmitha Karunanithi                         return task::completed;
883cb13a392SEd Tanous                     }
884b9d36b47SEd Tanous 
8858e31778eSAsmitha Karunanithi                     if (isProgressIntfPresent)
886a43be80fSAsmitha Karunanithi                     {
8878e31778eSAsmitha Karunanithi                         dbus::utility::DBusPropertiesMap values;
8888e31778eSAsmitha Karunanithi                         std::string prop;
8898e31778eSAsmitha Karunanithi                         msg.read(prop, values);
8908e31778eSAsmitha Karunanithi 
8918e31778eSAsmitha Karunanithi                         DumpCreationProgress dumpStatus =
8928e31778eSAsmitha Karunanithi                             getDumpCompletionStatus(values);
893bd79bce8SPatrick Williams                         if (dumpStatus ==
894bd79bce8SPatrick Williams                             DumpCreationProgress::DUMP_CREATE_FAILED)
8958e31778eSAsmitha Karunanithi                         {
89662598e31SEd Tanous                             BMCWEB_LOG_ERROR("{}: Error in creating dump",
89762598e31SEd Tanous                                              createdObjPath.str);
8988e31778eSAsmitha Karunanithi                             taskData->state = "Cancelled";
8998e31778eSAsmitha Karunanithi                             return task::completed;
9008e31778eSAsmitha Karunanithi                         }
9018e31778eSAsmitha Karunanithi 
902bd79bce8SPatrick Williams                         if (dumpStatus ==
903bd79bce8SPatrick Williams                             DumpCreationProgress::DUMP_CREATE_INPROGRESS)
9048e31778eSAsmitha Karunanithi                         {
905bd79bce8SPatrick Williams                             BMCWEB_LOG_DEBUG(
906bd79bce8SPatrick Williams                                 "{}: Dump creation task is in progress",
90762598e31SEd Tanous                                 createdObjPath.str);
9088e31778eSAsmitha Karunanithi                             return !task::completed;
9098e31778eSAsmitha Karunanithi                         }
9108e31778eSAsmitha Karunanithi                     }
9118e31778eSAsmitha Karunanithi 
912a43be80fSAsmitha Karunanithi                     nlohmann::json retMessage = messages::success();
913a43be80fSAsmitha Karunanithi                     taskData->messages.emplace_back(retMessage);
914a43be80fSAsmitha Karunanithi 
915c51a58eeSEd Tanous                     boost::urls::url url = boost::urls::format(
916253f11b8SEd Tanous                         "/redfish/v1/Managers/{}/LogServices/Dump/Entries/{}",
917253f11b8SEd Tanous                         BMCWEB_REDFISH_MANAGER_URI_NAME, dumpId);
918c51a58eeSEd Tanous 
919c51a58eeSEd Tanous                     std::string headerLoc = "Location: ";
920c51a58eeSEd Tanous                     headerLoc += url.buffer();
921c51a58eeSEd Tanous 
922bd79bce8SPatrick Williams                     taskData->payload->httpHeaders.emplace_back(
923bd79bce8SPatrick Williams                         std::move(headerLoc));
924a43be80fSAsmitha Karunanithi 
92562598e31SEd Tanous                     BMCWEB_LOG_DEBUG("{}: Dump creation task completed",
92662598e31SEd Tanous                                      createdObjPath.str);
927a43be80fSAsmitha Karunanithi                     taskData->state = "Completed";
928b47452b2SAsmitha Karunanithi                     return task::completed;
929a43be80fSAsmitha Karunanithi                 },
9308e31778eSAsmitha Karunanithi                 "type='signal',interface='org.freedesktop.DBus.Properties',"
9318e31778eSAsmitha Karunanithi                 "member='PropertiesChanged',path='" +
9328e31778eSAsmitha Karunanithi                     createdObjPath.str + "'");
933a43be80fSAsmitha Karunanithi 
9348e31778eSAsmitha Karunanithi             // The task timer is set to max time limit within which the
9358e31778eSAsmitha Karunanithi             // requested dump will be collected.
9368e31778eSAsmitha Karunanithi             task->startTimer(std::chrono::minutes(6));
9378e31778eSAsmitha Karunanithi             task->payload.emplace(payload);
938*29e2bdd7SChinmay Shripad Hegde             task->populateResp(asyncResp->res);
9398e31778eSAsmitha Karunanithi         },
9408e31778eSAsmitha Karunanithi         "xyz.openbmc_project.Dump.Manager", createdObjPath,
9418e31778eSAsmitha Karunanithi         "org.freedesktop.DBus.Introspectable", "Introspect");
942a43be80fSAsmitha Karunanithi }
943a43be80fSAsmitha Karunanithi 
9448d1b46d7Szhanghch05 inline void createDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
9458d1b46d7Szhanghch05                        const crow::Request& req, const std::string& dumpType)
946a43be80fSAsmitha Karunanithi {
947fdd26906SClaire Weinan     std::string dumpPath = getDumpEntriesPath(dumpType);
948fdd26906SClaire Weinan     if (dumpPath.empty())
949a43be80fSAsmitha Karunanithi     {
950a43be80fSAsmitha Karunanithi         messages::internalError(asyncResp->res);
951a43be80fSAsmitha Karunanithi         return;
952a43be80fSAsmitha Karunanithi     }
953a43be80fSAsmitha Karunanithi 
954a43be80fSAsmitha Karunanithi     std::optional<std::string> diagnosticDataType;
955a43be80fSAsmitha Karunanithi     std::optional<std::string> oemDiagnosticDataType;
956a43be80fSAsmitha Karunanithi 
957afc474aeSMyung Bae     if (!redfish::json_util::readJsonAction(               //
958afc474aeSMyung Bae             req, asyncResp->res,                           //
959afc474aeSMyung Bae             "DiagnosticDataType", diagnosticDataType,      //
960afc474aeSMyung Bae             "OEMDiagnosticDataType", oemDiagnosticDataType //
961afc474aeSMyung Bae             ))
962a43be80fSAsmitha Karunanithi     {
963a43be80fSAsmitha Karunanithi         return;
964a43be80fSAsmitha Karunanithi     }
965a43be80fSAsmitha Karunanithi 
966a43be80fSAsmitha Karunanithi     if (dumpType == "System")
967a43be80fSAsmitha Karunanithi     {
968a43be80fSAsmitha Karunanithi         if (!oemDiagnosticDataType || !diagnosticDataType)
969a43be80fSAsmitha Karunanithi         {
97062598e31SEd Tanous             BMCWEB_LOG_ERROR(
97162598e31SEd Tanous                 "CreateDump action parameter 'DiagnosticDataType'/'OEMDiagnosticDataType' value not found!");
972a43be80fSAsmitha Karunanithi             messages::actionParameterMissing(
973a43be80fSAsmitha Karunanithi                 asyncResp->res, "CollectDiagnosticData",
974a43be80fSAsmitha Karunanithi                 "DiagnosticDataType & OEMDiagnosticDataType");
975a43be80fSAsmitha Karunanithi             return;
976a43be80fSAsmitha Karunanithi         }
9773174e4dfSEd Tanous         if ((*oemDiagnosticDataType != "System") ||
978a43be80fSAsmitha Karunanithi             (*diagnosticDataType != "OEM"))
979a43be80fSAsmitha Karunanithi         {
98062598e31SEd Tanous             BMCWEB_LOG_ERROR("Wrong parameter values passed");
981ace85d60SEd Tanous             messages::internalError(asyncResp->res);
982a43be80fSAsmitha Karunanithi             return;
983a43be80fSAsmitha Karunanithi         }
984253f11b8SEd Tanous         dumpPath = std::format("/redfish/v1/Systems/{}/LogServices/Dump/",
985253f11b8SEd Tanous                                BMCWEB_REDFISH_SYSTEM_URI_NAME);
986a43be80fSAsmitha Karunanithi     }
987a43be80fSAsmitha Karunanithi     else if (dumpType == "BMC")
988a43be80fSAsmitha Karunanithi     {
989a43be80fSAsmitha Karunanithi         if (!diagnosticDataType)
990a43be80fSAsmitha Karunanithi         {
99162598e31SEd Tanous             BMCWEB_LOG_ERROR(
99262598e31SEd Tanous                 "CreateDump action parameter 'DiagnosticDataType' not found!");
993a43be80fSAsmitha Karunanithi             messages::actionParameterMissing(
994a43be80fSAsmitha Karunanithi                 asyncResp->res, "CollectDiagnosticData", "DiagnosticDataType");
995a43be80fSAsmitha Karunanithi             return;
996a43be80fSAsmitha Karunanithi         }
9973174e4dfSEd Tanous         if (*diagnosticDataType != "Manager")
998a43be80fSAsmitha Karunanithi         {
99962598e31SEd Tanous             BMCWEB_LOG_ERROR(
100062598e31SEd Tanous                 "Wrong parameter value passed for 'DiagnosticDataType'");
1001ace85d60SEd Tanous             messages::internalError(asyncResp->res);
1002a43be80fSAsmitha Karunanithi             return;
1003a43be80fSAsmitha Karunanithi         }
1004253f11b8SEd Tanous         dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/Dump/",
1005253f11b8SEd Tanous                                BMCWEB_REDFISH_MANAGER_URI_NAME);
10065907571dSAsmitha Karunanithi     }
10075907571dSAsmitha Karunanithi     else
10085907571dSAsmitha Karunanithi     {
100962598e31SEd Tanous         BMCWEB_LOG_ERROR("CreateDump failed. Unknown dump type");
10105907571dSAsmitha Karunanithi         messages::internalError(asyncResp->res);
10115907571dSAsmitha Karunanithi         return;
1012a43be80fSAsmitha Karunanithi     }
1013a43be80fSAsmitha Karunanithi 
10148e31778eSAsmitha Karunanithi     std::vector<std::pair<std::string, std::variant<std::string, uint64_t>>>
10158e31778eSAsmitha Karunanithi         createDumpParamVec;
10168e31778eSAsmitha Karunanithi 
1017f574a8e1SCarson Labrado     if (req.session != nullptr)
1018f574a8e1SCarson Labrado     {
101968dd075aSAsmitha Karunanithi         createDumpParamVec.emplace_back(
102068dd075aSAsmitha Karunanithi             "xyz.openbmc_project.Dump.Create.CreateParameters.OriginatorId",
102168dd075aSAsmitha Karunanithi             req.session->clientIp);
102268dd075aSAsmitha Karunanithi         createDumpParamVec.emplace_back(
102368dd075aSAsmitha Karunanithi             "xyz.openbmc_project.Dump.Create.CreateParameters.OriginatorType",
102468dd075aSAsmitha Karunanithi             "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Client");
1025f574a8e1SCarson Labrado     }
102668dd075aSAsmitha Karunanithi 
1027177612aaSEd Tanous     dbus::utility::async_method_call(
1028177612aaSEd Tanous         asyncResp,
10295e7e2dc5SEd Tanous         [asyncResp, payload(task::Payload(req)),
10305e7e2dc5SEd Tanous          dumpPath](const boost::system::error_code& ec,
10315e7e2dc5SEd Tanous                    const sdbusplus::message_t& msg,
10328e31778eSAsmitha Karunanithi                    const sdbusplus::message::object_path& objPath) mutable {
1033a43be80fSAsmitha Karunanithi             if (ec)
1034a43be80fSAsmitha Karunanithi             {
103562598e31SEd Tanous                 BMCWEB_LOG_ERROR("CreateDump resp_handler got error {}", ec);
10365907571dSAsmitha Karunanithi                 const sd_bus_error* dbusError = msg.get_error();
10375907571dSAsmitha Karunanithi                 if (dbusError == nullptr)
10385907571dSAsmitha Karunanithi                 {
10395907571dSAsmitha Karunanithi                     messages::internalError(asyncResp->res);
10405907571dSAsmitha Karunanithi                     return;
10415907571dSAsmitha Karunanithi                 }
10425907571dSAsmitha Karunanithi 
104362598e31SEd Tanous                 BMCWEB_LOG_ERROR("CreateDump DBus error: {} and error msg: {}",
104462598e31SEd Tanous                                  dbusError->name, dbusError->message);
10455907571dSAsmitha Karunanithi                 if (std::string_view(
10465907571dSAsmitha Karunanithi                         "xyz.openbmc_project.Common.Error.NotAllowed") ==
10475907571dSAsmitha Karunanithi                     dbusError->name)
10485907571dSAsmitha Karunanithi                 {
10495907571dSAsmitha Karunanithi                     messages::resourceInStandby(asyncResp->res);
10505907571dSAsmitha Karunanithi                     return;
10515907571dSAsmitha Karunanithi                 }
10525907571dSAsmitha Karunanithi                 if (std::string_view(
10535907571dSAsmitha Karunanithi                         "xyz.openbmc_project.Dump.Create.Error.Disabled") ==
10545907571dSAsmitha Karunanithi                     dbusError->name)
10555907571dSAsmitha Karunanithi                 {
10565907571dSAsmitha Karunanithi                     messages::serviceDisabled(asyncResp->res, dumpPath);
10575907571dSAsmitha Karunanithi                     return;
10585907571dSAsmitha Karunanithi                 }
10595907571dSAsmitha Karunanithi                 if (std::string_view(
10605907571dSAsmitha Karunanithi                         "xyz.openbmc_project.Common.Error.Unavailable") ==
10615907571dSAsmitha Karunanithi                     dbusError->name)
10625907571dSAsmitha Karunanithi                 {
10635907571dSAsmitha Karunanithi                     messages::resourceInUse(asyncResp->res);
10645907571dSAsmitha Karunanithi                     return;
10655907571dSAsmitha Karunanithi                 }
10665907571dSAsmitha Karunanithi                 // Other Dbus errors such as:
10675907571dSAsmitha Karunanithi                 // xyz.openbmc_project.Common.Error.InvalidArgument &
10685907571dSAsmitha Karunanithi                 // org.freedesktop.DBus.Error.InvalidArgs are all related to
10695907571dSAsmitha Karunanithi                 // the dbus call that is made here in the bmcweb
10705907571dSAsmitha Karunanithi                 // implementation and has nothing to do with the client's
10715907571dSAsmitha Karunanithi                 // input in the request. Hence, returning internal error
10725907571dSAsmitha Karunanithi                 // back to the client.
1073a43be80fSAsmitha Karunanithi                 messages::internalError(asyncResp->res);
1074a43be80fSAsmitha Karunanithi                 return;
1075a43be80fSAsmitha Karunanithi             }
107662598e31SEd Tanous             BMCWEB_LOG_DEBUG("Dump Created. Path: {}", objPath.str);
10778e31778eSAsmitha Karunanithi             createDumpTaskCallback(std::move(payload), asyncResp, objPath);
1078a43be80fSAsmitha Karunanithi         },
107918f8f608SEd Tanous         "xyz.openbmc_project.Dump.Manager", getDumpPath(dumpType),
10808e31778eSAsmitha Karunanithi         "xyz.openbmc_project.Dump.Create", "CreateDump", createDumpParamVec);
1081a43be80fSAsmitha Karunanithi }
1082a43be80fSAsmitha Karunanithi 
10838d1b46d7Szhanghch05 inline void clearDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
10848d1b46d7Szhanghch05                       const std::string& dumpType)
108580319af1SAsmitha Karunanithi {
1086177612aaSEd Tanous     dbus::utility::async_method_call(
1087177612aaSEd Tanous         asyncResp,
10880d946211SClaire Weinan         [asyncResp](const boost::system::error_code& ec) {
108980319af1SAsmitha Karunanithi             if (ec)
109080319af1SAsmitha Karunanithi             {
109162598e31SEd Tanous                 BMCWEB_LOG_ERROR("clearDump resp_handler got error {}", ec);
109280319af1SAsmitha Karunanithi                 messages::internalError(asyncResp->res);
109380319af1SAsmitha Karunanithi                 return;
109480319af1SAsmitha Karunanithi             }
1095e2460466SAmy Chang             messages::success(asyncResp->res);
10960d946211SClaire Weinan         },
109718f8f608SEd Tanous         "xyz.openbmc_project.Dump.Manager", getDumpPath(dumpType),
10980d946211SClaire Weinan         "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
109980319af1SAsmitha Karunanithi }
110080319af1SAsmitha Karunanithi 
1101bd79bce8SPatrick Williams inline void parseCrashdumpParameters(
1102bd79bce8SPatrick Williams     const dbus::utility::DBusPropertiesMap& params, std::string& filename,
1103bd79bce8SPatrick Williams     std::string& timestamp, std::string& logfile)
1104043a0536SJohnathan Mantey {
1105d1bde9e5SKrzysztof Grobelny     const std::string* filenamePtr = nullptr;
1106d1bde9e5SKrzysztof Grobelny     const std::string* timestampPtr = nullptr;
1107d1bde9e5SKrzysztof Grobelny     const std::string* logfilePtr = nullptr;
1108d1bde9e5SKrzysztof Grobelny 
1109d1bde9e5SKrzysztof Grobelny     const bool success = sdbusplus::unpackPropertiesNoThrow(
1110d1bde9e5SKrzysztof Grobelny         dbus_utils::UnpackErrorPrinter(), params, "Timestamp", timestampPtr,
1111d1bde9e5SKrzysztof Grobelny         "Filename", filenamePtr, "Log", logfilePtr);
1112d1bde9e5SKrzysztof Grobelny 
1113d1bde9e5SKrzysztof Grobelny     if (!success)
1114043a0536SJohnathan Mantey     {
1115d1bde9e5SKrzysztof Grobelny         return;
1116043a0536SJohnathan Mantey     }
1117d1bde9e5SKrzysztof Grobelny 
1118d1bde9e5SKrzysztof Grobelny     if (filenamePtr != nullptr)
1119043a0536SJohnathan Mantey     {
1120d1bde9e5SKrzysztof Grobelny         filename = *filenamePtr;
1121d1bde9e5SKrzysztof Grobelny     }
1122d1bde9e5SKrzysztof Grobelny 
1123d1bde9e5SKrzysztof Grobelny     if (timestampPtr != nullptr)
1124043a0536SJohnathan Mantey     {
1125d1bde9e5SKrzysztof Grobelny         timestamp = *timestampPtr;
1126043a0536SJohnathan Mantey     }
1127d1bde9e5SKrzysztof Grobelny 
1128d1bde9e5SKrzysztof Grobelny     if (logfilePtr != nullptr)
1129043a0536SJohnathan Mantey     {
1130d1bde9e5SKrzysztof Grobelny         logfile = *logfilePtr;
1131043a0536SJohnathan Mantey     }
1132043a0536SJohnathan Mantey }
1133043a0536SJohnathan Mantey 
11347e860f15SJohn Edward Broadbent inline void requestRoutesSystemLogServiceCollection(App& app)
11351da66f75SEd Tanous {
1136c4bf6374SJason M. Bills     /**
1137c4bf6374SJason M. Bills      * Functions triggers appropriate requests on DBus
1138c4bf6374SJason M. Bills      */
113922d268cbSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/")
1140ed398213SEd Tanous         .privileges(redfish::privileges::getLogServiceCollection)
1141bd79bce8SPatrick Williams         .methods(
1142bd79bce8SPatrick Williams             boost::beast::http::verb::
1143bd79bce8SPatrick Williams                 get)([&app](const crow::Request& req,
114422d268cbSEd Tanous                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
114522d268cbSEd Tanous                             const std::string& systemName) {
11463ba00073SCarson Labrado             if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1147c4bf6374SJason M. Bills             {
114845ca1b86SEd Tanous                 return;
114945ca1b86SEd Tanous             }
115025b54dbaSEd Tanous             if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
11517f3e84a1SEd Tanous             {
11527f3e84a1SEd Tanous                 // Option currently returns no systems.  TBD
11537f3e84a1SEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
11547f3e84a1SEd Tanous                                            systemName);
11557f3e84a1SEd Tanous                 return;
11567f3e84a1SEd Tanous             }
1157253f11b8SEd Tanous             if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
115822d268cbSEd Tanous             {
115922d268cbSEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
116022d268cbSEd Tanous                                            systemName);
116122d268cbSEd Tanous                 return;
116222d268cbSEd Tanous             }
116322d268cbSEd Tanous 
11647e860f15SJohn Edward Broadbent             // Collections don't include the static data added by SubRoute
11657e860f15SJohn Edward Broadbent             // because it has a duplicate entry for members
1166c4bf6374SJason M. Bills             asyncResp->res.jsonValue["@odata.type"] =
1167c4bf6374SJason M. Bills                 "#LogServiceCollection.LogServiceCollection";
1168c4bf6374SJason M. Bills             asyncResp->res.jsonValue["@odata.id"] =
1169253f11b8SEd Tanous                 std::format("/redfish/v1/Systems/{}/LogServices",
1170253f11b8SEd Tanous                             BMCWEB_REDFISH_SYSTEM_URI_NAME);
117145ca1b86SEd Tanous             asyncResp->res.jsonValue["Name"] = "System Log Services Collection";
1172c4bf6374SJason M. Bills             asyncResp->res.jsonValue["Description"] =
1173c4bf6374SJason M. Bills                 "Collection of LogServices for this Computer System";
1174bd79bce8SPatrick Williams             nlohmann::json& logServiceArray =
1175bd79bce8SPatrick Williams                 asyncResp->res.jsonValue["Members"];
1176c4bf6374SJason M. Bills             logServiceArray = nlohmann::json::array();
11771476687dSEd Tanous             nlohmann::json::object_t eventLog;
11781476687dSEd Tanous             eventLog["@odata.id"] =
1179253f11b8SEd Tanous                 std::format("/redfish/v1/Systems/{}/LogServices/EventLog",
1180253f11b8SEd Tanous                             BMCWEB_REDFISH_SYSTEM_URI_NAME);
1181b2ba3072SPatrick Williams             logServiceArray.emplace_back(std::move(eventLog));
118225b54dbaSEd Tanous             if constexpr (BMCWEB_REDFISH_DUMP_LOG)
118325b54dbaSEd Tanous             {
11841476687dSEd Tanous                 nlohmann::json::object_t dumpLog;
118525b54dbaSEd Tanous                 dumpLog["@odata.id"] =
1186253f11b8SEd Tanous                     std::format("/redfish/v1/Systems/{}/LogServices/Dump",
1187253f11b8SEd Tanous                                 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1188b2ba3072SPatrick Williams                 logServiceArray.emplace_back(std::move(dumpLog));
118925b54dbaSEd Tanous             }
1190c9bb6861Sraviteja-b 
11915ffd11f2SGunnar Mills             if constexpr (BMCWEB_REDFISH_CPU_LOG)
119225b54dbaSEd Tanous             {
11931476687dSEd Tanous                 nlohmann::json::object_t crashdump;
11941476687dSEd Tanous                 crashdump["@odata.id"] =
1195253f11b8SEd Tanous                     std::format("/redfish/v1/Systems/{}/LogServices/Crashdump",
1196253f11b8SEd Tanous                                 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1197b2ba3072SPatrick Williams                 logServiceArray.emplace_back(std::move(crashdump));
119825b54dbaSEd Tanous             }
1199b7028ebfSSpencer Ku 
120025b54dbaSEd Tanous             if constexpr (BMCWEB_REDFISH_HOST_LOGGER)
120125b54dbaSEd Tanous             {
12021476687dSEd Tanous                 nlohmann::json::object_t hostlogger;
12031476687dSEd Tanous                 hostlogger["@odata.id"] =
1204253f11b8SEd Tanous                     std::format("/redfish/v1/Systems/{}/LogServices/HostLogger",
1205253f11b8SEd Tanous                                 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1206b2ba3072SPatrick Williams                 logServiceArray.emplace_back(std::move(hostlogger));
120725b54dbaSEd Tanous             }
1208c4bf6374SJason M. Bills             asyncResp->res.jsonValue["Members@odata.count"] =
1209c4bf6374SJason M. Bills                 logServiceArray.size();
1210a3316fc6SZhikuiRen 
12117a1dbc48SGeorge Liu             constexpr std::array<std::string_view, 1> interfaces = {
12127a1dbc48SGeorge Liu                 "xyz.openbmc_project.State.Boot.PostCode"};
12137a1dbc48SGeorge Liu             dbus::utility::getSubTreePaths(
12147a1dbc48SGeorge Liu                 "/", 0, interfaces,
12157a1dbc48SGeorge Liu                 [asyncResp](const boost::system::error_code& ec,
1216b9d36b47SEd Tanous                             const dbus::utility::MapperGetSubTreePathsResponse&
1217b9d36b47SEd Tanous                                 subtreePath) {
1218a3316fc6SZhikuiRen                     if (ec)
1219a3316fc6SZhikuiRen                     {
122062598e31SEd Tanous                         BMCWEB_LOG_ERROR("{}", ec);
1221a3316fc6SZhikuiRen                         return;
1222a3316fc6SZhikuiRen                     }
1223a3316fc6SZhikuiRen 
122455f79e6fSEd Tanous                     for (const auto& pathStr : subtreePath)
1225a3316fc6SZhikuiRen                     {
1226a3316fc6SZhikuiRen                         if (pathStr.find("PostCode") != std::string::npos)
1227a3316fc6SZhikuiRen                         {
122823a21a1cSEd Tanous                             nlohmann::json& logServiceArrayLocal =
1229a3316fc6SZhikuiRen                                 asyncResp->res.jsonValue["Members"];
1230613dabeaSEd Tanous                             nlohmann::json::object_t member;
1231253f11b8SEd Tanous                             member["@odata.id"] = std::format(
1232253f11b8SEd Tanous                                 "/redfish/v1/Systems/{}/LogServices/PostCodes",
1233253f11b8SEd Tanous                                 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1234613dabeaSEd Tanous 
1235bd79bce8SPatrick Williams                             logServiceArrayLocal.emplace_back(
1236bd79bce8SPatrick Williams                                 std::move(member));
1237613dabeaSEd Tanous 
123845ca1b86SEd Tanous                             asyncResp->res.jsonValue["Members@odata.count"] =
123923a21a1cSEd Tanous                                 logServiceArrayLocal.size();
1240a3316fc6SZhikuiRen                             return;
1241a3316fc6SZhikuiRen                         }
1242a3316fc6SZhikuiRen                     }
12437a1dbc48SGeorge Liu                 });
12447e860f15SJohn Edward Broadbent         });
1245c4bf6374SJason M. Bills }
1246c4bf6374SJason M. Bills 
12477e860f15SJohn Edward Broadbent inline void requestRoutesEventLogService(App& app)
1248c4bf6374SJason M. Bills {
124922d268cbSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/")
1250ed398213SEd Tanous         .privileges(redfish::privileges::getLogService)
1251bd79bce8SPatrick Williams         .methods(
1252bd79bce8SPatrick Williams             boost::beast::http::verb::
1253bd79bce8SPatrick Williams                 get)([&app](const crow::Request& req,
125422d268cbSEd Tanous                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
125522d268cbSEd Tanous                             const std::string& systemName) {
12563ba00073SCarson Labrado             if (!redfish::setUpRedfishRoute(app, req, asyncResp))
125745ca1b86SEd Tanous             {
125845ca1b86SEd Tanous                 return;
125945ca1b86SEd Tanous             }
1260253f11b8SEd Tanous             if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
126122d268cbSEd Tanous             {
126222d268cbSEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
126322d268cbSEd Tanous                                            systemName);
126422d268cbSEd Tanous                 return;
126522d268cbSEd Tanous             }
1266c4bf6374SJason M. Bills             asyncResp->res.jsonValue["@odata.id"] =
1267253f11b8SEd Tanous                 std::format("/redfish/v1/Systems/{}/LogServices/EventLog",
1268253f11b8SEd Tanous                             BMCWEB_REDFISH_SYSTEM_URI_NAME);
1269c4bf6374SJason M. Bills             asyncResp->res.jsonValue["@odata.type"] =
1270b25644a1SJanet Adkins                 "#LogService.v1_2_0.LogService";
1271c4bf6374SJason M. Bills             asyncResp->res.jsonValue["Name"] = "Event Log Service";
1272bd79bce8SPatrick Williams             asyncResp->res.jsonValue["Description"] =
1273bd79bce8SPatrick Williams                 "System Event Log Service";
1274c4bf6374SJason M. Bills             asyncResp->res.jsonValue["Id"] = "EventLog";
1275539d8c6bSEd Tanous             asyncResp->res.jsonValue["OverWritePolicy"] =
1276539d8c6bSEd Tanous                 log_service::OverWritePolicy::WrapsWhenFull;
12777c8c4058STejas Patil 
12787c8c4058STejas Patil             std::pair<std::string, std::string> redfishDateTimeOffset =
12792b82937eSEd Tanous                 redfish::time_utils::getDateTimeOffsetNow();
12807c8c4058STejas Patil 
12817c8c4058STejas Patil             asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
12827c8c4058STejas Patil             asyncResp->res.jsonValue["DateTimeLocalOffset"] =
12837c8c4058STejas Patil                 redfishDateTimeOffset.second;
12847c8c4058STejas Patil 
1285bd79bce8SPatrick Williams             asyncResp->res.jsonValue["Entries"]["@odata.id"] = std::format(
1286bd79bce8SPatrick Williams                 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
1287253f11b8SEd Tanous                 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1288bd79bce8SPatrick Williams             asyncResp->res
1289bd79bce8SPatrick Williams                 .jsonValue["Actions"]["#LogService.ClearLog"]["target"]
1290e7d6c8b2SGunnar Mills 
129120fa6a2cSEd Tanous                 = std::format(
1292253f11b8SEd Tanous                     "/redfish/v1/Systems/{}/LogServices/EventLog/Actions/LogService.ClearLog",
129320fa6a2cSEd Tanous                     BMCWEB_REDFISH_SYSTEM_URI_NAME);
12947e860f15SJohn Edward Broadbent         });
1295489640c6SJason M. Bills }
1296489640c6SJason M. Bills 
1297599b9af3SAlexander Hansen inline void handleSystemsLogServicesEventLogActionsClearPost(
1298599b9af3SAlexander Hansen     App& app, const crow::Request& req,
129922d268cbSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1300599b9af3SAlexander Hansen     const std::string& systemName)
1301599b9af3SAlexander Hansen {
13023ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
130345ca1b86SEd Tanous     {
130445ca1b86SEd Tanous         return;
130545ca1b86SEd Tanous     }
1306253f11b8SEd Tanous     if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
130722d268cbSEd Tanous     {
130822d268cbSEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
130922d268cbSEd Tanous                                    systemName);
131022d268cbSEd Tanous         return;
131122d268cbSEd Tanous     }
1312599b9af3SAlexander Hansen 
1313489640c6SJason M. Bills     // Clear the EventLog by deleting the log files
1314489640c6SJason M. Bills     std::vector<std::filesystem::path> redfishLogFiles;
1315489640c6SJason M. Bills     if (getRedfishLogFiles(redfishLogFiles))
1316489640c6SJason M. Bills     {
1317489640c6SJason M. Bills         for (const std::filesystem::path& file : redfishLogFiles)
1318489640c6SJason M. Bills         {
1319489640c6SJason M. Bills             std::error_code ec;
1320489640c6SJason M. Bills             std::filesystem::remove(file, ec);
1321489640c6SJason M. Bills         }
1322489640c6SJason M. Bills     }
1323489640c6SJason M. Bills 
1324489640c6SJason M. Bills     // Reload rsyslog so it knows to start new log files
1325177612aaSEd Tanous     dbus::utility::async_method_call(
1326177612aaSEd Tanous         asyncResp,
13275e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
1328489640c6SJason M. Bills             if (ec)
1329489640c6SJason M. Bills             {
133062598e31SEd Tanous                 BMCWEB_LOG_ERROR("Failed to reload rsyslog: {}", ec);
1331489640c6SJason M. Bills                 messages::internalError(asyncResp->res);
1332489640c6SJason M. Bills                 return;
1333489640c6SJason M. Bills             }
1334489640c6SJason M. Bills 
1335489640c6SJason M. Bills             messages::success(asyncResp->res);
1336489640c6SJason M. Bills         },
1337489640c6SJason M. Bills         "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
1338002d39b4SEd Tanous         "org.freedesktop.systemd1.Manager", "ReloadUnit", "rsyslog.service",
1339002d39b4SEd Tanous         "replace");
1340599b9af3SAlexander Hansen }
1341599b9af3SAlexander Hansen 
1342599b9af3SAlexander Hansen inline void requestRoutesJournalEventLogClear(App& app)
1343599b9af3SAlexander Hansen {
1344599b9af3SAlexander Hansen     BMCWEB_ROUTE(
1345599b9af3SAlexander Hansen         app,
1346599b9af3SAlexander Hansen         "/redfish/v1/Systems/<str>/LogServices/EventLog/Actions/LogService.ClearLog/")
1347599b9af3SAlexander Hansen         .privileges({{"ConfigureComponents"}})
1348599b9af3SAlexander Hansen         .methods(boost::beast::http::verb::post)(std::bind_front(
1349599b9af3SAlexander Hansen             handleSystemsLogServicesEventLogActionsClearPost, std::ref(app)));
1350c4bf6374SJason M. Bills }
1351c4bf6374SJason M. Bills 
1352ac992cdeSJason M. Bills enum class LogParseError
1353ac992cdeSJason M. Bills {
1354ac992cdeSJason M. Bills     success,
1355ac992cdeSJason M. Bills     parseFailed,
1356ac992cdeSJason M. Bills     messageIdNotInRegistry,
1357ac992cdeSJason M. Bills };
1358ac992cdeSJason M. Bills 
1359bd79bce8SPatrick Williams static LogParseError fillEventLogEntryJson(
1360bd79bce8SPatrick Williams     const std::string& logEntryID, const std::string& logEntry,
1361de703c5dSJason M. Bills     nlohmann::json::object_t& logEntryJson)
1362c4bf6374SJason M. Bills {
136395820184SJason M. Bills     // The redfish log format is "<Timestamp> <MessageId>,<MessageArgs>"
1364cd225da8SJason M. Bills     // First get the Timestamp
1365f23b7296SEd Tanous     size_t space = logEntry.find_first_of(' ');
1366cd225da8SJason M. Bills     if (space == std::string::npos)
136795820184SJason M. Bills     {
1368ac992cdeSJason M. Bills         return LogParseError::parseFailed;
136995820184SJason M. Bills     }
1370cd225da8SJason M. Bills     std::string timestamp = logEntry.substr(0, space);
1371cd225da8SJason M. Bills     // Then get the log contents
1372f23b7296SEd Tanous     size_t entryStart = logEntry.find_first_not_of(' ', space);
1373cd225da8SJason M. Bills     if (entryStart == std::string::npos)
1374cd225da8SJason M. Bills     {
1375ac992cdeSJason M. Bills         return LogParseError::parseFailed;
1376cd225da8SJason M. Bills     }
1377cd225da8SJason M. Bills     std::string_view entry(logEntry);
1378cd225da8SJason M. Bills     entry.remove_prefix(entryStart);
1379cd225da8SJason M. Bills     // Use split to separate the entry into its fields
1380cd225da8SJason M. Bills     std::vector<std::string> logEntryFields;
138150ebd4afSEd Tanous     bmcweb::split(logEntryFields, entry, ',');
1382cd225da8SJason M. Bills     // We need at least a MessageId to be valid
13831e6deaf6SEd Tanous     auto logEntryIter = logEntryFields.begin();
13841e6deaf6SEd Tanous     if (logEntryIter == logEntryFields.end())
1385cd225da8SJason M. Bills     {
1386ac992cdeSJason M. Bills         return LogParseError::parseFailed;
1387cd225da8SJason M. Bills     }
13881e6deaf6SEd Tanous     std::string& messageID = *logEntryIter;
13894851d45dSJason M. Bills     // Get the Message from the MessageRegistry
1390fffb8c1fSEd Tanous     const registries::Message* message = registries::getMessage(messageID);
1391c4bf6374SJason M. Bills 
13921e6deaf6SEd Tanous     logEntryIter++;
139354417b02SSui Chen     if (message == nullptr)
1394c4bf6374SJason M. Bills     {
139562598e31SEd Tanous         BMCWEB_LOG_WARNING("Log entry not found in registry: {}", logEntry);
1396ac992cdeSJason M. Bills         return LogParseError::messageIdNotInRegistry;
1397c4bf6374SJason M. Bills     }
1398c4bf6374SJason M. Bills 
13991e6deaf6SEd Tanous     std::vector<std::string_view> messageArgs(logEntryIter,
14001e6deaf6SEd Tanous                                               logEntryFields.end());
1401c05bba45SEd Tanous     messageArgs.resize(message->numberOfArgs);
1402c05bba45SEd Tanous 
1403bd79bce8SPatrick Williams     std::string msg =
1404bd79bce8SPatrick Williams         redfish::registries::fillMessageArgs(messageArgs, message->message);
14051e6deaf6SEd Tanous     if (msg.empty())
140615a86ff6SJason M. Bills     {
14071e6deaf6SEd Tanous         return LogParseError::parseFailed;
140815a86ff6SJason M. Bills     }
14094851d45dSJason M. Bills 
141095820184SJason M. Bills     // Get the Created time from the timestamp. The log timestamp is in RFC3339
141195820184SJason M. Bills     // format which matches the Redfish format except for the fractional seconds
141295820184SJason M. Bills     // between the '.' and the '+', so just remove them.
1413f23b7296SEd Tanous     std::size_t dot = timestamp.find_first_of('.');
1414f23b7296SEd Tanous     std::size_t plus = timestamp.find_first_of('+');
141595820184SJason M. Bills     if (dot != std::string::npos && plus != std::string::npos)
1416c4bf6374SJason M. Bills     {
141795820184SJason M. Bills         timestamp.erase(dot, plus - dot);
1418c4bf6374SJason M. Bills     }
1419c4bf6374SJason M. Bills 
1420c4bf6374SJason M. Bills     // Fill in the log entry with the gathered data
14219c11a172SVijay Lobo     logEntryJson["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
1422ef4c65b7SEd Tanous     logEntryJson["@odata.id"] = boost::urls::format(
1423253f11b8SEd Tanous         "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}",
1424253f11b8SEd Tanous         BMCWEB_REDFISH_SYSTEM_URI_NAME, logEntryID);
142584afc48bSJason M. Bills     logEntryJson["Name"] = "System Event Log Entry";
142684afc48bSJason M. Bills     logEntryJson["Id"] = logEntryID;
142784afc48bSJason M. Bills     logEntryJson["Message"] = std::move(msg);
142884afc48bSJason M. Bills     logEntryJson["MessageId"] = std::move(messageID);
142984afc48bSJason M. Bills     logEntryJson["MessageArgs"] = messageArgs;
143084afc48bSJason M. Bills     logEntryJson["EntryType"] = "Event";
143184afc48bSJason M. Bills     logEntryJson["Severity"] = message->messageSeverity;
143284afc48bSJason M. Bills     logEntryJson["Created"] = std::move(timestamp);
1433ac992cdeSJason M. Bills     return LogParseError::success;
1434c4bf6374SJason M. Bills }
1435c4bf6374SJason M. Bills 
14367f3726a2SMyung Bae inline void fillEventLogLogEntryFromDbusLogEntry(
14377f3726a2SMyung Bae     const DbusEventLogEntry& entry, nlohmann::json& objectToFillOut)
1438898f2aa2SEd Tanous {
1439898f2aa2SEd Tanous     objectToFillOut["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
1440898f2aa2SEd Tanous     objectToFillOut["@odata.id"] = boost::urls::format(
1441898f2aa2SEd Tanous         "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}",
1442262dcc1cSAlexander Hansen         BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(entry.Id));
1443898f2aa2SEd Tanous     objectToFillOut["Name"] = "System Event Log Entry";
1444262dcc1cSAlexander Hansen     objectToFillOut["Id"] = std::to_string(entry.Id);
1445262dcc1cSAlexander Hansen     objectToFillOut["Message"] = entry.Message;
1446262dcc1cSAlexander Hansen     objectToFillOut["Resolved"] = entry.Resolved;
1447262dcc1cSAlexander Hansen     std::optional<bool> notifyAction =
1448262dcc1cSAlexander Hansen         getProviderNotifyAction(entry.ServiceProviderNotify);
1449898f2aa2SEd Tanous     if (notifyAction)
1450898f2aa2SEd Tanous     {
1451898f2aa2SEd Tanous         objectToFillOut["ServiceProviderNotified"] = *notifyAction;
1452898f2aa2SEd Tanous     }
1453262dcc1cSAlexander Hansen     if ((entry.Resolution != nullptr) && !entry.Resolution->empty())
1454898f2aa2SEd Tanous     {
1455262dcc1cSAlexander Hansen         objectToFillOut["Resolution"] = *entry.Resolution;
1456898f2aa2SEd Tanous     }
1457898f2aa2SEd Tanous     objectToFillOut["EntryType"] = "Event";
1458262dcc1cSAlexander Hansen     objectToFillOut["Severity"] =
1459262dcc1cSAlexander Hansen         translateSeverityDbusToRedfish(entry.Severity);
1460898f2aa2SEd Tanous     objectToFillOut["Created"] =
1461262dcc1cSAlexander Hansen         redfish::time_utils::getDateTimeUintMs(entry.Timestamp);
1462898f2aa2SEd Tanous     objectToFillOut["Modified"] =
1463262dcc1cSAlexander Hansen         redfish::time_utils::getDateTimeUintMs(entry.UpdateTimestamp);
1464262dcc1cSAlexander Hansen     if (entry.Path != nullptr)
1465898f2aa2SEd Tanous     {
1466898f2aa2SEd Tanous         objectToFillOut["AdditionalDataURI"] = boost::urls::format(
1467898f2aa2SEd Tanous             "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}/attachment",
1468262dcc1cSAlexander Hansen             BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(entry.Id));
1469898f2aa2SEd Tanous     }
1470898f2aa2SEd Tanous }
1471898f2aa2SEd Tanous 
1472b729096dSEd Tanous inline void afterLogEntriesGetManagedObjects(
1473b729096dSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1474b729096dSEd Tanous     const boost::system::error_code& ec,
1475b729096dSEd Tanous     const dbus::utility::ManagedObjectType& resp)
1476b729096dSEd Tanous {
1477b729096dSEd Tanous     if (ec)
1478b729096dSEd Tanous     {
1479b729096dSEd Tanous         // TODO Handle for specific error code
1480b729096dSEd Tanous         BMCWEB_LOG_ERROR("getLogEntriesIfaceData resp_handler got error {}",
1481b729096dSEd Tanous                          ec);
1482b729096dSEd Tanous         messages::internalError(asyncResp->res);
1483b729096dSEd Tanous         return;
1484b729096dSEd Tanous     }
1485b729096dSEd Tanous     nlohmann::json::array_t entriesArray;
1486b729096dSEd Tanous     for (const auto& objectPath : resp)
1487b729096dSEd Tanous     {
1488898f2aa2SEd Tanous         dbus::utility::DBusPropertiesMap propsFlattened;
1489bd79bce8SPatrick Williams         auto isEntry =
1490bd79bce8SPatrick Williams             std::ranges::find_if(objectPath.second, [](const auto& object) {
1491898f2aa2SEd Tanous                 return object.first == "xyz.openbmc_project.Logging.Entry";
1492898f2aa2SEd Tanous             });
1493898f2aa2SEd Tanous         if (isEntry == objectPath.second.end())
1494b729096dSEd Tanous         {
1495b729096dSEd Tanous             continue;
1496b729096dSEd Tanous         }
14977f3726a2SMyung Bae 
1498898f2aa2SEd Tanous         for (const auto& interfaceMap : objectPath.second)
1499b729096dSEd Tanous         {
1500898f2aa2SEd Tanous             for (const auto& propertyMap : interfaceMap.second)
1501b729096dSEd Tanous             {
1502898f2aa2SEd Tanous                 propsFlattened.emplace_back(propertyMap.first,
1503898f2aa2SEd Tanous                                             propertyMap.second);
1504b729096dSEd Tanous             }
1505b729096dSEd Tanous         }
15067f3726a2SMyung Bae         std::optional<DbusEventLogEntry> optEntry =
15077f3726a2SMyung Bae             fillDbusEventLogEntryFromPropertyMap(propsFlattened);
15087f3726a2SMyung Bae 
15097f3726a2SMyung Bae         if (!optEntry.has_value())
151090896601SIgor Kanyuka         {
15117f3726a2SMyung Bae             messages::internalError(asyncResp->res);
151290896601SIgor Kanyuka             return;
151390896601SIgor Kanyuka         }
15147f3726a2SMyung Bae         fillEventLogLogEntryFromDbusLogEntry(*optEntry,
15157f3726a2SMyung Bae                                              entriesArray.emplace_back());
1516b729096dSEd Tanous     }
1517898f2aa2SEd Tanous 
151890896601SIgor Kanyuka     redfish::json_util::sortJsonArrayByKey(entriesArray, "Id");
1519b729096dSEd Tanous     asyncResp->res.jsonValue["Members@odata.count"] = entriesArray.size();
1520b729096dSEd Tanous     asyncResp->res.jsonValue["Members"] = std::move(entriesArray);
1521b729096dSEd Tanous }
1522b729096dSEd Tanous 
1523599b9af3SAlexander Hansen inline void handleSystemsLogServiceEventLogLogEntryCollection(
1524599b9af3SAlexander Hansen     App& app, const crow::Request& req,
152522d268cbSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1526599b9af3SAlexander Hansen     const std::string& systemName)
1527599b9af3SAlexander Hansen {
1528c937d2bfSEd Tanous     query_param::QueryCapabilities capabilities = {
1529c937d2bfSEd Tanous         .canDelegateTop = true,
1530c937d2bfSEd Tanous         .canDelegateSkip = true,
1531c937d2bfSEd Tanous     };
1532c937d2bfSEd Tanous     query_param::Query delegatedQuery;
1533599b9af3SAlexander Hansen     if (!redfish::setUpRedfishRouteWithDelegation(app, req, asyncResp,
1534599b9af3SAlexander Hansen                                                   delegatedQuery, capabilities))
1535c4bf6374SJason M. Bills     {
1536c4bf6374SJason M. Bills         return;
1537c4bf6374SJason M. Bills     }
153825b54dbaSEd Tanous     if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
15397f3e84a1SEd Tanous     {
15407f3e84a1SEd Tanous         // Option currently returns no systems.  TBD
15417f3e84a1SEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
15427f3e84a1SEd Tanous                                    systemName);
15437f3e84a1SEd Tanous         return;
15447f3e84a1SEd Tanous     }
1545253f11b8SEd Tanous     if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
154622d268cbSEd Tanous     {
154722d268cbSEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
154822d268cbSEd Tanous                                    systemName);
154922d268cbSEd Tanous         return;
155022d268cbSEd Tanous     }
155122d268cbSEd Tanous 
15525143f7a5SJiaqing Zhao     size_t top = delegatedQuery.top.value_or(query_param::Query::maxTop);
15533648c8beSEd Tanous     size_t skip = delegatedQuery.skip.value_or(0);
15543648c8beSEd Tanous 
15557e860f15SJohn Edward Broadbent     // Collections don't include the static data added by SubRoute
15567e860f15SJohn Edward Broadbent     // because it has a duplicate entry for members
1557c4bf6374SJason M. Bills     asyncResp->res.jsonValue["@odata.type"] =
1558c4bf6374SJason M. Bills         "#LogEntryCollection.LogEntryCollection";
1559c4bf6374SJason M. Bills     asyncResp->res.jsonValue["@odata.id"] =
1560253f11b8SEd Tanous         std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
1561253f11b8SEd Tanous                     BMCWEB_REDFISH_SYSTEM_URI_NAME);
1562c4bf6374SJason M. Bills     asyncResp->res.jsonValue["Name"] = "System Event Log Entries";
1563c4bf6374SJason M. Bills     asyncResp->res.jsonValue["Description"] =
1564c4bf6374SJason M. Bills         "Collection of System Event Log Entries";
1565cb92c03bSAndrew Geissler 
15664978b63fSJason M. Bills     nlohmann::json& logEntryArray = asyncResp->res.jsonValue["Members"];
1567c4bf6374SJason M. Bills     logEntryArray = nlohmann::json::array();
15687e860f15SJohn Edward Broadbent     // Go through the log files and create a unique ID for each
15697e860f15SJohn Edward Broadbent     // entry
157095820184SJason M. Bills     std::vector<std::filesystem::path> redfishLogFiles;
157195820184SJason M. Bills     getRedfishLogFiles(redfishLogFiles);
1572b01bf299SEd Tanous     uint64_t entryCount = 0;
1573cd225da8SJason M. Bills     std::string logEntry;
157495820184SJason M. Bills 
15757e860f15SJohn Edward Broadbent     // Oldest logs are in the last file, so start there and loop
15767e860f15SJohn Edward Broadbent     // backwards
1577599b9af3SAlexander Hansen     for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend(); it++)
1578c4bf6374SJason M. Bills     {
1579cd225da8SJason M. Bills         std::ifstream logStream(*it);
158095820184SJason M. Bills         if (!logStream.is_open())
1581c4bf6374SJason M. Bills         {
1582c4bf6374SJason M. Bills             continue;
1583c4bf6374SJason M. Bills         }
1584c4bf6374SJason M. Bills 
1585e85d6b16SJason M. Bills         // Reset the unique ID on the first entry
1586e85d6b16SJason M. Bills         bool firstEntry = true;
158795820184SJason M. Bills         while (std::getline(logStream, logEntry))
158895820184SJason M. Bills         {
1589c4bf6374SJason M. Bills             std::string idStr;
1590e85d6b16SJason M. Bills             if (!getUniqueEntryID(logEntry, idStr, firstEntry))
1591c4bf6374SJason M. Bills             {
1592c4bf6374SJason M. Bills                 continue;
1593c4bf6374SJason M. Bills             }
1594e85d6b16SJason M. Bills             firstEntry = false;
1595e85d6b16SJason M. Bills 
1596de703c5dSJason M. Bills             nlohmann::json::object_t bmcLogEntry;
1597bd79bce8SPatrick Williams             LogParseError status =
1598bd79bce8SPatrick Williams                 fillEventLogEntryJson(idStr, logEntry, bmcLogEntry);
1599ac992cdeSJason M. Bills             if (status == LogParseError::messageIdNotInRegistry)
1600ac992cdeSJason M. Bills             {
1601ac992cdeSJason M. Bills                 continue;
1602ac992cdeSJason M. Bills             }
1603ac992cdeSJason M. Bills             if (status != LogParseError::success)
1604c4bf6374SJason M. Bills             {
1605c4bf6374SJason M. Bills                 messages::internalError(asyncResp->res);
1606c4bf6374SJason M. Bills                 return;
1607c4bf6374SJason M. Bills             }
1608de703c5dSJason M. Bills 
1609de703c5dSJason M. Bills             entryCount++;
1610de703c5dSJason M. Bills             // Handle paging using skip (number of entries to skip from the
1611de703c5dSJason M. Bills             // start) and top (number of entries to display)
16123648c8beSEd Tanous             if (entryCount <= skip || entryCount > skip + top)
1613de703c5dSJason M. Bills             {
1614de703c5dSJason M. Bills                 continue;
1615de703c5dSJason M. Bills             }
1616de703c5dSJason M. Bills 
1617b2ba3072SPatrick Williams             logEntryArray.emplace_back(std::move(bmcLogEntry));
1618c4bf6374SJason M. Bills         }
161995820184SJason M. Bills     }
1620c4bf6374SJason M. Bills     asyncResp->res.jsonValue["Members@odata.count"] = entryCount;
16213648c8beSEd Tanous     if (skip + top < entryCount)
1622c4bf6374SJason M. Bills     {
1623599b9af3SAlexander Hansen         asyncResp->res.jsonValue["Members@odata.nextLink"] =
1624599b9af3SAlexander Hansen             boost::urls::format(
1625253f11b8SEd Tanous                 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries?$skip={}",
1626253f11b8SEd Tanous                 BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(skip + top));
1627c4bf6374SJason M. Bills     }
1628897967deSJason M. Bills }
1629897967deSJason M. Bills 
1630599b9af3SAlexander Hansen inline void requestRoutesJournalEventLogEntryCollection(App& app)
1631897967deSJason M. Bills {
1632599b9af3SAlexander Hansen     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/")
1633599b9af3SAlexander Hansen         .privileges(redfish::privileges::getLogEntryCollection)
1634599b9af3SAlexander Hansen         .methods(boost::beast::http::verb::get)(std::bind_front(
1635599b9af3SAlexander Hansen             handleSystemsLogServiceEventLogLogEntryCollection, std::ref(app)));
1636599b9af3SAlexander Hansen }
1637599b9af3SAlexander Hansen 
1638599b9af3SAlexander Hansen inline void handleSystemsLogServiceEventLogEntriesGet(
1639599b9af3SAlexander Hansen     App& app, const crow::Request& req,
16407e860f15SJohn Edward Broadbent     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1641599b9af3SAlexander Hansen     const std::string& systemName, const std::string& param)
1642599b9af3SAlexander Hansen {
16433ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
164445ca1b86SEd Tanous     {
164545ca1b86SEd Tanous         return;
164645ca1b86SEd Tanous     }
164725b54dbaSEd Tanous     if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
16487f3e84a1SEd Tanous     {
16497f3e84a1SEd Tanous         // Option currently returns no systems.  TBD
16507f3e84a1SEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
16517f3e84a1SEd Tanous                                    systemName);
16527f3e84a1SEd Tanous         return;
16537f3e84a1SEd Tanous     }
165422d268cbSEd Tanous 
1655253f11b8SEd Tanous     if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
165622d268cbSEd Tanous     {
165722d268cbSEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
165822d268cbSEd Tanous                                    systemName);
165922d268cbSEd Tanous         return;
166022d268cbSEd Tanous     }
166122d268cbSEd Tanous 
16627e860f15SJohn Edward Broadbent     const std::string& targetID = param;
16638d1b46d7Szhanghch05 
16647e860f15SJohn Edward Broadbent     // Go through the log files and check the unique ID for each
16657e860f15SJohn Edward Broadbent     // entry to find the target entry
1666897967deSJason M. Bills     std::vector<std::filesystem::path> redfishLogFiles;
1667897967deSJason M. Bills     getRedfishLogFiles(redfishLogFiles);
1668897967deSJason M. Bills     std::string logEntry;
1669897967deSJason M. Bills 
16707e860f15SJohn Edward Broadbent     // Oldest logs are in the last file, so start there and loop
16717e860f15SJohn Edward Broadbent     // backwards
1672599b9af3SAlexander Hansen     for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend(); it++)
1673897967deSJason M. Bills     {
1674897967deSJason M. Bills         std::ifstream logStream(*it);
1675897967deSJason M. Bills         if (!logStream.is_open())
1676897967deSJason M. Bills         {
1677897967deSJason M. Bills             continue;
1678897967deSJason M. Bills         }
1679897967deSJason M. Bills 
1680897967deSJason M. Bills         // Reset the unique ID on the first entry
1681897967deSJason M. Bills         bool firstEntry = true;
1682897967deSJason M. Bills         while (std::getline(logStream, logEntry))
1683897967deSJason M. Bills         {
1684897967deSJason M. Bills             std::string idStr;
1685897967deSJason M. Bills             if (!getUniqueEntryID(logEntry, idStr, firstEntry))
1686897967deSJason M. Bills             {
1687897967deSJason M. Bills                 continue;
1688897967deSJason M. Bills             }
1689897967deSJason M. Bills             firstEntry = false;
1690897967deSJason M. Bills 
1691897967deSJason M. Bills             if (idStr == targetID)
1692897967deSJason M. Bills             {
1693de703c5dSJason M. Bills                 nlohmann::json::object_t bmcLogEntry;
1694bd79bce8SPatrick Williams                 LogParseError status =
1695bd79bce8SPatrick Williams                     fillEventLogEntryJson(idStr, logEntry, bmcLogEntry);
1696ac992cdeSJason M. Bills                 if (status != LogParseError::success)
1697897967deSJason M. Bills                 {
1698897967deSJason M. Bills                     messages::internalError(asyncResp->res);
1699897967deSJason M. Bills                     return;
1700897967deSJason M. Bills                 }
1701d405bb51SJason M. Bills                 asyncResp->res.jsonValue.update(bmcLogEntry);
1702897967deSJason M. Bills                 return;
1703897967deSJason M. Bills             }
1704897967deSJason M. Bills         }
1705897967deSJason M. Bills     }
1706897967deSJason M. Bills     // Requested ID was not found
17079db4ba25SJiaqing Zhao     messages::resourceNotFound(asyncResp->res, "LogEntry", targetID);
1708599b9af3SAlexander Hansen }
1709599b9af3SAlexander Hansen 
1710599b9af3SAlexander Hansen inline void requestRoutesJournalEventLogEntry(App& app)
1711599b9af3SAlexander Hansen {
1712599b9af3SAlexander Hansen     BMCWEB_ROUTE(
1713599b9af3SAlexander Hansen         app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
1714599b9af3SAlexander Hansen         .privileges(redfish::privileges::getLogEntry)
1715599b9af3SAlexander Hansen         .methods(boost::beast::http::verb::get)(std::bind_front(
1716599b9af3SAlexander Hansen             handleSystemsLogServiceEventLogEntriesGet, std::ref(app)));
1717599b9af3SAlexander Hansen }
1718599b9af3SAlexander Hansen 
1719599b9af3SAlexander Hansen inline void dBusEventLogEntryCollection(
1720599b9af3SAlexander Hansen     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1721599b9af3SAlexander Hansen {
1722599b9af3SAlexander Hansen     // Collections don't include the static data added by SubRoute
1723599b9af3SAlexander Hansen     // because it has a duplicate entry for members
1724599b9af3SAlexander Hansen     asyncResp->res.jsonValue["@odata.type"] =
1725599b9af3SAlexander Hansen         "#LogEntryCollection.LogEntryCollection";
1726599b9af3SAlexander Hansen     asyncResp->res.jsonValue["@odata.id"] =
1727599b9af3SAlexander Hansen         std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
1728599b9af3SAlexander Hansen                     BMCWEB_REDFISH_SYSTEM_URI_NAME);
1729599b9af3SAlexander Hansen     asyncResp->res.jsonValue["Name"] = "System Event Log Entries";
1730599b9af3SAlexander Hansen     asyncResp->res.jsonValue["Description"] =
1731599b9af3SAlexander Hansen         "Collection of System Event Log Entries";
1732599b9af3SAlexander Hansen 
1733599b9af3SAlexander Hansen     // DBus implementation of EventLog/Entries
1734599b9af3SAlexander Hansen     // Make call to Logging Service to find all log entry objects
1735599b9af3SAlexander Hansen     sdbusplus::message::object_path path("/xyz/openbmc_project/logging");
1736599b9af3SAlexander Hansen     dbus::utility::getManagedObjects(
1737599b9af3SAlexander Hansen         "xyz.openbmc_project.Logging", path,
1738599b9af3SAlexander Hansen         [asyncResp](const boost::system::error_code& ec,
1739599b9af3SAlexander Hansen                     const dbus::utility::ManagedObjectType& resp) {
1740b729096dSEd Tanous             afterLogEntriesGetManagedObjects(asyncResp, ec, resp);
17417e860f15SJohn Edward Broadbent         });
174208a4e4b5SAnthony Wilson }
174308a4e4b5SAnthony Wilson 
17447e860f15SJohn Edward Broadbent inline void requestRoutesDBusEventLogEntryCollection(App& app)
174508a4e4b5SAnthony Wilson {
174622d268cbSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/")
1747ed398213SEd Tanous         .privileges(redfish::privileges::getLogEntryCollection)
1748002d39b4SEd Tanous         .methods(boost::beast::http::verb::get)(
1749002d39b4SEd Tanous             [&app](const crow::Request& req,
175022d268cbSEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
175122d268cbSEd Tanous                    const std::string& systemName) {
17523ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
175345ca1b86SEd Tanous                 {
175445ca1b86SEd Tanous                     return;
175545ca1b86SEd Tanous                 }
175625b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
17577f3e84a1SEd Tanous                 {
17587f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
17597f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
17607f3e84a1SEd Tanous                                                systemName);
17617f3e84a1SEd Tanous                     return;
17627f3e84a1SEd Tanous                 }
1763253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
176422d268cbSEd Tanous                 {
176522d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
176622d268cbSEd Tanous                                                systemName);
176722d268cbSEd Tanous                     return;
176822d268cbSEd Tanous                 }
1769599b9af3SAlexander Hansen                 dBusEventLogEntryCollection(asyncResp);
1770599b9af3SAlexander Hansen             });
1771599b9af3SAlexander Hansen }
177222d268cbSEd Tanous 
1773c6b7cae2SMyung Bae inline void afterDBusEventLogEntryGet(
1774c6b7cae2SMyung Bae     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1775c6b7cae2SMyung Bae     const std::string& entryID, const boost::system::error_code& ec,
1776c6b7cae2SMyung Bae     const dbus::utility::DBusPropertiesMap& resp)
1777c6b7cae2SMyung Bae {
1778c6b7cae2SMyung Bae     if (ec.value() == EBADR)
1779c6b7cae2SMyung Bae     {
1780c6b7cae2SMyung Bae         messages::resourceNotFound(asyncResp->res, "EventLogEntry", entryID);
1781c6b7cae2SMyung Bae         return;
1782c6b7cae2SMyung Bae     }
1783c6b7cae2SMyung Bae     if (ec)
1784c6b7cae2SMyung Bae     {
1785c6b7cae2SMyung Bae         BMCWEB_LOG_ERROR("EventLogEntry (DBus) resp_handler got error {}", ec);
1786c6b7cae2SMyung Bae         messages::internalError(asyncResp->res);
1787c6b7cae2SMyung Bae         return;
1788c6b7cae2SMyung Bae     }
1789c6b7cae2SMyung Bae 
17907f3726a2SMyung Bae     std::optional<DbusEventLogEntry> optEntry =
17917f3726a2SMyung Bae         fillDbusEventLogEntryFromPropertyMap(resp);
17927f3726a2SMyung Bae 
17937f3726a2SMyung Bae     if (!optEntry.has_value())
17947f3726a2SMyung Bae     {
17957f3726a2SMyung Bae         messages::internalError(asyncResp->res);
17967f3726a2SMyung Bae         return;
17977f3726a2SMyung Bae     }
17987f3726a2SMyung Bae 
17997f3726a2SMyung Bae     fillEventLogLogEntryFromDbusLogEntry(*optEntry, asyncResp->res.jsonValue);
1800c6b7cae2SMyung Bae }
1801c6b7cae2SMyung Bae 
1802bd79bce8SPatrick Williams inline void dBusEventLogEntryGet(
1803bd79bce8SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID)
1804599b9af3SAlexander Hansen {
1805599b9af3SAlexander Hansen     dbus::utility::escapePathForDbus(entryID);
180608a4e4b5SAnthony Wilson 
1807cb92c03bSAndrew Geissler     // DBus implementation of EventLog/Entries
1808cb92c03bSAndrew Geissler     // Make call to Logging Service to find all log entry objects
1809deae6a78SEd Tanous     dbus::utility::getAllProperties(
1810deae6a78SEd Tanous         "xyz.openbmc_project.Logging",
1811599b9af3SAlexander Hansen         "/xyz/openbmc_project/logging/entry/" + entryID, "",
1812c6b7cae2SMyung Bae         std::bind_front(afterDBusEventLogEntryGet, asyncResp, entryID));
18137e860f15SJohn Edward Broadbent }
1814599b9af3SAlexander Hansen 
1815504af5a0SPatrick Williams inline void dBusEventLogEntryPatch(
1816504af5a0SPatrick Williams     const crow::Request& req,
1817599b9af3SAlexander Hansen     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1818599b9af3SAlexander Hansen     const std::string& entryId)
1819599b9af3SAlexander Hansen {
1820599b9af3SAlexander Hansen     std::optional<bool> resolved;
1821599b9af3SAlexander Hansen 
1822599b9af3SAlexander Hansen     if (!json_util::readJsonPatch(req, asyncResp->res, "Resolved", resolved))
1823599b9af3SAlexander Hansen     {
1824599b9af3SAlexander Hansen         return;
1825599b9af3SAlexander Hansen     }
1826599b9af3SAlexander Hansen     BMCWEB_LOG_DEBUG("Set Resolved");
1827599b9af3SAlexander Hansen 
1828599b9af3SAlexander Hansen     setDbusProperty(asyncResp, "Resolved", "xyz.openbmc_project.Logging",
1829599b9af3SAlexander Hansen                     "/xyz/openbmc_project/logging/entry/" + entryId,
1830599b9af3SAlexander Hansen                     "xyz.openbmc_project.Logging.Entry", "Resolved",
1831599b9af3SAlexander Hansen                     resolved.value_or(false));
1832599b9af3SAlexander Hansen }
1833599b9af3SAlexander Hansen 
1834bd79bce8SPatrick Williams inline void dBusEventLogEntryDelete(
1835bd79bce8SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID)
1836599b9af3SAlexander Hansen {
1837599b9af3SAlexander Hansen     BMCWEB_LOG_DEBUG("Do delete single event entries.");
1838599b9af3SAlexander Hansen 
1839599b9af3SAlexander Hansen     dbus::utility::escapePathForDbus(entryID);
1840599b9af3SAlexander Hansen 
1841599b9af3SAlexander Hansen     // Process response from Logging service.
1842599b9af3SAlexander Hansen     auto respHandler = [asyncResp,
1843599b9af3SAlexander Hansen                         entryID](const boost::system::error_code& ec) {
1844599b9af3SAlexander Hansen         BMCWEB_LOG_DEBUG("EventLogEntry (DBus) doDelete callback: Done");
1845599b9af3SAlexander Hansen         if (ec)
1846599b9af3SAlexander Hansen         {
1847599b9af3SAlexander Hansen             if (ec.value() == EBADR)
1848599b9af3SAlexander Hansen             {
1849599b9af3SAlexander Hansen                 messages::resourceNotFound(asyncResp->res, "LogEntry", entryID);
1850599b9af3SAlexander Hansen                 return;
1851599b9af3SAlexander Hansen             }
1852599b9af3SAlexander Hansen             // TODO Handle for specific error code
1853599b9af3SAlexander Hansen             BMCWEB_LOG_ERROR(
1854599b9af3SAlexander Hansen                 "EventLogEntry (DBus) doDelete respHandler got error {}", ec);
1855599b9af3SAlexander Hansen             asyncResp->res.result(
1856599b9af3SAlexander Hansen                 boost::beast::http::status::internal_server_error);
1857599b9af3SAlexander Hansen             return;
1858599b9af3SAlexander Hansen         }
1859599b9af3SAlexander Hansen 
1860599b9af3SAlexander Hansen         asyncResp->res.result(boost::beast::http::status::ok);
1861599b9af3SAlexander Hansen     };
1862599b9af3SAlexander Hansen 
1863599b9af3SAlexander Hansen     // Make call to Logging service to request Delete Log
1864177612aaSEd Tanous     dbus::utility::async_method_call(
1865177612aaSEd Tanous         asyncResp, respHandler, "xyz.openbmc_project.Logging",
1866599b9af3SAlexander Hansen         "/xyz/openbmc_project/logging/entry/" + entryID,
1867599b9af3SAlexander Hansen         "xyz.openbmc_project.Object.Delete", "Delete");
18687e860f15SJohn Edward Broadbent }
18697e860f15SJohn Edward Broadbent 
18707e860f15SJohn Edward Broadbent inline void requestRoutesDBusEventLogEntry(App& app)
18717e860f15SJohn Edward Broadbent {
18727e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
187322d268cbSEd Tanous         app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
1874ed398213SEd Tanous         .privileges(redfish::privileges::getLogEntry)
1875002d39b4SEd Tanous         .methods(boost::beast::http::verb::get)(
1876002d39b4SEd Tanous             [&app](const crow::Request& req,
18777e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1878898f2aa2SEd Tanous                    const std::string& systemName, const std::string& entryId) {
18793ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
18807e860f15SJohn Edward Broadbent                 {
188145ca1b86SEd Tanous                     return;
188245ca1b86SEd Tanous                 }
188325b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
18847f3e84a1SEd Tanous                 {
18857f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
18867f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
18877f3e84a1SEd Tanous                                                systemName);
18887f3e84a1SEd Tanous                     return;
18897f3e84a1SEd Tanous                 }
1890253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
189122d268cbSEd Tanous                 {
189222d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
189322d268cbSEd Tanous                                                systemName);
189422d268cbSEd Tanous                     return;
189522d268cbSEd Tanous                 }
189622d268cbSEd Tanous 
1897898f2aa2SEd Tanous                 dBusEventLogEntryGet(asyncResp, entryId);
18987e860f15SJohn Edward Broadbent             });
1899336e96c6SChicago Duan 
19007e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
190122d268cbSEd Tanous         app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
1902ed398213SEd Tanous         .privileges(redfish::privileges::patchLogEntry)
19037e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::patch)(
190445ca1b86SEd Tanous             [&app](const crow::Request& req,
19057e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
190622d268cbSEd Tanous                    const std::string& systemName, const std::string& entryId) {
19073ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
190845ca1b86SEd Tanous                 {
190945ca1b86SEd Tanous                     return;
191045ca1b86SEd Tanous                 }
191125b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
19127f3e84a1SEd Tanous                 {
19137f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
19147f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
19157f3e84a1SEd Tanous                                                systemName);
19167f3e84a1SEd Tanous                     return;
19177f3e84a1SEd Tanous                 }
1918253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
191922d268cbSEd Tanous                 {
192022d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
192122d268cbSEd Tanous                                                systemName);
192222d268cbSEd Tanous                     return;
192322d268cbSEd Tanous                 }
192475710de2SXiaochao Ma 
1925599b9af3SAlexander Hansen                 dBusEventLogEntryPatch(req, asyncResp, entryId);
19267e860f15SJohn Edward Broadbent             });
192775710de2SXiaochao Ma 
19287e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
192922d268cbSEd Tanous         app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
1930ed398213SEd Tanous         .privileges(redfish::privileges::deleteLogEntry)
1931ed398213SEd Tanous 
1932002d39b4SEd Tanous         .methods(boost::beast::http::verb::delete_)(
1933002d39b4SEd Tanous             [&app](const crow::Request& req,
1934002d39b4SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
193522d268cbSEd Tanous                    const std::string& systemName, const std::string& param) {
19363ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1937336e96c6SChicago Duan                 {
193845ca1b86SEd Tanous                     return;
193945ca1b86SEd Tanous                 }
194025b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
19417f3e84a1SEd Tanous                 {
19427f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
19437f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
19447f3e84a1SEd Tanous                                                systemName);
19457f3e84a1SEd Tanous                     return;
19467f3e84a1SEd Tanous                 }
1947253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
194822d268cbSEd Tanous                 {
194922d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
195022d268cbSEd Tanous                                                systemName);
195122d268cbSEd Tanous                     return;
195222d268cbSEd Tanous                 }
1953599b9af3SAlexander Hansen                 dBusEventLogEntryDelete(asyncResp, param);
19547e860f15SJohn Edward Broadbent             });
1955400fd1fbSAdriana Kobylak }
1956400fd1fbSAdriana Kobylak 
1957dd72e87bSClaire Weinan inline void handleBMCLogServicesCollectionGet(
1958fdd26906SClaire Weinan     crow::App& app, const crow::Request& req,
1959253f11b8SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1960253f11b8SEd Tanous     const std::string& managerId)
19611da66f75SEd Tanous {
19623ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
196345ca1b86SEd Tanous     {
196445ca1b86SEd Tanous         return;
196545ca1b86SEd Tanous     }
1966253f11b8SEd Tanous 
1967253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
1968253f11b8SEd Tanous     {
1969253f11b8SEd Tanous         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
1970253f11b8SEd Tanous         return;
1971253f11b8SEd Tanous     }
1972253f11b8SEd Tanous 
19737e860f15SJohn Edward Broadbent     // Collections don't include the static data added by SubRoute
19747e860f15SJohn Edward Broadbent     // because it has a duplicate entry for members
1975e1f26343SJason M. Bills     asyncResp->res.jsonValue["@odata.type"] =
19761da66f75SEd Tanous         "#LogServiceCollection.LogServiceCollection";
1977253f11b8SEd Tanous     asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
1978253f11b8SEd Tanous         "/redfish/v1/Managers/{}/LogServices", BMCWEB_REDFISH_MANAGER_URI_NAME);
1979002d39b4SEd Tanous     asyncResp->res.jsonValue["Name"] = "Open BMC Log Services Collection";
1980e1f26343SJason M. Bills     asyncResp->res.jsonValue["Description"] =
19811da66f75SEd Tanous         "Collection of LogServices for this Manager";
1982002d39b4SEd Tanous     nlohmann::json& logServiceArray = asyncResp->res.jsonValue["Members"];
1983c4bf6374SJason M. Bills     logServiceArray = nlohmann::json::array();
1984fdd26906SClaire Weinan 
198525b54dbaSEd Tanous     if constexpr (BMCWEB_REDFISH_BMC_JOURNAL)
198625b54dbaSEd Tanous     {
1987613dabeaSEd Tanous         nlohmann::json::object_t journal;
1988253f11b8SEd Tanous         journal["@odata.id"] =
1989253f11b8SEd Tanous             boost::urls::format("/redfish/v1/Managers/{}/LogServices/Journal",
1990253f11b8SEd Tanous                                 BMCWEB_REDFISH_MANAGER_URI_NAME);
1991b2ba3072SPatrick Williams         logServiceArray.emplace_back(std::move(journal));
199225b54dbaSEd Tanous     }
1993fdd26906SClaire Weinan 
1994fdd26906SClaire Weinan     asyncResp->res.jsonValue["Members@odata.count"] = logServiceArray.size();
1995fdd26906SClaire Weinan 
199625b54dbaSEd Tanous     if constexpr (BMCWEB_REDFISH_DUMP_LOG)
199725b54dbaSEd Tanous     {
199815912159SGeorge Liu         constexpr std::array<std::string_view, 1> interfaces = {
19997a1dbc48SGeorge Liu             "xyz.openbmc_project.Collection.DeleteAll"};
20007a1dbc48SGeorge Liu         dbus::utility::getSubTreePaths(
20017a1dbc48SGeorge Liu             "/xyz/openbmc_project/dump", 0, interfaces,
200225b54dbaSEd Tanous             [asyncResp](const boost::system::error_code& ec,
200325b54dbaSEd Tanous                         const dbus::utility::MapperGetSubTreePathsResponse&
200425b54dbaSEd Tanous                             subTreePaths) {
2005fdd26906SClaire Weinan                 if (ec)
2006fdd26906SClaire Weinan                 {
200762598e31SEd Tanous                     BMCWEB_LOG_ERROR(
200862598e31SEd Tanous                         "handleBMCLogServicesCollectionGet respHandler got error {}",
200962598e31SEd Tanous                         ec);
2010bd79bce8SPatrick Williams                     // Assume that getting an error simply means there are no
2011bd79bce8SPatrick Williams                     // dump LogServices. Return without adding any error
2012bd79bce8SPatrick Williams                     // response.
2013fdd26906SClaire Weinan                     return;
2014fdd26906SClaire Weinan                 }
2015fdd26906SClaire Weinan 
2016fdd26906SClaire Weinan                 nlohmann::json& logServiceArrayLocal =
2017fdd26906SClaire Weinan                     asyncResp->res.jsonValue["Members"];
2018fdd26906SClaire Weinan 
2019fdd26906SClaire Weinan                 for (const std::string& path : subTreePaths)
2020fdd26906SClaire Weinan                 {
2021fdd26906SClaire Weinan                     if (path == "/xyz/openbmc_project/dump/bmc")
2022fdd26906SClaire Weinan                     {
2023613dabeaSEd Tanous                         nlohmann::json::object_t member;
2024253f11b8SEd Tanous                         member["@odata.id"] = boost::urls::format(
2025253f11b8SEd Tanous                             "/redfish/v1/Managers/{}/LogServices/Dump",
2026253f11b8SEd Tanous                             BMCWEB_REDFISH_MANAGER_URI_NAME);
2027b2ba3072SPatrick Williams                         logServiceArrayLocal.emplace_back(std::move(member));
2028fdd26906SClaire Weinan                     }
2029fdd26906SClaire Weinan                     else if (path == "/xyz/openbmc_project/dump/faultlog")
2030fdd26906SClaire Weinan                     {
2031613dabeaSEd Tanous                         nlohmann::json::object_t member;
2032253f11b8SEd Tanous                         member["@odata.id"] = boost::urls::format(
2033253f11b8SEd Tanous                             "/redfish/v1/Managers/{}/LogServices/FaultLog",
2034253f11b8SEd Tanous                             BMCWEB_REDFISH_MANAGER_URI_NAME);
2035b2ba3072SPatrick Williams                         logServiceArrayLocal.emplace_back(std::move(member));
2036fdd26906SClaire Weinan                     }
2037fdd26906SClaire Weinan                 }
2038fdd26906SClaire Weinan 
2039e1f26343SJason M. Bills                 asyncResp->res.jsonValue["Members@odata.count"] =
2040fdd26906SClaire Weinan                     logServiceArrayLocal.size();
20417a1dbc48SGeorge Liu             });
204225b54dbaSEd Tanous     }
2043fdd26906SClaire Weinan }
2044fdd26906SClaire Weinan 
2045fdd26906SClaire Weinan inline void requestRoutesBMCLogServiceCollection(App& app)
2046fdd26906SClaire Weinan {
2047253f11b8SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/")
2048fdd26906SClaire Weinan         .privileges(redfish::privileges::getLogServiceCollection)
2049fdd26906SClaire Weinan         .methods(boost::beast::http::verb::get)(
2050dd72e87bSClaire Weinan             std::bind_front(handleBMCLogServicesCollectionGet, std::ref(app)));
2051e1f26343SJason M. Bills }
2052e1f26343SJason M. Bills 
2053504af5a0SPatrick Williams inline void getDumpServiceInfo(
2054504af5a0SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2055fdd26906SClaire Weinan     const std::string& dumpType)
2056c9bb6861Sraviteja-b {
2057fdd26906SClaire Weinan     std::string dumpPath;
2058539d8c6bSEd Tanous     log_service::OverWritePolicy overWritePolicy =
2059539d8c6bSEd Tanous         log_service::OverWritePolicy::Invalid;
2060fdd26906SClaire Weinan     bool collectDiagnosticDataSupported = false;
2061fdd26906SClaire Weinan 
2062fdd26906SClaire Weinan     if (dumpType == "BMC")
206345ca1b86SEd Tanous     {
2064253f11b8SEd Tanous         dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/Dump",
2065253f11b8SEd Tanous                                BMCWEB_REDFISH_MANAGER_URI_NAME);
2066539d8c6bSEd Tanous         overWritePolicy = log_service::OverWritePolicy::WrapsWhenFull;
2067fdd26906SClaire Weinan         collectDiagnosticDataSupported = true;
2068fdd26906SClaire Weinan     }
2069fdd26906SClaire Weinan     else if (dumpType == "FaultLog")
2070fdd26906SClaire Weinan     {
2071253f11b8SEd Tanous         dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/FaultLog",
2072253f11b8SEd Tanous                                BMCWEB_REDFISH_MANAGER_URI_NAME);
2073539d8c6bSEd Tanous         overWritePolicy = log_service::OverWritePolicy::Unknown;
2074fdd26906SClaire Weinan         collectDiagnosticDataSupported = false;
2075fdd26906SClaire Weinan     }
2076fdd26906SClaire Weinan     else if (dumpType == "System")
2077fdd26906SClaire Weinan     {
2078253f11b8SEd Tanous         dumpPath = std::format("/redfish/v1/Systems/{}/LogServices/Dump",
2079253f11b8SEd Tanous                                BMCWEB_REDFISH_SYSTEM_URI_NAME);
2080539d8c6bSEd Tanous         overWritePolicy = log_service::OverWritePolicy::WrapsWhenFull;
2081fdd26906SClaire Weinan         collectDiagnosticDataSupported = true;
2082fdd26906SClaire Weinan     }
2083fdd26906SClaire Weinan     else
2084fdd26906SClaire Weinan     {
208562598e31SEd Tanous         BMCWEB_LOG_ERROR("getDumpServiceInfo() invalid dump type: {}",
208662598e31SEd Tanous                          dumpType);
2087fdd26906SClaire Weinan         messages::internalError(asyncResp->res);
208845ca1b86SEd Tanous         return;
208945ca1b86SEd Tanous     }
2090fdd26906SClaire Weinan 
2091fdd26906SClaire Weinan     asyncResp->res.jsonValue["@odata.id"] = dumpPath;
2092fdd26906SClaire Weinan     asyncResp->res.jsonValue["@odata.type"] = "#LogService.v1_2_0.LogService";
2093c9bb6861Sraviteja-b     asyncResp->res.jsonValue["Name"] = "Dump LogService";
2094fdd26906SClaire Weinan     asyncResp->res.jsonValue["Description"] = dumpType + " Dump LogService";
2095fdd26906SClaire Weinan     asyncResp->res.jsonValue["Id"] = std::filesystem::path(dumpPath).filename();
2096539d8c6bSEd Tanous     asyncResp->res.jsonValue["OverWritePolicy"] = overWritePolicy;
20977c8c4058STejas Patil 
20987c8c4058STejas Patil     std::pair<std::string, std::string> redfishDateTimeOffset =
20992b82937eSEd Tanous         redfish::time_utils::getDateTimeOffsetNow();
21000fda0f12SGeorge Liu     asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
21017c8c4058STejas Patil     asyncResp->res.jsonValue["DateTimeLocalOffset"] =
21027c8c4058STejas Patil         redfishDateTimeOffset.second;
21037c8c4058STejas Patil 
2104fdd26906SClaire Weinan     asyncResp->res.jsonValue["Entries"]["@odata.id"] = dumpPath + "/Entries";
2105fdd26906SClaire Weinan 
2106fdd26906SClaire Weinan     if (collectDiagnosticDataSupported)
2107fdd26906SClaire Weinan     {
2108002d39b4SEd Tanous         asyncResp->res.jsonValue["Actions"]["#LogService.CollectDiagnosticData"]
21091476687dSEd Tanous                                 ["target"] =
2110fdd26906SClaire Weinan             dumpPath + "/Actions/LogService.CollectDiagnosticData";
2111fdd26906SClaire Weinan     }
21120d946211SClaire Weinan 
21130d946211SClaire Weinan     constexpr std::array<std::string_view, 1> interfaces = {deleteAllInterface};
21140d946211SClaire Weinan     dbus::utility::getSubTreePaths(
21150d946211SClaire Weinan         "/xyz/openbmc_project/dump", 0, interfaces,
21160d946211SClaire Weinan         [asyncResp, dumpType, dumpPath](
21170d946211SClaire Weinan             const boost::system::error_code& ec,
21180d946211SClaire Weinan             const dbus::utility::MapperGetSubTreePathsResponse& subTreePaths) {
21190d946211SClaire Weinan             if (ec)
21200d946211SClaire Weinan             {
2121bd79bce8SPatrick Williams                 BMCWEB_LOG_ERROR("getDumpServiceInfo respHandler got error {}",
2122bd79bce8SPatrick Williams                                  ec);
21230d946211SClaire Weinan                 // Assume that getting an error simply means there are no dump
21240d946211SClaire Weinan                 // LogServices. Return without adding any error response.
21250d946211SClaire Weinan                 return;
21260d946211SClaire Weinan             }
212718f8f608SEd Tanous             std::string dbusDumpPath = getDumpPath(dumpType);
21280d946211SClaire Weinan             for (const std::string& path : subTreePaths)
21290d946211SClaire Weinan             {
21300d946211SClaire Weinan                 if (path == dbusDumpPath)
21310d946211SClaire Weinan                 {
2132bd79bce8SPatrick Williams                     asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"]
2133bd79bce8SPatrick Williams                                             ["target"] =
21340d946211SClaire Weinan                         dumpPath + "/Actions/LogService.ClearLog";
21350d946211SClaire Weinan                     break;
21360d946211SClaire Weinan                 }
21370d946211SClaire Weinan             }
21380d946211SClaire Weinan         });
2139c9bb6861Sraviteja-b }
2140c9bb6861Sraviteja-b 
2141fdd26906SClaire Weinan inline void handleLogServicesDumpServiceGet(
2142fdd26906SClaire Weinan     crow::App& app, const std::string& dumpType, const crow::Request& req,
2143253f11b8SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2144253f11b8SEd Tanous     const std::string& managerId)
21457e860f15SJohn Edward Broadbent {
21463ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
214745ca1b86SEd Tanous     {
214845ca1b86SEd Tanous         return;
214945ca1b86SEd Tanous     }
2150253f11b8SEd Tanous 
2151253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2152253f11b8SEd Tanous     {
2153253f11b8SEd Tanous         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2154253f11b8SEd Tanous         return;
2155253f11b8SEd Tanous     }
2156253f11b8SEd Tanous 
2157fdd26906SClaire Weinan     getDumpServiceInfo(asyncResp, dumpType);
2158fdd26906SClaire Weinan }
2159c9bb6861Sraviteja-b 
216022d268cbSEd Tanous inline void handleLogServicesDumpServiceComputerSystemGet(
216122d268cbSEd Tanous     crow::App& app, const crow::Request& req,
216222d268cbSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
216322d268cbSEd Tanous     const std::string& chassisId)
216422d268cbSEd Tanous {
216522d268cbSEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
216622d268cbSEd Tanous     {
216722d268cbSEd Tanous         return;
216822d268cbSEd Tanous     }
2169253f11b8SEd Tanous     if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
217022d268cbSEd Tanous     {
217122d268cbSEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
217222d268cbSEd Tanous         return;
217322d268cbSEd Tanous     }
217422d268cbSEd Tanous     getDumpServiceInfo(asyncResp, "System");
217522d268cbSEd Tanous }
217622d268cbSEd Tanous 
2177fdd26906SClaire Weinan inline void handleLogServicesDumpEntriesCollectionGet(
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)
2181fdd26906SClaire Weinan {
2182fdd26906SClaire Weinan     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2183fdd26906SClaire Weinan     {
2184fdd26906SClaire Weinan         return;
2185fdd26906SClaire Weinan     }
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     }
2192fdd26906SClaire Weinan     getDumpEntryCollection(asyncResp, dumpType);
2193fdd26906SClaire Weinan }
2194fdd26906SClaire Weinan 
219522d268cbSEd Tanous inline void handleLogServicesDumpEntriesCollectionComputerSystemGet(
219622d268cbSEd Tanous     crow::App& app, const crow::Request& req,
219722d268cbSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
219822d268cbSEd Tanous     const std::string& chassisId)
219922d268cbSEd Tanous {
220022d268cbSEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
220122d268cbSEd Tanous     {
220222d268cbSEd Tanous         return;
220322d268cbSEd Tanous     }
2204253f11b8SEd Tanous     if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
220522d268cbSEd Tanous     {
220622d268cbSEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
220722d268cbSEd Tanous         return;
220822d268cbSEd Tanous     }
220922d268cbSEd Tanous     getDumpEntryCollection(asyncResp, "System");
221022d268cbSEd Tanous }
221122d268cbSEd Tanous 
2212fdd26906SClaire Weinan inline void handleLogServicesDumpEntryGet(
2213fdd26906SClaire Weinan     crow::App& app, const std::string& dumpType, const crow::Request& req,
2214fdd26906SClaire Weinan     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2215253f11b8SEd Tanous     const std::string& managerId, const std::string& dumpId)
2216fdd26906SClaire Weinan {
2217fdd26906SClaire Weinan     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2218fdd26906SClaire Weinan     {
2219fdd26906SClaire Weinan         return;
2220fdd26906SClaire Weinan     }
2221253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2222253f11b8SEd Tanous     {
2223253f11b8SEd Tanous         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2224253f11b8SEd Tanous         return;
2225253f11b8SEd Tanous     }
2226fdd26906SClaire Weinan     getDumpEntryById(asyncResp, dumpId, dumpType);
2227fdd26906SClaire Weinan }
2228168d1b1aSCarson Labrado 
222922d268cbSEd Tanous inline void handleLogServicesDumpEntryComputerSystemGet(
223022d268cbSEd Tanous     crow::App& app, const crow::Request& req,
223122d268cbSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
223222d268cbSEd Tanous     const std::string& chassisId, const std::string& dumpId)
223322d268cbSEd Tanous {
223422d268cbSEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
223522d268cbSEd Tanous     {
223622d268cbSEd Tanous         return;
223722d268cbSEd Tanous     }
2238253f11b8SEd Tanous     if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
223922d268cbSEd Tanous     {
224022d268cbSEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
224122d268cbSEd Tanous         return;
224222d268cbSEd Tanous     }
224322d268cbSEd Tanous     getDumpEntryById(asyncResp, dumpId, "System");
224422d268cbSEd Tanous }
2245fdd26906SClaire Weinan 
2246fdd26906SClaire Weinan inline void handleLogServicesDumpEntryDelete(
2247fdd26906SClaire Weinan     crow::App& app, const std::string& dumpType, const crow::Request& req,
2248fdd26906SClaire Weinan     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2249253f11b8SEd Tanous     const std::string& managerId, const std::string& dumpId)
2250fdd26906SClaire Weinan {
2251fdd26906SClaire Weinan     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2252fdd26906SClaire Weinan     {
2253fdd26906SClaire Weinan         return;
2254fdd26906SClaire Weinan     }
2255253f11b8SEd Tanous 
2256253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2257253f11b8SEd Tanous     {
2258253f11b8SEd Tanous         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2259253f11b8SEd Tanous         return;
2260253f11b8SEd Tanous     }
2261fdd26906SClaire Weinan     deleteDumpEntry(asyncResp, dumpId, dumpType);
2262fdd26906SClaire Weinan }
2263fdd26906SClaire Weinan 
226422d268cbSEd Tanous inline void handleLogServicesDumpEntryComputerSystemDelete(
226522d268cbSEd Tanous     crow::App& app, const crow::Request& req,
226622d268cbSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
226722d268cbSEd Tanous     const std::string& chassisId, const std::string& dumpId)
226822d268cbSEd Tanous {
226922d268cbSEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
227022d268cbSEd Tanous     {
227122d268cbSEd Tanous         return;
227222d268cbSEd Tanous     }
2273253f11b8SEd Tanous     if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
227422d268cbSEd Tanous     {
227522d268cbSEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
227622d268cbSEd Tanous         return;
227722d268cbSEd Tanous     }
227822d268cbSEd Tanous     deleteDumpEntry(asyncResp, dumpId, "System");
227922d268cbSEd Tanous }
228022d268cbSEd Tanous 
2281168d1b1aSCarson Labrado inline void handleLogServicesDumpEntryDownloadGet(
2282168d1b1aSCarson Labrado     crow::App& app, const std::string& dumpType, const crow::Request& req,
2283168d1b1aSCarson Labrado     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2284253f11b8SEd Tanous     const std::string& managerId, const std::string& dumpId)
2285168d1b1aSCarson Labrado {
2286168d1b1aSCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2287168d1b1aSCarson Labrado     {
2288168d1b1aSCarson Labrado         return;
2289168d1b1aSCarson Labrado     }
2290253f11b8SEd Tanous 
2291253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2292253f11b8SEd Tanous     {
2293253f11b8SEd Tanous         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2294253f11b8SEd Tanous         return;
2295253f11b8SEd Tanous     }
2296168d1b1aSCarson Labrado     downloadDumpEntry(asyncResp, dumpId, dumpType);
2297168d1b1aSCarson Labrado }
2298168d1b1aSCarson Labrado 
2299168d1b1aSCarson Labrado inline void handleDBusEventLogEntryDownloadGet(
2300168d1b1aSCarson Labrado     crow::App& app, const std::string& dumpType, const crow::Request& req,
2301168d1b1aSCarson Labrado     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2302168d1b1aSCarson Labrado     const std::string& systemName, const std::string& entryID)
2303168d1b1aSCarson Labrado {
2304168d1b1aSCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2305168d1b1aSCarson Labrado     {
2306168d1b1aSCarson Labrado         return;
2307168d1b1aSCarson Labrado     }
2308168d1b1aSCarson Labrado     if (!http_helpers::isContentTypeAllowed(
2309168d1b1aSCarson Labrado             req.getHeaderValue("Accept"),
2310168d1b1aSCarson Labrado             http_helpers::ContentType::OctetStream, true))
2311168d1b1aSCarson Labrado     {
2312168d1b1aSCarson Labrado         asyncResp->res.result(boost::beast::http::status::bad_request);
2313168d1b1aSCarson Labrado         return;
2314168d1b1aSCarson Labrado     }
2315168d1b1aSCarson Labrado     downloadEventLogEntry(asyncResp, systemName, entryID, dumpType);
2316168d1b1aSCarson Labrado }
2317168d1b1aSCarson Labrado 
2318fdd26906SClaire Weinan inline void handleLogServicesDumpCollectDiagnosticDataPost(
2319fdd26906SClaire Weinan     crow::App& app, const std::string& dumpType, const crow::Request& req,
2320253f11b8SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2321253f11b8SEd Tanous     const std::string& managerId)
2322fdd26906SClaire Weinan {
2323fdd26906SClaire Weinan     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2324fdd26906SClaire Weinan     {
2325fdd26906SClaire Weinan         return;
2326fdd26906SClaire Weinan     }
2327253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2328253f11b8SEd Tanous     {
2329253f11b8SEd Tanous         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2330253f11b8SEd Tanous         return;
2331253f11b8SEd Tanous     }
2332253f11b8SEd Tanous 
2333fdd26906SClaire Weinan     createDump(asyncResp, req, dumpType);
2334fdd26906SClaire Weinan }
2335fdd26906SClaire Weinan 
233622d268cbSEd Tanous inline void handleLogServicesDumpCollectDiagnosticDataComputerSystemPost(
233722d268cbSEd Tanous     crow::App& app, const crow::Request& req,
233822d268cbSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
23397f3e84a1SEd Tanous     const std::string& systemName)
234022d268cbSEd Tanous {
234122d268cbSEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
234222d268cbSEd Tanous     {
234322d268cbSEd Tanous         return;
234422d268cbSEd Tanous     }
23457f3e84a1SEd Tanous 
234625b54dbaSEd Tanous     if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
234722d268cbSEd Tanous     {
23487f3e84a1SEd Tanous         // Option currently returns no systems.  TBD
23497f3e84a1SEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
23507f3e84a1SEd Tanous                                    systemName);
23517f3e84a1SEd Tanous         return;
23527f3e84a1SEd Tanous     }
2353253f11b8SEd Tanous     if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
23547f3e84a1SEd Tanous     {
23557f3e84a1SEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
23567f3e84a1SEd Tanous                                    systemName);
235722d268cbSEd Tanous         return;
235822d268cbSEd Tanous     }
235922d268cbSEd Tanous     createDump(asyncResp, req, "System");
236022d268cbSEd Tanous }
236122d268cbSEd Tanous 
2362fdd26906SClaire Weinan inline void handleLogServicesDumpClearLogPost(
2363fdd26906SClaire Weinan     crow::App& app, const std::string& dumpType, const crow::Request& req,
2364253f11b8SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2365253f11b8SEd Tanous     const std::string& managerId)
2366fdd26906SClaire Weinan {
2367fdd26906SClaire Weinan     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2368fdd26906SClaire Weinan     {
2369fdd26906SClaire Weinan         return;
2370fdd26906SClaire Weinan     }
2371253f11b8SEd Tanous 
2372253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2373253f11b8SEd Tanous     {
2374253f11b8SEd Tanous         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2375253f11b8SEd Tanous         return;
2376253f11b8SEd Tanous     }
2377fdd26906SClaire Weinan     clearDump(asyncResp, dumpType);
2378fdd26906SClaire Weinan }
2379fdd26906SClaire Weinan 
238022d268cbSEd Tanous inline void handleLogServicesDumpClearLogComputerSystemPost(
238122d268cbSEd Tanous     crow::App& app, const crow::Request& req,
238222d268cbSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
23837f3e84a1SEd Tanous     const std::string& systemName)
238422d268cbSEd Tanous {
238522d268cbSEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
238622d268cbSEd Tanous     {
238722d268cbSEd Tanous         return;
238822d268cbSEd Tanous     }
238925b54dbaSEd Tanous     if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
239022d268cbSEd Tanous     {
23917f3e84a1SEd Tanous         // Option currently returns no systems.  TBD
23927f3e84a1SEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
23937f3e84a1SEd Tanous                                    systemName);
23947f3e84a1SEd Tanous         return;
23957f3e84a1SEd Tanous     }
2396253f11b8SEd Tanous     if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
23977f3e84a1SEd Tanous     {
23987f3e84a1SEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
23997f3e84a1SEd Tanous                                    systemName);
240022d268cbSEd Tanous         return;
240122d268cbSEd Tanous     }
240222d268cbSEd Tanous     clearDump(asyncResp, "System");
240322d268cbSEd Tanous }
240422d268cbSEd Tanous 
2405fdd26906SClaire Weinan inline void requestRoutesBMCDumpService(App& app)
2406fdd26906SClaire Weinan {
2407253f11b8SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/Dump/")
2408fdd26906SClaire Weinan         .privileges(redfish::privileges::getLogService)
2409fdd26906SClaire Weinan         .methods(boost::beast::http::verb::get)(std::bind_front(
2410fdd26906SClaire Weinan             handleLogServicesDumpServiceGet, std::ref(app), "BMC"));
2411fdd26906SClaire Weinan }
2412fdd26906SClaire Weinan 
2413fdd26906SClaire Weinan inline void requestRoutesBMCDumpEntryCollection(App& app)
2414fdd26906SClaire Weinan {
2415253f11b8SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/")
2416fdd26906SClaire Weinan         .privileges(redfish::privileges::getLogEntryCollection)
2417fdd26906SClaire Weinan         .methods(boost::beast::http::verb::get)(std::bind_front(
2418fdd26906SClaire Weinan             handleLogServicesDumpEntriesCollectionGet, std::ref(app), "BMC"));
2419c9bb6861Sraviteja-b }
2420c9bb6861Sraviteja-b 
24217e860f15SJohn Edward Broadbent inline void requestRoutesBMCDumpEntry(App& app)
2422c9bb6861Sraviteja-b {
24237e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
2424253f11b8SEd Tanous                  "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/")
2425ed398213SEd Tanous         .privileges(redfish::privileges::getLogEntry)
2426fdd26906SClaire Weinan         .methods(boost::beast::http::verb::get)(std::bind_front(
2427fdd26906SClaire Weinan             handleLogServicesDumpEntryGet, std::ref(app), "BMC"));
2428fdd26906SClaire Weinan 
24297e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
2430253f11b8SEd Tanous                  "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/")
2431ed398213SEd Tanous         .privileges(redfish::privileges::deleteLogEntry)
2432fdd26906SClaire Weinan         .methods(boost::beast::http::verb::delete_)(std::bind_front(
2433fdd26906SClaire Weinan             handleLogServicesDumpEntryDelete, std::ref(app), "BMC"));
2434c9bb6861Sraviteja-b }
2435c9bb6861Sraviteja-b 
2436168d1b1aSCarson Labrado inline void requestRoutesBMCDumpEntryDownload(App& app)
2437168d1b1aSCarson Labrado {
2438168d1b1aSCarson Labrado     BMCWEB_ROUTE(
2439168d1b1aSCarson Labrado         app,
2440253f11b8SEd Tanous         "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/attachment/")
2441168d1b1aSCarson Labrado         .privileges(redfish::privileges::getLogEntry)
2442168d1b1aSCarson Labrado         .methods(boost::beast::http::verb::get)(std::bind_front(
2443168d1b1aSCarson Labrado             handleLogServicesDumpEntryDownloadGet, std::ref(app), "BMC"));
2444168d1b1aSCarson Labrado }
2445168d1b1aSCarson Labrado 
24467e860f15SJohn Edward Broadbent inline void requestRoutesBMCDumpCreate(App& app)
2447c9bb6861Sraviteja-b {
24480fda0f12SGeorge Liu     BMCWEB_ROUTE(
24490fda0f12SGeorge Liu         app,
2450253f11b8SEd Tanous         "/redfish/v1/Managers/<str>/LogServices/Dump/Actions/LogService.CollectDiagnosticData/")
2451ed398213SEd Tanous         .privileges(redfish::privileges::postLogService)
24527e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
2453fdd26906SClaire Weinan             std::bind_front(handleLogServicesDumpCollectDiagnosticDataPost,
2454fdd26906SClaire Weinan                             std::ref(app), "BMC"));
2455a43be80fSAsmitha Karunanithi }
2456a43be80fSAsmitha Karunanithi 
24577e860f15SJohn Edward Broadbent inline void requestRoutesBMCDumpClear(App& app)
245880319af1SAsmitha Karunanithi {
24590fda0f12SGeorge Liu     BMCWEB_ROUTE(
24600fda0f12SGeorge Liu         app,
2461253f11b8SEd Tanous         "/redfish/v1/Managers/<str>/LogServices/Dump/Actions/LogService.ClearLog/")
2462ed398213SEd Tanous         .privileges(redfish::privileges::postLogService)
2463fdd26906SClaire Weinan         .methods(boost::beast::http::verb::post)(std::bind_front(
2464fdd26906SClaire Weinan             handleLogServicesDumpClearLogPost, std::ref(app), "BMC"));
246545ca1b86SEd Tanous }
2466fdd26906SClaire Weinan 
2467168d1b1aSCarson Labrado inline void requestRoutesDBusEventLogEntryDownload(App& app)
2468168d1b1aSCarson Labrado {
2469168d1b1aSCarson Labrado     BMCWEB_ROUTE(
2470168d1b1aSCarson Labrado         app,
24719e9d99daSRavi Teja         "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/attachment/")
2472168d1b1aSCarson Labrado         .privileges(redfish::privileges::getLogEntry)
2473168d1b1aSCarson Labrado         .methods(boost::beast::http::verb::get)(std::bind_front(
2474168d1b1aSCarson Labrado             handleDBusEventLogEntryDownloadGet, std::ref(app), "System"));
2475168d1b1aSCarson Labrado }
2476168d1b1aSCarson Labrado 
2477fdd26906SClaire Weinan inline void requestRoutesFaultLogDumpService(App& app)
2478fdd26906SClaire Weinan {
2479253f11b8SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/")
2480fdd26906SClaire Weinan         .privileges(redfish::privileges::getLogService)
2481fdd26906SClaire Weinan         .methods(boost::beast::http::verb::get)(std::bind_front(
2482fdd26906SClaire Weinan             handleLogServicesDumpServiceGet, std::ref(app), "FaultLog"));
2483fdd26906SClaire Weinan }
2484fdd26906SClaire Weinan 
2485fdd26906SClaire Weinan inline void requestRoutesFaultLogDumpEntryCollection(App& app)
2486fdd26906SClaire Weinan {
2487253f11b8SEd Tanous     BMCWEB_ROUTE(app,
2488253f11b8SEd Tanous                  "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/")
2489fdd26906SClaire Weinan         .privileges(redfish::privileges::getLogEntryCollection)
2490fdd26906SClaire Weinan         .methods(boost::beast::http::verb::get)(
2491fdd26906SClaire Weinan             std::bind_front(handleLogServicesDumpEntriesCollectionGet,
2492fdd26906SClaire Weinan                             std::ref(app), "FaultLog"));
2493fdd26906SClaire Weinan }
2494fdd26906SClaire Weinan 
2495fdd26906SClaire Weinan inline void requestRoutesFaultLogDumpEntry(App& app)
2496fdd26906SClaire Weinan {
2497253f11b8SEd Tanous     BMCWEB_ROUTE(
2498253f11b8SEd Tanous         app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/<str>/")
2499fdd26906SClaire Weinan         .privileges(redfish::privileges::getLogEntry)
2500fdd26906SClaire Weinan         .methods(boost::beast::http::verb::get)(std::bind_front(
2501fdd26906SClaire Weinan             handleLogServicesDumpEntryGet, std::ref(app), "FaultLog"));
2502fdd26906SClaire Weinan 
2503253f11b8SEd Tanous     BMCWEB_ROUTE(
2504253f11b8SEd Tanous         app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/<str>/")
2505fdd26906SClaire Weinan         .privileges(redfish::privileges::deleteLogEntry)
2506fdd26906SClaire Weinan         .methods(boost::beast::http::verb::delete_)(std::bind_front(
2507fdd26906SClaire Weinan             handleLogServicesDumpEntryDelete, std::ref(app), "FaultLog"));
2508fdd26906SClaire Weinan }
2509fdd26906SClaire Weinan 
2510fdd26906SClaire Weinan inline void requestRoutesFaultLogDumpClear(App& app)
2511fdd26906SClaire Weinan {
2512fdd26906SClaire Weinan     BMCWEB_ROUTE(
2513fdd26906SClaire Weinan         app,
2514253f11b8SEd Tanous         "/redfish/v1/Managers/<str>/LogServices/FaultLog/Actions/LogService.ClearLog/")
2515fdd26906SClaire Weinan         .privileges(redfish::privileges::postLogService)
2516fdd26906SClaire Weinan         .methods(boost::beast::http::verb::post)(std::bind_front(
2517fdd26906SClaire Weinan             handleLogServicesDumpClearLogPost, std::ref(app), "FaultLog"));
25185cb1dd27SAsmitha Karunanithi }
25195cb1dd27SAsmitha Karunanithi 
25207e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpService(App& app)
25215cb1dd27SAsmitha Karunanithi {
252222d268cbSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Dump/")
2523ed398213SEd Tanous         .privileges(redfish::privileges::getLogService)
25246ab9ad54SClaire Weinan         .methods(boost::beast::http::verb::get)(std::bind_front(
252522d268cbSEd Tanous             handleLogServicesDumpServiceComputerSystemGet, std::ref(app)));
25265cb1dd27SAsmitha Karunanithi }
25275cb1dd27SAsmitha Karunanithi 
25287e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpEntryCollection(App& app)
25297e860f15SJohn Edward Broadbent {
253022d268cbSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/")
2531ed398213SEd Tanous         .privileges(redfish::privileges::getLogEntryCollection)
253222d268cbSEd Tanous         .methods(boost::beast::http::verb::get)(std::bind_front(
253322d268cbSEd Tanous             handleLogServicesDumpEntriesCollectionComputerSystemGet,
253422d268cbSEd Tanous             std::ref(app)));
25355cb1dd27SAsmitha Karunanithi }
25365cb1dd27SAsmitha Karunanithi 
25377e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpEntry(App& app)
25385cb1dd27SAsmitha Karunanithi {
25397e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
254022d268cbSEd Tanous                  "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/<str>/")
2541ed398213SEd Tanous         .privileges(redfish::privileges::getLogEntry)
25426ab9ad54SClaire Weinan         .methods(boost::beast::http::verb::get)(std::bind_front(
254322d268cbSEd Tanous             handleLogServicesDumpEntryComputerSystemGet, std::ref(app)));
25448d1b46d7Szhanghch05 
25457e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
254622d268cbSEd Tanous                  "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/<str>/")
2547ed398213SEd Tanous         .privileges(redfish::privileges::deleteLogEntry)
25486ab9ad54SClaire Weinan         .methods(boost::beast::http::verb::delete_)(std::bind_front(
254922d268cbSEd Tanous             handleLogServicesDumpEntryComputerSystemDelete, std::ref(app)));
25505cb1dd27SAsmitha Karunanithi }
2551c9bb6861Sraviteja-b 
25527e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpCreate(App& app)
2553c9bb6861Sraviteja-b {
25540fda0f12SGeorge Liu     BMCWEB_ROUTE(
25550fda0f12SGeorge Liu         app,
255622d268cbSEd Tanous         "/redfish/v1/Systems/<str>/LogServices/Dump/Actions/LogService.CollectDiagnosticData/")
2557ed398213SEd Tanous         .privileges(redfish::privileges::postLogService)
255822d268cbSEd Tanous         .methods(boost::beast::http::verb::post)(std::bind_front(
255922d268cbSEd Tanous             handleLogServicesDumpCollectDiagnosticDataComputerSystemPost,
256022d268cbSEd Tanous             std::ref(app)));
2561a43be80fSAsmitha Karunanithi }
2562a43be80fSAsmitha Karunanithi 
25637e860f15SJohn Edward Broadbent inline void requestRoutesSystemDumpClear(App& app)
2564a43be80fSAsmitha Karunanithi {
25650fda0f12SGeorge Liu     BMCWEB_ROUTE(
25660fda0f12SGeorge Liu         app,
256722d268cbSEd Tanous         "/redfish/v1/Systems/<str>/LogServices/Dump/Actions/LogService.ClearLog/")
2568ed398213SEd Tanous         .privileges(redfish::privileges::postLogService)
25696ab9ad54SClaire Weinan         .methods(boost::beast::http::verb::post)(std::bind_front(
257022d268cbSEd Tanous             handleLogServicesDumpClearLogComputerSystemPost, std::ref(app)));
2571013487e5Sraviteja-b }
2572013487e5Sraviteja-b 
25737e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpService(App& app)
25741da66f75SEd Tanous {
25753946028dSAppaRao Puli     // Note: Deviated from redfish privilege registry for GET & HEAD
25763946028dSAppaRao Puli     // method for security reasons.
25771da66f75SEd Tanous     /**
25781da66f75SEd Tanous      * Functions triggers appropriate requests on DBus
25791da66f75SEd Tanous      */
258022d268cbSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Crashdump/")
2581ed398213SEd Tanous         // This is incorrect, should be:
2582ed398213SEd Tanous         //.privileges(redfish::privileges::getLogService)
2583432a890cSEd Tanous         .privileges({{"ConfigureManager"}})
2584bd79bce8SPatrick Williams         .methods(
2585bd79bce8SPatrick Williams             boost::beast::http::verb::
2586bd79bce8SPatrick Williams                 get)([&app](const crow::Request& req,
258722d268cbSEd Tanous                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
258822d268cbSEd Tanous                             const std::string& systemName) {
25893ba00073SCarson Labrado             if (!redfish::setUpRedfishRoute(app, req, asyncResp))
259045ca1b86SEd Tanous             {
259145ca1b86SEd Tanous                 return;
259245ca1b86SEd Tanous             }
259325b54dbaSEd Tanous             if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
25947f3e84a1SEd Tanous             {
25957f3e84a1SEd Tanous                 // Option currently returns no systems.  TBD
25967f3e84a1SEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
25977f3e84a1SEd Tanous                                            systemName);
25987f3e84a1SEd Tanous                 return;
25997f3e84a1SEd Tanous             }
2600253f11b8SEd Tanous             if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
260122d268cbSEd Tanous             {
260222d268cbSEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
260322d268cbSEd Tanous                                            systemName);
260422d268cbSEd Tanous                 return;
260522d268cbSEd Tanous             }
260622d268cbSEd Tanous 
26077e860f15SJohn Edward Broadbent             // Copy over the static data to include the entries added by
26087e860f15SJohn Edward Broadbent             // SubRoute
26090f74e643SEd Tanous             asyncResp->res.jsonValue["@odata.id"] =
2610253f11b8SEd Tanous                 std::format("/redfish/v1/Systems/{}/LogServices/Crashdump",
2611253f11b8SEd Tanous                             BMCWEB_REDFISH_SYSTEM_URI_NAME);
2612e1f26343SJason M. Bills             asyncResp->res.jsonValue["@odata.type"] =
26138e6c099aSJason M. Bills                 "#LogService.v1_2_0.LogService";
26144f50ae4bSGunnar Mills             asyncResp->res.jsonValue["Name"] = "Open BMC Oem Crashdump Service";
26154f50ae4bSGunnar Mills             asyncResp->res.jsonValue["Description"] = "Oem Crashdump Service";
261615b89725SV-Sanjana             asyncResp->res.jsonValue["Id"] = "Crashdump";
2617539d8c6bSEd Tanous             asyncResp->res.jsonValue["OverWritePolicy"] =
2618539d8c6bSEd Tanous                 log_service::OverWritePolicy::WrapsWhenFull;
2619e1f26343SJason M. Bills             asyncResp->res.jsonValue["MaxNumberOfRecords"] = 3;
26207c8c4058STejas Patil 
26217c8c4058STejas Patil             std::pair<std::string, std::string> redfishDateTimeOffset =
26222b82937eSEd Tanous                 redfish::time_utils::getDateTimeOffsetNow();
26237c8c4058STejas Patil             asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
26247c8c4058STejas Patil             asyncResp->res.jsonValue["DateTimeLocalOffset"] =
26257c8c4058STejas Patil                 redfishDateTimeOffset.second;
26267c8c4058STejas Patil 
2627bd79bce8SPatrick Williams             asyncResp->res.jsonValue["Entries"]["@odata.id"] = std::format(
2628bd79bce8SPatrick Williams                 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries",
2629253f11b8SEd Tanous                 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2630253f11b8SEd Tanous             asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"]
2631253f11b8SEd Tanous                                     ["target"] = std::format(
2632253f11b8SEd Tanous                 "/redfish/v1/Systems/{}/LogServices/Crashdump/Actions/LogService.ClearLog",
2633253f11b8SEd Tanous                 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2634bd79bce8SPatrick Williams             asyncResp->res
2635bd79bce8SPatrick Williams                 .jsonValue["Actions"]["#LogService.CollectDiagnosticData"]
2636253f11b8SEd Tanous                           ["target"] = std::format(
2637253f11b8SEd Tanous                 "/redfish/v1/Systems/{}/LogServices/Crashdump/Actions/LogService.CollectDiagnosticData",
2638253f11b8SEd Tanous                 BMCWEB_REDFISH_SYSTEM_URI_NAME);
26397e860f15SJohn Edward Broadbent         });
26401da66f75SEd Tanous }
26411da66f75SEd Tanous 
26427e860f15SJohn Edward Broadbent void inline requestRoutesCrashdumpClear(App& app)
26435b61b5e8SJason M. Bills {
26440fda0f12SGeorge Liu     BMCWEB_ROUTE(
26450fda0f12SGeorge Liu         app,
264622d268cbSEd Tanous         "/redfish/v1/Systems/<str>/LogServices/Crashdump/Actions/LogService.ClearLog/")
2647ed398213SEd Tanous         // This is incorrect, should be:
2648ed398213SEd Tanous         //.privileges(redfish::privileges::postLogService)
2649432a890cSEd Tanous         .privileges({{"ConfigureComponents"}})
26507e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
265145ca1b86SEd Tanous             [&app](const crow::Request& req,
265222d268cbSEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
265322d268cbSEd Tanous                    const std::string& systemName) {
26543ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
265545ca1b86SEd Tanous                 {
265645ca1b86SEd Tanous                     return;
265745ca1b86SEd Tanous                 }
265825b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
26597f3e84a1SEd Tanous                 {
26607f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
26617f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
26627f3e84a1SEd Tanous                                                systemName);
26637f3e84a1SEd Tanous                     return;
26647f3e84a1SEd Tanous                 }
2665253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
266622d268cbSEd Tanous                 {
266722d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
266822d268cbSEd Tanous                                                systemName);
266922d268cbSEd Tanous                     return;
267022d268cbSEd Tanous                 }
2671177612aaSEd Tanous                 dbus::utility::async_method_call(
2672177612aaSEd Tanous                     asyncResp,
26735e7e2dc5SEd Tanous                     [asyncResp](const boost::system::error_code& ec,
2674cb13a392SEd Tanous                                 const std::string&) {
26755b61b5e8SJason M. Bills                         if (ec)
26765b61b5e8SJason M. Bills                         {
26775b61b5e8SJason M. Bills                             messages::internalError(asyncResp->res);
26785b61b5e8SJason M. Bills                             return;
26795b61b5e8SJason M. Bills                         }
26805b61b5e8SJason M. Bills                         messages::success(asyncResp->res);
26815b61b5e8SJason M. Bills                     },
2682bd79bce8SPatrick Williams                     crashdumpObject, crashdumpPath, deleteAllInterface,
2683bd79bce8SPatrick Williams                     "DeleteAll");
26847e860f15SJohn Edward Broadbent             });
26855b61b5e8SJason M. Bills }
26865b61b5e8SJason M. Bills 
2687504af5a0SPatrick Williams inline void logCrashdumpEntry(
2688504af5a0SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
26898d1b46d7Szhanghch05     const std::string& logID, nlohmann::json& logEntryJson)
2690e855dd28SJason M. Bills {
2691043a0536SJohnathan Mantey     auto getStoredLogCallback =
2692b9d36b47SEd Tanous         [asyncResp, logID,
26935e7e2dc5SEd Tanous          &logEntryJson](const boost::system::error_code& ec,
2694b9d36b47SEd Tanous                         const dbus::utility::DBusPropertiesMap& params) {
2695e855dd28SJason M. Bills             if (ec)
2696e855dd28SJason M. Bills             {
269762598e31SEd Tanous                 BMCWEB_LOG_DEBUG("failed to get log ec: {}", ec.message());
26981ddcf01aSJason M. Bills                 if (ec.value() ==
26991ddcf01aSJason M. Bills                     boost::system::linux_error::bad_request_descriptor)
27001ddcf01aSJason M. Bills                 {
2701bd79bce8SPatrick Williams                     messages::resourceNotFound(asyncResp->res, "LogEntry",
2702bd79bce8SPatrick Williams                                                logID);
27031ddcf01aSJason M. Bills                 }
27041ddcf01aSJason M. Bills                 else
27051ddcf01aSJason M. Bills                 {
2706e855dd28SJason M. Bills                     messages::internalError(asyncResp->res);
27071ddcf01aSJason M. Bills                 }
2708e855dd28SJason M. Bills                 return;
2709e855dd28SJason M. Bills             }
2710043a0536SJohnathan Mantey 
2711043a0536SJohnathan Mantey             std::string timestamp{};
2712043a0536SJohnathan Mantey             std::string filename{};
2713043a0536SJohnathan Mantey             std::string logfile{};
27142c70f800SEd Tanous             parseCrashdumpParameters(params, filename, timestamp, logfile);
2715043a0536SJohnathan Mantey 
2716043a0536SJohnathan Mantey             if (filename.empty() || timestamp.empty())
2717e855dd28SJason M. Bills             {
27189db4ba25SJiaqing Zhao                 messages::resourceNotFound(asyncResp->res, "LogEntry", logID);
2719e855dd28SJason M. Bills                 return;
2720e855dd28SJason M. Bills             }
2721e855dd28SJason M. Bills 
2722043a0536SJohnathan Mantey             std::string crashdumpURI =
2723bd79bce8SPatrick Williams                 std::format(
2724bd79bce8SPatrick Williams                     "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries/",
2725253f11b8SEd Tanous                     BMCWEB_REDFISH_SYSTEM_URI_NAME) +
2726043a0536SJohnathan Mantey                 logID + "/" + filename;
272784afc48bSJason M. Bills             nlohmann::json::object_t logEntry;
27289c11a172SVijay Lobo             logEntry["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
2729ef4c65b7SEd Tanous             logEntry["@odata.id"] = boost::urls::format(
2730253f11b8SEd Tanous                 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries/{}",
2731253f11b8SEd Tanous                 BMCWEB_REDFISH_SYSTEM_URI_NAME, logID);
273284afc48bSJason M. Bills             logEntry["Name"] = "CPU Crashdump";
273384afc48bSJason M. Bills             logEntry["Id"] = logID;
2734539d8c6bSEd Tanous             logEntry["EntryType"] = log_entry::LogEntryType::Oem;
273584afc48bSJason M. Bills             logEntry["AdditionalDataURI"] = std::move(crashdumpURI);
273684afc48bSJason M. Bills             logEntry["DiagnosticDataType"] = "OEM";
273784afc48bSJason M. Bills             logEntry["OEMDiagnosticDataType"] = "PECICrashdump";
273884afc48bSJason M. Bills             logEntry["Created"] = std::move(timestamp);
27392b20ef6eSJason M. Bills 
27402b20ef6eSJason M. Bills             // If logEntryJson references an array of LogEntry resources
27412b20ef6eSJason M. Bills             // ('Members' list), then push this as a new entry, otherwise set it
27422b20ef6eSJason M. Bills             // directly
27432b20ef6eSJason M. Bills             if (logEntryJson.is_array())
27442b20ef6eSJason M. Bills             {
27452b20ef6eSJason M. Bills                 logEntryJson.push_back(logEntry);
27462b20ef6eSJason M. Bills                 asyncResp->res.jsonValue["Members@odata.count"] =
27472b20ef6eSJason M. Bills                     logEntryJson.size();
27482b20ef6eSJason M. Bills             }
27492b20ef6eSJason M. Bills             else
27502b20ef6eSJason M. Bills             {
2751d405bb51SJason M. Bills                 logEntryJson.update(logEntry);
27522b20ef6eSJason M. Bills             }
2753e855dd28SJason M. Bills         };
2754deae6a78SEd Tanous     dbus::utility::getAllProperties(
2755deae6a78SEd Tanous         crashdumpObject, crashdumpPath + std::string("/") + logID,
2756deae6a78SEd Tanous         crashdumpInterface, std::move(getStoredLogCallback));
2757e855dd28SJason M. Bills }
2758e855dd28SJason M. Bills 
27597e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpEntryCollection(App& app)
27601da66f75SEd Tanous {
27613946028dSAppaRao Puli     // Note: Deviated from redfish privilege registry for GET & HEAD
27623946028dSAppaRao Puli     // method for security reasons.
27631da66f75SEd Tanous     /**
27641da66f75SEd Tanous      * Functions triggers appropriate requests on DBus
27651da66f75SEd Tanous      */
27667e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
276722d268cbSEd Tanous                  "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/")
2768ed398213SEd Tanous         // This is incorrect, should be.
2769ed398213SEd Tanous         //.privileges(redfish::privileges::postLogEntryCollection)
2770432a890cSEd Tanous         .privileges({{"ConfigureComponents"}})
2771bd79bce8SPatrick Williams         .methods(
2772bd79bce8SPatrick Williams             boost::beast::http::verb::
2773bd79bce8SPatrick Williams                 get)([&app](const crow::Request& req,
277422d268cbSEd Tanous                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
277522d268cbSEd Tanous                             const std::string& systemName) {
27763ba00073SCarson Labrado             if (!redfish::setUpRedfishRoute(app, req, asyncResp))
277745ca1b86SEd Tanous             {
277845ca1b86SEd Tanous                 return;
277945ca1b86SEd Tanous             }
278025b54dbaSEd Tanous             if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
27817f3e84a1SEd Tanous             {
27827f3e84a1SEd Tanous                 // Option currently returns no systems.  TBD
27837f3e84a1SEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
27847f3e84a1SEd Tanous                                            systemName);
27857f3e84a1SEd Tanous                 return;
27867f3e84a1SEd Tanous             }
2787253f11b8SEd Tanous             if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
278822d268cbSEd Tanous             {
278922d268cbSEd Tanous                 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
279022d268cbSEd Tanous                                            systemName);
279122d268cbSEd Tanous                 return;
279222d268cbSEd Tanous             }
279322d268cbSEd Tanous 
27947a1dbc48SGeorge Liu             constexpr std::array<std::string_view, 1> interfaces = {
27957a1dbc48SGeorge Liu                 crashdumpInterface};
27967a1dbc48SGeorge Liu             dbus::utility::getSubTreePaths(
27977a1dbc48SGeorge Liu                 "/", 0, interfaces,
27987a1dbc48SGeorge Liu                 [asyncResp](const boost::system::error_code& ec,
27992b20ef6eSJason M. Bills                             const std::vector<std::string>& resp) {
28001da66f75SEd Tanous                     if (ec)
28011da66f75SEd Tanous                     {
28021da66f75SEd Tanous                         if (ec.value() !=
28031da66f75SEd Tanous                             boost::system::errc::no_such_file_or_directory)
28041da66f75SEd Tanous                         {
280562598e31SEd Tanous                             BMCWEB_LOG_DEBUG("failed to get entries ec: {}",
280662598e31SEd Tanous                                              ec.message());
2807f12894f8SJason M. Bills                             messages::internalError(asyncResp->res);
28081da66f75SEd Tanous                             return;
28091da66f75SEd Tanous                         }
28101da66f75SEd Tanous                     }
2811e1f26343SJason M. Bills                     asyncResp->res.jsonValue["@odata.type"] =
28121da66f75SEd Tanous                         "#LogEntryCollection.LogEntryCollection";
2813253f11b8SEd Tanous                     asyncResp->res.jsonValue["@odata.id"] = std::format(
2814253f11b8SEd Tanous                         "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries",
2815253f11b8SEd Tanous                         BMCWEB_REDFISH_SYSTEM_URI_NAME);
2816bd79bce8SPatrick Williams                     asyncResp->res.jsonValue["Name"] =
2817bd79bce8SPatrick Williams                         "Open BMC Crashdump Entries";
2818e1f26343SJason M. Bills                     asyncResp->res.jsonValue["Description"] =
2819424c4176SJason M. Bills                         "Collection of Crashdump Entries";
2820bd79bce8SPatrick Williams                     asyncResp->res.jsonValue["Members"] =
2821bd79bce8SPatrick Williams                         nlohmann::json::array();
2822a2dd60a6SBrandon Kim                     asyncResp->res.jsonValue["Members@odata.count"] = 0;
28232b20ef6eSJason M. Bills 
28242b20ef6eSJason M. Bills                     for (const std::string& path : resp)
28251da66f75SEd Tanous                     {
28262b20ef6eSJason M. Bills                         const sdbusplus::message::object_path objPath(path);
2827e855dd28SJason M. Bills                         // Get the log ID
28282b20ef6eSJason M. Bills                         std::string logID = objPath.filename();
28292b20ef6eSJason M. Bills                         if (logID.empty())
28301da66f75SEd Tanous                         {
2831e855dd28SJason M. Bills                             continue;
28321da66f75SEd Tanous                         }
2833e855dd28SJason M. Bills                         // Add the log entry to the array
28342b20ef6eSJason M. Bills                         logCrashdumpEntry(asyncResp, logID,
28352b20ef6eSJason M. Bills                                           asyncResp->res.jsonValue["Members"]);
28361da66f75SEd Tanous                     }
28377a1dbc48SGeorge Liu                 });
28387e860f15SJohn Edward Broadbent         });
28391da66f75SEd Tanous }
28401da66f75SEd Tanous 
28417e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpEntry(App& app)
28421da66f75SEd Tanous {
28433946028dSAppaRao Puli     // Note: Deviated from redfish privilege registry for GET & HEAD
28443946028dSAppaRao Puli     // method for security reasons.
28451da66f75SEd Tanous 
28467e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
284722d268cbSEd Tanous         app, "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/<str>/")
2848ed398213SEd Tanous         // this is incorrect, should be
2849ed398213SEd Tanous         // .privileges(redfish::privileges::getLogEntry)
2850432a890cSEd Tanous         .privileges({{"ConfigureComponents"}})
28517e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
285245ca1b86SEd Tanous             [&app](const crow::Request& req,
28537e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
285422d268cbSEd Tanous                    const std::string& systemName, const std::string& param) {
28553ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
285645ca1b86SEd Tanous                 {
285745ca1b86SEd Tanous                     return;
285845ca1b86SEd Tanous                 }
285925b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
28607f3e84a1SEd Tanous                 {
28617f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
28627f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
28637f3e84a1SEd Tanous                                                systemName);
28647f3e84a1SEd Tanous                     return;
28657f3e84a1SEd Tanous                 }
2866253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
286722d268cbSEd Tanous                 {
286822d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
286922d268cbSEd Tanous                                                systemName);
287022d268cbSEd Tanous                     return;
287122d268cbSEd Tanous                 }
28727e860f15SJohn Edward Broadbent                 const std::string& logID = param;
2873e855dd28SJason M. Bills                 logCrashdumpEntry(asyncResp, logID, asyncResp->res.jsonValue);
28747e860f15SJohn Edward Broadbent             });
2875e855dd28SJason M. Bills }
2876e855dd28SJason M. Bills 
28777e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpFile(App& app)
2878e855dd28SJason M. Bills {
28793946028dSAppaRao Puli     // Note: Deviated from redfish privilege registry for GET & HEAD
28803946028dSAppaRao Puli     // method for security reasons.
28817e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
28827e860f15SJohn Edward Broadbent         app,
288322d268cbSEd Tanous         "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/<str>/<str>/")
2884ed398213SEd Tanous         .privileges(redfish::privileges::getLogEntry)
28857e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
2886a4ce114aSNan Zhou             [](const crow::Request& req,
28877e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
288822d268cbSEd Tanous                const std::string& systemName, const std::string& logID,
288922d268cbSEd Tanous                const std::string& fileName) {
2890bd79bce8SPatrick Williams                 // Do not call getRedfishRoute here since the crashdump file is
2891bd79bce8SPatrick Williams                 // not a Redfish resource.
289222d268cbSEd Tanous 
289325b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
28947f3e84a1SEd Tanous                 {
28957f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
28967f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
28977f3e84a1SEd Tanous                                                systemName);
28987f3e84a1SEd Tanous                     return;
28997f3e84a1SEd Tanous                 }
2900253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
290122d268cbSEd Tanous                 {
290222d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
290322d268cbSEd Tanous                                                systemName);
290422d268cbSEd Tanous                     return;
290522d268cbSEd Tanous                 }
290622d268cbSEd Tanous 
2907043a0536SJohnathan Mantey                 auto getStoredLogCallback =
2908bd79bce8SPatrick Williams                     [asyncResp, logID, fileName,
2909bd79bce8SPatrick Williams                      url(boost::urls::url(req.url()))](
29105e7e2dc5SEd Tanous                         const boost::system::error_code& ec,
2911bd79bce8SPatrick Williams                         const std::vector<std::pair<
2912bd79bce8SPatrick Williams                             std::string, dbus::utility::DbusVariantType>>&
29137e860f15SJohn Edward Broadbent                             resp) {
29141da66f75SEd Tanous                         if (ec)
29151da66f75SEd Tanous                         {
2916bd79bce8SPatrick Williams                             BMCWEB_LOG_DEBUG("failed to get log ec: {}",
2917bd79bce8SPatrick Williams                                              ec.message());
2918f12894f8SJason M. Bills                             messages::internalError(asyncResp->res);
29191da66f75SEd Tanous                             return;
29201da66f75SEd Tanous                         }
2921e855dd28SJason M. Bills 
2922043a0536SJohnathan Mantey                         std::string dbusFilename{};
2923043a0536SJohnathan Mantey                         std::string dbusTimestamp{};
2924043a0536SJohnathan Mantey                         std::string dbusFilepath{};
2925043a0536SJohnathan Mantey 
2926bd79bce8SPatrick Williams                         parseCrashdumpParameters(resp, dbusFilename,
2927bd79bce8SPatrick Williams                                                  dbusTimestamp, dbusFilepath);
2928043a0536SJohnathan Mantey 
2929043a0536SJohnathan Mantey                         if (dbusFilename.empty() || dbusTimestamp.empty() ||
2930043a0536SJohnathan Mantey                             dbusFilepath.empty())
29311da66f75SEd Tanous                         {
2932bd79bce8SPatrick Williams                             messages::resourceNotFound(asyncResp->res,
2933bd79bce8SPatrick Williams                                                        "LogEntry", logID);
29341da66f75SEd Tanous                             return;
29351da66f75SEd Tanous                         }
2936e855dd28SJason M. Bills 
2937043a0536SJohnathan Mantey                         // Verify the file name parameter is correct
2938043a0536SJohnathan Mantey                         if (fileName != dbusFilename)
2939043a0536SJohnathan Mantey                         {
2940bd79bce8SPatrick Williams                             messages::resourceNotFound(asyncResp->res,
2941bd79bce8SPatrick Williams                                                        "LogEntry", logID);
2942043a0536SJohnathan Mantey                             return;
2943043a0536SJohnathan Mantey                         }
2944043a0536SJohnathan Mantey 
2945d51c61b4SMyung Bae                         if (asyncResp->res.openFile(dbusFilepath) !=
2946d51c61b4SMyung Bae                             crow::OpenCode::Success)
2947043a0536SJohnathan Mantey                         {
2948bd79bce8SPatrick Williams                             messages::resourceNotFound(asyncResp->res,
2949bd79bce8SPatrick Williams                                                        "LogEntry", logID);
2950043a0536SJohnathan Mantey                             return;
2951043a0536SJohnathan Mantey                         }
2952043a0536SJohnathan Mantey 
29537e860f15SJohn Edward Broadbent                         // Configure this to be a file download when accessed
29547e860f15SJohn Edward Broadbent                         // from a browser
2955d9f6c621SEd Tanous                         asyncResp->res.addHeader(
2956bd79bce8SPatrick Williams                             boost::beast::http::field::content_disposition,
2957bd79bce8SPatrick Williams                             "attachment");
29581da66f75SEd Tanous                     };
2959deae6a78SEd Tanous                 dbus::utility::getAllProperties(
2960d1bde9e5SKrzysztof Grobelny                     *crow::connections::systemBus, crashdumpObject,
2961bd79bce8SPatrick Williams                     crashdumpPath + std::string("/") + logID,
2962bd79bce8SPatrick Williams                     crashdumpInterface, std::move(getStoredLogCallback));
29637e860f15SJohn Edward Broadbent             });
29641da66f75SEd Tanous }
29651da66f75SEd Tanous 
2966c5a4c82aSJason M. Bills enum class OEMDiagnosticType
2967c5a4c82aSJason M. Bills {
2968c5a4c82aSJason M. Bills     onDemand,
2969c5a4c82aSJason M. Bills     telemetry,
2970c5a4c82aSJason M. Bills     invalid,
2971c5a4c82aSJason M. Bills };
2972c5a4c82aSJason M. Bills 
297326ccae32SEd Tanous inline OEMDiagnosticType getOEMDiagnosticType(std::string_view oemDiagStr)
2974c5a4c82aSJason M. Bills {
2975c5a4c82aSJason M. Bills     if (oemDiagStr == "OnDemand")
2976c5a4c82aSJason M. Bills     {
2977c5a4c82aSJason M. Bills         return OEMDiagnosticType::onDemand;
2978c5a4c82aSJason M. Bills     }
2979c5a4c82aSJason M. Bills     if (oemDiagStr == "Telemetry")
2980c5a4c82aSJason M. Bills     {
2981c5a4c82aSJason M. Bills         return OEMDiagnosticType::telemetry;
2982c5a4c82aSJason M. Bills     }
2983c5a4c82aSJason M. Bills 
2984c5a4c82aSJason M. Bills     return OEMDiagnosticType::invalid;
2985c5a4c82aSJason M. Bills }
2986c5a4c82aSJason M. Bills 
29877e860f15SJohn Edward Broadbent inline void requestRoutesCrashdumpCollect(App& app)
29881da66f75SEd Tanous {
29893946028dSAppaRao Puli     // Note: Deviated from redfish privilege registry for GET & HEAD
29903946028dSAppaRao Puli     // method for security reasons.
29910fda0f12SGeorge Liu     BMCWEB_ROUTE(
29920fda0f12SGeorge Liu         app,
299322d268cbSEd Tanous         "/redfish/v1/Systems/<str>/LogServices/Crashdump/Actions/LogService.CollectDiagnosticData/")
2994ed398213SEd Tanous         // The below is incorrect;  Should be ConfigureManager
2995ed398213SEd Tanous         //.privileges(redfish::privileges::postLogService)
2996432a890cSEd Tanous         .privileges({{"ConfigureComponents"}})
2997002d39b4SEd Tanous         .methods(boost::beast::http::verb::post)(
2998002d39b4SEd Tanous             [&app](const crow::Request& req,
299922d268cbSEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
300022d268cbSEd Tanous                    const std::string& systemName) {
30013ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
300245ca1b86SEd Tanous                 {
300345ca1b86SEd Tanous                     return;
300445ca1b86SEd Tanous                 }
300522d268cbSEd Tanous 
300625b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
30077f3e84a1SEd Tanous                 {
30087f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
30097f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
30107f3e84a1SEd Tanous                                                systemName);
30117f3e84a1SEd Tanous                     return;
30127f3e84a1SEd Tanous                 }
3013253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
301422d268cbSEd Tanous                 {
301522d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
301622d268cbSEd Tanous                                                systemName);
301722d268cbSEd Tanous                     return;
301822d268cbSEd Tanous                 }
301922d268cbSEd Tanous 
30208e6c099aSJason M. Bills                 std::string diagnosticDataType;
30218e6c099aSJason M. Bills                 std::string oemDiagnosticDataType;
3022afc474aeSMyung Bae                 if (!redfish::json_util::readJsonAction(               //
3023afc474aeSMyung Bae                         req, asyncResp->res,                           //
3024afc474aeSMyung Bae                         "DiagnosticDataType", diagnosticDataType,      //
3025afc474aeSMyung Bae                         "OEMDiagnosticDataType", oemDiagnosticDataType //
3026afc474aeSMyung Bae                         ))
30278e6c099aSJason M. Bills                 {
30288e6c099aSJason M. Bills                     return;
30298e6c099aSJason M. Bills                 }
30308e6c099aSJason M. Bills 
30318e6c099aSJason M. Bills                 if (diagnosticDataType != "OEM")
30328e6c099aSJason M. Bills                 {
303362598e31SEd Tanous                     BMCWEB_LOG_ERROR(
303462598e31SEd Tanous                         "Only OEM DiagnosticDataType supported for Crashdump");
30358e6c099aSJason M. Bills                     messages::actionParameterValueFormatError(
3036bd79bce8SPatrick Williams                         asyncResp->res, diagnosticDataType,
3037bd79bce8SPatrick Williams                         "DiagnosticDataType", "CollectDiagnosticData");
30388e6c099aSJason M. Bills                     return;
30398e6c099aSJason M. Bills                 }
30408e6c099aSJason M. Bills 
3041c5a4c82aSJason M. Bills                 OEMDiagnosticType oemDiagType =
3042c5a4c82aSJason M. Bills                     getOEMDiagnosticType(oemDiagnosticDataType);
3043c5a4c82aSJason M. Bills 
3044c5a4c82aSJason M. Bills                 std::string iface;
3045c5a4c82aSJason M. Bills                 std::string method;
3046c5a4c82aSJason M. Bills                 std::string taskMatchStr;
3047c5a4c82aSJason M. Bills                 if (oemDiagType == OEMDiagnosticType::onDemand)
3048c5a4c82aSJason M. Bills                 {
3049c5a4c82aSJason M. Bills                     iface = crashdumpOnDemandInterface;
3050c5a4c82aSJason M. Bills                     method = "GenerateOnDemandLog";
3051bd79bce8SPatrick Williams                     taskMatchStr =
3052bd79bce8SPatrick Williams                         "type='signal',"
3053c5a4c82aSJason M. Bills                         "interface='org.freedesktop.DBus.Properties',"
3054c5a4c82aSJason M. Bills                         "member='PropertiesChanged',"
3055c5a4c82aSJason M. Bills                         "arg0namespace='com.intel.crashdump'";
3056c5a4c82aSJason M. Bills                 }
3057c5a4c82aSJason M. Bills                 else if (oemDiagType == OEMDiagnosticType::telemetry)
3058c5a4c82aSJason M. Bills                 {
3059c5a4c82aSJason M. Bills                     iface = crashdumpTelemetryInterface;
3060c5a4c82aSJason M. Bills                     method = "GenerateTelemetryLog";
3061bd79bce8SPatrick Williams                     taskMatchStr =
3062bd79bce8SPatrick Williams                         "type='signal',"
3063c5a4c82aSJason M. Bills                         "interface='org.freedesktop.DBus.Properties',"
3064c5a4c82aSJason M. Bills                         "member='PropertiesChanged',"
3065c5a4c82aSJason M. Bills                         "arg0namespace='com.intel.crashdump'";
3066c5a4c82aSJason M. Bills                 }
3067c5a4c82aSJason M. Bills                 else
3068c5a4c82aSJason M. Bills                 {
306962598e31SEd Tanous                     BMCWEB_LOG_ERROR("Unsupported OEMDiagnosticDataType: {}",
307062598e31SEd Tanous                                      oemDiagnosticDataType);
3071c5a4c82aSJason M. Bills                     messages::actionParameterValueFormatError(
3072bd79bce8SPatrick Williams                         asyncResp->res, oemDiagnosticDataType,
3073bd79bce8SPatrick Williams                         "OEMDiagnosticDataType", "CollectDiagnosticData");
3074c5a4c82aSJason M. Bills                     return;
3075c5a4c82aSJason M. Bills                 }
3076c5a4c82aSJason M. Bills 
3077c5a4c82aSJason M. Bills                 auto collectCrashdumpCallback =
3078c5a4c82aSJason M. Bills                     [asyncResp, payload(task::Payload(req)),
30795e7e2dc5SEd Tanous                      taskMatchStr](const boost::system::error_code& ec,
308098be3e39SEd Tanous                                    const std::string&) mutable {
30811da66f75SEd Tanous                         if (ec)
30821da66f75SEd Tanous                         {
3083bd79bce8SPatrick Williams                             if (ec.value() ==
3084bd79bce8SPatrick Williams                                 boost::system::errc::operation_not_supported)
30851da66f75SEd Tanous                             {
3086f12894f8SJason M. Bills                                 messages::resourceInStandby(asyncResp->res);
30871da66f75SEd Tanous                             }
3088bd79bce8SPatrick Williams                             else if (ec.value() == boost::system::errc::
3089bd79bce8SPatrick Williams                                                        device_or_resource_busy)
30904363d3b2SJason M. Bills                             {
3091bd79bce8SPatrick Williams                                 messages::serviceTemporarilyUnavailable(
3092bd79bce8SPatrick Williams                                     asyncResp->res, "60");
30934363d3b2SJason M. Bills                             }
30941da66f75SEd Tanous                             else
30951da66f75SEd Tanous                             {
3096f12894f8SJason M. Bills                                 messages::internalError(asyncResp->res);
30971da66f75SEd Tanous                             }
30981da66f75SEd Tanous                             return;
30991da66f75SEd Tanous                         }
3100bd79bce8SPatrick Williams                         std::shared_ptr<task::TaskData> task =
3101bd79bce8SPatrick Williams                             task::TaskData::createTask(
3102bd79bce8SPatrick Williams                                 [](const boost::system::error_code& ec2,
3103bd79bce8SPatrick Williams                                    sdbusplus::message_t&,
3104bd79bce8SPatrick Williams                                    const std::shared_ptr<task::TaskData>&
3105bd79bce8SPatrick Williams                                        taskData) {
31068b24275dSEd Tanous                                     if (!ec2)
310766afe4faSJames Feist                                     {
3108bd79bce8SPatrick Williams                                         taskData->messages.emplace_back(
3109bd79bce8SPatrick Williams                                             messages::taskCompletedOK(
3110bd79bce8SPatrick Williams                                                 std::to_string(
3111bd79bce8SPatrick Williams                                                     taskData->index)));
3112831d6b09SJames Feist                                         taskData->state = "Completed";
311366afe4faSJames Feist                                     }
311432898ceaSJames Feist                                     return task::completed;
311566afe4faSJames Feist                                 },
3116c5a4c82aSJason M. Bills                                 taskMatchStr);
3117c5a4c82aSJason M. Bills 
311846229577SJames Feist                         task->startTimer(std::chrono::minutes(5));
311998be3e39SEd Tanous                         task->payload.emplace(std::move(payload));
3120*29e2bdd7SChinmay Shripad Hegde                         task->populateResp(asyncResp->res);
31211da66f75SEd Tanous                     };
31228e6c099aSJason M. Bills 
3123177612aaSEd Tanous                 dbus::utility::async_method_call(
3124177612aaSEd Tanous                     asyncResp, std::move(collectCrashdumpCallback),
3125177612aaSEd Tanous                     crashdumpObject, crashdumpPath, iface, method);
31267e860f15SJohn Edward Broadbent             });
31276eda7685SKenny L. Ku }
31286eda7685SKenny L. Ku 
3129599b9af3SAlexander Hansen inline void dBusLogServiceActionsClear(
3130599b9af3SAlexander Hansen     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
3131599b9af3SAlexander Hansen {
3132599b9af3SAlexander Hansen     BMCWEB_LOG_DEBUG("Do delete all entries.");
3133599b9af3SAlexander Hansen 
3134599b9af3SAlexander Hansen     // Process response from Logging service.
3135599b9af3SAlexander Hansen     auto respHandler = [asyncResp](const boost::system::error_code& ec) {
3136599b9af3SAlexander Hansen         BMCWEB_LOG_DEBUG("doClearLog resp_handler callback: Done");
3137599b9af3SAlexander Hansen         if (ec)
3138599b9af3SAlexander Hansen         {
3139599b9af3SAlexander Hansen             // TODO Handle for specific error code
3140599b9af3SAlexander Hansen             BMCWEB_LOG_ERROR("doClearLog resp_handler got error {}", ec);
3141599b9af3SAlexander Hansen             asyncResp->res.result(
3142599b9af3SAlexander Hansen                 boost::beast::http::status::internal_server_error);
3143599b9af3SAlexander Hansen             return;
3144599b9af3SAlexander Hansen         }
3145599b9af3SAlexander Hansen 
3146e2460466SAmy Chang         messages::success(asyncResp->res);
3147599b9af3SAlexander Hansen     };
3148599b9af3SAlexander Hansen 
3149599b9af3SAlexander Hansen     // Make call to Logging service to request Clear Log
3150177612aaSEd Tanous     dbus::utility::async_method_call(
3151177612aaSEd Tanous         asyncResp, respHandler, "xyz.openbmc_project.Logging",
3152599b9af3SAlexander Hansen         "/xyz/openbmc_project/logging",
3153599b9af3SAlexander Hansen         "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
3154599b9af3SAlexander Hansen }
3155599b9af3SAlexander Hansen 
3156cb92c03bSAndrew Geissler /**
3157cb92c03bSAndrew Geissler  * DBusLogServiceActionsClear class supports POST method for ClearLog action.
3158cb92c03bSAndrew Geissler  */
31597e860f15SJohn Edward Broadbent inline void requestRoutesDBusLogServiceActionsClear(App& app)
3160cb92c03bSAndrew Geissler {
3161cb92c03bSAndrew Geissler     /**
3162cb92c03bSAndrew Geissler      * Function handles POST method request.
3163cb92c03bSAndrew Geissler      * The Clear Log actions does not require any parameter.The action deletes
3164cb92c03bSAndrew Geissler      * all entries found in the Entries collection for this Log Service.
3165cb92c03bSAndrew Geissler      */
31667e860f15SJohn Edward Broadbent 
31670fda0f12SGeorge Liu     BMCWEB_ROUTE(
31680fda0f12SGeorge Liu         app,
316922d268cbSEd Tanous         "/redfish/v1/Systems/<str>/LogServices/EventLog/Actions/LogService.ClearLog/")
3170ed398213SEd Tanous         .privileges(redfish::privileges::postLogService)
31717e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
317245ca1b86SEd Tanous             [&app](const crow::Request& req,
317322d268cbSEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
317422d268cbSEd Tanous                    const std::string& systemName) {
31753ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
317645ca1b86SEd Tanous                 {
317745ca1b86SEd Tanous                     return;
317845ca1b86SEd Tanous                 }
317925b54dbaSEd Tanous                 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
31807f3e84a1SEd Tanous                 {
31817f3e84a1SEd Tanous                     // Option currently returns no systems.  TBD
31827f3e84a1SEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
31837f3e84a1SEd Tanous                                                systemName);
31847f3e84a1SEd Tanous                     return;
31857f3e84a1SEd Tanous                 }
3186253f11b8SEd Tanous                 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
318722d268cbSEd Tanous                 {
318822d268cbSEd Tanous                     messages::resourceNotFound(asyncResp->res, "ComputerSystem",
318922d268cbSEd Tanous                                                systemName);
319022d268cbSEd Tanous                     return;
319122d268cbSEd Tanous                 }
3192599b9af3SAlexander Hansen                 dBusLogServiceActionsClear(asyncResp);
31937e860f15SJohn Edward Broadbent             });
3194cb92c03bSAndrew Geissler }
3195a3316fc6SZhikuiRen 
31961da66f75SEd Tanous } // namespace redfish
3197