blob: 982f74e14e27a2188572b67e82c37c13410eea4c [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"
Spencer Kub7028eb2021-10-26 15:27:35 +080018#include "human_sort.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080019#include "logging.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080020#include "query.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080021#include "registries/privilege_registry.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080022#include "str_utility.hpp"
James Feist46229572020-02-19 15:11:58 -080023#include "task.hpp"
Ed Tanous5b904292024-04-16 11:10:17 -070024#include "task_messages.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080025#include "utils/dbus_utils.hpp"
Corey Ethington08fad5d2025-07-31 12:14:27 -040026#include "utils/etag_utils.hpp"
Oliver Brewka9d6459e2025-08-27 13:39:15 +020027#include "utils/eventlog_utils.hpp"
Ed Tanous5b904292024-04-16 11:10:17 -070028#include "utils/json_utils.hpp"
Oliver Brewkaff35df92025-08-26 08:21:30 +020029#include "utils/log_services_utils.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080030#include "utils/time_utils.hpp"
Ed Tanous1da66f72018-07-27 16:13:37 -070031
Ed Tanousd7857202025-01-28 15:32:26 -080032#include <asm-generic/errno.h>
33#include <systemd/sd-bus.h>
Asmitha Karunanithi8e317782020-12-10 03:35:05 -060034#include <tinyxml2.h>
Adriana Kobylak400fd1f2021-01-29 09:01:30 -060035#include <unistd.h>
Jason M. Billse1f26342018-07-18 12:12:00 -070036
Ed Tanousd7857202025-01-28 15:32:26 -080037#include <boost/beast/http/field.hpp>
38#include <boost/beast/http/status.hpp>
Ed Tanous07c8c202022-07-11 10:08:08 -070039#include <boost/beast/http/verb.hpp>
Jason M. Bills1ddcf012019-11-26 14:59:21 -080040#include <boost/system/linux_error.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070041#include <boost/url/format.hpp>
Ed Tanousd7857202025-01-28 15:32:26 -080042#include <boost/url/url.hpp>
43#include <sdbusplus/message.hpp>
44#include <sdbusplus/message/native_types.hpp>
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +020045#include <sdbusplus/unpack_properties.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050046
Ed Tanousd7857202025-01-28 15:32:26 -080047#include <algorithm>
George Liu7a1dbc42022-12-07 16:03:22 +080048#include <array>
Ed Tanousd7857202025-01-28 15:32:26 -080049#include <chrono>
Ed Tanousd7857202025-01-28 15:32:26 -080050#include <cstdint>
James Feist4418c7f2019-04-15 11:09:15 -070051#include <filesystem>
Ed Tanousd7857202025-01-28 15:32:26 -080052#include <format>
Ed Tanousd7857202025-01-28 15:32:26 -080053#include <functional>
Ed Tanous18f8f602023-07-18 10:07:23 -070054#include <iterator>
Ed Tanousd7857202025-01-28 15:32:26 -080055#include <memory>
Xiaochao Ma75710de2021-01-21 17:56:02 +080056#include <optional>
Ed Tanous3544d2a2023-08-06 18:12:20 -070057#include <ranges>
Ed Tanous26702d02021-11-03 15:02:33 -070058#include <span>
Ed Tanous18f8f602023-07-18 10:07:23 -070059#include <string>
Jason M. Billscd225da2019-05-08 15:31:57 -070060#include <string_view>
Ed Tanousd7857202025-01-28 15:32:26 -080061#include <utility>
Ed Tanousabf2add2019-01-22 16:40:12 -080062#include <variant>
Ed Tanousd7857202025-01-28 15:32:26 -080063#include <vector>
Ed Tanous1da66f72018-07-27 16:13:37 -070064
65namespace redfish
66{
67
Patrick Williams89492a12023-05-10 07:51:34 -050068constexpr const char* crashdumpObject = "com.intel.crashdump";
69constexpr const char* crashdumpPath = "/com/intel/crashdump";
70constexpr const char* crashdumpInterface = "com.intel.crashdump";
71constexpr const char* deleteAllInterface =
Jason M. Bills5b61b5e2019-10-16 10:59:02 -070072 "xyz.openbmc_project.Collection.DeleteAll";
Patrick Williams89492a12023-05-10 07:51:34 -050073constexpr const char* crashdumpOnDemandInterface =
Jason M. Bills424c4172019-03-21 13:50:33 -070074 "com.intel.crashdump.OnDemand";
Patrick Williams89492a12023-05-10 07:51:34 -050075constexpr const char* crashdumpTelemetryInterface =
Kenny L. Ku6eda7682020-06-19 09:48:36 -070076 "com.intel.crashdump.Telemetry";
Ed Tanous1da66f72018-07-27 16:13:37 -070077
Asmitha Karunanithi8e317782020-12-10 03:35:05 -060078enum class DumpCreationProgress
79{
80 DUMP_CREATE_SUCCESS,
81 DUMP_CREATE_FAILED,
82 DUMP_CREATE_INPROGRESS
83};
84
Ed Tanous18f8f602023-07-18 10:07:23 -070085inline std::string getDumpPath(std::string_view dumpType)
86{
87 std::string dbusDumpPath = "/xyz/openbmc_project/dump/";
88 std::ranges::transform(dumpType, std::back_inserter(dbusDumpPath),
89 bmcweb::asciiToLower);
90
91 return dbusDumpPath;
92}
93
Patrick Williams504af5a2025-02-03 14:29:03 -050094inline log_entry::OriginatorTypes mapDbusOriginatorTypeToRedfish(
95 const std::string& originatorType)
Asmitha Karunanithi68dd0752022-11-15 11:33:46 -060096{
97 if (originatorType ==
98 "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Client")
99 {
100 return log_entry::OriginatorTypes::Client;
101 }
102 if (originatorType ==
103 "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Internal")
104 {
105 return log_entry::OriginatorTypes::Internal;
106 }
107 if (originatorType ==
108 "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.SupportingService")
109 {
110 return log_entry::OriginatorTypes::SupportingService;
111 }
112 return log_entry::OriginatorTypes::Invalid;
113}
114
Claire Weinanaefe3782022-07-15 19:17:19 -0700115inline void parseDumpEntryFromDbusObject(
Jiaqing Zhao2d613eb2022-08-15 16:03:00 +0800116 const dbus::utility::ManagedObjectType::value_type& object,
Claire Weinanc6fecda2022-07-15 10:43:25 -0700117 std::string& dumpStatus, uint64_t& size, uint64_t& timestampUs,
Asmitha Karunanithi68dd0752022-11-15 11:33:46 -0600118 std::string& originatorId, log_entry::OriginatorTypes& originatorType,
Claire Weinanaefe3782022-07-15 19:17:19 -0700119 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
120{
121 for (const auto& interfaceMap : object.second)
122 {
123 if (interfaceMap.first == "xyz.openbmc_project.Common.Progress")
124 {
125 for (const auto& propertyMap : interfaceMap.second)
126 {
127 if (propertyMap.first == "Status")
128 {
129 const auto* status =
130 std::get_if<std::string>(&propertyMap.second);
131 if (status == nullptr)
132 {
133 messages::internalError(asyncResp->res);
134 break;
135 }
136 dumpStatus = *status;
137 }
138 }
139 }
140 else if (interfaceMap.first == "xyz.openbmc_project.Dump.Entry")
141 {
142 for (const auto& propertyMap : interfaceMap.second)
143 {
144 if (propertyMap.first == "Size")
145 {
146 const auto* sizePtr =
147 std::get_if<uint64_t>(&propertyMap.second);
148 if (sizePtr == nullptr)
149 {
150 messages::internalError(asyncResp->res);
151 break;
152 }
153 size = *sizePtr;
154 break;
155 }
156 }
157 }
158 else if (interfaceMap.first == "xyz.openbmc_project.Time.EpochTime")
159 {
160 for (const auto& propertyMap : interfaceMap.second)
161 {
162 if (propertyMap.first == "Elapsed")
163 {
164 const uint64_t* usecsTimeStamp =
165 std::get_if<uint64_t>(&propertyMap.second);
166 if (usecsTimeStamp == nullptr)
167 {
168 messages::internalError(asyncResp->res);
169 break;
170 }
Claire Weinanc6fecda2022-07-15 10:43:25 -0700171 timestampUs = *usecsTimeStamp;
Claire Weinanaefe3782022-07-15 19:17:19 -0700172 break;
173 }
174 }
175 }
Asmitha Karunanithi68dd0752022-11-15 11:33:46 -0600176 else if (interfaceMap.first ==
177 "xyz.openbmc_project.Common.OriginatedBy")
178 {
179 for (const auto& propertyMap : interfaceMap.second)
180 {
181 if (propertyMap.first == "OriginatorId")
182 {
183 const std::string* id =
184 std::get_if<std::string>(&propertyMap.second);
185 if (id == nullptr)
186 {
187 messages::internalError(asyncResp->res);
188 break;
189 }
190 originatorId = *id;
191 }
192
193 if (propertyMap.first == "OriginatorType")
194 {
195 const std::string* type =
196 std::get_if<std::string>(&propertyMap.second);
197 if (type == nullptr)
198 {
199 messages::internalError(asyncResp->res);
200 break;
201 }
202
203 originatorType = mapDbusOriginatorTypeToRedfish(*type);
204 if (originatorType == log_entry::OriginatorTypes::Invalid)
205 {
206 messages::internalError(asyncResp->res);
207 break;
208 }
209 }
210 }
211 }
Claire Weinanaefe3782022-07-15 19:17:19 -0700212 }
213}
214
Nan Zhou21ab4042022-06-26 23:07:40 +0000215static std::string getDumpEntriesPath(const std::string& dumpType)
Claire Weinanfdd26902022-03-01 14:18:25 -0800216{
217 std::string entriesPath;
218
219 if (dumpType == "BMC")
220 {
Ed Tanous253f11b2024-05-16 09:38:31 -0700221 entriesPath =
222 std::format("/redfish/v1/Managers/{}/LogServices/Dump/Entries/",
223 BMCWEB_REDFISH_MANAGER_URI_NAME);
Claire Weinanfdd26902022-03-01 14:18:25 -0800224 }
225 else if (dumpType == "FaultLog")
226 {
Ed Tanous253f11b2024-05-16 09:38:31 -0700227 entriesPath =
228 std::format("/redfish/v1/Managers/{}/LogServices/FaultLog/Entries/",
229 BMCWEB_REDFISH_MANAGER_URI_NAME);
Claire Weinanfdd26902022-03-01 14:18:25 -0800230 }
231 else if (dumpType == "System")
232 {
Ed Tanous253f11b2024-05-16 09:38:31 -0700233 entriesPath =
234 std::format("/redfish/v1/Systems/{}/LogServices/Dump/Entries/",
235 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Claire Weinanfdd26902022-03-01 14:18:25 -0800236 }
237 else
238 {
Ed Tanous62598e32023-07-17 17:06:25 -0700239 BMCWEB_LOG_ERROR("getDumpEntriesPath() invalid dump type: {}",
240 dumpType);
Claire Weinanfdd26902022-03-01 14:18:25 -0800241 }
242
243 // Returns empty string on error
244 return entriesPath;
245}
246
Patrick Williams504af5a2025-02-03 14:29:03 -0500247inline void getDumpEntryCollection(
248 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
249 const std::string& dumpType)
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500250{
Claire Weinanfdd26902022-03-01 14:18:25 -0800251 std::string entriesPath = getDumpEntriesPath(dumpType);
252 if (entriesPath.empty())
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500253 {
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500254 messages::internalError(asyncResp->res);
255 return;
256 }
257
George Liu5eb468d2023-06-20 17:03:24 +0800258 sdbusplus::message::object_path path("/xyz/openbmc_project/dump");
259 dbus::utility::getManagedObjects(
260 "xyz.openbmc_project.Dump.Manager", path,
Claire Weinanfdd26902022-03-01 14:18:25 -0800261 [asyncResp, entriesPath,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800262 dumpType](const boost::system::error_code& ec,
George Liu5eb468d2023-06-20 17:03:24 +0800263 const dbus::utility::ManagedObjectType& objects) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400264 if (ec)
265 {
266 BMCWEB_LOG_ERROR("DumpEntry resp_handler got error {}", ec);
267 messages::internalError(asyncResp->res);
268 return;
269 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700270
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400271 // Remove ending slash
272 std::string odataIdStr = entriesPath;
273 if (!odataIdStr.empty())
274 {
275 odataIdStr.pop_back();
276 }
Claire Weinanfdd26902022-03-01 14:18:25 -0800277
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400278 asyncResp->res.jsonValue["@odata.type"] =
279 "#LogEntryCollection.LogEntryCollection";
280 asyncResp->res.jsonValue["@odata.id"] = std::move(odataIdStr);
281 asyncResp->res.jsonValue["Name"] = dumpType + " Dump Entries";
282 asyncResp->res.jsonValue["Description"] =
283 "Collection of " + dumpType + " Dump Entries";
Claire Weinanfdd26902022-03-01 14:18:25 -0800284
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400285 nlohmann::json::array_t entriesArray;
286 std::string dumpEntryPath = getDumpPath(dumpType) + "/entry/";
Ed Tanous002d39b2022-05-31 08:59:27 -0700287
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400288 dbus::utility::ManagedObjectType resp(objects);
289 std::ranges::sort(resp, [](const auto& l, const auto& r) {
290 return AlphanumLess<std::string>()(l.first.filename(),
291 r.first.filename());
292 });
293
294 for (auto& object : resp)
295 {
296 if (object.first.str.find(dumpEntryPath) == std::string::npos)
297 {
298 continue;
299 }
300 uint64_t timestampUs = 0;
301 uint64_t size = 0;
302 std::string dumpStatus;
303 std::string originatorId;
304 log_entry::OriginatorTypes originatorType =
305 log_entry::OriginatorTypes::Internal;
306 nlohmann::json::object_t thisEntry;
307
308 std::string entryID = object.first.filename();
309 if (entryID.empty())
310 {
311 continue;
312 }
313
314 parseDumpEntryFromDbusObject(object, dumpStatus, size,
315 timestampUs, originatorId,
316 originatorType, asyncResp);
317
318 if (dumpStatus !=
319 "xyz.openbmc_project.Common.Progress.OperationStatus.Completed" &&
320 !dumpStatus.empty())
321 {
322 // Dump status is not Complete, no need to enumerate
323 continue;
324 }
325
326 thisEntry["@odata.type"] = "#LogEntry.v1_11_0.LogEntry";
327 thisEntry["@odata.id"] = entriesPath + entryID;
328 thisEntry["Id"] = entryID;
329 thisEntry["EntryType"] = "Event";
330 thisEntry["Name"] = dumpType + " Dump Entry";
331 thisEntry["Created"] =
332 redfish::time_utils::getDateTimeUintUs(timestampUs);
333
334 if (!originatorId.empty())
335 {
336 thisEntry["Originator"] = originatorId;
337 thisEntry["OriginatorType"] = originatorType;
338 }
339
340 if (dumpType == "BMC")
341 {
342 thisEntry["DiagnosticDataType"] = "Manager";
343 thisEntry["AdditionalDataURI"] =
344 entriesPath + entryID + "/attachment";
345 thisEntry["AdditionalDataSizeBytes"] = size;
346 }
347 else if (dumpType == "System")
348 {
349 thisEntry["DiagnosticDataType"] = "OEM";
350 thisEntry["OEMDiagnosticDataType"] = "System";
351 thisEntry["AdditionalDataURI"] =
352 entriesPath + entryID + "/attachment";
353 thisEntry["AdditionalDataSizeBytes"] = size;
354 }
355 entriesArray.emplace_back(std::move(thisEntry));
356 }
357 asyncResp->res.jsonValue["Members@odata.count"] =
358 entriesArray.size();
359 asyncResp->res.jsonValue["Members"] = std::move(entriesArray);
Ed Tanous002d39b2022-05-31 08:59:27 -0700360 });
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500361}
362
Patrick Williams504af5a2025-02-03 14:29:03 -0500363inline void getDumpEntryById(
364 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
365 const std::string& entryID, const std::string& dumpType)
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500366{
Claire Weinanfdd26902022-03-01 14:18:25 -0800367 std::string entriesPath = getDumpEntriesPath(dumpType);
368 if (entriesPath.empty())
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500369 {
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500370 messages::internalError(asyncResp->res);
371 return;
372 }
373
George Liu5eb468d2023-06-20 17:03:24 +0800374 sdbusplus::message::object_path path("/xyz/openbmc_project/dump");
375 dbus::utility::getManagedObjects(
376 "xyz.openbmc_project.Dump.Manager", path,
Claire Weinanfdd26902022-03-01 14:18:25 -0800377 [asyncResp, entryID, dumpType,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800378 entriesPath](const boost::system::error_code& ec,
Ed Tanous02cad962022-06-30 16:50:15 -0700379 const dbus::utility::ManagedObjectType& resp) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400380 if (ec)
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500381 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400382 BMCWEB_LOG_ERROR("DumpEntry resp_handler got error {}", ec);
383 messages::internalError(asyncResp->res);
384 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700385 }
386
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400387 bool foundDumpEntry = false;
388 std::string dumpEntryPath = getDumpPath(dumpType) + "/entry/";
Ed Tanous002d39b2022-05-31 08:59:27 -0700389
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400390 for (const auto& objectPath : resp)
Ed Tanous002d39b2022-05-31 08:59:27 -0700391 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400392 if (objectPath.first.str != dumpEntryPath + entryID)
393 {
394 continue;
395 }
396
397 foundDumpEntry = true;
398 uint64_t timestampUs = 0;
399 uint64_t size = 0;
400 std::string dumpStatus;
401 std::string originatorId;
402 log_entry::OriginatorTypes originatorType =
403 log_entry::OriginatorTypes::Internal;
404
405 parseDumpEntryFromDbusObject(objectPath, dumpStatus, size,
406 timestampUs, originatorId,
407 originatorType, asyncResp);
408
409 if (dumpStatus !=
410 "xyz.openbmc_project.Common.Progress.OperationStatus.Completed" &&
411 !dumpStatus.empty())
412 {
413 // Dump status is not Complete
414 // return not found until status is changed to Completed
415 messages::resourceNotFound(asyncResp->res,
416 dumpType + " dump", entryID);
417 return;
418 }
419
420 asyncResp->res.jsonValue["@odata.type"] =
421 "#LogEntry.v1_11_0.LogEntry";
422 asyncResp->res.jsonValue["@odata.id"] = entriesPath + entryID;
423 asyncResp->res.jsonValue["Id"] = entryID;
424 asyncResp->res.jsonValue["EntryType"] = "Event";
425 asyncResp->res.jsonValue["Name"] = dumpType + " Dump Entry";
426 asyncResp->res.jsonValue["Created"] =
427 redfish::time_utils::getDateTimeUintUs(timestampUs);
428
429 if (!originatorId.empty())
430 {
431 asyncResp->res.jsonValue["Originator"] = originatorId;
432 asyncResp->res.jsonValue["OriginatorType"] = originatorType;
433 }
434
435 if (dumpType == "BMC")
436 {
437 asyncResp->res.jsonValue["DiagnosticDataType"] = "Manager";
438 asyncResp->res.jsonValue["AdditionalDataURI"] =
439 entriesPath + entryID + "/attachment";
440 asyncResp->res.jsonValue["AdditionalDataSizeBytes"] = size;
441 }
442 else if (dumpType == "System")
443 {
444 asyncResp->res.jsonValue["DiagnosticDataType"] = "OEM";
445 asyncResp->res.jsonValue["OEMDiagnosticDataType"] =
446 "System";
447 asyncResp->res.jsonValue["AdditionalDataURI"] =
448 entriesPath + entryID + "/attachment";
449 asyncResp->res.jsonValue["AdditionalDataSizeBytes"] = size;
450 }
451 }
452 if (!foundDumpEntry)
453 {
454 BMCWEB_LOG_WARNING("Can't find Dump Entry {}", entryID);
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +0200455 messages::resourceNotFound(asyncResp->res, dumpType + " dump",
456 entryID);
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500457 return;
458 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400459 });
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500460}
461
zhanghch058d1b46d2021-04-01 11:18:24 +0800462inline void deleteDumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Stanley Chu98782562020-11-04 16:10:24 +0800463 const std::string& entryID,
Asmitha Karunanithib47452b2020-09-25 02:02:19 -0500464 const std::string& dumpType)
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500465{
Patrick Williams5a39f772023-10-20 11:20:21 -0500466 auto respHandler = [asyncResp,
467 entryID](const boost::system::error_code& ec) {
Ed Tanous62598e32023-07-17 17:06:25 -0700468 BMCWEB_LOG_DEBUG("Dump Entry doDelete callback: Done");
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500469 if (ec)
470 {
George Liu3de8d8b2021-03-22 17:49:39 +0800471 if (ec.value() == EBADR)
472 {
473 messages::resourceNotFound(asyncResp->res, "LogEntry", entryID);
474 return;
475 }
Ed Tanous62598e32023-07-17 17:06:25 -0700476 BMCWEB_LOG_ERROR(
477 "Dump (DBus) doDelete respHandler got error {} entryID={}", ec,
478 entryID);
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500479 messages::internalError(asyncResp->res);
480 return;
481 }
482 };
Ed Tanous18f8f602023-07-18 10:07:23 -0700483
Ed Tanous177612a2025-02-14 15:16:09 -0800484 dbus::utility::async_method_call(
485 asyncResp, respHandler, "xyz.openbmc_project.Dump.Manager",
Ed Tanous18f8f602023-07-18 10:07:23 -0700486 std::format("{}/entry/{}", getDumpPath(dumpType), entryID),
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500487 "xyz.openbmc_project.Object.Delete", "Delete");
488}
Carson Labrado168d1b12023-03-27 17:04:46 +0000489
Patrick Williams504af5a2025-02-03 14:29:03 -0500490inline void downloadDumpEntry(
491 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
492 const std::string& entryID, const std::string& dumpType)
Carson Labrado168d1b12023-03-27 17:04:46 +0000493{
494 if (dumpType != "BMC")
495 {
496 BMCWEB_LOG_WARNING("Can't find Dump Entry {}", entryID);
497 messages::resourceNotFound(asyncResp->res, dumpType + " dump", entryID);
498 return;
499 }
500
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400501 std::string dumpEntryPath =
502 std::format("{}/entry/{}", getDumpPath(dumpType), entryID);
Carson Labrado168d1b12023-03-27 17:04:46 +0000503
504 auto downloadDumpEntryHandler =
505 [asyncResp, entryID,
506 dumpType](const boost::system::error_code& ec,
507 const sdbusplus::message::unix_fd& unixfd) {
Oliver Brewkaff35df92025-08-26 08:21:30 +0200508 log_services_utils::downloadEntryCallback(asyncResp, entryID,
509 dumpType, ec, unixfd);
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400510 };
Carson Labrado168d1b12023-03-27 17:04:46 +0000511
Ed Tanous177612a2025-02-14 15:16:09 -0800512 dbus::utility::async_method_call(
513 asyncResp, std::move(downloadDumpEntryHandler),
514 "xyz.openbmc_project.Dump.Manager", dumpEntryPath,
515 "xyz.openbmc_project.Dump.Entry", "GetFileHandle");
Carson Labrado168d1b12023-03-27 17:04:46 +0000516}
517
Patrick Williams504af5a2025-02-03 14:29:03 -0500518inline DumpCreationProgress mapDbusStatusToDumpProgress(
519 const std::string& status)
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500520{
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600521 if (status ==
522 "xyz.openbmc_project.Common.Progress.OperationStatus.Failed" ||
523 status == "xyz.openbmc_project.Common.Progress.OperationStatus.Aborted")
524 {
525 return DumpCreationProgress::DUMP_CREATE_FAILED;
526 }
527 if (status ==
528 "xyz.openbmc_project.Common.Progress.OperationStatus.Completed")
529 {
530 return DumpCreationProgress::DUMP_CREATE_SUCCESS;
531 }
532 return DumpCreationProgress::DUMP_CREATE_INPROGRESS;
533}
534
Patrick Williams504af5a2025-02-03 14:29:03 -0500535inline DumpCreationProgress getDumpCompletionStatus(
536 const dbus::utility::DBusPropertiesMap& values)
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600537{
538 for (const auto& [key, val] : values)
539 {
540 if (key == "Status")
Ed Tanous002d39b2022-05-31 08:59:27 -0700541 {
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600542 const std::string* value = std::get_if<std::string>(&val);
543 if (value == nullptr)
544 {
Ed Tanous62598e32023-07-17 17:06:25 -0700545 BMCWEB_LOG_ERROR("Status property value is null");
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600546 return DumpCreationProgress::DUMP_CREATE_FAILED;
547 }
548 return mapDbusStatusToDumpProgress(*value);
549 }
550 }
551 return DumpCreationProgress::DUMP_CREATE_INPROGRESS;
552}
553
554inline std::string getDumpEntryPath(const std::string& dumpPath)
555{
556 if (dumpPath == "/xyz/openbmc_project/dump/bmc/entry")
557 {
Ed Tanous253f11b2024-05-16 09:38:31 -0700558 return std::format("/redfish/v1/Managers/{}/LogServices/Dump/Entries/",
Ed Tanous9f565092024-07-12 22:06:53 -0700559 BMCWEB_REDFISH_MANAGER_URI_NAME);
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600560 }
561 if (dumpPath == "/xyz/openbmc_project/dump/system/entry")
562 {
Ed Tanous253f11b2024-05-16 09:38:31 -0700563 return std::format("/redfish/v1/Systems/{}/LogServices/Dump/Entries/",
564 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600565 }
566 return "";
567}
568
569inline void createDumpTaskCallback(
570 task::Payload&& payload,
571 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
572 const sdbusplus::message::object_path& createdObjPath)
573{
574 const std::string dumpPath = createdObjPath.parent_path().str;
575 const std::string dumpId = createdObjPath.filename();
576
577 std::string dumpEntryPath = getDumpEntryPath(dumpPath);
578
579 if (dumpEntryPath.empty())
580 {
Ed Tanous62598e32023-07-17 17:06:25 -0700581 BMCWEB_LOG_ERROR("Invalid dump type received");
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600582 messages::internalError(asyncResp->res);
583 return;
584 }
585
Ed Tanous177612a2025-02-14 15:16:09 -0800586 dbus::utility::async_method_call(
587 asyncResp,
Ed Tanous8cb2c022024-03-27 16:31:46 -0700588 [asyncResp, payload = std::move(payload), createdObjPath,
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600589 dumpEntryPath{std::move(dumpEntryPath)},
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800590 dumpId](const boost::system::error_code& ec,
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600591 const std::string& introspectXml) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400592 if (ec)
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600593 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400594 BMCWEB_LOG_ERROR("Introspect call failed with error: {}",
595 ec.message());
596 messages::internalError(asyncResp->res);
597 return;
598 }
599
600 // Check if the created dump object has implemented Progress
601 // interface to track dump completion. If yes, fetch the "Status"
602 // property of the interface, modify the task state accordingly.
603 // Else, return task completed.
604 tinyxml2::XMLDocument doc;
605
606 doc.Parse(introspectXml.data(), introspectXml.size());
607 tinyxml2::XMLNode* pRoot = doc.FirstChildElement("node");
608 if (pRoot == nullptr)
609 {
610 BMCWEB_LOG_ERROR("XML document failed to parse");
611 messages::internalError(asyncResp->res);
612 return;
613 }
614 tinyxml2::XMLElement* interfaceNode =
615 pRoot->FirstChildElement("interface");
616
617 bool isProgressIntfPresent = false;
618 while (interfaceNode != nullptr)
619 {
620 const char* thisInterfaceName =
621 interfaceNode->Attribute("name");
622 if (thisInterfaceName != nullptr)
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600623 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400624 if (thisInterfaceName ==
625 std::string_view("xyz.openbmc_project.Common.Progress"))
626 {
627 interfaceNode =
628 interfaceNode->NextSiblingElement("interface");
629 continue;
630 }
631 isProgressIntfPresent = true;
632 break;
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600633 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400634 interfaceNode = interfaceNode->NextSiblingElement("interface");
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600635 }
636
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400637 std::shared_ptr<task::TaskData> task = task::TaskData::createTask(
638 [createdObjPath, dumpEntryPath, dumpId, isProgressIntfPresent](
639 const boost::system::error_code& ec2,
640 sdbusplus::message_t& msg,
641 const std::shared_ptr<task::TaskData>& taskData) {
642 if (ec2)
643 {
644 BMCWEB_LOG_ERROR("{}: Error in creating dump",
645 createdObjPath.str);
646 taskData->messages.emplace_back(
647 messages::internalError());
648 taskData->state = "Cancelled";
649 return task::completed;
650 }
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600651
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400652 if (isProgressIntfPresent)
653 {
654 dbus::utility::DBusPropertiesMap values;
655 std::string prop;
656 msg.read(prop, values);
657
658 DumpCreationProgress dumpStatus =
659 getDumpCompletionStatus(values);
660 if (dumpStatus ==
661 DumpCreationProgress::DUMP_CREATE_FAILED)
662 {
663 BMCWEB_LOG_ERROR("{}: Error in creating dump",
664 createdObjPath.str);
665 taskData->state = "Cancelled";
666 return task::completed;
667 }
668
669 if (dumpStatus ==
670 DumpCreationProgress::DUMP_CREATE_INPROGRESS)
671 {
672 BMCWEB_LOG_DEBUG(
673 "{}: Dump creation task is in progress",
674 createdObjPath.str);
675 return !task::completed;
676 }
677 }
678
679 nlohmann::json retMessage = messages::success();
680 taskData->messages.emplace_back(retMessage);
681
682 boost::urls::url url = boost::urls::format(
683 "/redfish/v1/Managers/{}/LogServices/Dump/Entries/{}",
684 BMCWEB_REDFISH_MANAGER_URI_NAME, dumpId);
685
686 std::string headerLoc = "Location: ";
687 headerLoc += url.buffer();
688
689 taskData->payload->httpHeaders.emplace_back(
690 std::move(headerLoc));
691
692 BMCWEB_LOG_DEBUG("{}: Dump creation task completed",
Ed Tanous62598e32023-07-17 17:06:25 -0700693 createdObjPath.str);
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400694 taskData->state = "Completed";
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600695 return task::completed;
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400696 },
697 "type='signal',interface='org.freedesktop.DBus.Properties',"
698 "member='PropertiesChanged',path='" +
699 createdObjPath.str + "'");
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600700
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400701 // The task timer is set to max time limit within which the
702 // requested dump will be collected.
703 task->startTimer(std::chrono::minutes(6));
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400704 task->payload.emplace(payload);
Chinmay Shripad Hegde29e2bdd2025-06-06 16:23:47 +0530705 task->populateResp(asyncResp->res);
Patrick Williams5a39f772023-10-20 11:20:21 -0500706 },
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600707 "xyz.openbmc_project.Dump.Manager", createdObjPath,
708 "org.freedesktop.DBus.Introspectable", "Introspect");
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500709}
710
zhanghch058d1b46d2021-04-01 11:18:24 +0800711inline void createDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
712 const crow::Request& req, const std::string& dumpType)
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500713{
Claire Weinanfdd26902022-03-01 14:18:25 -0800714 std::string dumpPath = getDumpEntriesPath(dumpType);
715 if (dumpPath.empty())
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500716 {
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500717 messages::internalError(asyncResp->res);
718 return;
719 }
720
721 std::optional<std::string> diagnosticDataType;
722 std::optional<std::string> oemDiagnosticDataType;
723
Patrick Williams504af5a2025-02-03 14:29:03 -0500724 if (!redfish::json_util::readJsonAction( //
725 req, asyncResp->res, //
726 "DiagnosticDataType", diagnosticDataType, //
Myung Baeafc474a2024-10-09 00:53:29 -0700727 "OEMDiagnosticDataType", oemDiagnosticDataType //
728 ))
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500729 {
730 return;
731 }
732
733 if (dumpType == "System")
734 {
735 if (!oemDiagnosticDataType || !diagnosticDataType)
736 {
Ed Tanous62598e32023-07-17 17:06:25 -0700737 BMCWEB_LOG_ERROR(
738 "CreateDump action parameter 'DiagnosticDataType'/'OEMDiagnosticDataType' value not found!");
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500739 messages::actionParameterMissing(
740 asyncResp->res, "CollectDiagnosticData",
741 "DiagnosticDataType & OEMDiagnosticDataType");
742 return;
743 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700744 if ((*oemDiagnosticDataType != "System") ||
745 (*diagnosticDataType != "OEM"))
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500746 {
Ed Tanous62598e32023-07-17 17:06:25 -0700747 BMCWEB_LOG_ERROR("Wrong parameter values passed");
Ed Tanousace85d62021-10-26 12:45:59 -0700748 messages::internalError(asyncResp->res);
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500749 return;
750 }
Ed Tanous253f11b2024-05-16 09:38:31 -0700751 dumpPath = std::format("/redfish/v1/Systems/{}/LogServices/Dump/",
752 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500753 }
754 else if (dumpType == "BMC")
755 {
756 if (!diagnosticDataType)
757 {
Ed Tanous62598e32023-07-17 17:06:25 -0700758 BMCWEB_LOG_ERROR(
759 "CreateDump action parameter 'DiagnosticDataType' not found!");
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500760 messages::actionParameterMissing(
761 asyncResp->res, "CollectDiagnosticData", "DiagnosticDataType");
762 return;
763 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700764 if (*diagnosticDataType != "Manager")
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500765 {
Ed Tanous62598e32023-07-17 17:06:25 -0700766 BMCWEB_LOG_ERROR(
767 "Wrong parameter value passed for 'DiagnosticDataType'");
Ed Tanousace85d62021-10-26 12:45:59 -0700768 messages::internalError(asyncResp->res);
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500769 return;
770 }
Ed Tanous253f11b2024-05-16 09:38:31 -0700771 dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/Dump/",
772 BMCWEB_REDFISH_MANAGER_URI_NAME);
Asmitha Karunanithi59075712021-10-22 01:17:41 -0500773 }
774 else
775 {
Ed Tanous62598e32023-07-17 17:06:25 -0700776 BMCWEB_LOG_ERROR("CreateDump failed. Unknown dump type");
Asmitha Karunanithi59075712021-10-22 01:17:41 -0500777 messages::internalError(asyncResp->res);
778 return;
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500779 }
780
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600781 std::vector<std::pair<std::string, std::variant<std::string, uint64_t>>>
782 createDumpParamVec;
783
Carson Labradof574a8e2023-03-22 02:26:00 +0000784 if (req.session != nullptr)
785 {
786 createDumpParamVec.emplace_back(
787 "xyz.openbmc_project.Dump.Create.CreateParameters.OriginatorId",
788 req.session->clientIp);
789 createDumpParamVec.emplace_back(
790 "xyz.openbmc_project.Dump.Create.CreateParameters.OriginatorType",
791 "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Client");
792 }
Asmitha Karunanithi68dd0752022-11-15 11:33:46 -0600793
Ed Tanous177612a2025-02-14 15:16:09 -0800794 dbus::utility::async_method_call(
795 asyncResp,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800796 [asyncResp, payload(task::Payload(req)),
797 dumpPath](const boost::system::error_code& ec,
798 const sdbusplus::message_t& msg,
799 const sdbusplus::message::object_path& objPath) mutable {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400800 if (ec)
Asmitha Karunanithi59075712021-10-22 01:17:41 -0500801 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400802 BMCWEB_LOG_ERROR("CreateDump resp_handler got error {}", ec);
803 const sd_bus_error* dbusError = msg.get_error();
804 if (dbusError == nullptr)
805 {
806 messages::internalError(asyncResp->res);
807 return;
808 }
809
810 BMCWEB_LOG_ERROR("CreateDump DBus error: {} and error msg: {}",
811 dbusError->name, dbusError->message);
812 if (std::string_view(
813 "xyz.openbmc_project.Common.Error.NotAllowed") ==
814 dbusError->name)
815 {
816 messages::resourceInStandby(asyncResp->res);
817 return;
818 }
819 if (std::string_view(
820 "xyz.openbmc_project.Dump.Create.Error.Disabled") ==
821 dbusError->name)
822 {
823 messages::serviceDisabled(asyncResp->res, dumpPath);
824 return;
825 }
826 if (std::string_view(
827 "xyz.openbmc_project.Common.Error.Unavailable") ==
828 dbusError->name)
829 {
830 messages::resourceInUse(asyncResp->res);
831 return;
832 }
833 // Other Dbus errors such as:
834 // xyz.openbmc_project.Common.Error.InvalidArgument &
835 // org.freedesktop.DBus.Error.InvalidArgs are all related to
836 // the dbus call that is made here in the bmcweb
837 // implementation and has nothing to do with the client's
838 // input in the request. Hence, returning internal error
839 // back to the client.
Asmitha Karunanithi59075712021-10-22 01:17:41 -0500840 messages::internalError(asyncResp->res);
841 return;
842 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400843 BMCWEB_LOG_DEBUG("Dump Created. Path: {}", objPath.str);
844 createDumpTaskCallback(std::move(payload), asyncResp, objPath);
845 },
Ed Tanous18f8f602023-07-18 10:07:23 -0700846 "xyz.openbmc_project.Dump.Manager", getDumpPath(dumpType),
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600847 "xyz.openbmc_project.Dump.Create", "CreateDump", createDumpParamVec);
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500848}
849
zhanghch058d1b46d2021-04-01 11:18:24 +0800850inline void clearDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
851 const std::string& dumpType)
Asmitha Karunanithi80319af2020-05-07 05:30:21 -0500852{
Ed Tanous177612a2025-02-14 15:16:09 -0800853 dbus::utility::async_method_call(
854 asyncResp,
Claire Weinan0d946212022-07-13 19:40:19 -0700855 [asyncResp](const boost::system::error_code& ec) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400856 if (ec)
857 {
858 BMCWEB_LOG_ERROR("clearDump resp_handler got error {}", ec);
859 messages::internalError(asyncResp->res);
860 return;
861 }
Amy Change2460462025-05-06 00:10:13 -0700862 messages::success(asyncResp->res);
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400863 },
Ed Tanous18f8f602023-07-18 10:07:23 -0700864 "xyz.openbmc_project.Dump.Manager", getDumpPath(dumpType),
Claire Weinan0d946212022-07-13 19:40:19 -0700865 "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
Asmitha Karunanithi80319af2020-05-07 05:30:21 -0500866}
867
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400868inline void parseCrashdumpParameters(
869 const dbus::utility::DBusPropertiesMap& params, std::string& filename,
870 std::string& timestamp, std::string& logfile)
Johnathan Mantey043a0532020-03-10 17:15:28 -0700871{
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +0200872 const std::string* filenamePtr = nullptr;
873 const std::string* timestampPtr = nullptr;
874 const std::string* logfilePtr = nullptr;
875
876 const bool success = sdbusplus::unpackPropertiesNoThrow(
877 dbus_utils::UnpackErrorPrinter(), params, "Timestamp", timestampPtr,
878 "Filename", filenamePtr, "Log", logfilePtr);
879
880 if (!success)
Johnathan Mantey043a0532020-03-10 17:15:28 -0700881 {
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +0200882 return;
883 }
884
885 if (filenamePtr != nullptr)
886 {
887 filename = *filenamePtr;
888 }
889
890 if (timestampPtr != nullptr)
891 {
892 timestamp = *timestampPtr;
893 }
894
895 if (logfilePtr != nullptr)
896 {
897 logfile = *logfilePtr;
Johnathan Mantey043a0532020-03-10 17:15:28 -0700898 }
899}
900
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700901inline void requestRoutesSystemLogServiceCollection(App& app)
Ed Tanous1da66f72018-07-27 16:13:37 -0700902{
Jason M. Billsc4bf6372018-11-05 13:48:27 -0800903 /**
904 * Functions triggers appropriate requests on DBus
905 */
Ed Tanous22d268c2022-05-19 09:39:07 -0700906 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/")
Ed Tanoused398212021-06-09 17:05:54 -0700907 .privileges(redfish::privileges::getLogServiceCollection)
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400908 .methods(
909 boost::beast::http::verb::
910 get)([&app](const crow::Request& req,
911 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
912 const std::string& systemName) {
913 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -0700914 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400915 return;
916 }
917 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
918 {
919 // Option currently returns no systems. TBD
920 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
921 systemName);
922 return;
923 }
924 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
925 {
926 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
927 systemName);
Ed Tanous002d39b2022-05-31 08:59:27 -0700928 return;
929 }
Ed Tanous45ca1b82022-03-25 13:07:27 -0700930
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400931 // Collections don't include the static data added by SubRoute
932 // because it has a duplicate entry for members
933 asyncResp->res.jsonValue["@odata.type"] =
934 "#LogServiceCollection.LogServiceCollection";
935 asyncResp->res.jsonValue["@odata.id"] =
936 std::format("/redfish/v1/Systems/{}/LogServices",
937 BMCWEB_REDFISH_SYSTEM_URI_NAME);
938 asyncResp->res.jsonValue["Name"] = "System Log Services Collection";
939 asyncResp->res.jsonValue["Description"] =
940 "Collection of LogServices for this Computer System";
941 nlohmann::json& logServiceArray =
942 asyncResp->res.jsonValue["Members"];
943 logServiceArray = nlohmann::json::array();
944 nlohmann::json::object_t eventLog;
945 eventLog["@odata.id"] =
946 std::format("/redfish/v1/Systems/{}/LogServices/EventLog",
947 BMCWEB_REDFISH_SYSTEM_URI_NAME);
948 logServiceArray.emplace_back(std::move(eventLog));
949 if constexpr (BMCWEB_REDFISH_DUMP_LOG)
Ed Tanous002d39b2022-05-31 08:59:27 -0700950 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400951 nlohmann::json::object_t dumpLog;
952 dumpLog["@odata.id"] =
953 std::format("/redfish/v1/Systems/{}/LogServices/Dump",
954 BMCWEB_REDFISH_SYSTEM_URI_NAME);
955 logServiceArray.emplace_back(std::move(dumpLog));
Ed Tanous002d39b2022-05-31 08:59:27 -0700956 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400957
958 if constexpr (BMCWEB_REDFISH_CPU_LOG)
959 {
960 nlohmann::json::object_t crashdump;
961 crashdump["@odata.id"] =
962 std::format("/redfish/v1/Systems/{}/LogServices/Crashdump",
963 BMCWEB_REDFISH_SYSTEM_URI_NAME);
964 logServiceArray.emplace_back(std::move(crashdump));
965 }
966
967 if constexpr (BMCWEB_REDFISH_HOST_LOGGER)
968 {
969 nlohmann::json::object_t hostlogger;
970 hostlogger["@odata.id"] =
971 std::format("/redfish/v1/Systems/{}/LogServices/HostLogger",
972 BMCWEB_REDFISH_SYSTEM_URI_NAME);
973 logServiceArray.emplace_back(std::move(hostlogger));
974 }
975 asyncResp->res.jsonValue["Members@odata.count"] =
976 logServiceArray.size();
977
978 constexpr std::array<std::string_view, 1> interfaces = {
979 "xyz.openbmc_project.State.Boot.PostCode"};
980 dbus::utility::getSubTreePaths(
981 "/", 0, interfaces,
982 [asyncResp](const boost::system::error_code& ec,
983 const dbus::utility::MapperGetSubTreePathsResponse&
984 subtreePath) {
985 if (ec)
986 {
987 BMCWEB_LOG_ERROR("{}", ec);
988 return;
989 }
990
991 for (const auto& pathStr : subtreePath)
992 {
993 if (pathStr.find("PostCode") != std::string::npos)
994 {
995 nlohmann::json& logServiceArrayLocal =
996 asyncResp->res.jsonValue["Members"];
997 nlohmann::json::object_t member;
998 member["@odata.id"] = std::format(
999 "/redfish/v1/Systems/{}/LogServices/PostCodes",
1000 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1001
1002 logServiceArrayLocal.emplace_back(
1003 std::move(member));
1004
1005 asyncResp->res.jsonValue["Members@odata.count"] =
1006 logServiceArrayLocal.size();
1007 return;
1008 }
1009 }
1010 });
Ed Tanous45ca1b82022-03-25 13:07:27 -07001011 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001012}
1013
Oliver Brewka9d6459e2025-08-27 13:39:15 +02001014inline void requestRoutesSystemsEventLogService(App& app)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001015{
Ed Tanous22d268c2022-05-19 09:39:07 -07001016 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/")
Ed Tanoused398212021-06-09 17:05:54 -07001017 .privileges(redfish::privileges::getLogService)
Oliver Brewka9d6459e2025-08-27 13:39:15 +02001018 .methods(boost::beast::http::verb::get)(
1019 [&app](const crow::Request& req,
1020 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1021 const std::string& systemName) {
1022 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1023 {
1024 return;
1025 }
1026 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1027 {
1028 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1029 systemName);
1030 return;
1031 }
1032 eventlog_utils::handleSystemsAndManagersEventLogServiceGet(
1033 asyncResp, eventlog_utils::LogServiceParent::Systems);
1034 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001035}
1036
Claire Weinandd72e872022-08-15 14:20:06 -07001037inline void handleBMCLogServicesCollectionGet(
Claire Weinanfdd26902022-03-01 14:18:25 -08001038 crow::App& app, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07001039 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1040 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08001041{
1042 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1043 {
1044 return;
1045 }
Ed Tanous253f11b2024-05-16 09:38:31 -07001046
1047 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
1048 {
1049 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
1050 return;
1051 }
1052
Claire Weinanfdd26902022-03-01 14:18:25 -08001053 // Collections don't include the static data added by SubRoute
1054 // because it has a duplicate entry for members
1055 asyncResp->res.jsonValue["@odata.type"] =
1056 "#LogServiceCollection.LogServiceCollection";
Ed Tanous253f11b2024-05-16 09:38:31 -07001057 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
1058 "/redfish/v1/Managers/{}/LogServices", BMCWEB_REDFISH_MANAGER_URI_NAME);
Claire Weinanfdd26902022-03-01 14:18:25 -08001059 asyncResp->res.jsonValue["Name"] = "Open BMC Log Services Collection";
1060 asyncResp->res.jsonValue["Description"] =
1061 "Collection of LogServices for this Manager";
1062 nlohmann::json& logServiceArray = asyncResp->res.jsonValue["Members"];
1063 logServiceArray = nlohmann::json::array();
1064
Ed Tanous25b54db2024-04-17 15:40:31 -07001065 if constexpr (BMCWEB_REDFISH_BMC_JOURNAL)
1066 {
1067 nlohmann::json::object_t journal;
Ed Tanous253f11b2024-05-16 09:38:31 -07001068 journal["@odata.id"] =
1069 boost::urls::format("/redfish/v1/Managers/{}/LogServices/Journal",
1070 BMCWEB_REDFISH_MANAGER_URI_NAME);
Ed Tanous25b54db2024-04-17 15:40:31 -07001071 logServiceArray.emplace_back(std::move(journal));
1072 }
Claire Weinanfdd26902022-03-01 14:18:25 -08001073
1074 asyncResp->res.jsonValue["Members@odata.count"] = logServiceArray.size();
1075
Ed Tanous25b54db2024-04-17 15:40:31 -07001076 if constexpr (BMCWEB_REDFISH_DUMP_LOG)
1077 {
1078 constexpr std::array<std::string_view, 1> interfaces = {
1079 "xyz.openbmc_project.Collection.DeleteAll"};
1080 dbus::utility::getSubTreePaths(
1081 "/xyz/openbmc_project/dump", 0, interfaces,
1082 [asyncResp](const boost::system::error_code& ec,
1083 const dbus::utility::MapperGetSubTreePathsResponse&
1084 subTreePaths) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001085 if (ec)
Ed Tanous25b54db2024-04-17 15:40:31 -07001086 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001087 BMCWEB_LOG_ERROR(
1088 "handleBMCLogServicesCollectionGet respHandler got error {}",
1089 ec);
1090 // Assume that getting an error simply means there are no
1091 // dump LogServices. Return without adding any error
1092 // response.
1093 return;
Ed Tanous25b54db2024-04-17 15:40:31 -07001094 }
Ed Tanous25b54db2024-04-17 15:40:31 -07001095
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001096 nlohmann::json& logServiceArrayLocal =
1097 asyncResp->res.jsonValue["Members"];
1098
1099 for (const std::string& path : subTreePaths)
1100 {
1101 if (path == "/xyz/openbmc_project/dump/bmc")
1102 {
1103 nlohmann::json::object_t member;
1104 member["@odata.id"] = boost::urls::format(
1105 "/redfish/v1/Managers/{}/LogServices/Dump",
1106 BMCWEB_REDFISH_MANAGER_URI_NAME);
1107 logServiceArrayLocal.emplace_back(std::move(member));
1108 }
1109 else if (path == "/xyz/openbmc_project/dump/faultlog")
1110 {
1111 nlohmann::json::object_t member;
1112 member["@odata.id"] = boost::urls::format(
1113 "/redfish/v1/Managers/{}/LogServices/FaultLog",
1114 BMCWEB_REDFISH_MANAGER_URI_NAME);
1115 logServiceArrayLocal.emplace_back(std::move(member));
1116 }
1117 }
1118
1119 asyncResp->res.jsonValue["Members@odata.count"] =
1120 logServiceArrayLocal.size();
1121 });
Ed Tanous25b54db2024-04-17 15:40:31 -07001122 }
Claire Weinanfdd26902022-03-01 14:18:25 -08001123}
1124
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001125inline void requestRoutesBMCLogServiceCollection(App& app)
1126{
Ed Tanous253f11b2024-05-16 09:38:31 -07001127 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/")
Gunnar Millsad89dcf2021-07-30 14:40:11 -05001128 .privileges(redfish::privileges::getLogServiceCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001129 .methods(boost::beast::http::verb::get)(
Claire Weinandd72e872022-08-15 14:20:06 -07001130 std::bind_front(handleBMCLogServicesCollectionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001131}
Ed Tanous1da66f72018-07-27 16:13:37 -07001132
Patrick Williams504af5a2025-02-03 14:29:03 -05001133inline void getDumpServiceInfo(
1134 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1135 const std::string& dumpType)
Claire Weinanfdd26902022-03-01 14:18:25 -08001136{
1137 std::string dumpPath;
Ed Tanous539d8c62024-06-19 14:38:27 -07001138 log_service::OverWritePolicy overWritePolicy =
1139 log_service::OverWritePolicy::Invalid;
Claire Weinanfdd26902022-03-01 14:18:25 -08001140 bool collectDiagnosticDataSupported = false;
1141
1142 if (dumpType == "BMC")
1143 {
Ed Tanous253f11b2024-05-16 09:38:31 -07001144 dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/Dump",
1145 BMCWEB_REDFISH_MANAGER_URI_NAME);
Ed Tanous539d8c62024-06-19 14:38:27 -07001146 overWritePolicy = log_service::OverWritePolicy::WrapsWhenFull;
Claire Weinanfdd26902022-03-01 14:18:25 -08001147 collectDiagnosticDataSupported = true;
1148 }
1149 else if (dumpType == "FaultLog")
1150 {
Ed Tanous253f11b2024-05-16 09:38:31 -07001151 dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/FaultLog",
1152 BMCWEB_REDFISH_MANAGER_URI_NAME);
Ed Tanous539d8c62024-06-19 14:38:27 -07001153 overWritePolicy = log_service::OverWritePolicy::Unknown;
Claire Weinanfdd26902022-03-01 14:18:25 -08001154 collectDiagnosticDataSupported = false;
1155 }
1156 else if (dumpType == "System")
1157 {
Ed Tanous253f11b2024-05-16 09:38:31 -07001158 dumpPath = std::format("/redfish/v1/Systems/{}/LogServices/Dump",
1159 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanous539d8c62024-06-19 14:38:27 -07001160 overWritePolicy = log_service::OverWritePolicy::WrapsWhenFull;
Claire Weinanfdd26902022-03-01 14:18:25 -08001161 collectDiagnosticDataSupported = true;
1162 }
1163 else
1164 {
Ed Tanous62598e32023-07-17 17:06:25 -07001165 BMCWEB_LOG_ERROR("getDumpServiceInfo() invalid dump type: {}",
1166 dumpType);
Claire Weinanfdd26902022-03-01 14:18:25 -08001167 messages::internalError(asyncResp->res);
1168 return;
1169 }
1170
1171 asyncResp->res.jsonValue["@odata.id"] = dumpPath;
1172 asyncResp->res.jsonValue["@odata.type"] = "#LogService.v1_2_0.LogService";
1173 asyncResp->res.jsonValue["Name"] = "Dump LogService";
1174 asyncResp->res.jsonValue["Description"] = dumpType + " Dump LogService";
1175 asyncResp->res.jsonValue["Id"] = std::filesystem::path(dumpPath).filename();
Ed Tanous539d8c62024-06-19 14:38:27 -07001176 asyncResp->res.jsonValue["OverWritePolicy"] = overWritePolicy;
Claire Weinanfdd26902022-03-01 14:18:25 -08001177
1178 std::pair<std::string, std::string> redfishDateTimeOffset =
Ed Tanous2b829372022-08-03 14:22:34 -07001179 redfish::time_utils::getDateTimeOffsetNow();
Claire Weinanfdd26902022-03-01 14:18:25 -08001180 asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
1181 asyncResp->res.jsonValue["DateTimeLocalOffset"] =
1182 redfishDateTimeOffset.second;
1183
1184 asyncResp->res.jsonValue["Entries"]["@odata.id"] = dumpPath + "/Entries";
Claire Weinanfdd26902022-03-01 14:18:25 -08001185
1186 if (collectDiagnosticDataSupported)
1187 {
1188 asyncResp->res.jsonValue["Actions"]["#LogService.CollectDiagnosticData"]
1189 ["target"] =
1190 dumpPath + "/Actions/LogService.CollectDiagnosticData";
1191 }
Claire Weinan0d946212022-07-13 19:40:19 -07001192
Corey Ethington08fad5d2025-07-31 12:14:27 -04001193 etag_utils::setEtagOmitDateTimeHandler(asyncResp);
1194
Claire Weinan0d946212022-07-13 19:40:19 -07001195 constexpr std::array<std::string_view, 1> interfaces = {deleteAllInterface};
1196 dbus::utility::getSubTreePaths(
1197 "/xyz/openbmc_project/dump", 0, interfaces,
1198 [asyncResp, dumpType, dumpPath](
1199 const boost::system::error_code& ec,
1200 const dbus::utility::MapperGetSubTreePathsResponse& subTreePaths) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001201 if (ec)
Claire Weinan0d946212022-07-13 19:40:19 -07001202 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001203 BMCWEB_LOG_ERROR("getDumpServiceInfo respHandler got error {}",
1204 ec);
1205 // Assume that getting an error simply means there are no dump
1206 // LogServices. Return without adding any error response.
1207 return;
Claire Weinan0d946212022-07-13 19:40:19 -07001208 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001209 std::string dbusDumpPath = getDumpPath(dumpType);
1210 for (const std::string& path : subTreePaths)
1211 {
1212 if (path == dbusDumpPath)
1213 {
1214 asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"]
1215 ["target"] =
1216 dumpPath + "/Actions/LogService.ClearLog";
1217 break;
1218 }
1219 }
1220 });
Claire Weinanfdd26902022-03-01 14:18:25 -08001221}
1222
1223inline void handleLogServicesDumpServiceGet(
1224 crow::App& app, const std::string& dumpType, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07001225 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1226 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08001227{
1228 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1229 {
1230 return;
1231 }
Ed Tanous253f11b2024-05-16 09:38:31 -07001232
1233 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
1234 {
1235 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
1236 return;
1237 }
1238
Claire Weinanfdd26902022-03-01 14:18:25 -08001239 getDumpServiceInfo(asyncResp, dumpType);
1240}
1241
Ed Tanous22d268c2022-05-19 09:39:07 -07001242inline void handleLogServicesDumpServiceComputerSystemGet(
1243 crow::App& app, const crow::Request& req,
1244 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1245 const std::string& chassisId)
1246{
1247 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1248 {
1249 return;
1250 }
Ed Tanous253f11b2024-05-16 09:38:31 -07001251 if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous22d268c2022-05-19 09:39:07 -07001252 {
1253 messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
1254 return;
1255 }
1256 getDumpServiceInfo(asyncResp, "System");
1257}
1258
Claire Weinanfdd26902022-03-01 14:18:25 -08001259inline void handleLogServicesDumpEntriesCollectionGet(
1260 crow::App& app, const std::string& dumpType, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07001261 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1262 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08001263{
1264 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1265 {
1266 return;
1267 }
Ed Tanous253f11b2024-05-16 09:38:31 -07001268
1269 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
1270 {
1271 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
1272 return;
1273 }
Claire Weinanfdd26902022-03-01 14:18:25 -08001274 getDumpEntryCollection(asyncResp, dumpType);
1275}
1276
Ed Tanous22d268c2022-05-19 09:39:07 -07001277inline void handleLogServicesDumpEntriesCollectionComputerSystemGet(
1278 crow::App& app, const crow::Request& req,
1279 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1280 const std::string& chassisId)
1281{
1282 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1283 {
1284 return;
1285 }
Ed Tanous253f11b2024-05-16 09:38:31 -07001286 if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous22d268c2022-05-19 09:39:07 -07001287 {
1288 messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
1289 return;
1290 }
1291 getDumpEntryCollection(asyncResp, "System");
1292}
1293
Claire Weinanfdd26902022-03-01 14:18:25 -08001294inline void handleLogServicesDumpEntryGet(
1295 crow::App& app, const std::string& dumpType, const crow::Request& req,
1296 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous253f11b2024-05-16 09:38:31 -07001297 const std::string& managerId, const std::string& dumpId)
Claire Weinanfdd26902022-03-01 14:18:25 -08001298{
1299 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1300 {
1301 return;
1302 }
Ed Tanous253f11b2024-05-16 09:38:31 -07001303 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
1304 {
1305 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
1306 return;
1307 }
Claire Weinanfdd26902022-03-01 14:18:25 -08001308 getDumpEntryById(asyncResp, dumpId, dumpType);
1309}
Carson Labrado168d1b12023-03-27 17:04:46 +00001310
Ed Tanous22d268c2022-05-19 09:39:07 -07001311inline void handleLogServicesDumpEntryComputerSystemGet(
1312 crow::App& app, const crow::Request& req,
1313 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1314 const std::string& chassisId, const std::string& dumpId)
1315{
1316 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1317 {
1318 return;
1319 }
Ed Tanous253f11b2024-05-16 09:38:31 -07001320 if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous22d268c2022-05-19 09:39:07 -07001321 {
1322 messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
1323 return;
1324 }
1325 getDumpEntryById(asyncResp, dumpId, "System");
1326}
Claire Weinanfdd26902022-03-01 14:18:25 -08001327
1328inline void handleLogServicesDumpEntryDelete(
1329 crow::App& app, const std::string& dumpType, const crow::Request& req,
1330 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous253f11b2024-05-16 09:38:31 -07001331 const std::string& managerId, const std::string& dumpId)
Claire Weinanfdd26902022-03-01 14:18:25 -08001332{
1333 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1334 {
1335 return;
1336 }
Ed Tanous253f11b2024-05-16 09:38:31 -07001337
1338 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
1339 {
1340 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
1341 return;
1342 }
Claire Weinanfdd26902022-03-01 14:18:25 -08001343 deleteDumpEntry(asyncResp, dumpId, dumpType);
1344}
1345
Ed Tanous22d268c2022-05-19 09:39:07 -07001346inline void handleLogServicesDumpEntryComputerSystemDelete(
1347 crow::App& app, const crow::Request& req,
1348 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1349 const std::string& chassisId, const std::string& dumpId)
1350{
1351 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1352 {
1353 return;
1354 }
Ed Tanous253f11b2024-05-16 09:38:31 -07001355 if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous22d268c2022-05-19 09:39:07 -07001356 {
1357 messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
1358 return;
1359 }
1360 deleteDumpEntry(asyncResp, dumpId, "System");
1361}
1362
Carson Labrado168d1b12023-03-27 17:04:46 +00001363inline void handleLogServicesDumpEntryDownloadGet(
1364 crow::App& app, const std::string& dumpType, const crow::Request& req,
1365 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous253f11b2024-05-16 09:38:31 -07001366 const std::string& managerId, const std::string& dumpId)
Carson Labrado168d1b12023-03-27 17:04:46 +00001367{
1368 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1369 {
1370 return;
1371 }
Ed Tanous253f11b2024-05-16 09:38:31 -07001372
1373 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
1374 {
1375 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
1376 return;
1377 }
Carson Labrado168d1b12023-03-27 17:04:46 +00001378 downloadDumpEntry(asyncResp, dumpId, dumpType);
1379}
1380
Claire Weinanfdd26902022-03-01 14:18:25 -08001381inline void handleLogServicesDumpCollectDiagnosticDataPost(
1382 crow::App& app, const std::string& dumpType, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07001383 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1384 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08001385{
1386 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1387 {
1388 return;
1389 }
Ed Tanous253f11b2024-05-16 09:38:31 -07001390 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
1391 {
1392 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
1393 return;
1394 }
1395
Claire Weinanfdd26902022-03-01 14:18:25 -08001396 createDump(asyncResp, req, dumpType);
1397}
1398
Ed Tanous22d268c2022-05-19 09:39:07 -07001399inline void handleLogServicesDumpCollectDiagnosticDataComputerSystemPost(
1400 crow::App& app, const crow::Request& req,
1401 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08001402 const std::string& systemName)
Ed Tanous22d268c2022-05-19 09:39:07 -07001403{
1404 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1405 {
1406 return;
1407 }
Ed Tanous7f3e84a2022-12-28 16:22:54 -08001408
Ed Tanous25b54db2024-04-17 15:40:31 -07001409 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous22d268c2022-05-19 09:39:07 -07001410 {
Ed Tanous7f3e84a2022-12-28 16:22:54 -08001411 // Option currently returns no systems. TBD
1412 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1413 systemName);
1414 return;
1415 }
Ed Tanous253f11b2024-05-16 09:38:31 -07001416 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous7f3e84a2022-12-28 16:22:54 -08001417 {
1418 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1419 systemName);
Ed Tanous22d268c2022-05-19 09:39:07 -07001420 return;
1421 }
1422 createDump(asyncResp, req, "System");
1423}
1424
Claire Weinanfdd26902022-03-01 14:18:25 -08001425inline void handleLogServicesDumpClearLogPost(
1426 crow::App& app, const std::string& dumpType, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07001427 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1428 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08001429{
1430 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1431 {
1432 return;
1433 }
Ed Tanous253f11b2024-05-16 09:38:31 -07001434
1435 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
1436 {
1437 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
1438 return;
1439 }
Claire Weinanfdd26902022-03-01 14:18:25 -08001440 clearDump(asyncResp, dumpType);
1441}
1442
Ed Tanous22d268c2022-05-19 09:39:07 -07001443inline void handleLogServicesDumpClearLogComputerSystemPost(
1444 crow::App& app, const crow::Request& req,
1445 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08001446 const std::string& systemName)
Ed Tanous22d268c2022-05-19 09:39:07 -07001447{
1448 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1449 {
1450 return;
1451 }
Ed Tanous25b54db2024-04-17 15:40:31 -07001452 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous22d268c2022-05-19 09:39:07 -07001453 {
Ed Tanous7f3e84a2022-12-28 16:22:54 -08001454 // Option currently returns no systems. TBD
1455 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1456 systemName);
1457 return;
1458 }
Ed Tanous253f11b2024-05-16 09:38:31 -07001459 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous7f3e84a2022-12-28 16:22:54 -08001460 {
1461 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1462 systemName);
Ed Tanous22d268c2022-05-19 09:39:07 -07001463 return;
1464 }
1465 clearDump(asyncResp, "System");
1466}
1467
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001468inline void requestRoutesBMCDumpService(App& app)
1469{
Ed Tanous253f11b2024-05-16 09:38:31 -07001470 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/Dump/")
Ed Tanoused398212021-06-09 17:05:54 -07001471 .privileges(redfish::privileges::getLogService)
Claire Weinanfdd26902022-03-01 14:18:25 -08001472 .methods(boost::beast::http::verb::get)(std::bind_front(
1473 handleLogServicesDumpServiceGet, std::ref(app), "BMC"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001474}
1475
1476inline void requestRoutesBMCDumpEntryCollection(App& app)
1477{
Ed Tanous253f11b2024-05-16 09:38:31 -07001478 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/")
Ed Tanoused398212021-06-09 17:05:54 -07001479 .privileges(redfish::privileges::getLogEntryCollection)
Claire Weinanfdd26902022-03-01 14:18:25 -08001480 .methods(boost::beast::http::verb::get)(std::bind_front(
1481 handleLogServicesDumpEntriesCollectionGet, std::ref(app), "BMC"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001482}
1483
1484inline void requestRoutesBMCDumpEntry(App& app)
1485{
1486 BMCWEB_ROUTE(app,
Ed Tanous253f11b2024-05-16 09:38:31 -07001487 "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001488 .privileges(redfish::privileges::getLogEntry)
Claire Weinanfdd26902022-03-01 14:18:25 -08001489 .methods(boost::beast::http::verb::get)(std::bind_front(
1490 handleLogServicesDumpEntryGet, std::ref(app), "BMC"));
1491
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001492 BMCWEB_ROUTE(app,
Ed Tanous253f11b2024-05-16 09:38:31 -07001493 "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001494 .privileges(redfish::privileges::deleteLogEntry)
Claire Weinanfdd26902022-03-01 14:18:25 -08001495 .methods(boost::beast::http::verb::delete_)(std::bind_front(
1496 handleLogServicesDumpEntryDelete, std::ref(app), "BMC"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001497}
1498
Carson Labrado168d1b12023-03-27 17:04:46 +00001499inline void requestRoutesBMCDumpEntryDownload(App& app)
1500{
1501 BMCWEB_ROUTE(
1502 app,
Ed Tanous253f11b2024-05-16 09:38:31 -07001503 "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/attachment/")
Carson Labrado168d1b12023-03-27 17:04:46 +00001504 .privileges(redfish::privileges::getLogEntry)
1505 .methods(boost::beast::http::verb::get)(std::bind_front(
1506 handleLogServicesDumpEntryDownloadGet, std::ref(app), "BMC"));
1507}
1508
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001509inline void requestRoutesBMCDumpCreate(App& app)
1510{
George Liu0fda0f12021-11-16 10:06:17 +08001511 BMCWEB_ROUTE(
1512 app,
Ed Tanous253f11b2024-05-16 09:38:31 -07001513 "/redfish/v1/Managers/<str>/LogServices/Dump/Actions/LogService.CollectDiagnosticData/")
Ed Tanoused398212021-06-09 17:05:54 -07001514 .privileges(redfish::privileges::postLogService)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001515 .methods(boost::beast::http::verb::post)(
Claire Weinanfdd26902022-03-01 14:18:25 -08001516 std::bind_front(handleLogServicesDumpCollectDiagnosticDataPost,
1517 std::ref(app), "BMC"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001518}
1519
1520inline void requestRoutesBMCDumpClear(App& app)
1521{
George Liu0fda0f12021-11-16 10:06:17 +08001522 BMCWEB_ROUTE(
1523 app,
Ed Tanous253f11b2024-05-16 09:38:31 -07001524 "/redfish/v1/Managers/<str>/LogServices/Dump/Actions/LogService.ClearLog/")
Ed Tanoused398212021-06-09 17:05:54 -07001525 .privileges(redfish::privileges::postLogService)
Claire Weinanfdd26902022-03-01 14:18:25 -08001526 .methods(boost::beast::http::verb::post)(std::bind_front(
1527 handleLogServicesDumpClearLogPost, std::ref(app), "BMC"));
1528}
1529
1530inline void requestRoutesFaultLogDumpService(App& app)
1531{
Ed Tanous253f11b2024-05-16 09:38:31 -07001532 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/")
Claire Weinanfdd26902022-03-01 14:18:25 -08001533 .privileges(redfish::privileges::getLogService)
1534 .methods(boost::beast::http::verb::get)(std::bind_front(
1535 handleLogServicesDumpServiceGet, std::ref(app), "FaultLog"));
1536}
1537
1538inline void requestRoutesFaultLogDumpEntryCollection(App& app)
1539{
Ed Tanous253f11b2024-05-16 09:38:31 -07001540 BMCWEB_ROUTE(app,
1541 "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/")
Claire Weinanfdd26902022-03-01 14:18:25 -08001542 .privileges(redfish::privileges::getLogEntryCollection)
1543 .methods(boost::beast::http::verb::get)(
1544 std::bind_front(handleLogServicesDumpEntriesCollectionGet,
1545 std::ref(app), "FaultLog"));
1546}
1547
1548inline void requestRoutesFaultLogDumpEntry(App& app)
1549{
Ed Tanous253f11b2024-05-16 09:38:31 -07001550 BMCWEB_ROUTE(
1551 app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/<str>/")
Claire Weinanfdd26902022-03-01 14:18:25 -08001552 .privileges(redfish::privileges::getLogEntry)
1553 .methods(boost::beast::http::verb::get)(std::bind_front(
1554 handleLogServicesDumpEntryGet, std::ref(app), "FaultLog"));
1555
Ed Tanous253f11b2024-05-16 09:38:31 -07001556 BMCWEB_ROUTE(
1557 app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/<str>/")
Claire Weinanfdd26902022-03-01 14:18:25 -08001558 .privileges(redfish::privileges::deleteLogEntry)
1559 .methods(boost::beast::http::verb::delete_)(std::bind_front(
1560 handleLogServicesDumpEntryDelete, std::ref(app), "FaultLog"));
1561}
1562
1563inline void requestRoutesFaultLogDumpClear(App& app)
1564{
1565 BMCWEB_ROUTE(
1566 app,
Ed Tanous253f11b2024-05-16 09:38:31 -07001567 "/redfish/v1/Managers/<str>/LogServices/FaultLog/Actions/LogService.ClearLog/")
Claire Weinanfdd26902022-03-01 14:18:25 -08001568 .privileges(redfish::privileges::postLogService)
1569 .methods(boost::beast::http::verb::post)(std::bind_front(
1570 handleLogServicesDumpClearLogPost, std::ref(app), "FaultLog"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001571}
1572
1573inline void requestRoutesSystemDumpService(App& app)
1574{
Ed Tanous22d268c2022-05-19 09:39:07 -07001575 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Dump/")
Ed Tanoused398212021-06-09 17:05:54 -07001576 .privileges(redfish::privileges::getLogService)
Claire Weinan6ab9ad52022-08-12 18:20:17 -07001577 .methods(boost::beast::http::verb::get)(std::bind_front(
Ed Tanous22d268c2022-05-19 09:39:07 -07001578 handleLogServicesDumpServiceComputerSystemGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001579}
1580
1581inline void requestRoutesSystemDumpEntryCollection(App& app)
1582{
Ed Tanous22d268c2022-05-19 09:39:07 -07001583 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/")
Ed Tanoused398212021-06-09 17:05:54 -07001584 .privileges(redfish::privileges::getLogEntryCollection)
Ed Tanous22d268c2022-05-19 09:39:07 -07001585 .methods(boost::beast::http::verb::get)(std::bind_front(
1586 handleLogServicesDumpEntriesCollectionComputerSystemGet,
1587 std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001588}
1589
1590inline void requestRoutesSystemDumpEntry(App& app)
1591{
1592 BMCWEB_ROUTE(app,
Ed Tanous22d268c2022-05-19 09:39:07 -07001593 "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001594 .privileges(redfish::privileges::getLogEntry)
Claire Weinan6ab9ad52022-08-12 18:20:17 -07001595 .methods(boost::beast::http::verb::get)(std::bind_front(
Ed Tanous22d268c2022-05-19 09:39:07 -07001596 handleLogServicesDumpEntryComputerSystemGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001597
1598 BMCWEB_ROUTE(app,
Ed Tanous22d268c2022-05-19 09:39:07 -07001599 "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001600 .privileges(redfish::privileges::deleteLogEntry)
Claire Weinan6ab9ad52022-08-12 18:20:17 -07001601 .methods(boost::beast::http::verb::delete_)(std::bind_front(
Ed Tanous22d268c2022-05-19 09:39:07 -07001602 handleLogServicesDumpEntryComputerSystemDelete, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001603}
1604
1605inline void requestRoutesSystemDumpCreate(App& app)
1606{
George Liu0fda0f12021-11-16 10:06:17 +08001607 BMCWEB_ROUTE(
1608 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07001609 "/redfish/v1/Systems/<str>/LogServices/Dump/Actions/LogService.CollectDiagnosticData/")
Abhishek Patelfff6a4d2021-07-21 11:29:45 -05001610 .privileges(redfish::privileges::
1611 postLogServiceSubOverComputerSystemLogServiceCollection)
Ed Tanous22d268c2022-05-19 09:39:07 -07001612 .methods(boost::beast::http::verb::post)(std::bind_front(
1613 handleLogServicesDumpCollectDiagnosticDataComputerSystemPost,
1614 std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001615}
1616
1617inline void requestRoutesSystemDumpClear(App& app)
1618{
George Liu0fda0f12021-11-16 10:06:17 +08001619 BMCWEB_ROUTE(
1620 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07001621 "/redfish/v1/Systems/<str>/LogServices/Dump/Actions/LogService.ClearLog/")
Abhishek Patelfff6a4d2021-07-21 11:29:45 -05001622 .privileges(redfish::privileges::
1623 postLogServiceSubOverComputerSystemLogServiceCollection)
Claire Weinan6ab9ad52022-08-12 18:20:17 -07001624 .methods(boost::beast::http::verb::post)(std::bind_front(
Ed Tanous22d268c2022-05-19 09:39:07 -07001625 handleLogServicesDumpClearLogComputerSystemPost, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001626}
1627
1628inline void requestRoutesCrashdumpService(App& app)
1629{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001630 /**
1631 * Functions triggers appropriate requests on DBus
1632 */
Ed Tanous22d268c2022-05-19 09:39:07 -07001633 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Crashdump/")
Myung Bae50d9f382025-06-13 09:40:18 -04001634 .privileges(redfish::privileges::getLogService)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001635 .methods(
1636 boost::beast::http::verb::
1637 get)([&app](const crow::Request& req,
1638 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1639 const std::string& systemName) {
1640 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1641 {
1642 return;
1643 }
1644 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1645 {
1646 // Option currently returns no systems. TBD
1647 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1648 systemName);
1649 return;
1650 }
1651 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1652 {
1653 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1654 systemName);
1655 return;
1656 }
Ed Tanous22d268c2022-05-19 09:39:07 -07001657
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001658 // Copy over the static data to include the entries added by
1659 // SubRoute
1660 asyncResp->res.jsonValue["@odata.id"] =
1661 std::format("/redfish/v1/Systems/{}/LogServices/Crashdump",
1662 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1663 asyncResp->res.jsonValue["@odata.type"] =
1664 "#LogService.v1_2_0.LogService";
1665 asyncResp->res.jsonValue["Name"] = "Open BMC Oem Crashdump Service";
1666 asyncResp->res.jsonValue["Description"] = "Oem Crashdump Service";
1667 asyncResp->res.jsonValue["Id"] = "Crashdump";
1668 asyncResp->res.jsonValue["OverWritePolicy"] =
1669 log_service::OverWritePolicy::WrapsWhenFull;
1670 asyncResp->res.jsonValue["MaxNumberOfRecords"] = 3;
Tejas Patil7c8c4052021-06-04 17:43:14 +05301671
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001672 std::pair<std::string, std::string> redfishDateTimeOffset =
1673 redfish::time_utils::getDateTimeOffsetNow();
1674 asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
1675 asyncResp->res.jsonValue["DateTimeLocalOffset"] =
1676 redfishDateTimeOffset.second;
Tejas Patil7c8c4052021-06-04 17:43:14 +05301677
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001678 asyncResp->res.jsonValue["Entries"]["@odata.id"] = std::format(
1679 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries",
1680 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1681 asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"]
1682 ["target"] = std::format(
1683 "/redfish/v1/Systems/{}/LogServices/Crashdump/Actions/LogService.ClearLog",
1684 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1685 asyncResp->res
1686 .jsonValue["Actions"]["#LogService.CollectDiagnosticData"]
1687 ["target"] = std::format(
1688 "/redfish/v1/Systems/{}/LogServices/Crashdump/Actions/LogService.CollectDiagnosticData",
1689 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Corey Ethington08fad5d2025-07-31 12:14:27 -04001690
1691 etag_utils::setEtagOmitDateTimeHandler(asyncResp);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001692 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001693}
1694
Ed Tanous8e4736b2025-08-19 10:14:02 -07001695inline void requestRoutesCrashdumpClear(App& app)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001696{
George Liu0fda0f12021-11-16 10:06:17 +08001697 BMCWEB_ROUTE(
1698 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07001699 "/redfish/v1/Systems/<str>/LogServices/Crashdump/Actions/LogService.ClearLog/")
Myung Bae50d9f382025-06-13 09:40:18 -04001700 .privileges(redfish::privileges::
1701 postLogServiceSubOverComputerSystemLogServiceCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001702 .methods(boost::beast::http::verb::post)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07001703 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07001704 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1705 const std::string& systemName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001706 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1707 {
1708 return;
1709 }
1710 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1711 {
1712 // Option currently returns no systems. TBD
1713 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1714 systemName);
1715 return;
1716 }
1717 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1718 {
1719 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1720 systemName);
1721 return;
1722 }
Ed Tanous177612a2025-02-14 15:16:09 -08001723 dbus::utility::async_method_call(
1724 asyncResp,
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001725 [asyncResp](const boost::system::error_code& ec,
1726 const std::string&) {
1727 if (ec)
1728 {
1729 messages::internalError(asyncResp->res);
1730 return;
1731 }
1732 messages::success(asyncResp->res);
1733 },
1734 crashdumpObject, crashdumpPath, deleteAllInterface,
1735 "DeleteAll");
1736 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001737}
Jason M. Bills5b61b5e2019-10-16 10:59:02 -07001738
Patrick Williams504af5a2025-02-03 14:29:03 -05001739inline void logCrashdumpEntry(
1740 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1741 const std::string& logID, nlohmann::json& logEntryJson)
Jason M. Billse855dd22019-10-08 11:37:48 -07001742{
Johnathan Mantey043a0532020-03-10 17:15:28 -07001743 auto getStoredLogCallback =
Ed Tanousb9d36b42022-02-26 21:42:46 -08001744 [asyncResp, logID,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001745 &logEntryJson](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001746 const dbus::utility::DBusPropertiesMap& params) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001747 if (ec)
1748 {
1749 BMCWEB_LOG_DEBUG("failed to get log ec: {}", ec.message());
1750 if (ec.value() ==
1751 boost::system::linux_error::bad_request_descriptor)
1752 {
1753 messages::resourceNotFound(asyncResp->res, "LogEntry",
1754 logID);
1755 }
1756 else
1757 {
1758 messages::internalError(asyncResp->res);
1759 }
1760 return;
1761 }
1762
1763 std::string timestamp{};
1764 std::string filename{};
1765 std::string logfile{};
1766 parseCrashdumpParameters(params, filename, timestamp, logfile);
1767
1768 if (filename.empty() || timestamp.empty())
Jason M. Bills1ddcf012019-11-26 14:59:21 -08001769 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001770 messages::resourceNotFound(asyncResp->res, "LogEntry", logID);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001771 return;
1772 }
1773
1774 std::string crashdumpURI =
1775 std::format(
1776 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries/",
1777 BMCWEB_REDFISH_SYSTEM_URI_NAME) +
1778 logID + "/" + filename;
1779 nlohmann::json::object_t logEntry;
1780 logEntry["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
1781 logEntry["@odata.id"] = boost::urls::format(
1782 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries/{}",
1783 BMCWEB_REDFISH_SYSTEM_URI_NAME, logID);
1784 logEntry["Name"] = "CPU Crashdump";
1785 logEntry["Id"] = logID;
1786 logEntry["EntryType"] = log_entry::LogEntryType::Oem;
1787 logEntry["AdditionalDataURI"] = std::move(crashdumpURI);
1788 logEntry["DiagnosticDataType"] = "OEM";
1789 logEntry["OEMDiagnosticDataType"] = "PECICrashdump";
1790 logEntry["Created"] = std::move(timestamp);
1791
1792 // If logEntryJson references an array of LogEntry resources
1793 // ('Members' list), then push this as a new entry, otherwise set it
1794 // directly
1795 if (logEntryJson.is_array())
1796 {
1797 logEntryJson.push_back(logEntry);
1798 asyncResp->res.jsonValue["Members@odata.count"] =
1799 logEntryJson.size();
Jason M. Bills2b20ef62022-01-06 15:48:07 -08001800 }
1801 else
1802 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001803 logEntryJson.update(logEntry);
Jason M. Bills2b20ef62022-01-06 15:48:07 -08001804 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001805 };
Ed Tanousdeae6a72024-11-11 21:58:57 -08001806 dbus::utility::getAllProperties(
1807 crashdumpObject, crashdumpPath + std::string("/") + logID,
1808 crashdumpInterface, std::move(getStoredLogCallback));
Jason M. Billse855dd22019-10-08 11:37:48 -07001809}
1810
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001811inline void requestRoutesCrashdumpEntryCollection(App& app)
Ed Tanous1da66f72018-07-27 16:13:37 -07001812{
Ed Tanous1da66f72018-07-27 16:13:37 -07001813 /**
1814 * Functions triggers appropriate requests on DBus
1815 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001816 BMCWEB_ROUTE(app,
Ed Tanous22d268c2022-05-19 09:39:07 -07001817 "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/")
Myung Bae50d9f382025-06-13 09:40:18 -04001818 .privileges(redfish::privileges::getLogEntryCollection)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001819 .methods(
1820 boost::beast::http::verb::
1821 get)([&app](const crow::Request& req,
1822 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1823 const std::string& systemName) {
1824 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous45ca1b82022-03-25 13:07:27 -07001825 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001826 return;
Ed Tanous45ca1b82022-03-25 13:07:27 -07001827 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001828 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous002d39b2022-05-31 08:59:27 -07001829 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001830 // Option currently returns no systems. TBD
1831 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1832 systemName);
1833 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07001834 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001835 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1836 {
1837 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1838 systemName);
1839 return;
1840 }
1841
1842 constexpr std::array<std::string_view, 1> interfaces = {
1843 crashdumpInterface};
1844 dbus::utility::getSubTreePaths(
1845 "/", 0, interfaces,
1846 [asyncResp](const boost::system::error_code& ec,
1847 const std::vector<std::string>& resp) {
1848 if (ec)
1849 {
1850 if (ec.value() !=
1851 boost::system::errc::no_such_file_or_directory)
1852 {
1853 BMCWEB_LOG_DEBUG("failed to get entries ec: {}",
1854 ec.message());
1855 messages::internalError(asyncResp->res);
1856 return;
1857 }
1858 }
1859 asyncResp->res.jsonValue["@odata.type"] =
1860 "#LogEntryCollection.LogEntryCollection";
1861 asyncResp->res.jsonValue["@odata.id"] = std::format(
1862 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries",
1863 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1864 asyncResp->res.jsonValue["Name"] =
1865 "Open BMC Crashdump Entries";
1866 asyncResp->res.jsonValue["Description"] =
1867 "Collection of Crashdump Entries";
1868 asyncResp->res.jsonValue["Members"] =
1869 nlohmann::json::array();
1870 asyncResp->res.jsonValue["Members@odata.count"] = 0;
1871
1872 for (const std::string& path : resp)
1873 {
1874 const sdbusplus::message::object_path objPath(path);
1875 // Get the log ID
1876 std::string logID = objPath.filename();
1877 if (logID.empty())
1878 {
1879 continue;
1880 }
1881 // Add the log entry to the array
1882 logCrashdumpEntry(asyncResp, logID,
1883 asyncResp->res.jsonValue["Members"]);
1884 }
1885 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001886 });
1887}
Ed Tanous1da66f72018-07-27 16:13:37 -07001888
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001889inline void requestRoutesCrashdumpEntry(App& app)
Ed Tanous1da66f72018-07-27 16:13:37 -07001890{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001891 BMCWEB_ROUTE(
Ed Tanous22d268c2022-05-19 09:39:07 -07001892 app, "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/<str>/")
Myung Bae50d9f382025-06-13 09:40:18 -04001893 .privileges(redfish::privileges::getLogEntry)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001894 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07001895 [&app](const crow::Request& req,
1896 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -07001897 const std::string& systemName, const std::string& param) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001898 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1899 {
1900 return;
1901 }
1902 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1903 {
1904 // Option currently returns no systems. TBD
1905 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1906 systemName);
1907 return;
1908 }
1909 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1910 {
1911 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1912 systemName);
1913 return;
1914 }
1915 const std::string& logID = param;
1916 logCrashdumpEntry(asyncResp, logID, asyncResp->res.jsonValue);
1917 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001918}
Ed Tanous1da66f72018-07-27 16:13:37 -07001919
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001920inline void requestRoutesCrashdumpFile(App& app)
1921{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001922 BMCWEB_ROUTE(
1923 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07001924 "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/<str>/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001925 .privileges(redfish::privileges::getLogEntry)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001926 .methods(boost::beast::http::verb::get)(
Nan Zhoua4ce1142022-08-02 18:45:25 +00001927 [](const crow::Request& req,
1928 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -07001929 const std::string& systemName, const std::string& logID,
1930 const std::string& fileName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001931 // Do not call getRedfishRoute here since the crashdump file is
1932 // not a Redfish resource.
Ed Tanous22d268c2022-05-19 09:39:07 -07001933
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001934 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1935 {
1936 // Option currently returns no systems. TBD
1937 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1938 systemName);
1939 return;
1940 }
1941 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1942 {
1943 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1944 systemName);
1945 return;
1946 }
Ed Tanous22d268c2022-05-19 09:39:07 -07001947
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001948 auto getStoredLogCallback =
1949 [asyncResp, logID, fileName,
1950 url(boost::urls::url(req.url()))](
1951 const boost::system::error_code& ec,
1952 const std::vector<std::pair<
1953 std::string, dbus::utility::DbusVariantType>>&
1954 resp) {
1955 if (ec)
1956 {
1957 BMCWEB_LOG_DEBUG("failed to get log ec: {}",
1958 ec.message());
1959 messages::internalError(asyncResp->res);
1960 return;
1961 }
Jason M. Bills8e6c0992021-03-11 16:26:53 -08001962
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001963 std::string dbusFilename{};
1964 std::string dbusTimestamp{};
1965 std::string dbusFilepath{};
Jason M. Bills8e6c0992021-03-11 16:26:53 -08001966
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001967 parseCrashdumpParameters(resp, dbusFilename,
1968 dbusTimestamp, dbusFilepath);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001969
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001970 if (dbusFilename.empty() || dbusTimestamp.empty() ||
1971 dbusFilepath.empty())
1972 {
1973 messages::resourceNotFound(asyncResp->res,
1974 "LogEntry", logID);
1975 return;
1976 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001977
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001978 // Verify the file name parameter is correct
1979 if (fileName != dbusFilename)
1980 {
1981 messages::resourceNotFound(asyncResp->res,
1982 "LogEntry", logID);
1983 return;
1984 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001985
Myung Baed51c61b2024-09-13 10:35:34 -05001986 if (asyncResp->res.openFile(dbusFilepath) !=
1987 crow::OpenCode::Success)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001988 {
1989 messages::resourceNotFound(asyncResp->res,
1990 "LogEntry", logID);
1991 return;
1992 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001993
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001994 // Configure this to be a file download when accessed
1995 // from a browser
1996 asyncResp->res.addHeader(
1997 boost::beast::http::field::content_disposition,
1998 "attachment");
1999 };
Ed Tanousdeae6a72024-11-11 21:58:57 -08002000 dbus::utility::getAllProperties(
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002001 *crow::connections::systemBus, crashdumpObject,
2002 crashdumpPath + std::string("/") + logID,
2003 crashdumpInterface, std::move(getStoredLogCallback));
2004 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002005}
2006
Jason M. Billsc5a4c822022-01-06 15:51:23 -08002007enum class OEMDiagnosticType
2008{
2009 onDemand,
2010 telemetry,
2011 invalid,
2012};
2013
Ed Tanous26ccae32023-02-16 10:28:44 -08002014inline OEMDiagnosticType getOEMDiagnosticType(std::string_view oemDiagStr)
Jason M. Billsc5a4c822022-01-06 15:51:23 -08002015{
2016 if (oemDiagStr == "OnDemand")
2017 {
2018 return OEMDiagnosticType::onDemand;
2019 }
2020 if (oemDiagStr == "Telemetry")
2021 {
2022 return OEMDiagnosticType::telemetry;
2023 }
2024
2025 return OEMDiagnosticType::invalid;
2026}
2027
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002028inline void requestRoutesCrashdumpCollect(App& app)
2029{
George Liu0fda0f12021-11-16 10:06:17 +08002030 BMCWEB_ROUTE(
2031 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002032 "/redfish/v1/Systems/<str>/LogServices/Crashdump/Actions/LogService.CollectDiagnosticData/")
Myung Bae50d9f382025-06-13 09:40:18 -04002033 .privileges(redfish::privileges::
2034 postLogServiceSubOverComputerSystemLogServiceCollection)
Ed Tanous002d39b2022-05-31 08:59:27 -07002035 .methods(boost::beast::http::verb::post)(
2036 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07002037 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2038 const std::string& systemName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002039 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07002040 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002041 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07002042 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002043
2044 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous002d39b2022-05-31 08:59:27 -07002045 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002046 // Option currently returns no systems. TBD
2047 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2048 systemName);
2049 return;
2050 }
2051 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2052 {
2053 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2054 systemName);
2055 return;
2056 }
2057
2058 std::string diagnosticDataType;
2059 std::string oemDiagnosticDataType;
Patrick Williams504af5a2025-02-03 14:29:03 -05002060 if (!redfish::json_util::readJsonAction( //
2061 req, asyncResp->res, //
2062 "DiagnosticDataType", diagnosticDataType, //
Myung Baeafc474a2024-10-09 00:53:29 -07002063 "OEMDiagnosticDataType", oemDiagnosticDataType //
2064 ))
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002065 {
2066 return;
2067 }
2068
2069 if (diagnosticDataType != "OEM")
2070 {
2071 BMCWEB_LOG_ERROR(
2072 "Only OEM DiagnosticDataType supported for Crashdump");
2073 messages::actionParameterValueFormatError(
2074 asyncResp->res, diagnosticDataType,
2075 "DiagnosticDataType", "CollectDiagnosticData");
2076 return;
2077 }
2078
2079 OEMDiagnosticType oemDiagType =
2080 getOEMDiagnosticType(oemDiagnosticDataType);
2081
2082 std::string iface;
2083 std::string method;
2084 std::string taskMatchStr;
2085 if (oemDiagType == OEMDiagnosticType::onDemand)
2086 {
2087 iface = crashdumpOnDemandInterface;
2088 method = "GenerateOnDemandLog";
2089 taskMatchStr =
2090 "type='signal',"
2091 "interface='org.freedesktop.DBus.Properties',"
2092 "member='PropertiesChanged',"
2093 "arg0namespace='com.intel.crashdump'";
2094 }
2095 else if (oemDiagType == OEMDiagnosticType::telemetry)
2096 {
2097 iface = crashdumpTelemetryInterface;
2098 method = "GenerateTelemetryLog";
2099 taskMatchStr =
2100 "type='signal',"
2101 "interface='org.freedesktop.DBus.Properties',"
2102 "member='PropertiesChanged',"
2103 "arg0namespace='com.intel.crashdump'";
Ed Tanous002d39b2022-05-31 08:59:27 -07002104 }
2105 else
2106 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002107 BMCWEB_LOG_ERROR("Unsupported OEMDiagnosticDataType: {}",
2108 oemDiagnosticDataType);
2109 messages::actionParameterValueFormatError(
2110 asyncResp->res, oemDiagnosticDataType,
2111 "OEMDiagnosticDataType", "CollectDiagnosticData");
2112 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07002113 }
Ed Tanous1da66f72018-07-27 16:13:37 -07002114
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002115 auto collectCrashdumpCallback =
2116 [asyncResp, payload(task::Payload(req)),
2117 taskMatchStr](const boost::system::error_code& ec,
2118 const std::string&) mutable {
2119 if (ec)
2120 {
2121 if (ec.value() ==
2122 boost::system::errc::operation_not_supported)
2123 {
2124 messages::resourceInStandby(asyncResp->res);
2125 }
2126 else if (ec.value() == boost::system::errc::
2127 device_or_resource_busy)
2128 {
2129 messages::serviceTemporarilyUnavailable(
2130 asyncResp->res, "60");
2131 }
2132 else
2133 {
2134 messages::internalError(asyncResp->res);
2135 }
2136 return;
2137 }
2138 std::shared_ptr<task::TaskData> task =
2139 task::TaskData::createTask(
2140 [](const boost::system::error_code& ec2,
2141 sdbusplus::message_t&,
2142 const std::shared_ptr<task::TaskData>&
2143 taskData) {
2144 if (!ec2)
2145 {
2146 taskData->messages.emplace_back(
2147 messages::taskCompletedOK(
2148 std::to_string(
2149 taskData->index)));
2150 taskData->state = "Completed";
2151 }
2152 return task::completed;
2153 },
2154 taskMatchStr);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002155
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002156 task->startTimer(std::chrono::minutes(5));
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002157 task->payload.emplace(std::move(payload));
Chinmay Shripad Hegde29e2bdd2025-06-06 16:23:47 +05302158 task->populateResp(asyncResp->res);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002159 };
2160
Ed Tanous177612a2025-02-14 15:16:09 -08002161 dbus::utility::async_method_call(
2162 asyncResp, std::move(collectCrashdumpCallback),
2163 crashdumpObject, crashdumpPath, iface, method);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002164 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002165}
Ed Tanous1da66f72018-07-27 16:13:37 -07002166} // namespace redfish