blob: 3538f76dd2238bddfd375b54a0ce51df0821a33a [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
Oliver Brewkaf8ae8872025-10-13 19:05:29 +0200901inline void handleSystemsLogServiceCollectionGet(
902 crow::App& app, const crow::Request& req,
903 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
904 const std::string& systemName)
Ed Tanous1da66f72018-07-27 16:13:37 -0700905{
Oliver Brewkaf8ae8872025-10-13 19:05:29 +0200906 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
907 {
908 return;
909 }
910 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
911 {
912 // Option currently returns no systems. TBD
913 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
914 systemName);
915 return;
916 }
917 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
918 {
919 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
920 systemName);
921 return;
922 }
923
924 // Collections don't include the static data added by SubRoute
925 // because it has a duplicate entry for members
926 asyncResp->res.jsonValue["@odata.type"] =
927 "#LogServiceCollection.LogServiceCollection";
928 asyncResp->res.jsonValue["@odata.id"] = std::format(
929 "/redfish/v1/Systems/{}/LogServices", BMCWEB_REDFISH_SYSTEM_URI_NAME);
930 asyncResp->res.jsonValue["Name"] = "System Log Services Collection";
931 asyncResp->res.jsonValue["Description"] =
932 "Collection of LogServices for this Computer System";
933 nlohmann::json& logServiceArray = asyncResp->res.jsonValue["Members"];
934 logServiceArray = nlohmann::json::array();
935 nlohmann::json::object_t eventLog;
936 eventLog["@odata.id"] =
937 std::format("/redfish/v1/Systems/{}/LogServices/EventLog",
938 BMCWEB_REDFISH_SYSTEM_URI_NAME);
939 logServiceArray.emplace_back(std::move(eventLog));
940 if constexpr (BMCWEB_REDFISH_DUMP_LOG)
941 {
942 nlohmann::json::object_t dumpLog;
943 dumpLog["@odata.id"] =
944 std::format("/redfish/v1/Systems/{}/LogServices/Dump",
945 BMCWEB_REDFISH_SYSTEM_URI_NAME);
946 logServiceArray.emplace_back(std::move(dumpLog));
947 }
948
949 if constexpr (BMCWEB_REDFISH_CPU_LOG)
950 {
951 nlohmann::json::object_t crashdump;
952 crashdump["@odata.id"] =
953 std::format("/redfish/v1/Systems/{}/LogServices/Crashdump",
954 BMCWEB_REDFISH_SYSTEM_URI_NAME);
955 logServiceArray.emplace_back(std::move(crashdump));
956 }
957
958 if constexpr (BMCWEB_REDFISH_HOST_LOGGER)
959 {
960 nlohmann::json::object_t hostlogger;
961 hostlogger["@odata.id"] =
962 std::format("/redfish/v1/Systems/{}/LogServices/HostLogger",
963 BMCWEB_REDFISH_SYSTEM_URI_NAME);
964 logServiceArray.emplace_back(std::move(hostlogger));
965 }
966 asyncResp->res.jsonValue["Members@odata.count"] = logServiceArray.size();
967
968 constexpr std::array<std::string_view, 1> interfaces = {
969 "xyz.openbmc_project.State.Boot.PostCode"};
970 dbus::utility::getSubTreePaths(
971 "/", 0, interfaces,
972 [asyncResp](
973 const boost::system::error_code& ec,
974 const dbus::utility::MapperGetSubTreePathsResponse& subtreePath) {
975 if (ec)
Ed Tanous002d39b2022-05-31 08:59:27 -0700976 {
Oliver Brewkaf8ae8872025-10-13 19:05:29 +0200977 BMCWEB_LOG_ERROR("{}", ec);
Ed Tanous002d39b2022-05-31 08:59:27 -0700978 return;
979 }
Ed Tanous45ca1b82022-03-25 13:07:27 -0700980
Oliver Brewkaf8ae8872025-10-13 19:05:29 +0200981 for (const auto& pathStr : subtreePath)
Ed Tanous002d39b2022-05-31 08:59:27 -0700982 {
Oliver Brewkaf8ae8872025-10-13 19:05:29 +0200983 if (pathStr.find("PostCode") != std::string::npos)
984 {
985 nlohmann::json& logServiceArrayLocal =
986 asyncResp->res.jsonValue["Members"];
987 nlohmann::json::object_t member;
988 member["@odata.id"] = std::format(
989 "/redfish/v1/Systems/{}/LogServices/PostCodes",
990 BMCWEB_REDFISH_SYSTEM_URI_NAME);
991
992 logServiceArrayLocal.emplace_back(std::move(member));
993
994 asyncResp->res.jsonValue["Members@odata.count"] =
995 logServiceArrayLocal.size();
996 return;
997 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700998 }
Ed Tanous45ca1b82022-03-25 13:07:27 -0700999 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001000}
1001
Oliver Brewkaf8ae8872025-10-13 19:05:29 +02001002inline void handleManagersLogServicesCollectionGet(
Claire Weinanfdd26902022-03-01 14:18:25 -08001003 crow::App& app, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07001004 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1005 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08001006{
1007 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1008 {
1009 return;
1010 }
Ed Tanous253f11b2024-05-16 09:38:31 -07001011
1012 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
1013 {
1014 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
1015 return;
1016 }
1017
Claire Weinanfdd26902022-03-01 14:18:25 -08001018 // Collections don't include the static data added by SubRoute
1019 // because it has a duplicate entry for members
1020 asyncResp->res.jsonValue["@odata.type"] =
1021 "#LogServiceCollection.LogServiceCollection";
Ed Tanous253f11b2024-05-16 09:38:31 -07001022 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
1023 "/redfish/v1/Managers/{}/LogServices", BMCWEB_REDFISH_MANAGER_URI_NAME);
Claire Weinanfdd26902022-03-01 14:18:25 -08001024 asyncResp->res.jsonValue["Name"] = "Open BMC Log Services Collection";
1025 asyncResp->res.jsonValue["Description"] =
1026 "Collection of LogServices for this Manager";
1027 nlohmann::json& logServiceArray = asyncResp->res.jsonValue["Members"];
1028 logServiceArray = nlohmann::json::array();
1029
Ed Tanous25b54db2024-04-17 15:40:31 -07001030 if constexpr (BMCWEB_REDFISH_BMC_JOURNAL)
1031 {
1032 nlohmann::json::object_t journal;
Ed Tanous253f11b2024-05-16 09:38:31 -07001033 journal["@odata.id"] =
1034 boost::urls::format("/redfish/v1/Managers/{}/LogServices/Journal",
1035 BMCWEB_REDFISH_MANAGER_URI_NAME);
Ed Tanous25b54db2024-04-17 15:40:31 -07001036 logServiceArray.emplace_back(std::move(journal));
1037 }
Claire Weinanfdd26902022-03-01 14:18:25 -08001038
1039 asyncResp->res.jsonValue["Members@odata.count"] = logServiceArray.size();
1040
Ed Tanous25b54db2024-04-17 15:40:31 -07001041 if constexpr (BMCWEB_REDFISH_DUMP_LOG)
1042 {
1043 constexpr std::array<std::string_view, 1> interfaces = {
1044 "xyz.openbmc_project.Collection.DeleteAll"};
1045 dbus::utility::getSubTreePaths(
1046 "/xyz/openbmc_project/dump", 0, interfaces,
1047 [asyncResp](const boost::system::error_code& ec,
1048 const dbus::utility::MapperGetSubTreePathsResponse&
1049 subTreePaths) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001050 if (ec)
Ed Tanous25b54db2024-04-17 15:40:31 -07001051 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001052 BMCWEB_LOG_ERROR(
Oliver Brewkaf8ae8872025-10-13 19:05:29 +02001053 "handleManagersLogServicesCollectionGet respHandler got error {}",
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001054 ec);
1055 // Assume that getting an error simply means there are no
1056 // dump LogServices. Return without adding any error
1057 // response.
1058 return;
Ed Tanous25b54db2024-04-17 15:40:31 -07001059 }
Ed Tanous25b54db2024-04-17 15:40:31 -07001060
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001061 nlohmann::json& logServiceArrayLocal =
1062 asyncResp->res.jsonValue["Members"];
1063
1064 for (const std::string& path : subTreePaths)
1065 {
1066 if (path == "/xyz/openbmc_project/dump/bmc")
1067 {
1068 nlohmann::json::object_t member;
1069 member["@odata.id"] = boost::urls::format(
1070 "/redfish/v1/Managers/{}/LogServices/Dump",
1071 BMCWEB_REDFISH_MANAGER_URI_NAME);
1072 logServiceArrayLocal.emplace_back(std::move(member));
1073 }
1074 else if (path == "/xyz/openbmc_project/dump/faultlog")
1075 {
1076 nlohmann::json::object_t member;
1077 member["@odata.id"] = boost::urls::format(
1078 "/redfish/v1/Managers/{}/LogServices/FaultLog",
1079 BMCWEB_REDFISH_MANAGER_URI_NAME);
1080 logServiceArrayLocal.emplace_back(std::move(member));
1081 }
1082 }
1083
1084 asyncResp->res.jsonValue["Members@odata.count"] =
1085 logServiceArrayLocal.size();
1086 });
Ed Tanous25b54db2024-04-17 15:40:31 -07001087 }
Claire Weinanfdd26902022-03-01 14:18:25 -08001088}
1089
Oliver Brewkaa93a2932025-10-10 00:53:02 +02001090inline void handleSystemsEventLogServiceGet(
1091 crow::App& app, const crow::Request& req,
1092 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1093 const std::string& systemName)
1094{
1095 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1096 {
1097 return;
1098 }
1099 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1100 {
1101 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1102 systemName);
1103 return;
1104 }
1105 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1106 {
1107 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1108 systemName);
1109 return;
1110 }
1111 eventlog_utils::handleSystemsAndManagersEventLogServiceGet(
1112 asyncResp, eventlog_utils::LogServiceParent::Systems);
1113}
1114
Patrick Williams504af5a2025-02-03 14:29:03 -05001115inline void getDumpServiceInfo(
1116 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1117 const std::string& dumpType)
Claire Weinanfdd26902022-03-01 14:18:25 -08001118{
1119 std::string dumpPath;
Ed Tanous539d8c62024-06-19 14:38:27 -07001120 log_service::OverWritePolicy overWritePolicy =
1121 log_service::OverWritePolicy::Invalid;
Claire Weinanfdd26902022-03-01 14:18:25 -08001122 bool collectDiagnosticDataSupported = false;
1123
1124 if (dumpType == "BMC")
1125 {
Ed Tanous253f11b2024-05-16 09:38:31 -07001126 dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/Dump",
1127 BMCWEB_REDFISH_MANAGER_URI_NAME);
Ed Tanous539d8c62024-06-19 14:38:27 -07001128 overWritePolicy = log_service::OverWritePolicy::WrapsWhenFull;
Claire Weinanfdd26902022-03-01 14:18:25 -08001129 collectDiagnosticDataSupported = true;
1130 }
1131 else if (dumpType == "FaultLog")
1132 {
Ed Tanous253f11b2024-05-16 09:38:31 -07001133 dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/FaultLog",
1134 BMCWEB_REDFISH_MANAGER_URI_NAME);
Ed Tanous539d8c62024-06-19 14:38:27 -07001135 overWritePolicy = log_service::OverWritePolicy::Unknown;
Claire Weinanfdd26902022-03-01 14:18:25 -08001136 collectDiagnosticDataSupported = false;
1137 }
1138 else if (dumpType == "System")
1139 {
Ed Tanous253f11b2024-05-16 09:38:31 -07001140 dumpPath = std::format("/redfish/v1/Systems/{}/LogServices/Dump",
1141 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanous539d8c62024-06-19 14:38:27 -07001142 overWritePolicy = log_service::OverWritePolicy::WrapsWhenFull;
Claire Weinanfdd26902022-03-01 14:18:25 -08001143 collectDiagnosticDataSupported = true;
1144 }
1145 else
1146 {
Ed Tanous62598e32023-07-17 17:06:25 -07001147 BMCWEB_LOG_ERROR("getDumpServiceInfo() invalid dump type: {}",
1148 dumpType);
Claire Weinanfdd26902022-03-01 14:18:25 -08001149 messages::internalError(asyncResp->res);
1150 return;
1151 }
1152
1153 asyncResp->res.jsonValue["@odata.id"] = dumpPath;
1154 asyncResp->res.jsonValue["@odata.type"] = "#LogService.v1_2_0.LogService";
1155 asyncResp->res.jsonValue["Name"] = "Dump LogService";
1156 asyncResp->res.jsonValue["Description"] = dumpType + " Dump LogService";
1157 asyncResp->res.jsonValue["Id"] = std::filesystem::path(dumpPath).filename();
Ed Tanous539d8c62024-06-19 14:38:27 -07001158 asyncResp->res.jsonValue["OverWritePolicy"] = overWritePolicy;
Claire Weinanfdd26902022-03-01 14:18:25 -08001159
1160 std::pair<std::string, std::string> redfishDateTimeOffset =
Ed Tanous2b829372022-08-03 14:22:34 -07001161 redfish::time_utils::getDateTimeOffsetNow();
Claire Weinanfdd26902022-03-01 14:18:25 -08001162 asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
1163 asyncResp->res.jsonValue["DateTimeLocalOffset"] =
1164 redfishDateTimeOffset.second;
1165
1166 asyncResp->res.jsonValue["Entries"]["@odata.id"] = dumpPath + "/Entries";
Claire Weinanfdd26902022-03-01 14:18:25 -08001167
1168 if (collectDiagnosticDataSupported)
1169 {
1170 asyncResp->res.jsonValue["Actions"]["#LogService.CollectDiagnosticData"]
1171 ["target"] =
1172 dumpPath + "/Actions/LogService.CollectDiagnosticData";
1173 }
Claire Weinan0d946212022-07-13 19:40:19 -07001174
Corey Ethington08fad5d2025-07-31 12:14:27 -04001175 etag_utils::setEtagOmitDateTimeHandler(asyncResp);
1176
Claire Weinan0d946212022-07-13 19:40:19 -07001177 constexpr std::array<std::string_view, 1> interfaces = {deleteAllInterface};
1178 dbus::utility::getSubTreePaths(
1179 "/xyz/openbmc_project/dump", 0, interfaces,
1180 [asyncResp, dumpType, dumpPath](
1181 const boost::system::error_code& ec,
1182 const dbus::utility::MapperGetSubTreePathsResponse& subTreePaths) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001183 if (ec)
Claire Weinan0d946212022-07-13 19:40:19 -07001184 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001185 BMCWEB_LOG_ERROR("getDumpServiceInfo respHandler got error {}",
1186 ec);
1187 // Assume that getting an error simply means there are no dump
1188 // LogServices. Return without adding any error response.
1189 return;
Claire Weinan0d946212022-07-13 19:40:19 -07001190 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001191 std::string dbusDumpPath = getDumpPath(dumpType);
1192 for (const std::string& path : subTreePaths)
1193 {
1194 if (path == dbusDumpPath)
1195 {
1196 asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"]
1197 ["target"] =
1198 dumpPath + "/Actions/LogService.ClearLog";
1199 break;
1200 }
1201 }
1202 });
Claire Weinanfdd26902022-03-01 14:18:25 -08001203}
1204
1205inline void handleLogServicesDumpServiceGet(
1206 crow::App& app, const std::string& dumpType, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07001207 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1208 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08001209{
1210 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1211 {
1212 return;
1213 }
Ed Tanous253f11b2024-05-16 09:38:31 -07001214
1215 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
1216 {
1217 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
1218 return;
1219 }
1220
Claire Weinanfdd26902022-03-01 14:18:25 -08001221 getDumpServiceInfo(asyncResp, dumpType);
1222}
1223
Ed Tanous22d268c2022-05-19 09:39:07 -07001224inline void handleLogServicesDumpServiceComputerSystemGet(
1225 crow::App& app, const crow::Request& req,
1226 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1227 const std::string& chassisId)
1228{
1229 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1230 {
1231 return;
1232 }
Ed Tanous253f11b2024-05-16 09:38:31 -07001233 if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous22d268c2022-05-19 09:39:07 -07001234 {
1235 messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
1236 return;
1237 }
1238 getDumpServiceInfo(asyncResp, "System");
1239}
1240
Claire Weinanfdd26902022-03-01 14:18:25 -08001241inline void handleLogServicesDumpEntriesCollectionGet(
1242 crow::App& app, const std::string& dumpType, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07001243 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1244 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08001245{
1246 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1247 {
1248 return;
1249 }
Ed Tanous253f11b2024-05-16 09:38:31 -07001250
1251 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
1252 {
1253 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
1254 return;
1255 }
Claire Weinanfdd26902022-03-01 14:18:25 -08001256 getDumpEntryCollection(asyncResp, dumpType);
1257}
1258
Ed Tanous22d268c2022-05-19 09:39:07 -07001259inline void handleLogServicesDumpEntriesCollectionComputerSystemGet(
1260 crow::App& app, const crow::Request& req,
1261 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1262 const std::string& chassisId)
1263{
1264 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1265 {
1266 return;
1267 }
Ed Tanous253f11b2024-05-16 09:38:31 -07001268 if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous22d268c2022-05-19 09:39:07 -07001269 {
1270 messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
1271 return;
1272 }
1273 getDumpEntryCollection(asyncResp, "System");
1274}
1275
Claire Weinanfdd26902022-03-01 14:18:25 -08001276inline void handleLogServicesDumpEntryGet(
1277 crow::App& app, const std::string& dumpType, const crow::Request& req,
1278 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous253f11b2024-05-16 09:38:31 -07001279 const std::string& managerId, const std::string& dumpId)
Claire Weinanfdd26902022-03-01 14:18:25 -08001280{
1281 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1282 {
1283 return;
1284 }
Ed Tanous253f11b2024-05-16 09:38:31 -07001285 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
1286 {
1287 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
1288 return;
1289 }
Claire Weinanfdd26902022-03-01 14:18:25 -08001290 getDumpEntryById(asyncResp, dumpId, dumpType);
1291}
Carson Labrado168d1b12023-03-27 17:04:46 +00001292
Ed Tanous22d268c2022-05-19 09:39:07 -07001293inline void handleLogServicesDumpEntryComputerSystemGet(
1294 crow::App& app, const crow::Request& req,
1295 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1296 const std::string& chassisId, const std::string& dumpId)
1297{
1298 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1299 {
1300 return;
1301 }
Ed Tanous253f11b2024-05-16 09:38:31 -07001302 if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous22d268c2022-05-19 09:39:07 -07001303 {
1304 messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
1305 return;
1306 }
1307 getDumpEntryById(asyncResp, dumpId, "System");
1308}
Claire Weinanfdd26902022-03-01 14:18:25 -08001309
1310inline void handleLogServicesDumpEntryDelete(
1311 crow::App& app, const std::string& dumpType, const crow::Request& req,
1312 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous253f11b2024-05-16 09:38:31 -07001313 const std::string& managerId, const std::string& dumpId)
Claire Weinanfdd26902022-03-01 14:18:25 -08001314{
1315 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1316 {
1317 return;
1318 }
Ed Tanous253f11b2024-05-16 09:38:31 -07001319
1320 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
1321 {
1322 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
1323 return;
1324 }
Claire Weinanfdd26902022-03-01 14:18:25 -08001325 deleteDumpEntry(asyncResp, dumpId, dumpType);
1326}
1327
Ed Tanous22d268c2022-05-19 09:39:07 -07001328inline void handleLogServicesDumpEntryComputerSystemDelete(
1329 crow::App& app, const crow::Request& req,
1330 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1331 const std::string& chassisId, const std::string& dumpId)
1332{
1333 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1334 {
1335 return;
1336 }
Ed Tanous253f11b2024-05-16 09:38:31 -07001337 if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous22d268c2022-05-19 09:39:07 -07001338 {
1339 messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
1340 return;
1341 }
1342 deleteDumpEntry(asyncResp, dumpId, "System");
1343}
1344
Carson Labrado168d1b12023-03-27 17:04:46 +00001345inline void handleLogServicesDumpEntryDownloadGet(
1346 crow::App& app, const std::string& dumpType, const crow::Request& req,
1347 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous253f11b2024-05-16 09:38:31 -07001348 const std::string& managerId, const std::string& dumpId)
Carson Labrado168d1b12023-03-27 17:04:46 +00001349{
1350 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1351 {
1352 return;
1353 }
Ed Tanous253f11b2024-05-16 09:38:31 -07001354
1355 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
1356 {
1357 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
1358 return;
1359 }
Carson Labrado168d1b12023-03-27 17:04:46 +00001360 downloadDumpEntry(asyncResp, dumpId, dumpType);
1361}
1362
Claire Weinanfdd26902022-03-01 14:18:25 -08001363inline void handleLogServicesDumpCollectDiagnosticDataPost(
1364 crow::App& app, const std::string& dumpType, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07001365 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1366 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08001367{
1368 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1369 {
1370 return;
1371 }
Ed Tanous253f11b2024-05-16 09:38:31 -07001372 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
1373 {
1374 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
1375 return;
1376 }
1377
Claire Weinanfdd26902022-03-01 14:18:25 -08001378 createDump(asyncResp, req, dumpType);
1379}
1380
Ed Tanous22d268c2022-05-19 09:39:07 -07001381inline void handleLogServicesDumpCollectDiagnosticDataComputerSystemPost(
1382 crow::App& app, const crow::Request& req,
1383 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08001384 const std::string& systemName)
Ed Tanous22d268c2022-05-19 09:39:07 -07001385{
1386 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1387 {
1388 return;
1389 }
Ed Tanous7f3e84a2022-12-28 16:22:54 -08001390
Ed Tanous25b54db2024-04-17 15:40:31 -07001391 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous22d268c2022-05-19 09:39:07 -07001392 {
Ed Tanous7f3e84a2022-12-28 16:22:54 -08001393 // Option currently returns no systems. TBD
1394 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1395 systemName);
1396 return;
1397 }
Ed Tanous253f11b2024-05-16 09:38:31 -07001398 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous7f3e84a2022-12-28 16:22:54 -08001399 {
1400 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1401 systemName);
Ed Tanous22d268c2022-05-19 09:39:07 -07001402 return;
1403 }
1404 createDump(asyncResp, req, "System");
1405}
1406
Claire Weinanfdd26902022-03-01 14:18:25 -08001407inline void handleLogServicesDumpClearLogPost(
1408 crow::App& app, const std::string& dumpType, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07001409 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1410 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08001411{
1412 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1413 {
1414 return;
1415 }
Ed Tanous253f11b2024-05-16 09:38:31 -07001416
1417 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
1418 {
1419 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
1420 return;
1421 }
Claire Weinanfdd26902022-03-01 14:18:25 -08001422 clearDump(asyncResp, dumpType);
1423}
1424
Ed Tanous22d268c2022-05-19 09:39:07 -07001425inline void handleLogServicesDumpClearLogComputerSystemPost(
1426 crow::App& app, const crow::Request& req,
1427 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08001428 const std::string& systemName)
Ed Tanous22d268c2022-05-19 09:39:07 -07001429{
1430 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1431 {
1432 return;
1433 }
Ed Tanous25b54db2024-04-17 15:40:31 -07001434 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous22d268c2022-05-19 09:39:07 -07001435 {
Ed Tanous7f3e84a2022-12-28 16:22:54 -08001436 // Option currently returns no systems. TBD
1437 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1438 systemName);
1439 return;
1440 }
Ed Tanous253f11b2024-05-16 09:38:31 -07001441 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous7f3e84a2022-12-28 16:22:54 -08001442 {
1443 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1444 systemName);
Ed Tanous22d268c2022-05-19 09:39:07 -07001445 return;
1446 }
1447 clearDump(asyncResp, "System");
1448}
1449
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001450inline void requestRoutesBMCDumpService(App& app)
1451{
Ed Tanous253f11b2024-05-16 09:38:31 -07001452 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/Dump/")
Ed Tanoused398212021-06-09 17:05:54 -07001453 .privileges(redfish::privileges::getLogService)
Claire Weinanfdd26902022-03-01 14:18:25 -08001454 .methods(boost::beast::http::verb::get)(std::bind_front(
1455 handleLogServicesDumpServiceGet, std::ref(app), "BMC"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001456}
1457
1458inline void requestRoutesBMCDumpEntryCollection(App& app)
1459{
Ed Tanous253f11b2024-05-16 09:38:31 -07001460 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/")
Ed Tanoused398212021-06-09 17:05:54 -07001461 .privileges(redfish::privileges::getLogEntryCollection)
Claire Weinanfdd26902022-03-01 14:18:25 -08001462 .methods(boost::beast::http::verb::get)(std::bind_front(
1463 handleLogServicesDumpEntriesCollectionGet, std::ref(app), "BMC"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001464}
1465
1466inline void requestRoutesBMCDumpEntry(App& app)
1467{
1468 BMCWEB_ROUTE(app,
Ed Tanous253f11b2024-05-16 09:38:31 -07001469 "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001470 .privileges(redfish::privileges::getLogEntry)
Claire Weinanfdd26902022-03-01 14:18:25 -08001471 .methods(boost::beast::http::verb::get)(std::bind_front(
1472 handleLogServicesDumpEntryGet, std::ref(app), "BMC"));
1473
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001474 BMCWEB_ROUTE(app,
Ed Tanous253f11b2024-05-16 09:38:31 -07001475 "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001476 .privileges(redfish::privileges::deleteLogEntry)
Claire Weinanfdd26902022-03-01 14:18:25 -08001477 .methods(boost::beast::http::verb::delete_)(std::bind_front(
1478 handleLogServicesDumpEntryDelete, std::ref(app), "BMC"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001479}
1480
Carson Labrado168d1b12023-03-27 17:04:46 +00001481inline void requestRoutesBMCDumpEntryDownload(App& app)
1482{
1483 BMCWEB_ROUTE(
1484 app,
Ed Tanous253f11b2024-05-16 09:38:31 -07001485 "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/attachment/")
Carson Labrado168d1b12023-03-27 17:04:46 +00001486 .privileges(redfish::privileges::getLogEntry)
1487 .methods(boost::beast::http::verb::get)(std::bind_front(
1488 handleLogServicesDumpEntryDownloadGet, std::ref(app), "BMC"));
1489}
1490
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001491inline void requestRoutesBMCDumpCreate(App& app)
1492{
George Liu0fda0f12021-11-16 10:06:17 +08001493 BMCWEB_ROUTE(
1494 app,
Ed Tanous253f11b2024-05-16 09:38:31 -07001495 "/redfish/v1/Managers/<str>/LogServices/Dump/Actions/LogService.CollectDiagnosticData/")
Ed Tanoused398212021-06-09 17:05:54 -07001496 .privileges(redfish::privileges::postLogService)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001497 .methods(boost::beast::http::verb::post)(
Claire Weinanfdd26902022-03-01 14:18:25 -08001498 std::bind_front(handleLogServicesDumpCollectDiagnosticDataPost,
1499 std::ref(app), "BMC"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001500}
1501
1502inline void requestRoutesBMCDumpClear(App& app)
1503{
George Liu0fda0f12021-11-16 10:06:17 +08001504 BMCWEB_ROUTE(
1505 app,
Ed Tanous253f11b2024-05-16 09:38:31 -07001506 "/redfish/v1/Managers/<str>/LogServices/Dump/Actions/LogService.ClearLog/")
Ed Tanoused398212021-06-09 17:05:54 -07001507 .privileges(redfish::privileges::postLogService)
Claire Weinanfdd26902022-03-01 14:18:25 -08001508 .methods(boost::beast::http::verb::post)(std::bind_front(
1509 handleLogServicesDumpClearLogPost, std::ref(app), "BMC"));
1510}
1511
1512inline void requestRoutesFaultLogDumpService(App& app)
1513{
Ed Tanous253f11b2024-05-16 09:38:31 -07001514 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/")
Claire Weinanfdd26902022-03-01 14:18:25 -08001515 .privileges(redfish::privileges::getLogService)
1516 .methods(boost::beast::http::verb::get)(std::bind_front(
1517 handleLogServicesDumpServiceGet, std::ref(app), "FaultLog"));
1518}
1519
1520inline void requestRoutesFaultLogDumpEntryCollection(App& app)
1521{
Ed Tanous253f11b2024-05-16 09:38:31 -07001522 BMCWEB_ROUTE(app,
1523 "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/")
Claire Weinanfdd26902022-03-01 14:18:25 -08001524 .privileges(redfish::privileges::getLogEntryCollection)
1525 .methods(boost::beast::http::verb::get)(
1526 std::bind_front(handleLogServicesDumpEntriesCollectionGet,
1527 std::ref(app), "FaultLog"));
1528}
1529
1530inline void requestRoutesFaultLogDumpEntry(App& app)
1531{
Ed Tanous253f11b2024-05-16 09:38:31 -07001532 BMCWEB_ROUTE(
1533 app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/<str>/")
Claire Weinanfdd26902022-03-01 14:18:25 -08001534 .privileges(redfish::privileges::getLogEntry)
1535 .methods(boost::beast::http::verb::get)(std::bind_front(
1536 handleLogServicesDumpEntryGet, std::ref(app), "FaultLog"));
1537
Ed Tanous253f11b2024-05-16 09:38:31 -07001538 BMCWEB_ROUTE(
1539 app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/<str>/")
Claire Weinanfdd26902022-03-01 14:18:25 -08001540 .privileges(redfish::privileges::deleteLogEntry)
1541 .methods(boost::beast::http::verb::delete_)(std::bind_front(
1542 handleLogServicesDumpEntryDelete, std::ref(app), "FaultLog"));
1543}
1544
1545inline void requestRoutesFaultLogDumpClear(App& app)
1546{
1547 BMCWEB_ROUTE(
1548 app,
Ed Tanous253f11b2024-05-16 09:38:31 -07001549 "/redfish/v1/Managers/<str>/LogServices/FaultLog/Actions/LogService.ClearLog/")
Claire Weinanfdd26902022-03-01 14:18:25 -08001550 .privileges(redfish::privileges::postLogService)
1551 .methods(boost::beast::http::verb::post)(std::bind_front(
1552 handleLogServicesDumpClearLogPost, std::ref(app), "FaultLog"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001553}
1554
1555inline void requestRoutesSystemDumpService(App& app)
1556{
Ed Tanous22d268c2022-05-19 09:39:07 -07001557 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Dump/")
Ed Tanoused398212021-06-09 17:05:54 -07001558 .privileges(redfish::privileges::getLogService)
Claire Weinan6ab9ad52022-08-12 18:20:17 -07001559 .methods(boost::beast::http::verb::get)(std::bind_front(
Ed Tanous22d268c2022-05-19 09:39:07 -07001560 handleLogServicesDumpServiceComputerSystemGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001561}
1562
1563inline void requestRoutesSystemDumpEntryCollection(App& app)
1564{
Ed Tanous22d268c2022-05-19 09:39:07 -07001565 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/")
Ed Tanoused398212021-06-09 17:05:54 -07001566 .privileges(redfish::privileges::getLogEntryCollection)
Ed Tanous22d268c2022-05-19 09:39:07 -07001567 .methods(boost::beast::http::verb::get)(std::bind_front(
1568 handleLogServicesDumpEntriesCollectionComputerSystemGet,
1569 std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001570}
1571
1572inline void requestRoutesSystemDumpEntry(App& app)
1573{
1574 BMCWEB_ROUTE(app,
Ed Tanous22d268c2022-05-19 09:39:07 -07001575 "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001576 .privileges(redfish::privileges::getLogEntry)
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 handleLogServicesDumpEntryComputerSystemGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001579
1580 BMCWEB_ROUTE(app,
Ed Tanous22d268c2022-05-19 09:39:07 -07001581 "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001582 .privileges(redfish::privileges::deleteLogEntry)
Claire Weinan6ab9ad52022-08-12 18:20:17 -07001583 .methods(boost::beast::http::verb::delete_)(std::bind_front(
Ed Tanous22d268c2022-05-19 09:39:07 -07001584 handleLogServicesDumpEntryComputerSystemDelete, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001585}
1586
1587inline void requestRoutesSystemDumpCreate(App& app)
1588{
George Liu0fda0f12021-11-16 10:06:17 +08001589 BMCWEB_ROUTE(
1590 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07001591 "/redfish/v1/Systems/<str>/LogServices/Dump/Actions/LogService.CollectDiagnosticData/")
Abhishek Patelfff6a4d2021-07-21 11:29:45 -05001592 .privileges(redfish::privileges::
1593 postLogServiceSubOverComputerSystemLogServiceCollection)
Ed Tanous22d268c2022-05-19 09:39:07 -07001594 .methods(boost::beast::http::verb::post)(std::bind_front(
1595 handleLogServicesDumpCollectDiagnosticDataComputerSystemPost,
1596 std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001597}
1598
1599inline void requestRoutesSystemDumpClear(App& app)
1600{
George Liu0fda0f12021-11-16 10:06:17 +08001601 BMCWEB_ROUTE(
1602 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07001603 "/redfish/v1/Systems/<str>/LogServices/Dump/Actions/LogService.ClearLog/")
Abhishek Patelfff6a4d2021-07-21 11:29:45 -05001604 .privileges(redfish::privileges::
1605 postLogServiceSubOverComputerSystemLogServiceCollection)
Claire Weinan6ab9ad52022-08-12 18:20:17 -07001606 .methods(boost::beast::http::verb::post)(std::bind_front(
Ed Tanous22d268c2022-05-19 09:39:07 -07001607 handleLogServicesDumpClearLogComputerSystemPost, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001608}
1609
1610inline void requestRoutesCrashdumpService(App& app)
1611{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001612 /**
1613 * Functions triggers appropriate requests on DBus
1614 */
Ed Tanous22d268c2022-05-19 09:39:07 -07001615 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Crashdump/")
Myung Bae50d9f382025-06-13 09:40:18 -04001616 .privileges(redfish::privileges::getLogService)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001617 .methods(
1618 boost::beast::http::verb::
1619 get)([&app](const crow::Request& req,
1620 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1621 const std::string& systemName) {
1622 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1623 {
1624 return;
1625 }
1626 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1627 {
1628 // Option currently returns no systems. TBD
1629 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1630 systemName);
1631 return;
1632 }
1633 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1634 {
1635 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1636 systemName);
1637 return;
1638 }
Ed Tanous22d268c2022-05-19 09:39:07 -07001639
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001640 // Copy over the static data to include the entries added by
1641 // SubRoute
1642 asyncResp->res.jsonValue["@odata.id"] =
1643 std::format("/redfish/v1/Systems/{}/LogServices/Crashdump",
1644 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1645 asyncResp->res.jsonValue["@odata.type"] =
1646 "#LogService.v1_2_0.LogService";
1647 asyncResp->res.jsonValue["Name"] = "Open BMC Oem Crashdump Service";
1648 asyncResp->res.jsonValue["Description"] = "Oem Crashdump Service";
1649 asyncResp->res.jsonValue["Id"] = "Crashdump";
1650 asyncResp->res.jsonValue["OverWritePolicy"] =
1651 log_service::OverWritePolicy::WrapsWhenFull;
1652 asyncResp->res.jsonValue["MaxNumberOfRecords"] = 3;
Tejas Patil7c8c4052021-06-04 17:43:14 +05301653
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001654 std::pair<std::string, std::string> redfishDateTimeOffset =
1655 redfish::time_utils::getDateTimeOffsetNow();
1656 asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
1657 asyncResp->res.jsonValue["DateTimeLocalOffset"] =
1658 redfishDateTimeOffset.second;
Tejas Patil7c8c4052021-06-04 17:43:14 +05301659
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001660 asyncResp->res.jsonValue["Entries"]["@odata.id"] = std::format(
1661 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries",
1662 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1663 asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"]
1664 ["target"] = std::format(
1665 "/redfish/v1/Systems/{}/LogServices/Crashdump/Actions/LogService.ClearLog",
1666 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1667 asyncResp->res
1668 .jsonValue["Actions"]["#LogService.CollectDiagnosticData"]
1669 ["target"] = std::format(
1670 "/redfish/v1/Systems/{}/LogServices/Crashdump/Actions/LogService.CollectDiagnosticData",
1671 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Corey Ethington08fad5d2025-07-31 12:14:27 -04001672
1673 etag_utils::setEtagOmitDateTimeHandler(asyncResp);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001674 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001675}
1676
Ed Tanous8e4736b2025-08-19 10:14:02 -07001677inline void requestRoutesCrashdumpClear(App& app)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001678{
George Liu0fda0f12021-11-16 10:06:17 +08001679 BMCWEB_ROUTE(
1680 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07001681 "/redfish/v1/Systems/<str>/LogServices/Crashdump/Actions/LogService.ClearLog/")
Myung Bae50d9f382025-06-13 09:40:18 -04001682 .privileges(redfish::privileges::
1683 postLogServiceSubOverComputerSystemLogServiceCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001684 .methods(boost::beast::http::verb::post)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07001685 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07001686 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1687 const std::string& systemName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001688 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1689 {
1690 return;
1691 }
1692 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1693 {
1694 // Option currently returns no systems. TBD
1695 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1696 systemName);
1697 return;
1698 }
1699 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1700 {
1701 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1702 systemName);
1703 return;
1704 }
Ed Tanous177612a2025-02-14 15:16:09 -08001705 dbus::utility::async_method_call(
1706 asyncResp,
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001707 [asyncResp](const boost::system::error_code& ec,
1708 const std::string&) {
1709 if (ec)
1710 {
1711 messages::internalError(asyncResp->res);
1712 return;
1713 }
1714 messages::success(asyncResp->res);
1715 },
1716 crashdumpObject, crashdumpPath, deleteAllInterface,
1717 "DeleteAll");
1718 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001719}
Jason M. Bills5b61b5e2019-10-16 10:59:02 -07001720
Patrick Williams504af5a2025-02-03 14:29:03 -05001721inline void logCrashdumpEntry(
1722 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1723 const std::string& logID, nlohmann::json& logEntryJson)
Jason M. Billse855dd22019-10-08 11:37:48 -07001724{
Johnathan Mantey043a0532020-03-10 17:15:28 -07001725 auto getStoredLogCallback =
Ed Tanousb9d36b42022-02-26 21:42:46 -08001726 [asyncResp, logID,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001727 &logEntryJson](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001728 const dbus::utility::DBusPropertiesMap& params) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001729 if (ec)
1730 {
1731 BMCWEB_LOG_DEBUG("failed to get log ec: {}", ec.message());
1732 if (ec.value() ==
1733 boost::system::linux_error::bad_request_descriptor)
1734 {
1735 messages::resourceNotFound(asyncResp->res, "LogEntry",
1736 logID);
1737 }
1738 else
1739 {
1740 messages::internalError(asyncResp->res);
1741 }
1742 return;
1743 }
1744
1745 std::string timestamp{};
1746 std::string filename{};
1747 std::string logfile{};
1748 parseCrashdumpParameters(params, filename, timestamp, logfile);
1749
1750 if (filename.empty() || timestamp.empty())
Jason M. Bills1ddcf012019-11-26 14:59:21 -08001751 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001752 messages::resourceNotFound(asyncResp->res, "LogEntry", logID);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001753 return;
1754 }
1755
1756 std::string crashdumpURI =
1757 std::format(
1758 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries/",
1759 BMCWEB_REDFISH_SYSTEM_URI_NAME) +
1760 logID + "/" + filename;
1761 nlohmann::json::object_t logEntry;
1762 logEntry["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
1763 logEntry["@odata.id"] = boost::urls::format(
1764 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries/{}",
1765 BMCWEB_REDFISH_SYSTEM_URI_NAME, logID);
1766 logEntry["Name"] = "CPU Crashdump";
1767 logEntry["Id"] = logID;
1768 logEntry["EntryType"] = log_entry::LogEntryType::Oem;
1769 logEntry["AdditionalDataURI"] = std::move(crashdumpURI);
1770 logEntry["DiagnosticDataType"] = "OEM";
1771 logEntry["OEMDiagnosticDataType"] = "PECICrashdump";
1772 logEntry["Created"] = std::move(timestamp);
1773
1774 // If logEntryJson references an array of LogEntry resources
1775 // ('Members' list), then push this as a new entry, otherwise set it
1776 // directly
1777 if (logEntryJson.is_array())
1778 {
1779 logEntryJson.push_back(logEntry);
1780 asyncResp->res.jsonValue["Members@odata.count"] =
1781 logEntryJson.size();
Jason M. Bills2b20ef62022-01-06 15:48:07 -08001782 }
1783 else
1784 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001785 logEntryJson.update(logEntry);
Jason M. Bills2b20ef62022-01-06 15:48:07 -08001786 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001787 };
Ed Tanousdeae6a72024-11-11 21:58:57 -08001788 dbus::utility::getAllProperties(
1789 crashdumpObject, crashdumpPath + std::string("/") + logID,
1790 crashdumpInterface, std::move(getStoredLogCallback));
Jason M. Billse855dd22019-10-08 11:37:48 -07001791}
1792
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001793inline void requestRoutesCrashdumpEntryCollection(App& app)
Ed Tanous1da66f72018-07-27 16:13:37 -07001794{
Ed Tanous1da66f72018-07-27 16:13:37 -07001795 /**
1796 * Functions triggers appropriate requests on DBus
1797 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001798 BMCWEB_ROUTE(app,
Ed Tanous22d268c2022-05-19 09:39:07 -07001799 "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/")
Myung Bae50d9f382025-06-13 09:40:18 -04001800 .privileges(redfish::privileges::getLogEntryCollection)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001801 .methods(
1802 boost::beast::http::verb::
1803 get)([&app](const crow::Request& req,
1804 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1805 const std::string& systemName) {
1806 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous45ca1b82022-03-25 13:07:27 -07001807 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001808 return;
Ed Tanous45ca1b82022-03-25 13:07:27 -07001809 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001810 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous002d39b2022-05-31 08:59:27 -07001811 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001812 // Option currently returns no systems. TBD
1813 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1814 systemName);
1815 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07001816 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001817 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1818 {
1819 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1820 systemName);
1821 return;
1822 }
1823
1824 constexpr std::array<std::string_view, 1> interfaces = {
1825 crashdumpInterface};
1826 dbus::utility::getSubTreePaths(
1827 "/", 0, interfaces,
1828 [asyncResp](const boost::system::error_code& ec,
1829 const std::vector<std::string>& resp) {
1830 if (ec)
1831 {
1832 if (ec.value() !=
1833 boost::system::errc::no_such_file_or_directory)
1834 {
1835 BMCWEB_LOG_DEBUG("failed to get entries ec: {}",
1836 ec.message());
1837 messages::internalError(asyncResp->res);
1838 return;
1839 }
1840 }
1841 asyncResp->res.jsonValue["@odata.type"] =
1842 "#LogEntryCollection.LogEntryCollection";
1843 asyncResp->res.jsonValue["@odata.id"] = std::format(
1844 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries",
1845 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1846 asyncResp->res.jsonValue["Name"] =
1847 "Open BMC Crashdump Entries";
1848 asyncResp->res.jsonValue["Description"] =
1849 "Collection of Crashdump Entries";
1850 asyncResp->res.jsonValue["Members"] =
1851 nlohmann::json::array();
1852 asyncResp->res.jsonValue["Members@odata.count"] = 0;
1853
1854 for (const std::string& path : resp)
1855 {
1856 const sdbusplus::message::object_path objPath(path);
1857 // Get the log ID
1858 std::string logID = objPath.filename();
1859 if (logID.empty())
1860 {
1861 continue;
1862 }
1863 // Add the log entry to the array
1864 logCrashdumpEntry(asyncResp, logID,
1865 asyncResp->res.jsonValue["Members"]);
1866 }
1867 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001868 });
1869}
Ed Tanous1da66f72018-07-27 16:13:37 -07001870
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001871inline void requestRoutesCrashdumpEntry(App& app)
Ed Tanous1da66f72018-07-27 16:13:37 -07001872{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001873 BMCWEB_ROUTE(
Ed Tanous22d268c2022-05-19 09:39:07 -07001874 app, "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/<str>/")
Myung Bae50d9f382025-06-13 09:40:18 -04001875 .privileges(redfish::privileges::getLogEntry)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001876 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07001877 [&app](const crow::Request& req,
1878 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -07001879 const std::string& systemName, const std::string& param) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001880 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1881 {
1882 return;
1883 }
1884 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1885 {
1886 // Option currently returns no systems. TBD
1887 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1888 systemName);
1889 return;
1890 }
1891 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1892 {
1893 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1894 systemName);
1895 return;
1896 }
1897 const std::string& logID = param;
1898 logCrashdumpEntry(asyncResp, logID, asyncResp->res.jsonValue);
1899 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001900}
Ed Tanous1da66f72018-07-27 16:13:37 -07001901
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001902inline void requestRoutesCrashdumpFile(App& app)
1903{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001904 BMCWEB_ROUTE(
1905 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07001906 "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/<str>/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001907 .privileges(redfish::privileges::getLogEntry)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001908 .methods(boost::beast::http::verb::get)(
Nan Zhoua4ce1142022-08-02 18:45:25 +00001909 [](const crow::Request& req,
1910 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -07001911 const std::string& systemName, const std::string& logID,
1912 const std::string& fileName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001913 // Do not call getRedfishRoute here since the crashdump file is
1914 // not a Redfish resource.
Ed Tanous22d268c2022-05-19 09:39:07 -07001915
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001916 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1917 {
1918 // Option currently returns no systems. TBD
1919 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1920 systemName);
1921 return;
1922 }
1923 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1924 {
1925 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1926 systemName);
1927 return;
1928 }
Ed Tanous22d268c2022-05-19 09:39:07 -07001929
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001930 auto getStoredLogCallback =
1931 [asyncResp, logID, fileName,
1932 url(boost::urls::url(req.url()))](
1933 const boost::system::error_code& ec,
1934 const std::vector<std::pair<
1935 std::string, dbus::utility::DbusVariantType>>&
1936 resp) {
1937 if (ec)
1938 {
1939 BMCWEB_LOG_DEBUG("failed to get log ec: {}",
1940 ec.message());
1941 messages::internalError(asyncResp->res);
1942 return;
1943 }
Jason M. Bills8e6c0992021-03-11 16:26:53 -08001944
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001945 std::string dbusFilename{};
1946 std::string dbusTimestamp{};
1947 std::string dbusFilepath{};
Jason M. Bills8e6c0992021-03-11 16:26:53 -08001948
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001949 parseCrashdumpParameters(resp, dbusFilename,
1950 dbusTimestamp, dbusFilepath);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001951
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001952 if (dbusFilename.empty() || dbusTimestamp.empty() ||
1953 dbusFilepath.empty())
1954 {
1955 messages::resourceNotFound(asyncResp->res,
1956 "LogEntry", logID);
1957 return;
1958 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001959
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001960 // Verify the file name parameter is correct
1961 if (fileName != dbusFilename)
1962 {
1963 messages::resourceNotFound(asyncResp->res,
1964 "LogEntry", logID);
1965 return;
1966 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001967
Myung Baed51c61b2024-09-13 10:35:34 -05001968 if (asyncResp->res.openFile(dbusFilepath) !=
1969 crow::OpenCode::Success)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001970 {
1971 messages::resourceNotFound(asyncResp->res,
1972 "LogEntry", logID);
1973 return;
1974 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001975
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001976 // Configure this to be a file download when accessed
1977 // from a browser
1978 asyncResp->res.addHeader(
1979 boost::beast::http::field::content_disposition,
1980 "attachment");
1981 };
Ed Tanousdeae6a72024-11-11 21:58:57 -08001982 dbus::utility::getAllProperties(
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001983 *crow::connections::systemBus, crashdumpObject,
1984 crashdumpPath + std::string("/") + logID,
1985 crashdumpInterface, std::move(getStoredLogCallback));
1986 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001987}
1988
Jason M. Billsc5a4c822022-01-06 15:51:23 -08001989enum class OEMDiagnosticType
1990{
1991 onDemand,
1992 telemetry,
1993 invalid,
1994};
1995
Ed Tanous26ccae32023-02-16 10:28:44 -08001996inline OEMDiagnosticType getOEMDiagnosticType(std::string_view oemDiagStr)
Jason M. Billsc5a4c822022-01-06 15:51:23 -08001997{
1998 if (oemDiagStr == "OnDemand")
1999 {
2000 return OEMDiagnosticType::onDemand;
2001 }
2002 if (oemDiagStr == "Telemetry")
2003 {
2004 return OEMDiagnosticType::telemetry;
2005 }
2006
2007 return OEMDiagnosticType::invalid;
2008}
2009
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002010inline void requestRoutesCrashdumpCollect(App& app)
2011{
George Liu0fda0f12021-11-16 10:06:17 +08002012 BMCWEB_ROUTE(
2013 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002014 "/redfish/v1/Systems/<str>/LogServices/Crashdump/Actions/LogService.CollectDiagnosticData/")
Myung Bae50d9f382025-06-13 09:40:18 -04002015 .privileges(redfish::privileges::
2016 postLogServiceSubOverComputerSystemLogServiceCollection)
Ed Tanous002d39b2022-05-31 08:59:27 -07002017 .methods(boost::beast::http::verb::post)(
2018 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07002019 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2020 const std::string& systemName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002021 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07002022 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002023 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07002024 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002025
2026 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous002d39b2022-05-31 08:59:27 -07002027 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002028 // Option currently returns no systems. TBD
2029 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2030 systemName);
2031 return;
2032 }
2033 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2034 {
2035 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2036 systemName);
2037 return;
2038 }
2039
2040 std::string diagnosticDataType;
2041 std::string oemDiagnosticDataType;
Patrick Williams504af5a2025-02-03 14:29:03 -05002042 if (!redfish::json_util::readJsonAction( //
2043 req, asyncResp->res, //
2044 "DiagnosticDataType", diagnosticDataType, //
Myung Baeafc474a2024-10-09 00:53:29 -07002045 "OEMDiagnosticDataType", oemDiagnosticDataType //
2046 ))
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002047 {
2048 return;
2049 }
2050
2051 if (diagnosticDataType != "OEM")
2052 {
2053 BMCWEB_LOG_ERROR(
2054 "Only OEM DiagnosticDataType supported for Crashdump");
2055 messages::actionParameterValueFormatError(
2056 asyncResp->res, diagnosticDataType,
2057 "DiagnosticDataType", "CollectDiagnosticData");
2058 return;
2059 }
2060
2061 OEMDiagnosticType oemDiagType =
2062 getOEMDiagnosticType(oemDiagnosticDataType);
2063
2064 std::string iface;
2065 std::string method;
2066 std::string taskMatchStr;
2067 if (oemDiagType == OEMDiagnosticType::onDemand)
2068 {
2069 iface = crashdumpOnDemandInterface;
2070 method = "GenerateOnDemandLog";
2071 taskMatchStr =
2072 "type='signal',"
2073 "interface='org.freedesktop.DBus.Properties',"
2074 "member='PropertiesChanged',"
2075 "arg0namespace='com.intel.crashdump'";
2076 }
2077 else if (oemDiagType == OEMDiagnosticType::telemetry)
2078 {
2079 iface = crashdumpTelemetryInterface;
2080 method = "GenerateTelemetryLog";
2081 taskMatchStr =
2082 "type='signal',"
2083 "interface='org.freedesktop.DBus.Properties',"
2084 "member='PropertiesChanged',"
2085 "arg0namespace='com.intel.crashdump'";
Ed Tanous002d39b2022-05-31 08:59:27 -07002086 }
2087 else
2088 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002089 BMCWEB_LOG_ERROR("Unsupported OEMDiagnosticDataType: {}",
2090 oemDiagnosticDataType);
2091 messages::actionParameterValueFormatError(
2092 asyncResp->res, oemDiagnosticDataType,
2093 "OEMDiagnosticDataType", "CollectDiagnosticData");
2094 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07002095 }
Ed Tanous1da66f72018-07-27 16:13:37 -07002096
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002097 auto collectCrashdumpCallback =
2098 [asyncResp, payload(task::Payload(req)),
2099 taskMatchStr](const boost::system::error_code& ec,
2100 const std::string&) mutable {
2101 if (ec)
2102 {
2103 if (ec.value() ==
2104 boost::system::errc::operation_not_supported)
2105 {
2106 messages::resourceInStandby(asyncResp->res);
2107 }
2108 else if (ec.value() == boost::system::errc::
2109 device_or_resource_busy)
2110 {
2111 messages::serviceTemporarilyUnavailable(
2112 asyncResp->res, "60");
2113 }
2114 else
2115 {
2116 messages::internalError(asyncResp->res);
2117 }
2118 return;
2119 }
2120 std::shared_ptr<task::TaskData> task =
2121 task::TaskData::createTask(
2122 [](const boost::system::error_code& ec2,
2123 sdbusplus::message_t&,
2124 const std::shared_ptr<task::TaskData>&
2125 taskData) {
2126 if (!ec2)
2127 {
2128 taskData->messages.emplace_back(
2129 messages::taskCompletedOK(
2130 std::to_string(
2131 taskData->index)));
2132 taskData->state = "Completed";
2133 }
2134 return task::completed;
2135 },
2136 taskMatchStr);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002137
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002138 task->startTimer(std::chrono::minutes(5));
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002139 task->payload.emplace(std::move(payload));
Chinmay Shripad Hegde29e2bdd2025-06-06 16:23:47 +05302140 task->populateResp(asyncResp->res);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002141 };
2142
Ed Tanous177612a2025-02-14 15:16:09 -08002143 dbus::utility::async_method_call(
2144 asyncResp, std::move(collectCrashdumpCallback),
2145 crashdumpObject, crashdumpPath, iface, method);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002146 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002147}
Oliver Brewkaa93a2932025-10-10 00:53:02 +02002148
Oliver Brewkaf8ae8872025-10-13 19:05:29 +02002149inline void requestRoutesSystemsLogServiceCollection(App& app)
2150{
2151 /**
2152 * Functions triggers appropriate requests on DBus
2153 */
2154 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/")
2155 .privileges(redfish::privileges::getLogServiceCollection)
2156 .methods(boost::beast::http::verb::get)(std::bind_front(
2157 handleSystemsLogServiceCollectionGet, std::ref(app)));
2158}
2159
2160inline void requestRoutesManagersLogServiceCollection(App& app)
2161{
2162 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/")
2163 .privileges(redfish::privileges::getLogServiceCollection)
2164 .methods(boost::beast::http::verb::get)(std::bind_front(
2165 handleManagersLogServicesCollectionGet, std::ref(app)));
2166}
2167
Oliver Brewkaa93a2932025-10-10 00:53:02 +02002168inline void requestRoutesSystemsEventLogService(App& app)
2169{
2170 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/")
2171 .privileges(redfish::privileges::getLogService)
2172 .methods(boost::beast::http::verb::get)(
2173 std::bind_front(handleSystemsEventLogServiceGet, std::ref(app)));
2174}
2175
Ed Tanous1da66f72018-07-27 16:13:37 -07002176} // namespace redfish