blob: c65875a36992816e852dd97214ddac8769aa35f5 [file] [log] [blame]
Ed Tanous40e9b922024-09-10 13:50:16 -07001// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright OpenBMC Authors
3// SPDX-FileCopyrightText: Copyright 2018 Intel Corporation
Ed Tanous1da66f72018-07-27 16:13:37 -07004#pragma once
5
Ed Tanousd7857202025-01-28 15:32:26 -08006#include "bmcweb_config.h"
7
Ed Tanous3ccb3ad2023-01-13 17:40:03 -08008#include "app.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -08009#include "async_resp.hpp"
10#include "dbus_singleton.hpp"
George Liu7a1dbc42022-12-07 16:03:22 +080011#include "dbus_utility.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080012#include "error_messages.hpp"
Asmitha Karunanithi68dd0752022-11-15 11:33:46 -060013#include "generated/enums/log_entry.hpp"
Ed Tanous539d8c62024-06-19 14:38:27 -070014#include "generated/enums/log_service.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080015#include "http_body.hpp"
16#include "http_request.hpp"
17#include "http_response.hpp"
George Liu647b3cd2021-07-05 12:43:56 +080018#include "http_utility.hpp"
Spencer Kub7028eb2021-10-26 15:27:35 +080019#include "human_sort.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080020#include "logging.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080021#include "query.hpp"
Jason M. Bills4851d452019-03-28 11:27:48 -070022#include "registries.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080023#include "registries/privilege_registry.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080024#include "str_utility.hpp"
James Feist46229572020-02-19 15:11:58 -080025#include "task.hpp"
Ed Tanous5b904292024-04-16 11:10:17 -070026#include "task_messages.hpp"
Alexander Hansen262dcc12024-09-19 12:04:03 +020027#include "utils/dbus_event_log_entry.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080028#include "utils/dbus_utils.hpp"
Ed Tanous5b904292024-04-16 11:10:17 -070029#include "utils/json_utils.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080030#include "utils/query_param.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080031#include "utils/time_utils.hpp"
Ed Tanous1da66f72018-07-27 16:13:37 -070032
Ed Tanousd7857202025-01-28 15:32:26 -080033#include <asm-generic/errno.h>
34#include <systemd/sd-bus.h>
Asmitha Karunanithi8e317782020-12-10 03:35:05 -060035#include <tinyxml2.h>
Adriana Kobylak400fd1f2021-01-29 09:01:30 -060036#include <unistd.h>
Jason M. Billse1f26342018-07-18 12:12:00 -070037
Ed Tanousd7857202025-01-28 15:32:26 -080038#include <boost/beast/http/field.hpp>
39#include <boost/beast/http/status.hpp>
Ed Tanous07c8c202022-07-11 10:08:08 -070040#include <boost/beast/http/verb.hpp>
Jason M. Bills1ddcf012019-11-26 14:59:21 -080041#include <boost/system/linux_error.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070042#include <boost/url/format.hpp>
Ed Tanousd7857202025-01-28 15:32:26 -080043#include <boost/url/url.hpp>
44#include <sdbusplus/message.hpp>
45#include <sdbusplus/message/native_types.hpp>
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +020046#include <sdbusplus/unpack_properties.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050047
Ed Tanousd7857202025-01-28 15:32:26 -080048#include <algorithm>
George Liu7a1dbc42022-12-07 16:03:22 +080049#include <array>
Ed Tanousd7857202025-01-28 15:32:26 -080050#include <chrono>
Abhilash Rajub5f288d2023-11-08 22:32:44 -060051#include <cstddef>
Ed Tanousd7857202025-01-28 15:32:26 -080052#include <cstdint>
53#include <cstdio>
54#include <ctime>
James Feist4418c7f2019-04-15 11:09:15 -070055#include <filesystem>
Ed Tanousd7857202025-01-28 15:32:26 -080056#include <format>
57#include <fstream>
58#include <functional>
59#include <iomanip>
Ed Tanous18f8f602023-07-18 10:07:23 -070060#include <iterator>
Ed Tanousd7857202025-01-28 15:32:26 -080061#include <memory>
Xiaochao Ma75710de2021-01-21 17:56:02 +080062#include <optional>
Ed Tanous3544d2a2023-08-06 18:12:20 -070063#include <ranges>
Ed Tanous26702d02021-11-03 15:02:33 -070064#include <span>
Ed Tanousd7857202025-01-28 15:32:26 -080065#include <sstream>
Ed Tanous18f8f602023-07-18 10:07:23 -070066#include <string>
Jason M. Billscd225da2019-05-08 15:31:57 -070067#include <string_view>
Ed Tanousd7857202025-01-28 15:32:26 -080068#include <system_error>
69#include <utility>
Ed Tanousabf2add2019-01-22 16:40:12 -080070#include <variant>
Ed Tanousd7857202025-01-28 15:32:26 -080071#include <vector>
Ed Tanous1da66f72018-07-27 16:13:37 -070072
73namespace redfish
74{
75
Patrick Williams89492a12023-05-10 07:51:34 -050076constexpr const char* crashdumpObject = "com.intel.crashdump";
77constexpr const char* crashdumpPath = "/com/intel/crashdump";
78constexpr const char* crashdumpInterface = "com.intel.crashdump";
79constexpr const char* deleteAllInterface =
Jason M. Bills5b61b5e2019-10-16 10:59:02 -070080 "xyz.openbmc_project.Collection.DeleteAll";
Patrick Williams89492a12023-05-10 07:51:34 -050081constexpr const char* crashdumpOnDemandInterface =
Jason M. Bills424c4172019-03-21 13:50:33 -070082 "com.intel.crashdump.OnDemand";
Patrick Williams89492a12023-05-10 07:51:34 -050083constexpr const char* crashdumpTelemetryInterface =
Kenny L. Ku6eda7682020-06-19 09:48:36 -070084 "com.intel.crashdump.Telemetry";
Ed Tanous1da66f72018-07-27 16:13:37 -070085
Asmitha Karunanithi8e317782020-12-10 03:35:05 -060086enum class DumpCreationProgress
87{
88 DUMP_CREATE_SUCCESS,
89 DUMP_CREATE_FAILED,
90 DUMP_CREATE_INPROGRESS
91};
92
Gunnar Mills1214b7e2020-06-04 10:11:30 -050093inline std::string translateSeverityDbusToRedfish(const std::string& s)
Andrew Geisslercb92c032018-08-17 07:56:14 -070094{
Ed Tanousd4d25792020-09-29 15:15:03 -070095 if ((s == "xyz.openbmc_project.Logging.Entry.Level.Alert") ||
96 (s == "xyz.openbmc_project.Logging.Entry.Level.Critical") ||
97 (s == "xyz.openbmc_project.Logging.Entry.Level.Emergency") ||
98 (s == "xyz.openbmc_project.Logging.Entry.Level.Error"))
Andrew Geisslercb92c032018-08-17 07:56:14 -070099 {
100 return "Critical";
101 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700102 if ((s == "xyz.openbmc_project.Logging.Entry.Level.Debug") ||
103 (s == "xyz.openbmc_project.Logging.Entry.Level.Informational") ||
104 (s == "xyz.openbmc_project.Logging.Entry.Level.Notice"))
Andrew Geisslercb92c032018-08-17 07:56:14 -0700105 {
106 return "OK";
107 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700108 if (s == "xyz.openbmc_project.Logging.Entry.Level.Warning")
Andrew Geisslercb92c032018-08-17 07:56:14 -0700109 {
110 return "Warning";
111 }
112 return "";
113}
114
Abhishek Patel9017faf2021-09-14 22:48:55 -0500115inline std::optional<bool> getProviderNotifyAction(const std::string& notify)
116{
117 std::optional<bool> notifyAction;
118 if (notify == "xyz.openbmc_project.Logging.Entry.Notify.Notify")
119 {
120 notifyAction = true;
121 }
122 else if (notify == "xyz.openbmc_project.Logging.Entry.Notify.Inhibit")
123 {
124 notifyAction = false;
125 }
126
127 return notifyAction;
128}
129
Ed Tanous18f8f602023-07-18 10:07:23 -0700130inline std::string getDumpPath(std::string_view dumpType)
131{
132 std::string dbusDumpPath = "/xyz/openbmc_project/dump/";
133 std::ranges::transform(dumpType, std::back_inserter(dbusDumpPath),
134 bmcweb::asciiToLower);
135
136 return dbusDumpPath;
137}
138
Ed Tanous055713e2024-07-17 17:19:36 -0700139inline bool getUniqueEntryID(const std::string& logEntry, std::string& entryID,
Jason M. Billse85d6b12019-07-29 17:01:15 -0700140 const bool firstEntry = true)
Jason M. Bills95820182019-04-22 16:25:34 -0700141{
Ed Tanous271584a2019-07-09 16:24:22 -0700142 static time_t prevTs = 0;
Jason M. Bills95820182019-04-22 16:25:34 -0700143 static int index = 0;
Jason M. Billse85d6b12019-07-29 17:01:15 -0700144 if (firstEntry)
145 {
146 prevTs = 0;
147 }
148
Jason M. Bills95820182019-04-22 16:25:34 -0700149 // Get the entry timestamp
Ed Tanous271584a2019-07-09 16:24:22 -0700150 std::time_t curTs = 0;
Jason M. Bills95820182019-04-22 16:25:34 -0700151 std::tm timeStruct = {};
152 std::istringstream entryStream(logEntry);
153 if (entryStream >> std::get_time(&timeStruct, "%Y-%m-%dT%H:%M:%S"))
154 {
155 curTs = std::mktime(&timeStruct);
156 }
157 // If the timestamp isn't unique, increment the index
158 if (curTs == prevTs)
159 {
160 index++;
161 }
162 else
163 {
164 // Otherwise, reset it
165 index = 0;
166 }
167 // Save the timestamp
168 prevTs = curTs;
169
170 entryID = std::to_string(curTs);
171 if (index > 0)
172 {
173 entryID += "_" + std::to_string(index);
174 }
175 return true;
176}
177
Patrick Williams504af5a2025-02-03 14:29:03 -0500178inline bool getRedfishLogFiles(
179 std::vector<std::filesystem::path>& redfishLogFiles)
Jason M. Bills95820182019-04-22 16:25:34 -0700180{
181 static const std::filesystem::path redfishLogDir = "/var/log";
182 static const std::string redfishLogFilename = "redfish";
183
184 // Loop through the directory looking for redfish log files
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500185 for (const std::filesystem::directory_entry& dirEnt :
Jason M. Bills95820182019-04-22 16:25:34 -0700186 std::filesystem::directory_iterator(redfishLogDir))
187 {
188 // If we find a redfish log file, save the path
189 std::string filename = dirEnt.path().filename();
Ed Tanous11ba3972022-07-11 09:50:41 -0700190 if (filename.starts_with(redfishLogFilename))
Jason M. Bills95820182019-04-22 16:25:34 -0700191 {
192 redfishLogFiles.emplace_back(redfishLogDir / filename);
193 }
194 }
195 // As the log files rotate, they are appended with a ".#" that is higher for
196 // the older logs. Since we don't expect more than 10 log files, we
197 // can just sort the list to get them in order from newest to oldest
Ed Tanous3544d2a2023-08-06 18:12:20 -0700198 std::ranges::sort(redfishLogFiles);
Jason M. Bills95820182019-04-22 16:25:34 -0700199
200 return !redfishLogFiles.empty();
201}
202
Patrick Williams504af5a2025-02-03 14:29:03 -0500203inline log_entry::OriginatorTypes mapDbusOriginatorTypeToRedfish(
204 const std::string& originatorType)
Asmitha Karunanithi68dd0752022-11-15 11:33:46 -0600205{
206 if (originatorType ==
207 "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Client")
208 {
209 return log_entry::OriginatorTypes::Client;
210 }
211 if (originatorType ==
212 "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Internal")
213 {
214 return log_entry::OriginatorTypes::Internal;
215 }
216 if (originatorType ==
217 "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.SupportingService")
218 {
219 return log_entry::OriginatorTypes::SupportingService;
220 }
221 return log_entry::OriginatorTypes::Invalid;
222}
223
Claire Weinanaefe3782022-07-15 19:17:19 -0700224inline void parseDumpEntryFromDbusObject(
Jiaqing Zhao2d613eb2022-08-15 16:03:00 +0800225 const dbus::utility::ManagedObjectType::value_type& object,
Claire Weinanc6fecda2022-07-15 10:43:25 -0700226 std::string& dumpStatus, uint64_t& size, uint64_t& timestampUs,
Asmitha Karunanithi68dd0752022-11-15 11:33:46 -0600227 std::string& originatorId, log_entry::OriginatorTypes& originatorType,
Claire Weinanaefe3782022-07-15 19:17:19 -0700228 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
229{
230 for (const auto& interfaceMap : object.second)
231 {
232 if (interfaceMap.first == "xyz.openbmc_project.Common.Progress")
233 {
234 for (const auto& propertyMap : interfaceMap.second)
235 {
236 if (propertyMap.first == "Status")
237 {
238 const auto* status =
239 std::get_if<std::string>(&propertyMap.second);
240 if (status == nullptr)
241 {
242 messages::internalError(asyncResp->res);
243 break;
244 }
245 dumpStatus = *status;
246 }
247 }
248 }
249 else if (interfaceMap.first == "xyz.openbmc_project.Dump.Entry")
250 {
251 for (const auto& propertyMap : interfaceMap.second)
252 {
253 if (propertyMap.first == "Size")
254 {
255 const auto* sizePtr =
256 std::get_if<uint64_t>(&propertyMap.second);
257 if (sizePtr == nullptr)
258 {
259 messages::internalError(asyncResp->res);
260 break;
261 }
262 size = *sizePtr;
263 break;
264 }
265 }
266 }
267 else if (interfaceMap.first == "xyz.openbmc_project.Time.EpochTime")
268 {
269 for (const auto& propertyMap : interfaceMap.second)
270 {
271 if (propertyMap.first == "Elapsed")
272 {
273 const uint64_t* usecsTimeStamp =
274 std::get_if<uint64_t>(&propertyMap.second);
275 if (usecsTimeStamp == nullptr)
276 {
277 messages::internalError(asyncResp->res);
278 break;
279 }
Claire Weinanc6fecda2022-07-15 10:43:25 -0700280 timestampUs = *usecsTimeStamp;
Claire Weinanaefe3782022-07-15 19:17:19 -0700281 break;
282 }
283 }
284 }
Asmitha Karunanithi68dd0752022-11-15 11:33:46 -0600285 else if (interfaceMap.first ==
286 "xyz.openbmc_project.Common.OriginatedBy")
287 {
288 for (const auto& propertyMap : interfaceMap.second)
289 {
290 if (propertyMap.first == "OriginatorId")
291 {
292 const std::string* id =
293 std::get_if<std::string>(&propertyMap.second);
294 if (id == nullptr)
295 {
296 messages::internalError(asyncResp->res);
297 break;
298 }
299 originatorId = *id;
300 }
301
302 if (propertyMap.first == "OriginatorType")
303 {
304 const std::string* type =
305 std::get_if<std::string>(&propertyMap.second);
306 if (type == nullptr)
307 {
308 messages::internalError(asyncResp->res);
309 break;
310 }
311
312 originatorType = mapDbusOriginatorTypeToRedfish(*type);
313 if (originatorType == log_entry::OriginatorTypes::Invalid)
314 {
315 messages::internalError(asyncResp->res);
316 break;
317 }
318 }
319 }
320 }
Claire Weinanaefe3782022-07-15 19:17:19 -0700321 }
322}
323
Nan Zhou21ab4042022-06-26 23:07:40 +0000324static std::string getDumpEntriesPath(const std::string& dumpType)
Claire Weinanfdd26902022-03-01 14:18:25 -0800325{
326 std::string entriesPath;
327
328 if (dumpType == "BMC")
329 {
Ed Tanous253f11b2024-05-16 09:38:31 -0700330 entriesPath =
331 std::format("/redfish/v1/Managers/{}/LogServices/Dump/Entries/",
332 BMCWEB_REDFISH_MANAGER_URI_NAME);
Claire Weinanfdd26902022-03-01 14:18:25 -0800333 }
334 else if (dumpType == "FaultLog")
335 {
Ed Tanous253f11b2024-05-16 09:38:31 -0700336 entriesPath =
337 std::format("/redfish/v1/Managers/{}/LogServices/FaultLog/Entries/",
338 BMCWEB_REDFISH_MANAGER_URI_NAME);
Claire Weinanfdd26902022-03-01 14:18:25 -0800339 }
340 else if (dumpType == "System")
341 {
Ed Tanous253f11b2024-05-16 09:38:31 -0700342 entriesPath =
343 std::format("/redfish/v1/Systems/{}/LogServices/Dump/Entries/",
344 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Claire Weinanfdd26902022-03-01 14:18:25 -0800345 }
346 else
347 {
Ed Tanous62598e32023-07-17 17:06:25 -0700348 BMCWEB_LOG_ERROR("getDumpEntriesPath() invalid dump type: {}",
349 dumpType);
Claire Weinanfdd26902022-03-01 14:18:25 -0800350 }
351
352 // Returns empty string on error
353 return entriesPath;
354}
355
Patrick Williams504af5a2025-02-03 14:29:03 -0500356inline void getDumpEntryCollection(
357 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
358 const std::string& dumpType)
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500359{
Claire Weinanfdd26902022-03-01 14:18:25 -0800360 std::string entriesPath = getDumpEntriesPath(dumpType);
361 if (entriesPath.empty())
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500362 {
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500363 messages::internalError(asyncResp->res);
364 return;
365 }
366
George Liu5eb468d2023-06-20 17:03:24 +0800367 sdbusplus::message::object_path path("/xyz/openbmc_project/dump");
368 dbus::utility::getManagedObjects(
369 "xyz.openbmc_project.Dump.Manager", path,
Claire Weinanfdd26902022-03-01 14:18:25 -0800370 [asyncResp, entriesPath,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800371 dumpType](const boost::system::error_code& ec,
George Liu5eb468d2023-06-20 17:03:24 +0800372 const dbus::utility::ManagedObjectType& objects) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400373 if (ec)
374 {
375 BMCWEB_LOG_ERROR("DumpEntry resp_handler got error {}", ec);
376 messages::internalError(asyncResp->res);
377 return;
378 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700379
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400380 // Remove ending slash
381 std::string odataIdStr = entriesPath;
382 if (!odataIdStr.empty())
383 {
384 odataIdStr.pop_back();
385 }
Claire Weinanfdd26902022-03-01 14:18:25 -0800386
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400387 asyncResp->res.jsonValue["@odata.type"] =
388 "#LogEntryCollection.LogEntryCollection";
389 asyncResp->res.jsonValue["@odata.id"] = std::move(odataIdStr);
390 asyncResp->res.jsonValue["Name"] = dumpType + " Dump Entries";
391 asyncResp->res.jsonValue["Description"] =
392 "Collection of " + dumpType + " Dump Entries";
Claire Weinanfdd26902022-03-01 14:18:25 -0800393
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400394 nlohmann::json::array_t entriesArray;
395 std::string dumpEntryPath = getDumpPath(dumpType) + "/entry/";
Ed Tanous002d39b2022-05-31 08:59:27 -0700396
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400397 dbus::utility::ManagedObjectType resp(objects);
398 std::ranges::sort(resp, [](const auto& l, const auto& r) {
399 return AlphanumLess<std::string>()(l.first.filename(),
400 r.first.filename());
401 });
402
403 for (auto& object : resp)
404 {
405 if (object.first.str.find(dumpEntryPath) == std::string::npos)
406 {
407 continue;
408 }
409 uint64_t timestampUs = 0;
410 uint64_t size = 0;
411 std::string dumpStatus;
412 std::string originatorId;
413 log_entry::OriginatorTypes originatorType =
414 log_entry::OriginatorTypes::Internal;
415 nlohmann::json::object_t thisEntry;
416
417 std::string entryID = object.first.filename();
418 if (entryID.empty())
419 {
420 continue;
421 }
422
423 parseDumpEntryFromDbusObject(object, dumpStatus, size,
424 timestampUs, originatorId,
425 originatorType, asyncResp);
426
427 if (dumpStatus !=
428 "xyz.openbmc_project.Common.Progress.OperationStatus.Completed" &&
429 !dumpStatus.empty())
430 {
431 // Dump status is not Complete, no need to enumerate
432 continue;
433 }
434
435 thisEntry["@odata.type"] = "#LogEntry.v1_11_0.LogEntry";
436 thisEntry["@odata.id"] = entriesPath + entryID;
437 thisEntry["Id"] = entryID;
438 thisEntry["EntryType"] = "Event";
439 thisEntry["Name"] = dumpType + " Dump Entry";
440 thisEntry["Created"] =
441 redfish::time_utils::getDateTimeUintUs(timestampUs);
442
443 if (!originatorId.empty())
444 {
445 thisEntry["Originator"] = originatorId;
446 thisEntry["OriginatorType"] = originatorType;
447 }
448
449 if (dumpType == "BMC")
450 {
451 thisEntry["DiagnosticDataType"] = "Manager";
452 thisEntry["AdditionalDataURI"] =
453 entriesPath + entryID + "/attachment";
454 thisEntry["AdditionalDataSizeBytes"] = size;
455 }
456 else if (dumpType == "System")
457 {
458 thisEntry["DiagnosticDataType"] = "OEM";
459 thisEntry["OEMDiagnosticDataType"] = "System";
460 thisEntry["AdditionalDataURI"] =
461 entriesPath + entryID + "/attachment";
462 thisEntry["AdditionalDataSizeBytes"] = size;
463 }
464 entriesArray.emplace_back(std::move(thisEntry));
465 }
466 asyncResp->res.jsonValue["Members@odata.count"] =
467 entriesArray.size();
468 asyncResp->res.jsonValue["Members"] = std::move(entriesArray);
Ed Tanous002d39b2022-05-31 08:59:27 -0700469 });
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500470}
471
Patrick Williams504af5a2025-02-03 14:29:03 -0500472inline void getDumpEntryById(
473 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
474 const std::string& entryID, const std::string& dumpType)
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500475{
Claire Weinanfdd26902022-03-01 14:18:25 -0800476 std::string entriesPath = getDumpEntriesPath(dumpType);
477 if (entriesPath.empty())
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500478 {
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500479 messages::internalError(asyncResp->res);
480 return;
481 }
482
George Liu5eb468d2023-06-20 17:03:24 +0800483 sdbusplus::message::object_path path("/xyz/openbmc_project/dump");
484 dbus::utility::getManagedObjects(
485 "xyz.openbmc_project.Dump.Manager", path,
Claire Weinanfdd26902022-03-01 14:18:25 -0800486 [asyncResp, entryID, dumpType,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800487 entriesPath](const boost::system::error_code& ec,
Ed Tanous02cad962022-06-30 16:50:15 -0700488 const dbus::utility::ManagedObjectType& resp) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400489 if (ec)
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500490 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400491 BMCWEB_LOG_ERROR("DumpEntry resp_handler got error {}", ec);
492 messages::internalError(asyncResp->res);
493 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700494 }
495
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400496 bool foundDumpEntry = false;
497 std::string dumpEntryPath = getDumpPath(dumpType) + "/entry/";
Ed Tanous002d39b2022-05-31 08:59:27 -0700498
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400499 for (const auto& objectPath : resp)
Ed Tanous002d39b2022-05-31 08:59:27 -0700500 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400501 if (objectPath.first.str != dumpEntryPath + entryID)
502 {
503 continue;
504 }
505
506 foundDumpEntry = true;
507 uint64_t timestampUs = 0;
508 uint64_t size = 0;
509 std::string dumpStatus;
510 std::string originatorId;
511 log_entry::OriginatorTypes originatorType =
512 log_entry::OriginatorTypes::Internal;
513
514 parseDumpEntryFromDbusObject(objectPath, dumpStatus, size,
515 timestampUs, originatorId,
516 originatorType, asyncResp);
517
518 if (dumpStatus !=
519 "xyz.openbmc_project.Common.Progress.OperationStatus.Completed" &&
520 !dumpStatus.empty())
521 {
522 // Dump status is not Complete
523 // return not found until status is changed to Completed
524 messages::resourceNotFound(asyncResp->res,
525 dumpType + " dump", entryID);
526 return;
527 }
528
529 asyncResp->res.jsonValue["@odata.type"] =
530 "#LogEntry.v1_11_0.LogEntry";
531 asyncResp->res.jsonValue["@odata.id"] = entriesPath + entryID;
532 asyncResp->res.jsonValue["Id"] = entryID;
533 asyncResp->res.jsonValue["EntryType"] = "Event";
534 asyncResp->res.jsonValue["Name"] = dumpType + " Dump Entry";
535 asyncResp->res.jsonValue["Created"] =
536 redfish::time_utils::getDateTimeUintUs(timestampUs);
537
538 if (!originatorId.empty())
539 {
540 asyncResp->res.jsonValue["Originator"] = originatorId;
541 asyncResp->res.jsonValue["OriginatorType"] = originatorType;
542 }
543
544 if (dumpType == "BMC")
545 {
546 asyncResp->res.jsonValue["DiagnosticDataType"] = "Manager";
547 asyncResp->res.jsonValue["AdditionalDataURI"] =
548 entriesPath + entryID + "/attachment";
549 asyncResp->res.jsonValue["AdditionalDataSizeBytes"] = size;
550 }
551 else if (dumpType == "System")
552 {
553 asyncResp->res.jsonValue["DiagnosticDataType"] = "OEM";
554 asyncResp->res.jsonValue["OEMDiagnosticDataType"] =
555 "System";
556 asyncResp->res.jsonValue["AdditionalDataURI"] =
557 entriesPath + entryID + "/attachment";
558 asyncResp->res.jsonValue["AdditionalDataSizeBytes"] = size;
559 }
560 }
561 if (!foundDumpEntry)
562 {
563 BMCWEB_LOG_WARNING("Can't find Dump Entry {}", entryID);
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +0200564 messages::resourceNotFound(asyncResp->res, dumpType + " dump",
565 entryID);
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500566 return;
567 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400568 });
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500569}
570
zhanghch058d1b46d2021-04-01 11:18:24 +0800571inline void deleteDumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Stanley Chu98782562020-11-04 16:10:24 +0800572 const std::string& entryID,
Asmitha Karunanithib47452b2020-09-25 02:02:19 -0500573 const std::string& dumpType)
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500574{
Patrick Williams5a39f772023-10-20 11:20:21 -0500575 auto respHandler = [asyncResp,
576 entryID](const boost::system::error_code& ec) {
Ed Tanous62598e32023-07-17 17:06:25 -0700577 BMCWEB_LOG_DEBUG("Dump Entry doDelete callback: Done");
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500578 if (ec)
579 {
George Liu3de8d8b2021-03-22 17:49:39 +0800580 if (ec.value() == EBADR)
581 {
582 messages::resourceNotFound(asyncResp->res, "LogEntry", entryID);
583 return;
584 }
Ed Tanous62598e32023-07-17 17:06:25 -0700585 BMCWEB_LOG_ERROR(
586 "Dump (DBus) doDelete respHandler got error {} entryID={}", ec,
587 entryID);
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500588 messages::internalError(asyncResp->res);
589 return;
590 }
591 };
Ed Tanous18f8f602023-07-18 10:07:23 -0700592
Ed Tanous177612a2025-02-14 15:16:09 -0800593 dbus::utility::async_method_call(
594 asyncResp, respHandler, "xyz.openbmc_project.Dump.Manager",
Ed Tanous18f8f602023-07-18 10:07:23 -0700595 std::format("{}/entry/{}", getDumpPath(dumpType), entryID),
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500596 "xyz.openbmc_project.Object.Delete", "Delete");
597}
Abhilash Rajub5f288d2023-11-08 22:32:44 -0600598inline bool checkSizeLimit(int fd, crow::Response& res)
599{
600 long long int size = lseek(fd, 0, SEEK_END);
601 if (size <= 0)
602 {
603 BMCWEB_LOG_ERROR("Failed to get size of file, lseek() returned {}",
604 size);
605 messages::internalError(res);
606 return false;
607 }
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500608
Abhilash Rajub5f288d2023-11-08 22:32:44 -0600609 // Arbitrary max size of 20MB to accommodate BMC dumps
610 constexpr long long int maxFileSize = 20LL * 1024LL * 1024LL;
611 if (size > maxFileSize)
612 {
613 BMCWEB_LOG_ERROR("File size {} exceeds maximum allowed size of {}",
614 size, maxFileSize);
615 messages::internalError(res);
616 return false;
617 }
618 off_t rc = lseek(fd, 0, SEEK_SET);
619 if (rc < 0)
620 {
621 BMCWEB_LOG_ERROR("Failed to reset file offset to 0");
622 messages::internalError(res);
623 return false;
624 }
625 return true;
626}
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400627inline void downloadEntryCallback(
628 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
629 const std::string& entryID, const std::string& downloadEntryType,
630 const boost::system::error_code& ec,
631 const sdbusplus::message::unix_fd& unixfd)
Carson Labrado168d1b12023-03-27 17:04:46 +0000632{
633 if (ec.value() == EBADR)
634 {
635 messages::resourceNotFound(asyncResp->res, "EntryAttachment", entryID);
636 return;
637 }
638 if (ec)
639 {
640 BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
641 messages::internalError(asyncResp->res);
642 return;
643 }
644
645 // Make sure we know how to process the retrieved entry attachment
646 if ((downloadEntryType != "BMC") && (downloadEntryType != "System"))
647 {
648 BMCWEB_LOG_ERROR("downloadEntryCallback() invalid entry type: {}",
649 downloadEntryType);
650 messages::internalError(asyncResp->res);
651 }
652
653 int fd = -1;
654 fd = dup(unixfd);
655 if (fd < 0)
656 {
657 BMCWEB_LOG_ERROR("Failed to open file");
658 messages::internalError(asyncResp->res);
659 return;
660 }
Abhilash Rajub5f288d2023-11-08 22:32:44 -0600661 if (!checkSizeLimit(fd, asyncResp->res))
Carson Labrado168d1b12023-03-27 17:04:46 +0000662 {
Carson Labrado168d1b12023-03-27 17:04:46 +0000663 close(fd);
664 return;
665 }
Carson Labrado168d1b12023-03-27 17:04:46 +0000666 if (downloadEntryType == "System")
667 {
Abhilash Rajub5f288d2023-11-08 22:32:44 -0600668 if (!asyncResp->res.openFd(fd, bmcweb::EncodingType::Base64))
669 {
670 messages::internalError(asyncResp->res);
671 close(fd);
672 return;
673 }
Carson Labrado168d1b12023-03-27 17:04:46 +0000674 asyncResp->res.addHeader(
675 boost::beast::http::field::content_transfer_encoding, "Base64");
Abhilash Rajub5f288d2023-11-08 22:32:44 -0600676 return;
Carson Labrado168d1b12023-03-27 17:04:46 +0000677 }
Abhilash Rajub5f288d2023-11-08 22:32:44 -0600678 if (!asyncResp->res.openFd(fd))
Ed Tanous27b0cf92023-08-07 12:02:40 -0700679 {
Abhilash Rajub5f288d2023-11-08 22:32:44 -0600680 messages::internalError(asyncResp->res);
681 close(fd);
682 return;
Ed Tanous27b0cf92023-08-07 12:02:40 -0700683 }
Carson Labrado168d1b12023-03-27 17:04:46 +0000684 asyncResp->res.addHeader(boost::beast::http::field::content_type,
685 "application/octet-stream");
686}
687
Patrick Williams504af5a2025-02-03 14:29:03 -0500688inline void downloadDumpEntry(
689 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
690 const std::string& entryID, const std::string& dumpType)
Carson Labrado168d1b12023-03-27 17:04:46 +0000691{
692 if (dumpType != "BMC")
693 {
694 BMCWEB_LOG_WARNING("Can't find Dump Entry {}", entryID);
695 messages::resourceNotFound(asyncResp->res, dumpType + " dump", entryID);
696 return;
697 }
698
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400699 std::string dumpEntryPath =
700 std::format("{}/entry/{}", getDumpPath(dumpType), entryID);
Carson Labrado168d1b12023-03-27 17:04:46 +0000701
702 auto downloadDumpEntryHandler =
703 [asyncResp, entryID,
704 dumpType](const boost::system::error_code& ec,
705 const sdbusplus::message::unix_fd& unixfd) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400706 downloadEntryCallback(asyncResp, entryID, dumpType, ec, unixfd);
707 };
Carson Labrado168d1b12023-03-27 17:04:46 +0000708
Ed Tanous177612a2025-02-14 15:16:09 -0800709 dbus::utility::async_method_call(
710 asyncResp, std::move(downloadDumpEntryHandler),
711 "xyz.openbmc_project.Dump.Manager", dumpEntryPath,
712 "xyz.openbmc_project.Dump.Entry", "GetFileHandle");
Carson Labrado168d1b12023-03-27 17:04:46 +0000713}
714
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400715inline void downloadEventLogEntry(
716 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
717 const std::string& systemName, const std::string& entryID,
718 const std::string& dumpType)
Carson Labrado168d1b12023-03-27 17:04:46 +0000719{
Ed Tanous25b54db2024-04-17 15:40:31 -0700720 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Carson Labrado168d1b12023-03-27 17:04:46 +0000721 {
722 // Option currently returns no systems. TBD
723 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
724 systemName);
725 return;
726 }
Ed Tanous253f11b2024-05-16 09:38:31 -0700727 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Carson Labrado168d1b12023-03-27 17:04:46 +0000728 {
729 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
730 systemName);
731 return;
732 }
733
734 std::string entryPath =
735 sdbusplus::message::object_path("/xyz/openbmc_project/logging/entry") /
736 entryID;
737
738 auto downloadEventLogEntryHandler =
739 [asyncResp, entryID,
740 dumpType](const boost::system::error_code& ec,
741 const sdbusplus::message::unix_fd& unixfd) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400742 downloadEntryCallback(asyncResp, entryID, dumpType, ec, unixfd);
743 };
Carson Labrado168d1b12023-03-27 17:04:46 +0000744
Ed Tanous177612a2025-02-14 15:16:09 -0800745 dbus::utility::async_method_call(
746 asyncResp, std::move(downloadEventLogEntryHandler),
747 "xyz.openbmc_project.Logging", entryPath,
748 "xyz.openbmc_project.Logging.Entry", "GetEntry");
Carson Labrado168d1b12023-03-27 17:04:46 +0000749}
750
Patrick Williams504af5a2025-02-03 14:29:03 -0500751inline DumpCreationProgress mapDbusStatusToDumpProgress(
752 const std::string& status)
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500753{
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600754 if (status ==
755 "xyz.openbmc_project.Common.Progress.OperationStatus.Failed" ||
756 status == "xyz.openbmc_project.Common.Progress.OperationStatus.Aborted")
757 {
758 return DumpCreationProgress::DUMP_CREATE_FAILED;
759 }
760 if (status ==
761 "xyz.openbmc_project.Common.Progress.OperationStatus.Completed")
762 {
763 return DumpCreationProgress::DUMP_CREATE_SUCCESS;
764 }
765 return DumpCreationProgress::DUMP_CREATE_INPROGRESS;
766}
767
Patrick Williams504af5a2025-02-03 14:29:03 -0500768inline DumpCreationProgress getDumpCompletionStatus(
769 const dbus::utility::DBusPropertiesMap& values)
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600770{
771 for (const auto& [key, val] : values)
772 {
773 if (key == "Status")
Ed Tanous002d39b2022-05-31 08:59:27 -0700774 {
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600775 const std::string* value = std::get_if<std::string>(&val);
776 if (value == nullptr)
777 {
Ed Tanous62598e32023-07-17 17:06:25 -0700778 BMCWEB_LOG_ERROR("Status property value is null");
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600779 return DumpCreationProgress::DUMP_CREATE_FAILED;
780 }
781 return mapDbusStatusToDumpProgress(*value);
782 }
783 }
784 return DumpCreationProgress::DUMP_CREATE_INPROGRESS;
785}
786
787inline std::string getDumpEntryPath(const std::string& dumpPath)
788{
789 if (dumpPath == "/xyz/openbmc_project/dump/bmc/entry")
790 {
Ed Tanous253f11b2024-05-16 09:38:31 -0700791 return std::format("/redfish/v1/Managers/{}/LogServices/Dump/Entries/",
Ed Tanous9f565092024-07-12 22:06:53 -0700792 BMCWEB_REDFISH_MANAGER_URI_NAME);
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600793 }
794 if (dumpPath == "/xyz/openbmc_project/dump/system/entry")
795 {
Ed Tanous253f11b2024-05-16 09:38:31 -0700796 return std::format("/redfish/v1/Systems/{}/LogServices/Dump/Entries/",
797 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600798 }
799 return "";
800}
801
802inline void createDumpTaskCallback(
803 task::Payload&& payload,
804 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
805 const sdbusplus::message::object_path& createdObjPath)
806{
807 const std::string dumpPath = createdObjPath.parent_path().str;
808 const std::string dumpId = createdObjPath.filename();
809
810 std::string dumpEntryPath = getDumpEntryPath(dumpPath);
811
812 if (dumpEntryPath.empty())
813 {
Ed Tanous62598e32023-07-17 17:06:25 -0700814 BMCWEB_LOG_ERROR("Invalid dump type received");
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600815 messages::internalError(asyncResp->res);
816 return;
817 }
818
Ed Tanous177612a2025-02-14 15:16:09 -0800819 dbus::utility::async_method_call(
820 asyncResp,
Ed Tanous8cb2c022024-03-27 16:31:46 -0700821 [asyncResp, payload = std::move(payload), createdObjPath,
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600822 dumpEntryPath{std::move(dumpEntryPath)},
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800823 dumpId](const boost::system::error_code& ec,
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600824 const std::string& introspectXml) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400825 if (ec)
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600826 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400827 BMCWEB_LOG_ERROR("Introspect call failed with error: {}",
828 ec.message());
829 messages::internalError(asyncResp->res);
830 return;
831 }
832
833 // Check if the created dump object has implemented Progress
834 // interface to track dump completion. If yes, fetch the "Status"
835 // property of the interface, modify the task state accordingly.
836 // Else, return task completed.
837 tinyxml2::XMLDocument doc;
838
839 doc.Parse(introspectXml.data(), introspectXml.size());
840 tinyxml2::XMLNode* pRoot = doc.FirstChildElement("node");
841 if (pRoot == nullptr)
842 {
843 BMCWEB_LOG_ERROR("XML document failed to parse");
844 messages::internalError(asyncResp->res);
845 return;
846 }
847 tinyxml2::XMLElement* interfaceNode =
848 pRoot->FirstChildElement("interface");
849
850 bool isProgressIntfPresent = false;
851 while (interfaceNode != nullptr)
852 {
853 const char* thisInterfaceName =
854 interfaceNode->Attribute("name");
855 if (thisInterfaceName != nullptr)
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600856 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400857 if (thisInterfaceName ==
858 std::string_view("xyz.openbmc_project.Common.Progress"))
859 {
860 interfaceNode =
861 interfaceNode->NextSiblingElement("interface");
862 continue;
863 }
864 isProgressIntfPresent = true;
865 break;
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600866 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400867 interfaceNode = interfaceNode->NextSiblingElement("interface");
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600868 }
869
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400870 std::shared_ptr<task::TaskData> task = task::TaskData::createTask(
871 [createdObjPath, dumpEntryPath, dumpId, isProgressIntfPresent](
872 const boost::system::error_code& ec2,
873 sdbusplus::message_t& msg,
874 const std::shared_ptr<task::TaskData>& taskData) {
875 if (ec2)
876 {
877 BMCWEB_LOG_ERROR("{}: Error in creating dump",
878 createdObjPath.str);
879 taskData->messages.emplace_back(
880 messages::internalError());
881 taskData->state = "Cancelled";
882 return task::completed;
883 }
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600884
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400885 if (isProgressIntfPresent)
886 {
887 dbus::utility::DBusPropertiesMap values;
888 std::string prop;
889 msg.read(prop, values);
890
891 DumpCreationProgress dumpStatus =
892 getDumpCompletionStatus(values);
893 if (dumpStatus ==
894 DumpCreationProgress::DUMP_CREATE_FAILED)
895 {
896 BMCWEB_LOG_ERROR("{}: Error in creating dump",
897 createdObjPath.str);
898 taskData->state = "Cancelled";
899 return task::completed;
900 }
901
902 if (dumpStatus ==
903 DumpCreationProgress::DUMP_CREATE_INPROGRESS)
904 {
905 BMCWEB_LOG_DEBUG(
906 "{}: Dump creation task is in progress",
907 createdObjPath.str);
908 return !task::completed;
909 }
910 }
911
912 nlohmann::json retMessage = messages::success();
913 taskData->messages.emplace_back(retMessage);
914
915 boost::urls::url url = boost::urls::format(
916 "/redfish/v1/Managers/{}/LogServices/Dump/Entries/{}",
917 BMCWEB_REDFISH_MANAGER_URI_NAME, dumpId);
918
919 std::string headerLoc = "Location: ";
920 headerLoc += url.buffer();
921
922 taskData->payload->httpHeaders.emplace_back(
923 std::move(headerLoc));
924
925 BMCWEB_LOG_DEBUG("{}: Dump creation task completed",
Ed Tanous62598e32023-07-17 17:06:25 -0700926 createdObjPath.str);
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400927 taskData->state = "Completed";
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600928 return task::completed;
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400929 },
930 "type='signal',interface='org.freedesktop.DBus.Properties',"
931 "member='PropertiesChanged',path='" +
932 createdObjPath.str + "'");
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600933
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400934 // The task timer is set to max time limit within which the
935 // requested dump will be collected.
936 task->startTimer(std::chrono::minutes(6));
937 task->populateResp(asyncResp->res);
938 task->payload.emplace(payload);
Patrick Williams5a39f772023-10-20 11:20:21 -0500939 },
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600940 "xyz.openbmc_project.Dump.Manager", createdObjPath,
941 "org.freedesktop.DBus.Introspectable", "Introspect");
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500942}
943
zhanghch058d1b46d2021-04-01 11:18:24 +0800944inline void createDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
945 const crow::Request& req, const std::string& dumpType)
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500946{
Claire Weinanfdd26902022-03-01 14:18:25 -0800947 std::string dumpPath = getDumpEntriesPath(dumpType);
948 if (dumpPath.empty())
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500949 {
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500950 messages::internalError(asyncResp->res);
951 return;
952 }
953
954 std::optional<std::string> diagnosticDataType;
955 std::optional<std::string> oemDiagnosticDataType;
956
Patrick Williams504af5a2025-02-03 14:29:03 -0500957 if (!redfish::json_util::readJsonAction( //
958 req, asyncResp->res, //
959 "DiagnosticDataType", diagnosticDataType, //
Myung Baeafc474a2024-10-09 00:53:29 -0700960 "OEMDiagnosticDataType", oemDiagnosticDataType //
961 ))
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500962 {
963 return;
964 }
965
966 if (dumpType == "System")
967 {
968 if (!oemDiagnosticDataType || !diagnosticDataType)
969 {
Ed Tanous62598e32023-07-17 17:06:25 -0700970 BMCWEB_LOG_ERROR(
971 "CreateDump action parameter 'DiagnosticDataType'/'OEMDiagnosticDataType' value not found!");
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500972 messages::actionParameterMissing(
973 asyncResp->res, "CollectDiagnosticData",
974 "DiagnosticDataType & OEMDiagnosticDataType");
975 return;
976 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700977 if ((*oemDiagnosticDataType != "System") ||
978 (*diagnosticDataType != "OEM"))
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500979 {
Ed Tanous62598e32023-07-17 17:06:25 -0700980 BMCWEB_LOG_ERROR("Wrong parameter values passed");
Ed Tanousace85d62021-10-26 12:45:59 -0700981 messages::internalError(asyncResp->res);
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500982 return;
983 }
Ed Tanous253f11b2024-05-16 09:38:31 -0700984 dumpPath = std::format("/redfish/v1/Systems/{}/LogServices/Dump/",
985 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500986 }
987 else if (dumpType == "BMC")
988 {
989 if (!diagnosticDataType)
990 {
Ed Tanous62598e32023-07-17 17:06:25 -0700991 BMCWEB_LOG_ERROR(
992 "CreateDump action parameter 'DiagnosticDataType' not found!");
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500993 messages::actionParameterMissing(
994 asyncResp->res, "CollectDiagnosticData", "DiagnosticDataType");
995 return;
996 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700997 if (*diagnosticDataType != "Manager")
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500998 {
Ed Tanous62598e32023-07-17 17:06:25 -0700999 BMCWEB_LOG_ERROR(
1000 "Wrong parameter value passed for 'DiagnosticDataType'");
Ed Tanousace85d62021-10-26 12:45:59 -07001001 messages::internalError(asyncResp->res);
Asmitha Karunanithia43be802020-05-07 05:05:36 -05001002 return;
1003 }
Ed Tanous253f11b2024-05-16 09:38:31 -07001004 dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/Dump/",
1005 BMCWEB_REDFISH_MANAGER_URI_NAME);
Asmitha Karunanithi59075712021-10-22 01:17:41 -05001006 }
1007 else
1008 {
Ed Tanous62598e32023-07-17 17:06:25 -07001009 BMCWEB_LOG_ERROR("CreateDump failed. Unknown dump type");
Asmitha Karunanithi59075712021-10-22 01:17:41 -05001010 messages::internalError(asyncResp->res);
1011 return;
Asmitha Karunanithia43be802020-05-07 05:05:36 -05001012 }
1013
Asmitha Karunanithi8e317782020-12-10 03:35:05 -06001014 std::vector<std::pair<std::string, std::variant<std::string, uint64_t>>>
1015 createDumpParamVec;
1016
Carson Labradof574a8e2023-03-22 02:26:00 +00001017 if (req.session != nullptr)
1018 {
1019 createDumpParamVec.emplace_back(
1020 "xyz.openbmc_project.Dump.Create.CreateParameters.OriginatorId",
1021 req.session->clientIp);
1022 createDumpParamVec.emplace_back(
1023 "xyz.openbmc_project.Dump.Create.CreateParameters.OriginatorType",
1024 "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Client");
1025 }
Asmitha Karunanithi68dd0752022-11-15 11:33:46 -06001026
Ed Tanous177612a2025-02-14 15:16:09 -08001027 dbus::utility::async_method_call(
1028 asyncResp,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001029 [asyncResp, payload(task::Payload(req)),
1030 dumpPath](const boost::system::error_code& ec,
1031 const sdbusplus::message_t& msg,
1032 const sdbusplus::message::object_path& objPath) mutable {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001033 if (ec)
Asmitha Karunanithi59075712021-10-22 01:17:41 -05001034 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001035 BMCWEB_LOG_ERROR("CreateDump resp_handler got error {}", ec);
1036 const sd_bus_error* dbusError = msg.get_error();
1037 if (dbusError == nullptr)
1038 {
1039 messages::internalError(asyncResp->res);
1040 return;
1041 }
1042
1043 BMCWEB_LOG_ERROR("CreateDump DBus error: {} and error msg: {}",
1044 dbusError->name, dbusError->message);
1045 if (std::string_view(
1046 "xyz.openbmc_project.Common.Error.NotAllowed") ==
1047 dbusError->name)
1048 {
1049 messages::resourceInStandby(asyncResp->res);
1050 return;
1051 }
1052 if (std::string_view(
1053 "xyz.openbmc_project.Dump.Create.Error.Disabled") ==
1054 dbusError->name)
1055 {
1056 messages::serviceDisabled(asyncResp->res, dumpPath);
1057 return;
1058 }
1059 if (std::string_view(
1060 "xyz.openbmc_project.Common.Error.Unavailable") ==
1061 dbusError->name)
1062 {
1063 messages::resourceInUse(asyncResp->res);
1064 return;
1065 }
1066 // Other Dbus errors such as:
1067 // xyz.openbmc_project.Common.Error.InvalidArgument &
1068 // org.freedesktop.DBus.Error.InvalidArgs are all related to
1069 // the dbus call that is made here in the bmcweb
1070 // implementation and has nothing to do with the client's
1071 // input in the request. Hence, returning internal error
1072 // back to the client.
Asmitha Karunanithi59075712021-10-22 01:17:41 -05001073 messages::internalError(asyncResp->res);
1074 return;
1075 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001076 BMCWEB_LOG_DEBUG("Dump Created. Path: {}", objPath.str);
1077 createDumpTaskCallback(std::move(payload), asyncResp, objPath);
1078 },
Ed Tanous18f8f602023-07-18 10:07:23 -07001079 "xyz.openbmc_project.Dump.Manager", getDumpPath(dumpType),
Asmitha Karunanithi8e317782020-12-10 03:35:05 -06001080 "xyz.openbmc_project.Dump.Create", "CreateDump", createDumpParamVec);
Asmitha Karunanithia43be802020-05-07 05:05:36 -05001081}
1082
zhanghch058d1b46d2021-04-01 11:18:24 +08001083inline void clearDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1084 const std::string& dumpType)
Asmitha Karunanithi80319af2020-05-07 05:30:21 -05001085{
Ed Tanous177612a2025-02-14 15:16:09 -08001086 dbus::utility::async_method_call(
1087 asyncResp,
Claire Weinan0d946212022-07-13 19:40:19 -07001088 [asyncResp](const boost::system::error_code& ec) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001089 if (ec)
1090 {
1091 BMCWEB_LOG_ERROR("clearDump resp_handler got error {}", ec);
1092 messages::internalError(asyncResp->res);
1093 return;
1094 }
Amy Change2460462025-05-06 00:10:13 -07001095 messages::success(asyncResp->res);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001096 },
Ed Tanous18f8f602023-07-18 10:07:23 -07001097 "xyz.openbmc_project.Dump.Manager", getDumpPath(dumpType),
Claire Weinan0d946212022-07-13 19:40:19 -07001098 "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
Asmitha Karunanithi80319af2020-05-07 05:30:21 -05001099}
1100
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001101inline void parseCrashdumpParameters(
1102 const dbus::utility::DBusPropertiesMap& params, std::string& filename,
1103 std::string& timestamp, std::string& logfile)
Johnathan Mantey043a0532020-03-10 17:15:28 -07001104{
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +02001105 const std::string* filenamePtr = nullptr;
1106 const std::string* timestampPtr = nullptr;
1107 const std::string* logfilePtr = nullptr;
1108
1109 const bool success = sdbusplus::unpackPropertiesNoThrow(
1110 dbus_utils::UnpackErrorPrinter(), params, "Timestamp", timestampPtr,
1111 "Filename", filenamePtr, "Log", logfilePtr);
1112
1113 if (!success)
Johnathan Mantey043a0532020-03-10 17:15:28 -07001114 {
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +02001115 return;
1116 }
1117
1118 if (filenamePtr != nullptr)
1119 {
1120 filename = *filenamePtr;
1121 }
1122
1123 if (timestampPtr != nullptr)
1124 {
1125 timestamp = *timestampPtr;
1126 }
1127
1128 if (logfilePtr != nullptr)
1129 {
1130 logfile = *logfilePtr;
Johnathan Mantey043a0532020-03-10 17:15:28 -07001131 }
1132}
1133
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001134inline void requestRoutesSystemLogServiceCollection(App& app)
Ed Tanous1da66f72018-07-27 16:13:37 -07001135{
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001136 /**
1137 * Functions triggers appropriate requests on DBus
1138 */
Ed Tanous22d268c2022-05-19 09:39:07 -07001139 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/")
Ed Tanoused398212021-06-09 17:05:54 -07001140 .privileges(redfish::privileges::getLogServiceCollection)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001141 .methods(
1142 boost::beast::http::verb::
1143 get)([&app](const crow::Request& req,
1144 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1145 const std::string& systemName) {
1146 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07001147 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001148 return;
1149 }
1150 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1151 {
1152 // Option currently returns no systems. TBD
1153 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1154 systemName);
1155 return;
1156 }
1157 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1158 {
1159 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1160 systemName);
Ed Tanous002d39b2022-05-31 08:59:27 -07001161 return;
1162 }
Ed Tanous45ca1b82022-03-25 13:07:27 -07001163
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001164 // Collections don't include the static data added by SubRoute
1165 // because it has a duplicate entry for members
1166 asyncResp->res.jsonValue["@odata.type"] =
1167 "#LogServiceCollection.LogServiceCollection";
1168 asyncResp->res.jsonValue["@odata.id"] =
1169 std::format("/redfish/v1/Systems/{}/LogServices",
1170 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1171 asyncResp->res.jsonValue["Name"] = "System Log Services Collection";
1172 asyncResp->res.jsonValue["Description"] =
1173 "Collection of LogServices for this Computer System";
1174 nlohmann::json& logServiceArray =
1175 asyncResp->res.jsonValue["Members"];
1176 logServiceArray = nlohmann::json::array();
1177 nlohmann::json::object_t eventLog;
1178 eventLog["@odata.id"] =
1179 std::format("/redfish/v1/Systems/{}/LogServices/EventLog",
1180 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1181 logServiceArray.emplace_back(std::move(eventLog));
1182 if constexpr (BMCWEB_REDFISH_DUMP_LOG)
Ed Tanous002d39b2022-05-31 08:59:27 -07001183 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001184 nlohmann::json::object_t dumpLog;
1185 dumpLog["@odata.id"] =
1186 std::format("/redfish/v1/Systems/{}/LogServices/Dump",
1187 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1188 logServiceArray.emplace_back(std::move(dumpLog));
Ed Tanous002d39b2022-05-31 08:59:27 -07001189 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001190
1191 if constexpr (BMCWEB_REDFISH_CPU_LOG)
1192 {
1193 nlohmann::json::object_t crashdump;
1194 crashdump["@odata.id"] =
1195 std::format("/redfish/v1/Systems/{}/LogServices/Crashdump",
1196 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1197 logServiceArray.emplace_back(std::move(crashdump));
1198 }
1199
1200 if constexpr (BMCWEB_REDFISH_HOST_LOGGER)
1201 {
1202 nlohmann::json::object_t hostlogger;
1203 hostlogger["@odata.id"] =
1204 std::format("/redfish/v1/Systems/{}/LogServices/HostLogger",
1205 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1206 logServiceArray.emplace_back(std::move(hostlogger));
1207 }
1208 asyncResp->res.jsonValue["Members@odata.count"] =
1209 logServiceArray.size();
1210
1211 constexpr std::array<std::string_view, 1> interfaces = {
1212 "xyz.openbmc_project.State.Boot.PostCode"};
1213 dbus::utility::getSubTreePaths(
1214 "/", 0, interfaces,
1215 [asyncResp](const boost::system::error_code& ec,
1216 const dbus::utility::MapperGetSubTreePathsResponse&
1217 subtreePath) {
1218 if (ec)
1219 {
1220 BMCWEB_LOG_ERROR("{}", ec);
1221 return;
1222 }
1223
1224 for (const auto& pathStr : subtreePath)
1225 {
1226 if (pathStr.find("PostCode") != std::string::npos)
1227 {
1228 nlohmann::json& logServiceArrayLocal =
1229 asyncResp->res.jsonValue["Members"];
1230 nlohmann::json::object_t member;
1231 member["@odata.id"] = std::format(
1232 "/redfish/v1/Systems/{}/LogServices/PostCodes",
1233 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1234
1235 logServiceArrayLocal.emplace_back(
1236 std::move(member));
1237
1238 asyncResp->res.jsonValue["Members@odata.count"] =
1239 logServiceArrayLocal.size();
1240 return;
1241 }
1242 }
1243 });
Ed Tanous45ca1b82022-03-25 13:07:27 -07001244 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001245}
1246
1247inline void requestRoutesEventLogService(App& app)
1248{
Ed Tanous22d268c2022-05-19 09:39:07 -07001249 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/")
Ed Tanoused398212021-06-09 17:05:54 -07001250 .privileges(redfish::privileges::getLogService)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001251 .methods(
1252 boost::beast::http::verb::
1253 get)([&app](const crow::Request& req,
1254 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1255 const std::string& systemName) {
1256 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1257 {
1258 return;
1259 }
1260 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1261 {
1262 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1263 systemName);
1264 return;
1265 }
1266 asyncResp->res.jsonValue["@odata.id"] =
1267 std::format("/redfish/v1/Systems/{}/LogServices/EventLog",
1268 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1269 asyncResp->res.jsonValue["@odata.type"] =
1270 "#LogService.v1_2_0.LogService";
1271 asyncResp->res.jsonValue["Name"] = "Event Log Service";
1272 asyncResp->res.jsonValue["Description"] =
1273 "System Event Log Service";
1274 asyncResp->res.jsonValue["Id"] = "EventLog";
1275 asyncResp->res.jsonValue["OverWritePolicy"] =
1276 log_service::OverWritePolicy::WrapsWhenFull;
Tejas Patil7c8c4052021-06-04 17:43:14 +05301277
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001278 std::pair<std::string, std::string> redfishDateTimeOffset =
1279 redfish::time_utils::getDateTimeOffsetNow();
Tejas Patil7c8c4052021-06-04 17:43:14 +05301280
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001281 asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
1282 asyncResp->res.jsonValue["DateTimeLocalOffset"] =
1283 redfishDateTimeOffset.second;
Tejas Patil7c8c4052021-06-04 17:43:14 +05301284
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001285 asyncResp->res.jsonValue["Entries"]["@odata.id"] = std::format(
1286 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
Ed Tanous20fa6a22024-05-20 18:02:58 -07001287 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001288 asyncResp->res
1289 .jsonValue["Actions"]["#LogService.ClearLog"]["target"]
1290
1291 = std::format(
1292 "/redfish/v1/Systems/{}/LogServices/EventLog/Actions/LogService.ClearLog",
1293 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1294 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001295}
1296
Alexander Hansen599b9af2024-08-06 15:11:57 +02001297inline void handleSystemsLogServicesEventLogActionsClearPost(
1298 App& app, const crow::Request& req,
1299 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1300 const std::string& systemName)
1301{
1302 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1303 {
1304 return;
1305 }
1306 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1307 {
1308 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1309 systemName);
1310 return;
1311 }
1312
1313 // Clear the EventLog by deleting the log files
1314 std::vector<std::filesystem::path> redfishLogFiles;
1315 if (getRedfishLogFiles(redfishLogFiles))
1316 {
1317 for (const std::filesystem::path& file : redfishLogFiles)
1318 {
1319 std::error_code ec;
1320 std::filesystem::remove(file, ec);
1321 }
1322 }
1323
1324 // Reload rsyslog so it knows to start new log files
Ed Tanous177612a2025-02-14 15:16:09 -08001325 dbus::utility::async_method_call(
1326 asyncResp,
Alexander Hansen599b9af2024-08-06 15:11:57 +02001327 [asyncResp](const boost::system::error_code& ec) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001328 if (ec)
1329 {
1330 BMCWEB_LOG_ERROR("Failed to reload rsyslog: {}", ec);
1331 messages::internalError(asyncResp->res);
1332 return;
1333 }
Alexander Hansen599b9af2024-08-06 15:11:57 +02001334
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001335 messages::success(asyncResp->res);
1336 },
Alexander Hansen599b9af2024-08-06 15:11:57 +02001337 "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
1338 "org.freedesktop.systemd1.Manager", "ReloadUnit", "rsyslog.service",
1339 "replace");
1340}
1341
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001342inline void requestRoutesJournalEventLogClear(App& app)
1343{
Jason M. Bills4978b632022-02-22 14:17:43 -08001344 BMCWEB_ROUTE(
1345 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07001346 "/redfish/v1/Systems/<str>/LogServices/EventLog/Actions/LogService.ClearLog/")
Ed Tanous432a8902021-06-14 15:28:56 -07001347 .privileges({{"ConfigureComponents"}})
Alexander Hansen599b9af2024-08-06 15:11:57 +02001348 .methods(boost::beast::http::verb::post)(std::bind_front(
1349 handleSystemsLogServicesEventLogActionsClearPost, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001350}
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001351
Jason M. Billsac992cd2022-06-24 13:31:46 -07001352enum class LogParseError
1353{
1354 success,
1355 parseFailed,
1356 messageIdNotInRegistry,
1357};
1358
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001359static LogParseError fillEventLogEntryJson(
1360 const std::string& logEntryID, const std::string& logEntry,
1361 nlohmann::json::object_t& logEntryJson)
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001362{
Jason M. Bills95820182019-04-22 16:25:34 -07001363 // The redfish log format is "<Timestamp> <MessageId>,<MessageArgs>"
Jason M. Billscd225da2019-05-08 15:31:57 -07001364 // First get the Timestamp
Ed Tanousf23b7292020-10-15 09:41:17 -07001365 size_t space = logEntry.find_first_of(' ');
Jason M. Billscd225da2019-05-08 15:31:57 -07001366 if (space == std::string::npos)
Jason M. Bills95820182019-04-22 16:25:34 -07001367 {
Jason M. Billsac992cd2022-06-24 13:31:46 -07001368 return LogParseError::parseFailed;
Jason M. Bills95820182019-04-22 16:25:34 -07001369 }
Jason M. Billscd225da2019-05-08 15:31:57 -07001370 std::string timestamp = logEntry.substr(0, space);
1371 // Then get the log contents
Ed Tanousf23b7292020-10-15 09:41:17 -07001372 size_t entryStart = logEntry.find_first_not_of(' ', space);
Jason M. Billscd225da2019-05-08 15:31:57 -07001373 if (entryStart == std::string::npos)
1374 {
Jason M. Billsac992cd2022-06-24 13:31:46 -07001375 return LogParseError::parseFailed;
Jason M. Billscd225da2019-05-08 15:31:57 -07001376 }
1377 std::string_view entry(logEntry);
1378 entry.remove_prefix(entryStart);
1379 // Use split to separate the entry into its fields
1380 std::vector<std::string> logEntryFields;
Ed Tanous50ebd4a2023-01-19 19:03:17 -08001381 bmcweb::split(logEntryFields, entry, ',');
Jason M. Billscd225da2019-05-08 15:31:57 -07001382 // We need at least a MessageId to be valid
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001383 auto logEntryIter = logEntryFields.begin();
1384 if (logEntryIter == logEntryFields.end())
Jason M. Billscd225da2019-05-08 15:31:57 -07001385 {
Jason M. Billsac992cd2022-06-24 13:31:46 -07001386 return LogParseError::parseFailed;
Jason M. Billscd225da2019-05-08 15:31:57 -07001387 }
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001388 std::string& messageID = *logEntryIter;
Jason M. Bills4851d452019-03-28 11:27:48 -07001389 // Get the Message from the MessageRegistry
Ed Tanousfffb8c12022-02-07 23:53:03 -08001390 const registries::Message* message = registries::getMessage(messageID);
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001391
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001392 logEntryIter++;
Sui Chen54417b02022-03-24 14:59:52 -07001393 if (message == nullptr)
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001394 {
Ed Tanous62598e32023-07-17 17:06:25 -07001395 BMCWEB_LOG_WARNING("Log entry not found in registry: {}", logEntry);
Jason M. Billsac992cd2022-06-24 13:31:46 -07001396 return LogParseError::messageIdNotInRegistry;
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001397 }
1398
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001399 std::vector<std::string_view> messageArgs(logEntryIter,
1400 logEntryFields.end());
Ed Tanousc05bba42023-06-28 08:33:29 -07001401 messageArgs.resize(message->numberOfArgs);
1402
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001403 std::string msg =
1404 redfish::registries::fillMessageArgs(messageArgs, message->message);
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001405 if (msg.empty())
Jason M. Bills4851d452019-03-28 11:27:48 -07001406 {
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001407 return LogParseError::parseFailed;
Jason M. Bills4851d452019-03-28 11:27:48 -07001408 }
1409
Jason M. Bills95820182019-04-22 16:25:34 -07001410 // Get the Created time from the timestamp. The log timestamp is in RFC3339
1411 // format which matches the Redfish format except for the fractional seconds
1412 // between the '.' and the '+', so just remove them.
Ed Tanousf23b7292020-10-15 09:41:17 -07001413 std::size_t dot = timestamp.find_first_of('.');
1414 std::size_t plus = timestamp.find_first_of('+');
Jason M. Bills95820182019-04-22 16:25:34 -07001415 if (dot != std::string::npos && plus != std::string::npos)
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001416 {
Jason M. Bills95820182019-04-22 16:25:34 -07001417 timestamp.erase(dot, plus - dot);
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001418 }
1419
1420 // Fill in the log entry with the gathered data
Vijay Lobo9c11a172021-10-07 16:53:16 -05001421 logEntryJson["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
Ed Tanousef4c65b2023-04-24 15:28:50 -07001422 logEntryJson["@odata.id"] = boost::urls::format(
Ed Tanous253f11b2024-05-16 09:38:31 -07001423 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}",
1424 BMCWEB_REDFISH_SYSTEM_URI_NAME, logEntryID);
Jason M. Bills84afc482022-06-24 12:38:23 -07001425 logEntryJson["Name"] = "System Event Log Entry";
1426 logEntryJson["Id"] = logEntryID;
1427 logEntryJson["Message"] = std::move(msg);
1428 logEntryJson["MessageId"] = std::move(messageID);
1429 logEntryJson["MessageArgs"] = messageArgs;
1430 logEntryJson["EntryType"] = "Event";
1431 logEntryJson["Severity"] = message->messageSeverity;
1432 logEntryJson["Created"] = std::move(timestamp);
Jason M. Billsac992cd2022-06-24 13:31:46 -07001433 return LogParseError::success;
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001434}
1435
Igor Kanyuka90896602025-03-13 08:52:38 +00001436inline bool fillEventLogLogEntryFromPropertyMap(
Ed Tanous898f2aa2024-08-07 12:18:22 -07001437 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1438 const dbus::utility::DBusPropertiesMap& resp,
1439 nlohmann::json& objectToFillOut)
1440{
Alexander Hansen262dcc12024-09-19 12:04:03 +02001441 std::optional<DbusEventLogEntry> optEntry =
1442 fillDbusEventLogEntryFromPropertyMap(resp);
Ed Tanous898f2aa2024-08-07 12:18:22 -07001443
Alexander Hansen262dcc12024-09-19 12:04:03 +02001444 if (!optEntry.has_value())
Ed Tanous898f2aa2024-08-07 12:18:22 -07001445 {
1446 messages::internalError(asyncResp->res);
Igor Kanyuka90896602025-03-13 08:52:38 +00001447 return false;
Ed Tanous898f2aa2024-08-07 12:18:22 -07001448 }
Alexander Hansen262dcc12024-09-19 12:04:03 +02001449 DbusEventLogEntry entry = optEntry.value();
Ed Tanous898f2aa2024-08-07 12:18:22 -07001450
1451 objectToFillOut["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
1452 objectToFillOut["@odata.id"] = boost::urls::format(
1453 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}",
Alexander Hansen262dcc12024-09-19 12:04:03 +02001454 BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(entry.Id));
Ed Tanous898f2aa2024-08-07 12:18:22 -07001455 objectToFillOut["Name"] = "System Event Log Entry";
Alexander Hansen262dcc12024-09-19 12:04:03 +02001456 objectToFillOut["Id"] = std::to_string(entry.Id);
1457 objectToFillOut["Message"] = entry.Message;
1458 objectToFillOut["Resolved"] = entry.Resolved;
1459 std::optional<bool> notifyAction =
1460 getProviderNotifyAction(entry.ServiceProviderNotify);
Ed Tanous898f2aa2024-08-07 12:18:22 -07001461 if (notifyAction)
1462 {
1463 objectToFillOut["ServiceProviderNotified"] = *notifyAction;
1464 }
Alexander Hansen262dcc12024-09-19 12:04:03 +02001465 if ((entry.Resolution != nullptr) && !entry.Resolution->empty())
Ed Tanous898f2aa2024-08-07 12:18:22 -07001466 {
Alexander Hansen262dcc12024-09-19 12:04:03 +02001467 objectToFillOut["Resolution"] = *entry.Resolution;
Ed Tanous898f2aa2024-08-07 12:18:22 -07001468 }
1469 objectToFillOut["EntryType"] = "Event";
Alexander Hansen262dcc12024-09-19 12:04:03 +02001470 objectToFillOut["Severity"] =
1471 translateSeverityDbusToRedfish(entry.Severity);
Ed Tanous898f2aa2024-08-07 12:18:22 -07001472 objectToFillOut["Created"] =
Alexander Hansen262dcc12024-09-19 12:04:03 +02001473 redfish::time_utils::getDateTimeUintMs(entry.Timestamp);
Ed Tanous898f2aa2024-08-07 12:18:22 -07001474 objectToFillOut["Modified"] =
Alexander Hansen262dcc12024-09-19 12:04:03 +02001475 redfish::time_utils::getDateTimeUintMs(entry.UpdateTimestamp);
1476 if (entry.Path != nullptr)
Ed Tanous898f2aa2024-08-07 12:18:22 -07001477 {
1478 objectToFillOut["AdditionalDataURI"] = boost::urls::format(
1479 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}/attachment",
Alexander Hansen262dcc12024-09-19 12:04:03 +02001480 BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(entry.Id));
Ed Tanous898f2aa2024-08-07 12:18:22 -07001481 }
Igor Kanyuka90896602025-03-13 08:52:38 +00001482 return true;
Ed Tanous898f2aa2024-08-07 12:18:22 -07001483}
1484
Ed Tanousb7290962024-08-07 11:09:51 -07001485inline void afterLogEntriesGetManagedObjects(
1486 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1487 const boost::system::error_code& ec,
1488 const dbus::utility::ManagedObjectType& resp)
1489{
1490 if (ec)
1491 {
1492 // TODO Handle for specific error code
1493 BMCWEB_LOG_ERROR("getLogEntriesIfaceData resp_handler got error {}",
1494 ec);
1495 messages::internalError(asyncResp->res);
1496 return;
1497 }
1498 nlohmann::json::array_t entriesArray;
1499 for (const auto& objectPath : resp)
1500 {
Ed Tanous898f2aa2024-08-07 12:18:22 -07001501 dbus::utility::DBusPropertiesMap propsFlattened;
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001502 auto isEntry =
1503 std::ranges::find_if(objectPath.second, [](const auto& object) {
1504 return object.first == "xyz.openbmc_project.Logging.Entry";
1505 });
Ed Tanous898f2aa2024-08-07 12:18:22 -07001506 if (isEntry == objectPath.second.end())
Ed Tanousb7290962024-08-07 11:09:51 -07001507 {
1508 continue;
1509 }
Ed Tanous898f2aa2024-08-07 12:18:22 -07001510 for (const auto& interfaceMap : objectPath.second)
Ed Tanousb7290962024-08-07 11:09:51 -07001511 {
Ed Tanous898f2aa2024-08-07 12:18:22 -07001512 for (const auto& propertyMap : interfaceMap.second)
Ed Tanousb7290962024-08-07 11:09:51 -07001513 {
Ed Tanous898f2aa2024-08-07 12:18:22 -07001514 propsFlattened.emplace_back(propertyMap.first,
1515 propertyMap.second);
Ed Tanousb7290962024-08-07 11:09:51 -07001516 }
1517 }
Igor Kanyuka90896602025-03-13 08:52:38 +00001518 bool success = fillEventLogLogEntryFromPropertyMap(
1519 asyncResp, propsFlattened, entriesArray.emplace_back());
1520 if (!success)
1521 {
1522 return;
1523 }
Ed Tanousb7290962024-08-07 11:09:51 -07001524 }
Ed Tanous898f2aa2024-08-07 12:18:22 -07001525
Igor Kanyuka90896602025-03-13 08:52:38 +00001526 redfish::json_util::sortJsonArrayByKey(entriesArray, "Id");
Ed Tanousb7290962024-08-07 11:09:51 -07001527 asyncResp->res.jsonValue["Members@odata.count"] = entriesArray.size();
1528 asyncResp->res.jsonValue["Members"] = std::move(entriesArray);
1529}
1530
Alexander Hansen599b9af2024-08-06 15:11:57 +02001531inline void handleSystemsLogServiceEventLogLogEntryCollection(
1532 App& app, const crow::Request& req,
1533 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1534 const std::string& systemName)
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001535{
Alexander Hansen599b9af2024-08-06 15:11:57 +02001536 query_param::QueryCapabilities capabilities = {
1537 .canDelegateTop = true,
1538 .canDelegateSkip = true,
1539 };
1540 query_param::Query delegatedQuery;
1541 if (!redfish::setUpRedfishRouteWithDelegation(app, req, asyncResp,
1542 delegatedQuery, capabilities))
1543 {
1544 return;
1545 }
1546 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1547 {
1548 // Option currently returns no systems. TBD
1549 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1550 systemName);
1551 return;
1552 }
1553 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1554 {
1555 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1556 systemName);
1557 return;
1558 }
1559
1560 size_t top = delegatedQuery.top.value_or(query_param::Query::maxTop);
1561 size_t skip = delegatedQuery.skip.value_or(0);
1562
1563 // Collections don't include the static data added by SubRoute
1564 // because it has a duplicate entry for members
1565 asyncResp->res.jsonValue["@odata.type"] =
1566 "#LogEntryCollection.LogEntryCollection";
1567 asyncResp->res.jsonValue["@odata.id"] =
1568 std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
1569 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1570 asyncResp->res.jsonValue["Name"] = "System Event Log Entries";
1571 asyncResp->res.jsonValue["Description"] =
1572 "Collection of System Event Log Entries";
1573
1574 nlohmann::json& logEntryArray = asyncResp->res.jsonValue["Members"];
1575 logEntryArray = nlohmann::json::array();
1576 // Go through the log files and create a unique ID for each
1577 // entry
1578 std::vector<std::filesystem::path> redfishLogFiles;
1579 getRedfishLogFiles(redfishLogFiles);
1580 uint64_t entryCount = 0;
1581 std::string logEntry;
1582
1583 // Oldest logs are in the last file, so start there and loop
1584 // backwards
1585 for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend(); it++)
1586 {
1587 std::ifstream logStream(*it);
1588 if (!logStream.is_open())
Ed Tanous002d39b2022-05-31 08:59:27 -07001589 {
Alexander Hansen599b9af2024-08-06 15:11:57 +02001590 continue;
Ed Tanous22d268c2022-05-19 09:39:07 -07001591 }
1592
Alexander Hansen599b9af2024-08-06 15:11:57 +02001593 // Reset the unique ID on the first entry
1594 bool firstEntry = true;
1595 while (std::getline(logStream, logEntry))
Ed Tanous002d39b2022-05-31 08:59:27 -07001596 {
Alexander Hansen599b9af2024-08-06 15:11:57 +02001597 std::string idStr;
1598 if (!getUniqueEntryID(logEntry, idStr, firstEntry))
1599 {
1600 continue;
1601 }
1602 firstEntry = false;
1603
1604 nlohmann::json::object_t bmcLogEntry;
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001605 LogParseError status =
1606 fillEventLogEntryJson(idStr, logEntry, bmcLogEntry);
Alexander Hansen599b9af2024-08-06 15:11:57 +02001607 if (status == LogParseError::messageIdNotInRegistry)
1608 {
1609 continue;
1610 }
1611 if (status != LogParseError::success)
1612 {
1613 messages::internalError(asyncResp->res);
1614 return;
1615 }
1616
1617 entryCount++;
1618 // Handle paging using skip (number of entries to skip from the
1619 // start) and top (number of entries to display)
1620 if (entryCount <= skip || entryCount > skip + top)
Jason M. Bills4978b632022-02-22 14:17:43 -08001621 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001622 continue;
Jason M. Bills4978b632022-02-22 14:17:43 -08001623 }
Jason M. Bills897967d2019-07-29 17:05:30 -07001624
Alexander Hansen599b9af2024-08-06 15:11:57 +02001625 logEntryArray.emplace_back(std::move(bmcLogEntry));
1626 }
1627 }
1628 asyncResp->res.jsonValue["Members@odata.count"] = entryCount;
1629 if (skip + top < entryCount)
1630 {
1631 asyncResp->res.jsonValue["Members@odata.nextLink"] =
1632 boost::urls::format(
1633 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries?$skip={}",
1634 BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(skip + top));
1635 }
1636}
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001637
Alexander Hansen599b9af2024-08-06 15:11:57 +02001638inline void requestRoutesJournalEventLogEntryCollection(App& app)
1639{
1640 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/")
1641 .privileges(redfish::privileges::getLogEntryCollection)
1642 .methods(boost::beast::http::verb::get)(std::bind_front(
1643 handleSystemsLogServiceEventLogLogEntryCollection, std::ref(app)));
1644}
1645
1646inline void handleSystemsLogServiceEventLogEntriesGet(
1647 App& app, const crow::Request& req,
1648 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1649 const std::string& systemName, const std::string& param)
1650{
1651 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1652 {
1653 return;
1654 }
1655 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1656 {
1657 // Option currently returns no systems. TBD
1658 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1659 systemName);
1660 return;
1661 }
1662
1663 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1664 {
1665 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1666 systemName);
1667 return;
1668 }
1669
1670 const std::string& targetID = param;
1671
1672 // Go through the log files and check the unique ID for each
1673 // entry to find the target entry
1674 std::vector<std::filesystem::path> redfishLogFiles;
1675 getRedfishLogFiles(redfishLogFiles);
1676 std::string logEntry;
1677
1678 // Oldest logs are in the last file, so start there and loop
1679 // backwards
1680 for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend(); it++)
1681 {
1682 std::ifstream logStream(*it);
1683 if (!logStream.is_open())
1684 {
1685 continue;
1686 }
1687
1688 // Reset the unique ID on the first entry
1689 bool firstEntry = true;
1690 while (std::getline(logStream, logEntry))
1691 {
1692 std::string idStr;
1693 if (!getUniqueEntryID(logEntry, idStr, firstEntry))
1694 {
1695 continue;
1696 }
1697 firstEntry = false;
1698
1699 if (idStr == targetID)
1700 {
Jason M. Billsde703c52022-06-23 14:19:04 -07001701 nlohmann::json::object_t bmcLogEntry;
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001702 LogParseError status =
1703 fillEventLogEntryJson(idStr, logEntry, bmcLogEntry);
Jason M. Billsac992cd2022-06-24 13:31:46 -07001704 if (status != LogParseError::success)
Ed Tanous002d39b2022-05-31 08:59:27 -07001705 {
1706 messages::internalError(asyncResp->res);
1707 return;
Andrew Geisslercb92c032018-08-17 07:56:14 -07001708 }
Alexander Hansen599b9af2024-08-06 15:11:57 +02001709 asyncResp->res.jsonValue.update(bmcLogEntry);
1710 return;
Jason M. Bills4978b632022-02-22 14:17:43 -08001711 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001712 }
Alexander Hansen599b9af2024-08-06 15:11:57 +02001713 }
1714 // Requested ID was not found
1715 messages::resourceNotFound(asyncResp->res, "LogEntry", targetID);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001716}
Chicago Duan336e96c2019-07-15 14:22:08 +08001717
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001718inline void requestRoutesJournalEventLogEntry(App& app)
1719{
1720 BMCWEB_ROUTE(
Ed Tanous22d268c2022-05-19 09:39:07 -07001721 app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001722 .privileges(redfish::privileges::getLogEntry)
Alexander Hansen599b9af2024-08-06 15:11:57 +02001723 .methods(boost::beast::http::verb::get)(std::bind_front(
1724 handleSystemsLogServiceEventLogEntriesGet, std::ref(app)));
1725}
1726
1727inline void dBusEventLogEntryCollection(
1728 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1729{
1730 // Collections don't include the static data added by SubRoute
1731 // because it has a duplicate entry for members
1732 asyncResp->res.jsonValue["@odata.type"] =
1733 "#LogEntryCollection.LogEntryCollection";
1734 asyncResp->res.jsonValue["@odata.id"] =
1735 std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
1736 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1737 asyncResp->res.jsonValue["Name"] = "System Event Log Entries";
1738 asyncResp->res.jsonValue["Description"] =
1739 "Collection of System Event Log Entries";
1740
1741 // DBus implementation of EventLog/Entries
1742 // Make call to Logging Service to find all log entry objects
1743 sdbusplus::message::object_path path("/xyz/openbmc_project/logging");
1744 dbus::utility::getManagedObjects(
1745 "xyz.openbmc_project.Logging", path,
1746 [asyncResp](const boost::system::error_code& ec,
1747 const dbus::utility::ManagedObjectType& resp) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001748 afterLogEntriesGetManagedObjects(asyncResp, ec, resp);
1749 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001750}
1751
1752inline void requestRoutesDBusEventLogEntryCollection(App& app)
1753{
Ed Tanous22d268c2022-05-19 09:39:07 -07001754 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/")
Ed Tanoused398212021-06-09 17:05:54 -07001755 .privileges(redfish::privileges::getLogEntryCollection)
Ed Tanous002d39b2022-05-31 08:59:27 -07001756 .methods(boost::beast::http::verb::get)(
1757 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07001758 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1759 const std::string& systemName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001760 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1761 {
1762 return;
1763 }
1764 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1765 {
1766 // Option currently returns no systems. TBD
1767 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1768 systemName);
1769 return;
1770 }
1771 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1772 {
1773 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1774 systemName);
1775 return;
1776 }
1777 dBusEventLogEntryCollection(asyncResp);
1778 });
Alexander Hansen599b9af2024-08-06 15:11:57 +02001779}
Ed Tanous22d268c2022-05-19 09:39:07 -07001780
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001781inline void dBusEventLogEntryGet(
1782 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID)
Alexander Hansen599b9af2024-08-06 15:11:57 +02001783{
1784 dbus::utility::escapePathForDbus(entryID);
Ed Tanous002d39b2022-05-31 08:59:27 -07001785
Alexander Hansen599b9af2024-08-06 15:11:57 +02001786 // DBus implementation of EventLog/Entries
1787 // Make call to Logging Service to find all log entry objects
Ed Tanousdeae6a72024-11-11 21:58:57 -08001788 dbus::utility::getAllProperties(
1789 "xyz.openbmc_project.Logging",
Alexander Hansen599b9af2024-08-06 15:11:57 +02001790 "/xyz/openbmc_project/logging/entry/" + entryID, "",
1791 [asyncResp, entryID](const boost::system::error_code& ec,
1792 const dbus::utility::DBusPropertiesMap& resp) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001793 if (ec.value() == EBADR)
1794 {
1795 messages::resourceNotFound(asyncResp->res, "EventLogEntry",
1796 entryID);
1797 return;
1798 }
1799 if (ec)
1800 {
1801 BMCWEB_LOG_ERROR(
1802 "EventLogEntry (DBus) resp_handler got error {}", ec);
1803 messages::internalError(asyncResp->res);
1804 return;
1805 }
Alexander Hansen599b9af2024-08-06 15:11:57 +02001806
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001807 fillEventLogLogEntryFromPropertyMap(asyncResp, resp,
1808 asyncResp->res.jsonValue);
1809 });
Alexander Hansen599b9af2024-08-06 15:11:57 +02001810}
1811
Patrick Williams504af5a2025-02-03 14:29:03 -05001812inline void dBusEventLogEntryPatch(
1813 const crow::Request& req,
1814 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1815 const std::string& entryId)
Alexander Hansen599b9af2024-08-06 15:11:57 +02001816{
1817 std::optional<bool> resolved;
1818
1819 if (!json_util::readJsonPatch(req, asyncResp->res, "Resolved", resolved))
1820 {
1821 return;
1822 }
1823 BMCWEB_LOG_DEBUG("Set Resolved");
1824
1825 setDbusProperty(asyncResp, "Resolved", "xyz.openbmc_project.Logging",
1826 "/xyz/openbmc_project/logging/entry/" + entryId,
1827 "xyz.openbmc_project.Logging.Entry", "Resolved",
1828 resolved.value_or(false));
1829}
1830
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001831inline void dBusEventLogEntryDelete(
1832 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID)
Alexander Hansen599b9af2024-08-06 15:11:57 +02001833{
1834 BMCWEB_LOG_DEBUG("Do delete single event entries.");
1835
1836 dbus::utility::escapePathForDbus(entryID);
1837
1838 // Process response from Logging service.
1839 auto respHandler = [asyncResp,
1840 entryID](const boost::system::error_code& ec) {
1841 BMCWEB_LOG_DEBUG("EventLogEntry (DBus) doDelete callback: Done");
1842 if (ec)
1843 {
1844 if (ec.value() == EBADR)
Ed Tanous45ca1b82022-03-25 13:07:27 -07001845 {
Alexander Hansen599b9af2024-08-06 15:11:57 +02001846 messages::resourceNotFound(asyncResp->res, "LogEntry", entryID);
Ed Tanous45ca1b82022-03-25 13:07:27 -07001847 return;
1848 }
Alexander Hansen599b9af2024-08-06 15:11:57 +02001849 // TODO Handle for specific error code
1850 BMCWEB_LOG_ERROR(
1851 "EventLogEntry (DBus) doDelete respHandler got error {}", ec);
1852 asyncResp->res.result(
1853 boost::beast::http::status::internal_server_error);
1854 return;
1855 }
Abhishek Patel9017faf2021-09-14 22:48:55 -05001856
Alexander Hansen599b9af2024-08-06 15:11:57 +02001857 asyncResp->res.result(boost::beast::http::status::ok);
1858 };
1859
1860 // Make call to Logging service to request Delete Log
Ed Tanous177612a2025-02-14 15:16:09 -08001861 dbus::utility::async_method_call(
1862 asyncResp, respHandler, "xyz.openbmc_project.Logging",
Alexander Hansen599b9af2024-08-06 15:11:57 +02001863 "/xyz/openbmc_project/logging/entry/" + entryID,
1864 "xyz.openbmc_project.Object.Delete", "Delete");
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001865}
Xiaochao Ma75710de2021-01-21 17:56:02 +08001866
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001867inline void requestRoutesDBusEventLogEntry(App& app)
Adriana Kobylak400fd1f2021-01-29 09:01:30 -06001868{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001869 BMCWEB_ROUTE(
Ed Tanous22d268c2022-05-19 09:39:07 -07001870 app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001871 .privileges(redfish::privileges::getLogEntry)
Ed Tanous002d39b2022-05-31 08:59:27 -07001872 .methods(boost::beast::http::verb::get)(
1873 [&app](const crow::Request& req,
1874 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous898f2aa2024-08-07 12:18:22 -07001875 const std::string& systemName, const std::string& entryId) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001876 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1877 {
1878 return;
1879 }
1880 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1881 {
1882 // Option currently returns no systems. TBD
1883 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1884 systemName);
1885 return;
1886 }
1887 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1888 {
1889 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1890 systemName);
1891 return;
1892 }
Ed Tanous22d268c2022-05-19 09:39:07 -07001893
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001894 dBusEventLogEntryGet(asyncResp, entryId);
1895 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001896
1897 BMCWEB_ROUTE(
Ed Tanous22d268c2022-05-19 09:39:07 -07001898 app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001899 .privileges(redfish::privileges::patchLogEntry)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001900 .methods(boost::beast::http::verb::patch)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07001901 [&app](const crow::Request& req,
1902 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -07001903 const std::string& systemName, const std::string& entryId) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001904 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1905 {
1906 return;
1907 }
1908 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1909 {
1910 // Option currently returns no systems. TBD
1911 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1912 systemName);
1913 return;
1914 }
1915 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1916 {
1917 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1918 systemName);
1919 return;
1920 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001921
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001922 dBusEventLogEntryPatch(req, asyncResp, entryId);
1923 });
Adriana Kobylak400fd1f2021-01-29 09:01:30 -06001924
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001925 BMCWEB_ROUTE(
Ed Tanous22d268c2022-05-19 09:39:07 -07001926 app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001927 .privileges(redfish::privileges::deleteLogEntry)
1928
Ed Tanous002d39b2022-05-31 08:59:27 -07001929 .methods(boost::beast::http::verb::delete_)(
1930 [&app](const crow::Request& req,
1931 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -07001932 const std::string& systemName, const std::string& param) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001933 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1934 {
1935 return;
1936 }
1937 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1938 {
1939 // Option currently returns no systems. TBD
1940 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1941 systemName);
1942 return;
1943 }
1944 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1945 {
1946 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1947 systemName);
1948 return;
1949 }
1950 dBusEventLogEntryDelete(asyncResp, param);
1951 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001952}
1953
Claire Weinandd72e872022-08-15 14:20:06 -07001954inline void handleBMCLogServicesCollectionGet(
Claire Weinanfdd26902022-03-01 14:18:25 -08001955 crow::App& app, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07001956 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1957 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08001958{
1959 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1960 {
1961 return;
1962 }
Ed Tanous253f11b2024-05-16 09:38:31 -07001963
1964 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
1965 {
1966 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
1967 return;
1968 }
1969
Claire Weinanfdd26902022-03-01 14:18:25 -08001970 // Collections don't include the static data added by SubRoute
1971 // because it has a duplicate entry for members
1972 asyncResp->res.jsonValue["@odata.type"] =
1973 "#LogServiceCollection.LogServiceCollection";
Ed Tanous253f11b2024-05-16 09:38:31 -07001974 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
1975 "/redfish/v1/Managers/{}/LogServices", BMCWEB_REDFISH_MANAGER_URI_NAME);
Claire Weinanfdd26902022-03-01 14:18:25 -08001976 asyncResp->res.jsonValue["Name"] = "Open BMC Log Services Collection";
1977 asyncResp->res.jsonValue["Description"] =
1978 "Collection of LogServices for this Manager";
1979 nlohmann::json& logServiceArray = asyncResp->res.jsonValue["Members"];
1980 logServiceArray = nlohmann::json::array();
1981
Ed Tanous25b54db2024-04-17 15:40:31 -07001982 if constexpr (BMCWEB_REDFISH_BMC_JOURNAL)
1983 {
1984 nlohmann::json::object_t journal;
Ed Tanous253f11b2024-05-16 09:38:31 -07001985 journal["@odata.id"] =
1986 boost::urls::format("/redfish/v1/Managers/{}/LogServices/Journal",
1987 BMCWEB_REDFISH_MANAGER_URI_NAME);
Ed Tanous25b54db2024-04-17 15:40:31 -07001988 logServiceArray.emplace_back(std::move(journal));
1989 }
Claire Weinanfdd26902022-03-01 14:18:25 -08001990
1991 asyncResp->res.jsonValue["Members@odata.count"] = logServiceArray.size();
1992
Ed Tanous25b54db2024-04-17 15:40:31 -07001993 if constexpr (BMCWEB_REDFISH_DUMP_LOG)
1994 {
1995 constexpr std::array<std::string_view, 1> interfaces = {
1996 "xyz.openbmc_project.Collection.DeleteAll"};
1997 dbus::utility::getSubTreePaths(
1998 "/xyz/openbmc_project/dump", 0, interfaces,
1999 [asyncResp](const boost::system::error_code& ec,
2000 const dbus::utility::MapperGetSubTreePathsResponse&
2001 subTreePaths) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002002 if (ec)
Ed Tanous25b54db2024-04-17 15:40:31 -07002003 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002004 BMCWEB_LOG_ERROR(
2005 "handleBMCLogServicesCollectionGet respHandler got error {}",
2006 ec);
2007 // Assume that getting an error simply means there are no
2008 // dump LogServices. Return without adding any error
2009 // response.
2010 return;
Ed Tanous25b54db2024-04-17 15:40:31 -07002011 }
Ed Tanous25b54db2024-04-17 15:40:31 -07002012
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002013 nlohmann::json& logServiceArrayLocal =
2014 asyncResp->res.jsonValue["Members"];
2015
2016 for (const std::string& path : subTreePaths)
2017 {
2018 if (path == "/xyz/openbmc_project/dump/bmc")
2019 {
2020 nlohmann::json::object_t member;
2021 member["@odata.id"] = boost::urls::format(
2022 "/redfish/v1/Managers/{}/LogServices/Dump",
2023 BMCWEB_REDFISH_MANAGER_URI_NAME);
2024 logServiceArrayLocal.emplace_back(std::move(member));
2025 }
2026 else if (path == "/xyz/openbmc_project/dump/faultlog")
2027 {
2028 nlohmann::json::object_t member;
2029 member["@odata.id"] = boost::urls::format(
2030 "/redfish/v1/Managers/{}/LogServices/FaultLog",
2031 BMCWEB_REDFISH_MANAGER_URI_NAME);
2032 logServiceArrayLocal.emplace_back(std::move(member));
2033 }
2034 }
2035
2036 asyncResp->res.jsonValue["Members@odata.count"] =
2037 logServiceArrayLocal.size();
2038 });
Ed Tanous25b54db2024-04-17 15:40:31 -07002039 }
Claire Weinanfdd26902022-03-01 14:18:25 -08002040}
2041
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002042inline void requestRoutesBMCLogServiceCollection(App& app)
2043{
Ed Tanous253f11b2024-05-16 09:38:31 -07002044 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/")
Gunnar Millsad89dcf2021-07-30 14:40:11 -05002045 .privileges(redfish::privileges::getLogServiceCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002046 .methods(boost::beast::http::verb::get)(
Claire Weinandd72e872022-08-15 14:20:06 -07002047 std::bind_front(handleBMCLogServicesCollectionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002048}
Ed Tanous1da66f72018-07-27 16:13:37 -07002049
Patrick Williams504af5a2025-02-03 14:29:03 -05002050inline void getDumpServiceInfo(
2051 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2052 const std::string& dumpType)
Claire Weinanfdd26902022-03-01 14:18:25 -08002053{
2054 std::string dumpPath;
Ed Tanous539d8c62024-06-19 14:38:27 -07002055 log_service::OverWritePolicy overWritePolicy =
2056 log_service::OverWritePolicy::Invalid;
Claire Weinanfdd26902022-03-01 14:18:25 -08002057 bool collectDiagnosticDataSupported = false;
2058
2059 if (dumpType == "BMC")
2060 {
Ed Tanous253f11b2024-05-16 09:38:31 -07002061 dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/Dump",
2062 BMCWEB_REDFISH_MANAGER_URI_NAME);
Ed Tanous539d8c62024-06-19 14:38:27 -07002063 overWritePolicy = log_service::OverWritePolicy::WrapsWhenFull;
Claire Weinanfdd26902022-03-01 14:18:25 -08002064 collectDiagnosticDataSupported = true;
2065 }
2066 else if (dumpType == "FaultLog")
2067 {
Ed Tanous253f11b2024-05-16 09:38:31 -07002068 dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/FaultLog",
2069 BMCWEB_REDFISH_MANAGER_URI_NAME);
Ed Tanous539d8c62024-06-19 14:38:27 -07002070 overWritePolicy = log_service::OverWritePolicy::Unknown;
Claire Weinanfdd26902022-03-01 14:18:25 -08002071 collectDiagnosticDataSupported = false;
2072 }
2073 else if (dumpType == "System")
2074 {
Ed Tanous253f11b2024-05-16 09:38:31 -07002075 dumpPath = std::format("/redfish/v1/Systems/{}/LogServices/Dump",
2076 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanous539d8c62024-06-19 14:38:27 -07002077 overWritePolicy = log_service::OverWritePolicy::WrapsWhenFull;
Claire Weinanfdd26902022-03-01 14:18:25 -08002078 collectDiagnosticDataSupported = true;
2079 }
2080 else
2081 {
Ed Tanous62598e32023-07-17 17:06:25 -07002082 BMCWEB_LOG_ERROR("getDumpServiceInfo() invalid dump type: {}",
2083 dumpType);
Claire Weinanfdd26902022-03-01 14:18:25 -08002084 messages::internalError(asyncResp->res);
2085 return;
2086 }
2087
2088 asyncResp->res.jsonValue["@odata.id"] = dumpPath;
2089 asyncResp->res.jsonValue["@odata.type"] = "#LogService.v1_2_0.LogService";
2090 asyncResp->res.jsonValue["Name"] = "Dump LogService";
2091 asyncResp->res.jsonValue["Description"] = dumpType + " Dump LogService";
2092 asyncResp->res.jsonValue["Id"] = std::filesystem::path(dumpPath).filename();
Ed Tanous539d8c62024-06-19 14:38:27 -07002093 asyncResp->res.jsonValue["OverWritePolicy"] = overWritePolicy;
Claire Weinanfdd26902022-03-01 14:18:25 -08002094
2095 std::pair<std::string, std::string> redfishDateTimeOffset =
Ed Tanous2b829372022-08-03 14:22:34 -07002096 redfish::time_utils::getDateTimeOffsetNow();
Claire Weinanfdd26902022-03-01 14:18:25 -08002097 asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
2098 asyncResp->res.jsonValue["DateTimeLocalOffset"] =
2099 redfishDateTimeOffset.second;
2100
2101 asyncResp->res.jsonValue["Entries"]["@odata.id"] = dumpPath + "/Entries";
Claire Weinanfdd26902022-03-01 14:18:25 -08002102
2103 if (collectDiagnosticDataSupported)
2104 {
2105 asyncResp->res.jsonValue["Actions"]["#LogService.CollectDiagnosticData"]
2106 ["target"] =
2107 dumpPath + "/Actions/LogService.CollectDiagnosticData";
2108 }
Claire Weinan0d946212022-07-13 19:40:19 -07002109
2110 constexpr std::array<std::string_view, 1> interfaces = {deleteAllInterface};
2111 dbus::utility::getSubTreePaths(
2112 "/xyz/openbmc_project/dump", 0, interfaces,
2113 [asyncResp, dumpType, dumpPath](
2114 const boost::system::error_code& ec,
2115 const dbus::utility::MapperGetSubTreePathsResponse& subTreePaths) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002116 if (ec)
Claire Weinan0d946212022-07-13 19:40:19 -07002117 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002118 BMCWEB_LOG_ERROR("getDumpServiceInfo respHandler got error {}",
2119 ec);
2120 // Assume that getting an error simply means there are no dump
2121 // LogServices. Return without adding any error response.
2122 return;
Claire Weinan0d946212022-07-13 19:40:19 -07002123 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002124 std::string dbusDumpPath = getDumpPath(dumpType);
2125 for (const std::string& path : subTreePaths)
2126 {
2127 if (path == dbusDumpPath)
2128 {
2129 asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"]
2130 ["target"] =
2131 dumpPath + "/Actions/LogService.ClearLog";
2132 break;
2133 }
2134 }
2135 });
Claire Weinanfdd26902022-03-01 14:18:25 -08002136}
2137
2138inline void handleLogServicesDumpServiceGet(
2139 crow::App& app, const std::string& dumpType, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07002140 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2141 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002142{
2143 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2144 {
2145 return;
2146 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002147
2148 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2149 {
2150 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2151 return;
2152 }
2153
Claire Weinanfdd26902022-03-01 14:18:25 -08002154 getDumpServiceInfo(asyncResp, dumpType);
2155}
2156
Ed Tanous22d268c2022-05-19 09:39:07 -07002157inline void handleLogServicesDumpServiceComputerSystemGet(
2158 crow::App& app, const crow::Request& req,
2159 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2160 const std::string& chassisId)
2161{
2162 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2163 {
2164 return;
2165 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002166 if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous22d268c2022-05-19 09:39:07 -07002167 {
2168 messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
2169 return;
2170 }
2171 getDumpServiceInfo(asyncResp, "System");
2172}
2173
Claire Weinanfdd26902022-03-01 14:18:25 -08002174inline void handleLogServicesDumpEntriesCollectionGet(
2175 crow::App& app, const std::string& dumpType, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07002176 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2177 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002178{
2179 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2180 {
2181 return;
2182 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002183
2184 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2185 {
2186 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2187 return;
2188 }
Claire Weinanfdd26902022-03-01 14:18:25 -08002189 getDumpEntryCollection(asyncResp, dumpType);
2190}
2191
Ed Tanous22d268c2022-05-19 09:39:07 -07002192inline void handleLogServicesDumpEntriesCollectionComputerSystemGet(
2193 crow::App& app, const crow::Request& req,
2194 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2195 const std::string& chassisId)
2196{
2197 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2198 {
2199 return;
2200 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002201 if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous22d268c2022-05-19 09:39:07 -07002202 {
2203 messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
2204 return;
2205 }
2206 getDumpEntryCollection(asyncResp, "System");
2207}
2208
Claire Weinanfdd26902022-03-01 14:18:25 -08002209inline void handleLogServicesDumpEntryGet(
2210 crow::App& app, const std::string& dumpType, const crow::Request& req,
2211 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous253f11b2024-05-16 09:38:31 -07002212 const std::string& managerId, const std::string& dumpId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002213{
2214 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2215 {
2216 return;
2217 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002218 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2219 {
2220 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2221 return;
2222 }
Claire Weinanfdd26902022-03-01 14:18:25 -08002223 getDumpEntryById(asyncResp, dumpId, dumpType);
2224}
Carson Labrado168d1b12023-03-27 17:04:46 +00002225
Ed Tanous22d268c2022-05-19 09:39:07 -07002226inline void handleLogServicesDumpEntryComputerSystemGet(
2227 crow::App& app, const crow::Request& req,
2228 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2229 const std::string& chassisId, const std::string& dumpId)
2230{
2231 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2232 {
2233 return;
2234 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002235 if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous22d268c2022-05-19 09:39:07 -07002236 {
2237 messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
2238 return;
2239 }
2240 getDumpEntryById(asyncResp, dumpId, "System");
2241}
Claire Weinanfdd26902022-03-01 14:18:25 -08002242
2243inline void handleLogServicesDumpEntryDelete(
2244 crow::App& app, const std::string& dumpType, const crow::Request& req,
2245 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous253f11b2024-05-16 09:38:31 -07002246 const std::string& managerId, const std::string& dumpId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002247{
2248 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2249 {
2250 return;
2251 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002252
2253 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2254 {
2255 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2256 return;
2257 }
Claire Weinanfdd26902022-03-01 14:18:25 -08002258 deleteDumpEntry(asyncResp, dumpId, dumpType);
2259}
2260
Ed Tanous22d268c2022-05-19 09:39:07 -07002261inline void handleLogServicesDumpEntryComputerSystemDelete(
2262 crow::App& app, const crow::Request& req,
2263 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2264 const std::string& chassisId, const std::string& dumpId)
2265{
2266 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2267 {
2268 return;
2269 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002270 if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous22d268c2022-05-19 09:39:07 -07002271 {
2272 messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
2273 return;
2274 }
2275 deleteDumpEntry(asyncResp, dumpId, "System");
2276}
2277
Carson Labrado168d1b12023-03-27 17:04:46 +00002278inline void handleLogServicesDumpEntryDownloadGet(
2279 crow::App& app, const std::string& dumpType, const crow::Request& req,
2280 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous253f11b2024-05-16 09:38:31 -07002281 const std::string& managerId, const std::string& dumpId)
Carson Labrado168d1b12023-03-27 17:04:46 +00002282{
2283 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2284 {
2285 return;
2286 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002287
2288 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2289 {
2290 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2291 return;
2292 }
Carson Labrado168d1b12023-03-27 17:04:46 +00002293 downloadDumpEntry(asyncResp, dumpId, dumpType);
2294}
2295
2296inline void handleDBusEventLogEntryDownloadGet(
2297 crow::App& app, const std::string& dumpType, const crow::Request& req,
2298 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2299 const std::string& systemName, const std::string& entryID)
2300{
2301 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2302 {
2303 return;
2304 }
2305 if (!http_helpers::isContentTypeAllowed(
2306 req.getHeaderValue("Accept"),
2307 http_helpers::ContentType::OctetStream, true))
2308 {
2309 asyncResp->res.result(boost::beast::http::status::bad_request);
2310 return;
2311 }
2312 downloadEventLogEntry(asyncResp, systemName, entryID, dumpType);
2313}
2314
Claire Weinanfdd26902022-03-01 14:18:25 -08002315inline void handleLogServicesDumpCollectDiagnosticDataPost(
2316 crow::App& app, const std::string& dumpType, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07002317 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2318 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002319{
2320 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2321 {
2322 return;
2323 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002324 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2325 {
2326 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2327 return;
2328 }
2329
Claire Weinanfdd26902022-03-01 14:18:25 -08002330 createDump(asyncResp, req, dumpType);
2331}
2332
Ed Tanous22d268c2022-05-19 09:39:07 -07002333inline void handleLogServicesDumpCollectDiagnosticDataComputerSystemPost(
2334 crow::App& app, const crow::Request& req,
2335 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002336 const std::string& systemName)
Ed Tanous22d268c2022-05-19 09:39:07 -07002337{
2338 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2339 {
2340 return;
2341 }
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002342
Ed Tanous25b54db2024-04-17 15:40:31 -07002343 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous22d268c2022-05-19 09:39:07 -07002344 {
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002345 // Option currently returns no systems. TBD
2346 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2347 systemName);
2348 return;
2349 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002350 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002351 {
2352 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2353 systemName);
Ed Tanous22d268c2022-05-19 09:39:07 -07002354 return;
2355 }
2356 createDump(asyncResp, req, "System");
2357}
2358
Claire Weinanfdd26902022-03-01 14:18:25 -08002359inline void handleLogServicesDumpClearLogPost(
2360 crow::App& app, const std::string& dumpType, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07002361 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2362 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002363{
2364 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2365 {
2366 return;
2367 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002368
2369 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2370 {
2371 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2372 return;
2373 }
Claire Weinanfdd26902022-03-01 14:18:25 -08002374 clearDump(asyncResp, dumpType);
2375}
2376
Ed Tanous22d268c2022-05-19 09:39:07 -07002377inline void handleLogServicesDumpClearLogComputerSystemPost(
2378 crow::App& app, const crow::Request& req,
2379 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002380 const std::string& systemName)
Ed Tanous22d268c2022-05-19 09:39:07 -07002381{
2382 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2383 {
2384 return;
2385 }
Ed Tanous25b54db2024-04-17 15:40:31 -07002386 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous22d268c2022-05-19 09:39:07 -07002387 {
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002388 // Option currently returns no systems. TBD
2389 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2390 systemName);
2391 return;
2392 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002393 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002394 {
2395 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2396 systemName);
Ed Tanous22d268c2022-05-19 09:39:07 -07002397 return;
2398 }
2399 clearDump(asyncResp, "System");
2400}
2401
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002402inline void requestRoutesBMCDumpService(App& app)
2403{
Ed Tanous253f11b2024-05-16 09:38:31 -07002404 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/Dump/")
Ed Tanoused398212021-06-09 17:05:54 -07002405 .privileges(redfish::privileges::getLogService)
Claire Weinanfdd26902022-03-01 14:18:25 -08002406 .methods(boost::beast::http::verb::get)(std::bind_front(
2407 handleLogServicesDumpServiceGet, std::ref(app), "BMC"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002408}
2409
2410inline void requestRoutesBMCDumpEntryCollection(App& app)
2411{
Ed Tanous253f11b2024-05-16 09:38:31 -07002412 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/")
Ed Tanoused398212021-06-09 17:05:54 -07002413 .privileges(redfish::privileges::getLogEntryCollection)
Claire Weinanfdd26902022-03-01 14:18:25 -08002414 .methods(boost::beast::http::verb::get)(std::bind_front(
2415 handleLogServicesDumpEntriesCollectionGet, std::ref(app), "BMC"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002416}
2417
2418inline void requestRoutesBMCDumpEntry(App& app)
2419{
2420 BMCWEB_ROUTE(app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002421 "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002422 .privileges(redfish::privileges::getLogEntry)
Claire Weinanfdd26902022-03-01 14:18:25 -08002423 .methods(boost::beast::http::verb::get)(std::bind_front(
2424 handleLogServicesDumpEntryGet, std::ref(app), "BMC"));
2425
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002426 BMCWEB_ROUTE(app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002427 "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002428 .privileges(redfish::privileges::deleteLogEntry)
Claire Weinanfdd26902022-03-01 14:18:25 -08002429 .methods(boost::beast::http::verb::delete_)(std::bind_front(
2430 handleLogServicesDumpEntryDelete, std::ref(app), "BMC"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002431}
2432
Carson Labrado168d1b12023-03-27 17:04:46 +00002433inline void requestRoutesBMCDumpEntryDownload(App& app)
2434{
2435 BMCWEB_ROUTE(
2436 app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002437 "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/attachment/")
Carson Labrado168d1b12023-03-27 17:04:46 +00002438 .privileges(redfish::privileges::getLogEntry)
2439 .methods(boost::beast::http::verb::get)(std::bind_front(
2440 handleLogServicesDumpEntryDownloadGet, std::ref(app), "BMC"));
2441}
2442
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002443inline void requestRoutesBMCDumpCreate(App& app)
2444{
George Liu0fda0f12021-11-16 10:06:17 +08002445 BMCWEB_ROUTE(
2446 app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002447 "/redfish/v1/Managers/<str>/LogServices/Dump/Actions/LogService.CollectDiagnosticData/")
Ed Tanoused398212021-06-09 17:05:54 -07002448 .privileges(redfish::privileges::postLogService)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002449 .methods(boost::beast::http::verb::post)(
Claire Weinanfdd26902022-03-01 14:18:25 -08002450 std::bind_front(handleLogServicesDumpCollectDiagnosticDataPost,
2451 std::ref(app), "BMC"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002452}
2453
2454inline void requestRoutesBMCDumpClear(App& app)
2455{
George Liu0fda0f12021-11-16 10:06:17 +08002456 BMCWEB_ROUTE(
2457 app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002458 "/redfish/v1/Managers/<str>/LogServices/Dump/Actions/LogService.ClearLog/")
Ed Tanoused398212021-06-09 17:05:54 -07002459 .privileges(redfish::privileges::postLogService)
Claire Weinanfdd26902022-03-01 14:18:25 -08002460 .methods(boost::beast::http::verb::post)(std::bind_front(
2461 handleLogServicesDumpClearLogPost, std::ref(app), "BMC"));
2462}
2463
Carson Labrado168d1b12023-03-27 17:04:46 +00002464inline void requestRoutesDBusEventLogEntryDownload(App& app)
2465{
2466 BMCWEB_ROUTE(
2467 app,
Ravi Teja9e9d99d2023-11-08 05:33:59 -06002468 "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/attachment/")
Carson Labrado168d1b12023-03-27 17:04:46 +00002469 .privileges(redfish::privileges::getLogEntry)
2470 .methods(boost::beast::http::verb::get)(std::bind_front(
2471 handleDBusEventLogEntryDownloadGet, std::ref(app), "System"));
2472}
2473
Claire Weinanfdd26902022-03-01 14:18:25 -08002474inline void requestRoutesFaultLogDumpService(App& app)
2475{
Ed Tanous253f11b2024-05-16 09:38:31 -07002476 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/")
Claire Weinanfdd26902022-03-01 14:18:25 -08002477 .privileges(redfish::privileges::getLogService)
2478 .methods(boost::beast::http::verb::get)(std::bind_front(
2479 handleLogServicesDumpServiceGet, std::ref(app), "FaultLog"));
2480}
2481
2482inline void requestRoutesFaultLogDumpEntryCollection(App& app)
2483{
Ed Tanous253f11b2024-05-16 09:38:31 -07002484 BMCWEB_ROUTE(app,
2485 "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/")
Claire Weinanfdd26902022-03-01 14:18:25 -08002486 .privileges(redfish::privileges::getLogEntryCollection)
2487 .methods(boost::beast::http::verb::get)(
2488 std::bind_front(handleLogServicesDumpEntriesCollectionGet,
2489 std::ref(app), "FaultLog"));
2490}
2491
2492inline void requestRoutesFaultLogDumpEntry(App& app)
2493{
Ed Tanous253f11b2024-05-16 09:38:31 -07002494 BMCWEB_ROUTE(
2495 app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/<str>/")
Claire Weinanfdd26902022-03-01 14:18:25 -08002496 .privileges(redfish::privileges::getLogEntry)
2497 .methods(boost::beast::http::verb::get)(std::bind_front(
2498 handleLogServicesDumpEntryGet, std::ref(app), "FaultLog"));
2499
Ed Tanous253f11b2024-05-16 09:38:31 -07002500 BMCWEB_ROUTE(
2501 app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/<str>/")
Claire Weinanfdd26902022-03-01 14:18:25 -08002502 .privileges(redfish::privileges::deleteLogEntry)
2503 .methods(boost::beast::http::verb::delete_)(std::bind_front(
2504 handleLogServicesDumpEntryDelete, std::ref(app), "FaultLog"));
2505}
2506
2507inline void requestRoutesFaultLogDumpClear(App& app)
2508{
2509 BMCWEB_ROUTE(
2510 app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002511 "/redfish/v1/Managers/<str>/LogServices/FaultLog/Actions/LogService.ClearLog/")
Claire Weinanfdd26902022-03-01 14:18:25 -08002512 .privileges(redfish::privileges::postLogService)
2513 .methods(boost::beast::http::verb::post)(std::bind_front(
2514 handleLogServicesDumpClearLogPost, std::ref(app), "FaultLog"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002515}
2516
2517inline void requestRoutesSystemDumpService(App& app)
2518{
Ed Tanous22d268c2022-05-19 09:39:07 -07002519 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Dump/")
Ed Tanoused398212021-06-09 17:05:54 -07002520 .privileges(redfish::privileges::getLogService)
Claire Weinan6ab9ad52022-08-12 18:20:17 -07002521 .methods(boost::beast::http::verb::get)(std::bind_front(
Ed Tanous22d268c2022-05-19 09:39:07 -07002522 handleLogServicesDumpServiceComputerSystemGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002523}
2524
2525inline void requestRoutesSystemDumpEntryCollection(App& app)
2526{
Ed Tanous22d268c2022-05-19 09:39:07 -07002527 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/")
Ed Tanoused398212021-06-09 17:05:54 -07002528 .privileges(redfish::privileges::getLogEntryCollection)
Ed Tanous22d268c2022-05-19 09:39:07 -07002529 .methods(boost::beast::http::verb::get)(std::bind_front(
2530 handleLogServicesDumpEntriesCollectionComputerSystemGet,
2531 std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002532}
2533
2534inline void requestRoutesSystemDumpEntry(App& app)
2535{
2536 BMCWEB_ROUTE(app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002537 "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002538 .privileges(redfish::privileges::getLogEntry)
Claire Weinan6ab9ad52022-08-12 18:20:17 -07002539 .methods(boost::beast::http::verb::get)(std::bind_front(
Ed Tanous22d268c2022-05-19 09:39:07 -07002540 handleLogServicesDumpEntryComputerSystemGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002541
2542 BMCWEB_ROUTE(app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002543 "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002544 .privileges(redfish::privileges::deleteLogEntry)
Claire Weinan6ab9ad52022-08-12 18:20:17 -07002545 .methods(boost::beast::http::verb::delete_)(std::bind_front(
Ed Tanous22d268c2022-05-19 09:39:07 -07002546 handleLogServicesDumpEntryComputerSystemDelete, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002547}
2548
2549inline void requestRoutesSystemDumpCreate(App& app)
2550{
George Liu0fda0f12021-11-16 10:06:17 +08002551 BMCWEB_ROUTE(
2552 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002553 "/redfish/v1/Systems/<str>/LogServices/Dump/Actions/LogService.CollectDiagnosticData/")
Ed Tanoused398212021-06-09 17:05:54 -07002554 .privileges(redfish::privileges::postLogService)
Ed Tanous22d268c2022-05-19 09:39:07 -07002555 .methods(boost::beast::http::verb::post)(std::bind_front(
2556 handleLogServicesDumpCollectDiagnosticDataComputerSystemPost,
2557 std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002558}
2559
2560inline void requestRoutesSystemDumpClear(App& app)
2561{
George Liu0fda0f12021-11-16 10:06:17 +08002562 BMCWEB_ROUTE(
2563 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002564 "/redfish/v1/Systems/<str>/LogServices/Dump/Actions/LogService.ClearLog/")
Ed Tanoused398212021-06-09 17:05:54 -07002565 .privileges(redfish::privileges::postLogService)
Claire Weinan6ab9ad52022-08-12 18:20:17 -07002566 .methods(boost::beast::http::verb::post)(std::bind_front(
Ed Tanous22d268c2022-05-19 09:39:07 -07002567 handleLogServicesDumpClearLogComputerSystemPost, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002568}
2569
2570inline void requestRoutesCrashdumpService(App& app)
2571{
2572 // Note: Deviated from redfish privilege registry for GET & HEAD
2573 // method for security reasons.
2574 /**
2575 * Functions triggers appropriate requests on DBus
2576 */
Ed Tanous22d268c2022-05-19 09:39:07 -07002577 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Crashdump/")
Ed Tanoused398212021-06-09 17:05:54 -07002578 // This is incorrect, should be:
2579 //.privileges(redfish::privileges::getLogService)
Ed Tanous432a8902021-06-14 15:28:56 -07002580 .privileges({{"ConfigureManager"}})
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002581 .methods(
2582 boost::beast::http::verb::
2583 get)([&app](const crow::Request& req,
2584 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2585 const std::string& systemName) {
2586 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2587 {
2588 return;
2589 }
2590 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
2591 {
2592 // Option currently returns no systems. TBD
2593 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2594 systemName);
2595 return;
2596 }
2597 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2598 {
2599 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2600 systemName);
2601 return;
2602 }
Ed Tanous22d268c2022-05-19 09:39:07 -07002603
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002604 // Copy over the static data to include the entries added by
2605 // SubRoute
2606 asyncResp->res.jsonValue["@odata.id"] =
2607 std::format("/redfish/v1/Systems/{}/LogServices/Crashdump",
2608 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2609 asyncResp->res.jsonValue["@odata.type"] =
2610 "#LogService.v1_2_0.LogService";
2611 asyncResp->res.jsonValue["Name"] = "Open BMC Oem Crashdump Service";
2612 asyncResp->res.jsonValue["Description"] = "Oem Crashdump Service";
2613 asyncResp->res.jsonValue["Id"] = "Crashdump";
2614 asyncResp->res.jsonValue["OverWritePolicy"] =
2615 log_service::OverWritePolicy::WrapsWhenFull;
2616 asyncResp->res.jsonValue["MaxNumberOfRecords"] = 3;
Tejas Patil7c8c4052021-06-04 17:43:14 +05302617
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002618 std::pair<std::string, std::string> redfishDateTimeOffset =
2619 redfish::time_utils::getDateTimeOffsetNow();
2620 asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
2621 asyncResp->res.jsonValue["DateTimeLocalOffset"] =
2622 redfishDateTimeOffset.second;
Tejas Patil7c8c4052021-06-04 17:43:14 +05302623
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002624 asyncResp->res.jsonValue["Entries"]["@odata.id"] = std::format(
2625 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries",
2626 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2627 asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"]
2628 ["target"] = std::format(
2629 "/redfish/v1/Systems/{}/LogServices/Crashdump/Actions/LogService.ClearLog",
2630 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2631 asyncResp->res
2632 .jsonValue["Actions"]["#LogService.CollectDiagnosticData"]
2633 ["target"] = std::format(
2634 "/redfish/v1/Systems/{}/LogServices/Crashdump/Actions/LogService.CollectDiagnosticData",
2635 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2636 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002637}
2638
2639void inline requestRoutesCrashdumpClear(App& app)
2640{
George Liu0fda0f12021-11-16 10:06:17 +08002641 BMCWEB_ROUTE(
2642 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002643 "/redfish/v1/Systems/<str>/LogServices/Crashdump/Actions/LogService.ClearLog/")
Ed Tanoused398212021-06-09 17:05:54 -07002644 // This is incorrect, should be:
2645 //.privileges(redfish::privileges::postLogService)
Ed Tanous432a8902021-06-14 15:28:56 -07002646 .privileges({{"ConfigureComponents"}})
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002647 .methods(boost::beast::http::verb::post)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07002648 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07002649 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2650 const std::string& systemName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002651 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2652 {
2653 return;
2654 }
2655 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
2656 {
2657 // Option currently returns no systems. TBD
2658 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2659 systemName);
2660 return;
2661 }
2662 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2663 {
2664 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2665 systemName);
2666 return;
2667 }
Ed Tanous177612a2025-02-14 15:16:09 -08002668 dbus::utility::async_method_call(
2669 asyncResp,
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002670 [asyncResp](const boost::system::error_code& ec,
2671 const std::string&) {
2672 if (ec)
2673 {
2674 messages::internalError(asyncResp->res);
2675 return;
2676 }
2677 messages::success(asyncResp->res);
2678 },
2679 crashdumpObject, crashdumpPath, deleteAllInterface,
2680 "DeleteAll");
2681 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002682}
Jason M. Bills5b61b5e2019-10-16 10:59:02 -07002683
Patrick Williams504af5a2025-02-03 14:29:03 -05002684inline void logCrashdumpEntry(
2685 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2686 const std::string& logID, nlohmann::json& logEntryJson)
Jason M. Billse855dd22019-10-08 11:37:48 -07002687{
Johnathan Mantey043a0532020-03-10 17:15:28 -07002688 auto getStoredLogCallback =
Ed Tanousb9d36b42022-02-26 21:42:46 -08002689 [asyncResp, logID,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002690 &logEntryJson](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002691 const dbus::utility::DBusPropertiesMap& params) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002692 if (ec)
2693 {
2694 BMCWEB_LOG_DEBUG("failed to get log ec: {}", ec.message());
2695 if (ec.value() ==
2696 boost::system::linux_error::bad_request_descriptor)
2697 {
2698 messages::resourceNotFound(asyncResp->res, "LogEntry",
2699 logID);
2700 }
2701 else
2702 {
2703 messages::internalError(asyncResp->res);
2704 }
2705 return;
2706 }
2707
2708 std::string timestamp{};
2709 std::string filename{};
2710 std::string logfile{};
2711 parseCrashdumpParameters(params, filename, timestamp, logfile);
2712
2713 if (filename.empty() || timestamp.empty())
Jason M. Bills1ddcf012019-11-26 14:59:21 -08002714 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002715 messages::resourceNotFound(asyncResp->res, "LogEntry", logID);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002716 return;
2717 }
2718
2719 std::string crashdumpURI =
2720 std::format(
2721 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries/",
2722 BMCWEB_REDFISH_SYSTEM_URI_NAME) +
2723 logID + "/" + filename;
2724 nlohmann::json::object_t logEntry;
2725 logEntry["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
2726 logEntry["@odata.id"] = boost::urls::format(
2727 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries/{}",
2728 BMCWEB_REDFISH_SYSTEM_URI_NAME, logID);
2729 logEntry["Name"] = "CPU Crashdump";
2730 logEntry["Id"] = logID;
2731 logEntry["EntryType"] = log_entry::LogEntryType::Oem;
2732 logEntry["AdditionalDataURI"] = std::move(crashdumpURI);
2733 logEntry["DiagnosticDataType"] = "OEM";
2734 logEntry["OEMDiagnosticDataType"] = "PECICrashdump";
2735 logEntry["Created"] = std::move(timestamp);
2736
2737 // If logEntryJson references an array of LogEntry resources
2738 // ('Members' list), then push this as a new entry, otherwise set it
2739 // directly
2740 if (logEntryJson.is_array())
2741 {
2742 logEntryJson.push_back(logEntry);
2743 asyncResp->res.jsonValue["Members@odata.count"] =
2744 logEntryJson.size();
Jason M. Bills2b20ef62022-01-06 15:48:07 -08002745 }
2746 else
2747 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002748 logEntryJson.update(logEntry);
Jason M. Bills2b20ef62022-01-06 15:48:07 -08002749 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002750 };
Ed Tanousdeae6a72024-11-11 21:58:57 -08002751 dbus::utility::getAllProperties(
2752 crashdumpObject, crashdumpPath + std::string("/") + logID,
2753 crashdumpInterface, std::move(getStoredLogCallback));
Jason M. Billse855dd22019-10-08 11:37:48 -07002754}
2755
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002756inline void requestRoutesCrashdumpEntryCollection(App& app)
Ed Tanous1da66f72018-07-27 16:13:37 -07002757{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002758 // Note: Deviated from redfish privilege registry for GET & HEAD
2759 // method for security reasons.
Ed Tanous1da66f72018-07-27 16:13:37 -07002760 /**
2761 * Functions triggers appropriate requests on DBus
2762 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002763 BMCWEB_ROUTE(app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002764 "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/")
Ed Tanoused398212021-06-09 17:05:54 -07002765 // This is incorrect, should be.
2766 //.privileges(redfish::privileges::postLogEntryCollection)
Ed Tanous432a8902021-06-14 15:28:56 -07002767 .privileges({{"ConfigureComponents"}})
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002768 .methods(
2769 boost::beast::http::verb::
2770 get)([&app](const crow::Request& req,
2771 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2772 const std::string& systemName) {
2773 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous45ca1b82022-03-25 13:07:27 -07002774 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002775 return;
Ed Tanous45ca1b82022-03-25 13:07:27 -07002776 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002777 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous002d39b2022-05-31 08:59:27 -07002778 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002779 // Option currently returns no systems. TBD
2780 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2781 systemName);
2782 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07002783 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002784 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2785 {
2786 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2787 systemName);
2788 return;
2789 }
2790
2791 constexpr std::array<std::string_view, 1> interfaces = {
2792 crashdumpInterface};
2793 dbus::utility::getSubTreePaths(
2794 "/", 0, interfaces,
2795 [asyncResp](const boost::system::error_code& ec,
2796 const std::vector<std::string>& resp) {
2797 if (ec)
2798 {
2799 if (ec.value() !=
2800 boost::system::errc::no_such_file_or_directory)
2801 {
2802 BMCWEB_LOG_DEBUG("failed to get entries ec: {}",
2803 ec.message());
2804 messages::internalError(asyncResp->res);
2805 return;
2806 }
2807 }
2808 asyncResp->res.jsonValue["@odata.type"] =
2809 "#LogEntryCollection.LogEntryCollection";
2810 asyncResp->res.jsonValue["@odata.id"] = std::format(
2811 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries",
2812 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2813 asyncResp->res.jsonValue["Name"] =
2814 "Open BMC Crashdump Entries";
2815 asyncResp->res.jsonValue["Description"] =
2816 "Collection of Crashdump Entries";
2817 asyncResp->res.jsonValue["Members"] =
2818 nlohmann::json::array();
2819 asyncResp->res.jsonValue["Members@odata.count"] = 0;
2820
2821 for (const std::string& path : resp)
2822 {
2823 const sdbusplus::message::object_path objPath(path);
2824 // Get the log ID
2825 std::string logID = objPath.filename();
2826 if (logID.empty())
2827 {
2828 continue;
2829 }
2830 // Add the log entry to the array
2831 logCrashdumpEntry(asyncResp, logID,
2832 asyncResp->res.jsonValue["Members"]);
2833 }
2834 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002835 });
2836}
Ed Tanous1da66f72018-07-27 16:13:37 -07002837
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002838inline void requestRoutesCrashdumpEntry(App& app)
Ed Tanous1da66f72018-07-27 16:13:37 -07002839{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002840 // Note: Deviated from redfish privilege registry for GET & HEAD
2841 // method for security reasons.
Ed Tanous1da66f72018-07-27 16:13:37 -07002842
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002843 BMCWEB_ROUTE(
Ed Tanous22d268c2022-05-19 09:39:07 -07002844 app, "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002845 // this is incorrect, should be
2846 // .privileges(redfish::privileges::getLogEntry)
Ed Tanous432a8902021-06-14 15:28:56 -07002847 .privileges({{"ConfigureComponents"}})
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002848 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07002849 [&app](const crow::Request& req,
2850 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -07002851 const std::string& systemName, const std::string& param) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002852 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2853 {
2854 return;
2855 }
2856 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
2857 {
2858 // Option currently returns no systems. TBD
2859 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2860 systemName);
2861 return;
2862 }
2863 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2864 {
2865 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2866 systemName);
2867 return;
2868 }
2869 const std::string& logID = param;
2870 logCrashdumpEntry(asyncResp, logID, asyncResp->res.jsonValue);
2871 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002872}
Ed Tanous1da66f72018-07-27 16:13:37 -07002873
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002874inline void requestRoutesCrashdumpFile(App& app)
2875{
2876 // Note: Deviated from redfish privilege registry for GET & HEAD
2877 // method for security reasons.
2878 BMCWEB_ROUTE(
2879 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002880 "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/<str>/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002881 .privileges(redfish::privileges::getLogEntry)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002882 .methods(boost::beast::http::verb::get)(
Nan Zhoua4ce1142022-08-02 18:45:25 +00002883 [](const crow::Request& req,
2884 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -07002885 const std::string& systemName, const std::string& logID,
2886 const std::string& fileName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002887 // Do not call getRedfishRoute here since the crashdump file is
2888 // not a Redfish resource.
Ed Tanous22d268c2022-05-19 09:39:07 -07002889
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002890 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
2891 {
2892 // Option currently returns no systems. TBD
2893 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2894 systemName);
2895 return;
2896 }
2897 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2898 {
2899 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2900 systemName);
2901 return;
2902 }
Ed Tanous22d268c2022-05-19 09:39:07 -07002903
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002904 auto getStoredLogCallback =
2905 [asyncResp, logID, fileName,
2906 url(boost::urls::url(req.url()))](
2907 const boost::system::error_code& ec,
2908 const std::vector<std::pair<
2909 std::string, dbus::utility::DbusVariantType>>&
2910 resp) {
2911 if (ec)
2912 {
2913 BMCWEB_LOG_DEBUG("failed to get log ec: {}",
2914 ec.message());
2915 messages::internalError(asyncResp->res);
2916 return;
2917 }
Jason M. Bills8e6c0992021-03-11 16:26:53 -08002918
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002919 std::string dbusFilename{};
2920 std::string dbusTimestamp{};
2921 std::string dbusFilepath{};
Jason M. Bills8e6c0992021-03-11 16:26:53 -08002922
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002923 parseCrashdumpParameters(resp, dbusFilename,
2924 dbusTimestamp, dbusFilepath);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002925
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002926 if (dbusFilename.empty() || dbusTimestamp.empty() ||
2927 dbusFilepath.empty())
2928 {
2929 messages::resourceNotFound(asyncResp->res,
2930 "LogEntry", logID);
2931 return;
2932 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002933
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002934 // Verify the file name parameter is correct
2935 if (fileName != dbusFilename)
2936 {
2937 messages::resourceNotFound(asyncResp->res,
2938 "LogEntry", logID);
2939 return;
2940 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002941
Myung Baed51c61b2024-09-13 10:35:34 -05002942 if (asyncResp->res.openFile(dbusFilepath) !=
2943 crow::OpenCode::Success)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002944 {
2945 messages::resourceNotFound(asyncResp->res,
2946 "LogEntry", logID);
2947 return;
2948 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002949
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002950 // Configure this to be a file download when accessed
2951 // from a browser
2952 asyncResp->res.addHeader(
2953 boost::beast::http::field::content_disposition,
2954 "attachment");
2955 };
Ed Tanousdeae6a72024-11-11 21:58:57 -08002956 dbus::utility::getAllProperties(
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002957 *crow::connections::systemBus, crashdumpObject,
2958 crashdumpPath + std::string("/") + logID,
2959 crashdumpInterface, std::move(getStoredLogCallback));
2960 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002961}
2962
Jason M. Billsc5a4c822022-01-06 15:51:23 -08002963enum class OEMDiagnosticType
2964{
2965 onDemand,
2966 telemetry,
2967 invalid,
2968};
2969
Ed Tanous26ccae32023-02-16 10:28:44 -08002970inline OEMDiagnosticType getOEMDiagnosticType(std::string_view oemDiagStr)
Jason M. Billsc5a4c822022-01-06 15:51:23 -08002971{
2972 if (oemDiagStr == "OnDemand")
2973 {
2974 return OEMDiagnosticType::onDemand;
2975 }
2976 if (oemDiagStr == "Telemetry")
2977 {
2978 return OEMDiagnosticType::telemetry;
2979 }
2980
2981 return OEMDiagnosticType::invalid;
2982}
2983
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002984inline void requestRoutesCrashdumpCollect(App& app)
2985{
2986 // Note: Deviated from redfish privilege registry for GET & HEAD
2987 // method for security reasons.
George Liu0fda0f12021-11-16 10:06:17 +08002988 BMCWEB_ROUTE(
2989 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002990 "/redfish/v1/Systems/<str>/LogServices/Crashdump/Actions/LogService.CollectDiagnosticData/")
Ed Tanoused398212021-06-09 17:05:54 -07002991 // The below is incorrect; Should be ConfigureManager
2992 //.privileges(redfish::privileges::postLogService)
Ed Tanous432a8902021-06-14 15:28:56 -07002993 .privileges({{"ConfigureComponents"}})
Ed Tanous002d39b2022-05-31 08:59:27 -07002994 .methods(boost::beast::http::verb::post)(
2995 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07002996 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2997 const std::string& systemName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002998 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07002999 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003000 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07003001 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003002
3003 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous002d39b2022-05-31 08:59:27 -07003004 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003005 // Option currently returns no systems. TBD
3006 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3007 systemName);
3008 return;
3009 }
3010 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
3011 {
3012 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3013 systemName);
3014 return;
3015 }
3016
3017 std::string diagnosticDataType;
3018 std::string oemDiagnosticDataType;
Patrick Williams504af5a2025-02-03 14:29:03 -05003019 if (!redfish::json_util::readJsonAction( //
3020 req, asyncResp->res, //
3021 "DiagnosticDataType", diagnosticDataType, //
Myung Baeafc474a2024-10-09 00:53:29 -07003022 "OEMDiagnosticDataType", oemDiagnosticDataType //
3023 ))
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003024 {
3025 return;
3026 }
3027
3028 if (diagnosticDataType != "OEM")
3029 {
3030 BMCWEB_LOG_ERROR(
3031 "Only OEM DiagnosticDataType supported for Crashdump");
3032 messages::actionParameterValueFormatError(
3033 asyncResp->res, diagnosticDataType,
3034 "DiagnosticDataType", "CollectDiagnosticData");
3035 return;
3036 }
3037
3038 OEMDiagnosticType oemDiagType =
3039 getOEMDiagnosticType(oemDiagnosticDataType);
3040
3041 std::string iface;
3042 std::string method;
3043 std::string taskMatchStr;
3044 if (oemDiagType == OEMDiagnosticType::onDemand)
3045 {
3046 iface = crashdumpOnDemandInterface;
3047 method = "GenerateOnDemandLog";
3048 taskMatchStr =
3049 "type='signal',"
3050 "interface='org.freedesktop.DBus.Properties',"
3051 "member='PropertiesChanged',"
3052 "arg0namespace='com.intel.crashdump'";
3053 }
3054 else if (oemDiagType == OEMDiagnosticType::telemetry)
3055 {
3056 iface = crashdumpTelemetryInterface;
3057 method = "GenerateTelemetryLog";
3058 taskMatchStr =
3059 "type='signal',"
3060 "interface='org.freedesktop.DBus.Properties',"
3061 "member='PropertiesChanged',"
3062 "arg0namespace='com.intel.crashdump'";
Ed Tanous002d39b2022-05-31 08:59:27 -07003063 }
3064 else
3065 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003066 BMCWEB_LOG_ERROR("Unsupported OEMDiagnosticDataType: {}",
3067 oemDiagnosticDataType);
3068 messages::actionParameterValueFormatError(
3069 asyncResp->res, oemDiagnosticDataType,
3070 "OEMDiagnosticDataType", "CollectDiagnosticData");
3071 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07003072 }
Ed Tanous1da66f72018-07-27 16:13:37 -07003073
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003074 auto collectCrashdumpCallback =
3075 [asyncResp, payload(task::Payload(req)),
3076 taskMatchStr](const boost::system::error_code& ec,
3077 const std::string&) mutable {
3078 if (ec)
3079 {
3080 if (ec.value() ==
3081 boost::system::errc::operation_not_supported)
3082 {
3083 messages::resourceInStandby(asyncResp->res);
3084 }
3085 else if (ec.value() == boost::system::errc::
3086 device_or_resource_busy)
3087 {
3088 messages::serviceTemporarilyUnavailable(
3089 asyncResp->res, "60");
3090 }
3091 else
3092 {
3093 messages::internalError(asyncResp->res);
3094 }
3095 return;
3096 }
3097 std::shared_ptr<task::TaskData> task =
3098 task::TaskData::createTask(
3099 [](const boost::system::error_code& ec2,
3100 sdbusplus::message_t&,
3101 const std::shared_ptr<task::TaskData>&
3102 taskData) {
3103 if (!ec2)
3104 {
3105 taskData->messages.emplace_back(
3106 messages::taskCompletedOK(
3107 std::to_string(
3108 taskData->index)));
3109 taskData->state = "Completed";
3110 }
3111 return task::completed;
3112 },
3113 taskMatchStr);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003114
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003115 task->startTimer(std::chrono::minutes(5));
3116 task->populateResp(asyncResp->res);
3117 task->payload.emplace(std::move(payload));
3118 };
3119
Ed Tanous177612a2025-02-14 15:16:09 -08003120 dbus::utility::async_method_call(
3121 asyncResp, std::move(collectCrashdumpCallback),
3122 crashdumpObject, crashdumpPath, iface, method);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003123 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003124}
Kenny L. Ku6eda7682020-06-19 09:48:36 -07003125
Alexander Hansen599b9af2024-08-06 15:11:57 +02003126inline void dBusLogServiceActionsClear(
3127 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
3128{
3129 BMCWEB_LOG_DEBUG("Do delete all entries.");
3130
3131 // Process response from Logging service.
3132 auto respHandler = [asyncResp](const boost::system::error_code& ec) {
3133 BMCWEB_LOG_DEBUG("doClearLog resp_handler callback: Done");
3134 if (ec)
3135 {
3136 // TODO Handle for specific error code
3137 BMCWEB_LOG_ERROR("doClearLog resp_handler got error {}", ec);
3138 asyncResp->res.result(
3139 boost::beast::http::status::internal_server_error);
3140 return;
3141 }
3142
Amy Change2460462025-05-06 00:10:13 -07003143 messages::success(asyncResp->res);
Alexander Hansen599b9af2024-08-06 15:11:57 +02003144 };
3145
3146 // Make call to Logging service to request Clear Log
Ed Tanous177612a2025-02-14 15:16:09 -08003147 dbus::utility::async_method_call(
3148 asyncResp, respHandler, "xyz.openbmc_project.Logging",
Alexander Hansen599b9af2024-08-06 15:11:57 +02003149 "/xyz/openbmc_project/logging",
3150 "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
3151}
3152
Andrew Geisslercb92c032018-08-17 07:56:14 -07003153/**
3154 * DBusLogServiceActionsClear class supports POST method for ClearLog action.
3155 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003156inline void requestRoutesDBusLogServiceActionsClear(App& app)
Andrew Geisslercb92c032018-08-17 07:56:14 -07003157{
Andrew Geisslercb92c032018-08-17 07:56:14 -07003158 /**
3159 * Function handles POST method request.
3160 * The Clear Log actions does not require any parameter.The action deletes
3161 * all entries found in the Entries collection for this Log Service.
3162 */
Andrew Geisslercb92c032018-08-17 07:56:14 -07003163
George Liu0fda0f12021-11-16 10:06:17 +08003164 BMCWEB_ROUTE(
3165 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07003166 "/redfish/v1/Systems/<str>/LogServices/EventLog/Actions/LogService.ClearLog/")
Ed Tanoused398212021-06-09 17:05:54 -07003167 .privileges(redfish::privileges::postLogService)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003168 .methods(boost::beast::http::verb::post)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07003169 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07003170 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3171 const std::string& systemName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003172 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3173 {
3174 return;
3175 }
3176 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
3177 {
3178 // Option currently returns no systems. TBD
3179 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3180 systemName);
3181 return;
3182 }
3183 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
3184 {
3185 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3186 systemName);
3187 return;
3188 }
3189 dBusLogServiceActionsClear(asyncResp);
3190 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003191}
ZhikuiRena3316fc2020-01-29 14:58:08 -08003192
Ed Tanous1da66f72018-07-27 16:13:37 -07003193} // namespace redfish