blob: e1f3fb600196dac9a9047290a041f10d15f94d04 [file] [log] [blame]
Ed Tanous40e9b922024-09-10 13:50:16 -07001// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright OpenBMC Authors
3// SPDX-FileCopyrightText: Copyright 2018 Intel Corporation
Ed Tanous1da66f72018-07-27 16:13:37 -07004#pragma once
5
Ed Tanousd7857202025-01-28 15:32:26 -08006#include "bmcweb_config.h"
7
Ed Tanous3ccb3ad2023-01-13 17:40:03 -08008#include "app.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -08009#include "async_resp.hpp"
10#include "dbus_singleton.hpp"
George Liu7a1dbc42022-12-07 16:03:22 +080011#include "dbus_utility.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080012#include "error_messages.hpp"
Asmitha Karunanithi68dd0752022-11-15 11:33:46 -060013#include "generated/enums/log_entry.hpp"
Ed Tanous539d8c62024-06-19 14:38:27 -070014#include "generated/enums/log_service.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080015#include "http_body.hpp"
16#include "http_request.hpp"
17#include "http_response.hpp"
George Liu647b3cd2021-07-05 12:43:56 +080018#include "http_utility.hpp"
Spencer Kub7028eb2021-10-26 15:27:35 +080019#include "human_sort.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080020#include "logging.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080021#include "query.hpp"
Jason M. Bills4851d452019-03-28 11:27:48 -070022#include "registries.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080023#include "registries/privilege_registry.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080024#include "str_utility.hpp"
James Feist46229572020-02-19 15:11:58 -080025#include "task.hpp"
Ed Tanous5b904292024-04-16 11:10:17 -070026#include "task_messages.hpp"
Alexander Hansen262dcc12024-09-19 12:04:03 +020027#include "utils/dbus_event_log_entry.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080028#include "utils/dbus_utils.hpp"
Ed Tanous5b904292024-04-16 11:10:17 -070029#include "utils/json_utils.hpp"
Oliver Brewkaff35df92025-08-26 08:21:30 +020030#include "utils/log_services_utils.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080031#include "utils/query_param.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080032#include "utils/time_utils.hpp"
Ed Tanous1da66f72018-07-27 16:13:37 -070033
Ed Tanousd7857202025-01-28 15:32:26 -080034#include <asm-generic/errno.h>
35#include <systemd/sd-bus.h>
Asmitha Karunanithi8e317782020-12-10 03:35:05 -060036#include <tinyxml2.h>
Adriana Kobylak400fd1f2021-01-29 09:01:30 -060037#include <unistd.h>
Jason M. Billse1f26342018-07-18 12:12:00 -070038
Ed Tanousd7857202025-01-28 15:32:26 -080039#include <boost/beast/http/field.hpp>
40#include <boost/beast/http/status.hpp>
Ed Tanous07c8c202022-07-11 10:08:08 -070041#include <boost/beast/http/verb.hpp>
Jason M. Bills1ddcf012019-11-26 14:59:21 -080042#include <boost/system/linux_error.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070043#include <boost/url/format.hpp>
Ed Tanousd7857202025-01-28 15:32:26 -080044#include <boost/url/url.hpp>
45#include <sdbusplus/message.hpp>
46#include <sdbusplus/message/native_types.hpp>
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +020047#include <sdbusplus/unpack_properties.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050048
Ed Tanousd7857202025-01-28 15:32:26 -080049#include <algorithm>
George Liu7a1dbc42022-12-07 16:03:22 +080050#include <array>
Ed Tanousd7857202025-01-28 15:32:26 -080051#include <chrono>
Abhilash Rajub5f288d2023-11-08 22:32:44 -060052#include <cstddef>
Ed Tanousd7857202025-01-28 15:32:26 -080053#include <cstdint>
54#include <cstdio>
55#include <ctime>
James Feist4418c7f2019-04-15 11:09:15 -070056#include <filesystem>
Ed Tanousd7857202025-01-28 15:32:26 -080057#include <format>
58#include <fstream>
59#include <functional>
60#include <iomanip>
Ed Tanous18f8f602023-07-18 10:07:23 -070061#include <iterator>
Ed Tanousd7857202025-01-28 15:32:26 -080062#include <memory>
Xiaochao Ma75710de2021-01-21 17:56:02 +080063#include <optional>
Ed Tanous3544d2a2023-08-06 18:12:20 -070064#include <ranges>
Ed Tanous26702d02021-11-03 15:02:33 -070065#include <span>
Ed Tanousd7857202025-01-28 15:32:26 -080066#include <sstream>
Ed Tanous18f8f602023-07-18 10:07:23 -070067#include <string>
Jason M. Billscd225da2019-05-08 15:31:57 -070068#include <string_view>
Ed Tanousd7857202025-01-28 15:32:26 -080069#include <system_error>
70#include <utility>
Ed Tanousabf2add2019-01-22 16:40:12 -080071#include <variant>
Ed Tanousd7857202025-01-28 15:32:26 -080072#include <vector>
Ed Tanous1da66f72018-07-27 16:13:37 -070073
74namespace redfish
75{
76
Patrick Williams89492a12023-05-10 07:51:34 -050077constexpr const char* crashdumpObject = "com.intel.crashdump";
78constexpr const char* crashdumpPath = "/com/intel/crashdump";
79constexpr const char* crashdumpInterface = "com.intel.crashdump";
80constexpr const char* deleteAllInterface =
Jason M. Bills5b61b5e2019-10-16 10:59:02 -070081 "xyz.openbmc_project.Collection.DeleteAll";
Patrick Williams89492a12023-05-10 07:51:34 -050082constexpr const char* crashdumpOnDemandInterface =
Jason M. Bills424c4172019-03-21 13:50:33 -070083 "com.intel.crashdump.OnDemand";
Patrick Williams89492a12023-05-10 07:51:34 -050084constexpr const char* crashdumpTelemetryInterface =
Kenny L. Ku6eda7682020-06-19 09:48:36 -070085 "com.intel.crashdump.Telemetry";
Ed Tanous1da66f72018-07-27 16:13:37 -070086
Asmitha Karunanithi8e317782020-12-10 03:35:05 -060087enum class DumpCreationProgress
88{
89 DUMP_CREATE_SUCCESS,
90 DUMP_CREATE_FAILED,
91 DUMP_CREATE_INPROGRESS
92};
93
Gunnar Mills1214b7e2020-06-04 10:11:30 -050094inline std::string translateSeverityDbusToRedfish(const std::string& s)
Andrew Geisslercb92c032018-08-17 07:56:14 -070095{
Ed Tanousd4d25792020-09-29 15:15:03 -070096 if ((s == "xyz.openbmc_project.Logging.Entry.Level.Alert") ||
97 (s == "xyz.openbmc_project.Logging.Entry.Level.Critical") ||
98 (s == "xyz.openbmc_project.Logging.Entry.Level.Emergency") ||
99 (s == "xyz.openbmc_project.Logging.Entry.Level.Error"))
Andrew Geisslercb92c032018-08-17 07:56:14 -0700100 {
101 return "Critical";
102 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700103 if ((s == "xyz.openbmc_project.Logging.Entry.Level.Debug") ||
104 (s == "xyz.openbmc_project.Logging.Entry.Level.Informational") ||
105 (s == "xyz.openbmc_project.Logging.Entry.Level.Notice"))
Andrew Geisslercb92c032018-08-17 07:56:14 -0700106 {
107 return "OK";
108 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700109 if (s == "xyz.openbmc_project.Logging.Entry.Level.Warning")
Andrew Geisslercb92c032018-08-17 07:56:14 -0700110 {
111 return "Warning";
112 }
113 return "";
114}
115
Abhishek Patel9017faf2021-09-14 22:48:55 -0500116inline std::optional<bool> getProviderNotifyAction(const std::string& notify)
117{
118 std::optional<bool> notifyAction;
119 if (notify == "xyz.openbmc_project.Logging.Entry.Notify.Notify")
120 {
121 notifyAction = true;
122 }
123 else if (notify == "xyz.openbmc_project.Logging.Entry.Notify.Inhibit")
124 {
125 notifyAction = false;
126 }
127
128 return notifyAction;
129}
130
Ed Tanous18f8f602023-07-18 10:07:23 -0700131inline std::string getDumpPath(std::string_view dumpType)
132{
133 std::string dbusDumpPath = "/xyz/openbmc_project/dump/";
134 std::ranges::transform(dumpType, std::back_inserter(dbusDumpPath),
135 bmcweb::asciiToLower);
136
137 return dbusDumpPath;
138}
139
Ed Tanous055713e2024-07-17 17:19:36 -0700140inline bool getUniqueEntryID(const std::string& logEntry, std::string& entryID,
Jason M. Billse85d6b12019-07-29 17:01:15 -0700141 const bool firstEntry = true)
Jason M. Bills95820182019-04-22 16:25:34 -0700142{
Ed Tanous271584a2019-07-09 16:24:22 -0700143 static time_t prevTs = 0;
Jason M. Bills95820182019-04-22 16:25:34 -0700144 static int index = 0;
Jason M. Billse85d6b12019-07-29 17:01:15 -0700145 if (firstEntry)
146 {
147 prevTs = 0;
148 }
149
Jason M. Bills95820182019-04-22 16:25:34 -0700150 // Get the entry timestamp
Ed Tanous271584a2019-07-09 16:24:22 -0700151 std::time_t curTs = 0;
Jason M. Bills95820182019-04-22 16:25:34 -0700152 std::tm timeStruct = {};
153 std::istringstream entryStream(logEntry);
154 if (entryStream >> std::get_time(&timeStruct, "%Y-%m-%dT%H:%M:%S"))
155 {
156 curTs = std::mktime(&timeStruct);
157 }
158 // If the timestamp isn't unique, increment the index
159 if (curTs == prevTs)
160 {
161 index++;
162 }
163 else
164 {
165 // Otherwise, reset it
166 index = 0;
167 }
168 // Save the timestamp
169 prevTs = curTs;
170
171 entryID = std::to_string(curTs);
172 if (index > 0)
173 {
174 entryID += "_" + std::to_string(index);
175 }
176 return true;
177}
178
Patrick Williams504af5a2025-02-03 14:29:03 -0500179inline bool getRedfishLogFiles(
180 std::vector<std::filesystem::path>& redfishLogFiles)
Jason M. Bills95820182019-04-22 16:25:34 -0700181{
182 static const std::filesystem::path redfishLogDir = "/var/log";
183 static const std::string redfishLogFilename = "redfish";
184
185 // Loop through the directory looking for redfish log files
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500186 for (const std::filesystem::directory_entry& dirEnt :
Jason M. Bills95820182019-04-22 16:25:34 -0700187 std::filesystem::directory_iterator(redfishLogDir))
188 {
189 // If we find a redfish log file, save the path
190 std::string filename = dirEnt.path().filename();
Ed Tanous11ba3972022-07-11 09:50:41 -0700191 if (filename.starts_with(redfishLogFilename))
Jason M. Bills95820182019-04-22 16:25:34 -0700192 {
193 redfishLogFiles.emplace_back(redfishLogDir / filename);
194 }
195 }
196 // As the log files rotate, they are appended with a ".#" that is higher for
197 // the older logs. Since we don't expect more than 10 log files, we
198 // can just sort the list to get them in order from newest to oldest
Ed Tanous3544d2a2023-08-06 18:12:20 -0700199 std::ranges::sort(redfishLogFiles);
Jason M. Bills95820182019-04-22 16:25:34 -0700200
201 return !redfishLogFiles.empty();
202}
203
Patrick Williams504af5a2025-02-03 14:29:03 -0500204inline log_entry::OriginatorTypes mapDbusOriginatorTypeToRedfish(
205 const std::string& originatorType)
Asmitha Karunanithi68dd0752022-11-15 11:33:46 -0600206{
207 if (originatorType ==
208 "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Client")
209 {
210 return log_entry::OriginatorTypes::Client;
211 }
212 if (originatorType ==
213 "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Internal")
214 {
215 return log_entry::OriginatorTypes::Internal;
216 }
217 if (originatorType ==
218 "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.SupportingService")
219 {
220 return log_entry::OriginatorTypes::SupportingService;
221 }
222 return log_entry::OriginatorTypes::Invalid;
223}
224
Claire Weinanaefe3782022-07-15 19:17:19 -0700225inline void parseDumpEntryFromDbusObject(
Jiaqing Zhao2d613eb2022-08-15 16:03:00 +0800226 const dbus::utility::ManagedObjectType::value_type& object,
Claire Weinanc6fecda2022-07-15 10:43:25 -0700227 std::string& dumpStatus, uint64_t& size, uint64_t& timestampUs,
Asmitha Karunanithi68dd0752022-11-15 11:33:46 -0600228 std::string& originatorId, log_entry::OriginatorTypes& originatorType,
Claire Weinanaefe3782022-07-15 19:17:19 -0700229 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
230{
231 for (const auto& interfaceMap : object.second)
232 {
233 if (interfaceMap.first == "xyz.openbmc_project.Common.Progress")
234 {
235 for (const auto& propertyMap : interfaceMap.second)
236 {
237 if (propertyMap.first == "Status")
238 {
239 const auto* status =
240 std::get_if<std::string>(&propertyMap.second);
241 if (status == nullptr)
242 {
243 messages::internalError(asyncResp->res);
244 break;
245 }
246 dumpStatus = *status;
247 }
248 }
249 }
250 else if (interfaceMap.first == "xyz.openbmc_project.Dump.Entry")
251 {
252 for (const auto& propertyMap : interfaceMap.second)
253 {
254 if (propertyMap.first == "Size")
255 {
256 const auto* sizePtr =
257 std::get_if<uint64_t>(&propertyMap.second);
258 if (sizePtr == nullptr)
259 {
260 messages::internalError(asyncResp->res);
261 break;
262 }
263 size = *sizePtr;
264 break;
265 }
266 }
267 }
268 else if (interfaceMap.first == "xyz.openbmc_project.Time.EpochTime")
269 {
270 for (const auto& propertyMap : interfaceMap.second)
271 {
272 if (propertyMap.first == "Elapsed")
273 {
274 const uint64_t* usecsTimeStamp =
275 std::get_if<uint64_t>(&propertyMap.second);
276 if (usecsTimeStamp == nullptr)
277 {
278 messages::internalError(asyncResp->res);
279 break;
280 }
Claire Weinanc6fecda2022-07-15 10:43:25 -0700281 timestampUs = *usecsTimeStamp;
Claire Weinanaefe3782022-07-15 19:17:19 -0700282 break;
283 }
284 }
285 }
Asmitha Karunanithi68dd0752022-11-15 11:33:46 -0600286 else if (interfaceMap.first ==
287 "xyz.openbmc_project.Common.OriginatedBy")
288 {
289 for (const auto& propertyMap : interfaceMap.second)
290 {
291 if (propertyMap.first == "OriginatorId")
292 {
293 const std::string* id =
294 std::get_if<std::string>(&propertyMap.second);
295 if (id == nullptr)
296 {
297 messages::internalError(asyncResp->res);
298 break;
299 }
300 originatorId = *id;
301 }
302
303 if (propertyMap.first == "OriginatorType")
304 {
305 const std::string* type =
306 std::get_if<std::string>(&propertyMap.second);
307 if (type == nullptr)
308 {
309 messages::internalError(asyncResp->res);
310 break;
311 }
312
313 originatorType = mapDbusOriginatorTypeToRedfish(*type);
314 if (originatorType == log_entry::OriginatorTypes::Invalid)
315 {
316 messages::internalError(asyncResp->res);
317 break;
318 }
319 }
320 }
321 }
Claire Weinanaefe3782022-07-15 19:17:19 -0700322 }
323}
324
Nan Zhou21ab4042022-06-26 23:07:40 +0000325static std::string getDumpEntriesPath(const std::string& dumpType)
Claire Weinanfdd26902022-03-01 14:18:25 -0800326{
327 std::string entriesPath;
328
329 if (dumpType == "BMC")
330 {
Ed Tanous253f11b2024-05-16 09:38:31 -0700331 entriesPath =
332 std::format("/redfish/v1/Managers/{}/LogServices/Dump/Entries/",
333 BMCWEB_REDFISH_MANAGER_URI_NAME);
Claire Weinanfdd26902022-03-01 14:18:25 -0800334 }
335 else if (dumpType == "FaultLog")
336 {
Ed Tanous253f11b2024-05-16 09:38:31 -0700337 entriesPath =
338 std::format("/redfish/v1/Managers/{}/LogServices/FaultLog/Entries/",
339 BMCWEB_REDFISH_MANAGER_URI_NAME);
Claire Weinanfdd26902022-03-01 14:18:25 -0800340 }
341 else if (dumpType == "System")
342 {
Ed Tanous253f11b2024-05-16 09:38:31 -0700343 entriesPath =
344 std::format("/redfish/v1/Systems/{}/LogServices/Dump/Entries/",
345 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Claire Weinanfdd26902022-03-01 14:18:25 -0800346 }
347 else
348 {
Ed Tanous62598e32023-07-17 17:06:25 -0700349 BMCWEB_LOG_ERROR("getDumpEntriesPath() invalid dump type: {}",
350 dumpType);
Claire Weinanfdd26902022-03-01 14:18:25 -0800351 }
352
353 // Returns empty string on error
354 return entriesPath;
355}
356
Patrick Williams504af5a2025-02-03 14:29:03 -0500357inline void getDumpEntryCollection(
358 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
359 const std::string& dumpType)
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500360{
Claire Weinanfdd26902022-03-01 14:18:25 -0800361 std::string entriesPath = getDumpEntriesPath(dumpType);
362 if (entriesPath.empty())
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500363 {
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500364 messages::internalError(asyncResp->res);
365 return;
366 }
367
George Liu5eb468d2023-06-20 17:03:24 +0800368 sdbusplus::message::object_path path("/xyz/openbmc_project/dump");
369 dbus::utility::getManagedObjects(
370 "xyz.openbmc_project.Dump.Manager", path,
Claire Weinanfdd26902022-03-01 14:18:25 -0800371 [asyncResp, entriesPath,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800372 dumpType](const boost::system::error_code& ec,
George Liu5eb468d2023-06-20 17:03:24 +0800373 const dbus::utility::ManagedObjectType& objects) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400374 if (ec)
375 {
376 BMCWEB_LOG_ERROR("DumpEntry resp_handler got error {}", ec);
377 messages::internalError(asyncResp->res);
378 return;
379 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700380
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400381 // Remove ending slash
382 std::string odataIdStr = entriesPath;
383 if (!odataIdStr.empty())
384 {
385 odataIdStr.pop_back();
386 }
Claire Weinanfdd26902022-03-01 14:18:25 -0800387
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400388 asyncResp->res.jsonValue["@odata.type"] =
389 "#LogEntryCollection.LogEntryCollection";
390 asyncResp->res.jsonValue["@odata.id"] = std::move(odataIdStr);
391 asyncResp->res.jsonValue["Name"] = dumpType + " Dump Entries";
392 asyncResp->res.jsonValue["Description"] =
393 "Collection of " + dumpType + " Dump Entries";
Claire Weinanfdd26902022-03-01 14:18:25 -0800394
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400395 nlohmann::json::array_t entriesArray;
396 std::string dumpEntryPath = getDumpPath(dumpType) + "/entry/";
Ed Tanous002d39b2022-05-31 08:59:27 -0700397
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400398 dbus::utility::ManagedObjectType resp(objects);
399 std::ranges::sort(resp, [](const auto& l, const auto& r) {
400 return AlphanumLess<std::string>()(l.first.filename(),
401 r.first.filename());
402 });
403
404 for (auto& object : resp)
405 {
406 if (object.first.str.find(dumpEntryPath) == std::string::npos)
407 {
408 continue;
409 }
410 uint64_t timestampUs = 0;
411 uint64_t size = 0;
412 std::string dumpStatus;
413 std::string originatorId;
414 log_entry::OriginatorTypes originatorType =
415 log_entry::OriginatorTypes::Internal;
416 nlohmann::json::object_t thisEntry;
417
418 std::string entryID = object.first.filename();
419 if (entryID.empty())
420 {
421 continue;
422 }
423
424 parseDumpEntryFromDbusObject(object, dumpStatus, size,
425 timestampUs, originatorId,
426 originatorType, asyncResp);
427
428 if (dumpStatus !=
429 "xyz.openbmc_project.Common.Progress.OperationStatus.Completed" &&
430 !dumpStatus.empty())
431 {
432 // Dump status is not Complete, no need to enumerate
433 continue;
434 }
435
436 thisEntry["@odata.type"] = "#LogEntry.v1_11_0.LogEntry";
437 thisEntry["@odata.id"] = entriesPath + entryID;
438 thisEntry["Id"] = entryID;
439 thisEntry["EntryType"] = "Event";
440 thisEntry["Name"] = dumpType + " Dump Entry";
441 thisEntry["Created"] =
442 redfish::time_utils::getDateTimeUintUs(timestampUs);
443
444 if (!originatorId.empty())
445 {
446 thisEntry["Originator"] = originatorId;
447 thisEntry["OriginatorType"] = originatorType;
448 }
449
450 if (dumpType == "BMC")
451 {
452 thisEntry["DiagnosticDataType"] = "Manager";
453 thisEntry["AdditionalDataURI"] =
454 entriesPath + entryID + "/attachment";
455 thisEntry["AdditionalDataSizeBytes"] = size;
456 }
457 else if (dumpType == "System")
458 {
459 thisEntry["DiagnosticDataType"] = "OEM";
460 thisEntry["OEMDiagnosticDataType"] = "System";
461 thisEntry["AdditionalDataURI"] =
462 entriesPath + entryID + "/attachment";
463 thisEntry["AdditionalDataSizeBytes"] = size;
464 }
465 entriesArray.emplace_back(std::move(thisEntry));
466 }
467 asyncResp->res.jsonValue["Members@odata.count"] =
468 entriesArray.size();
469 asyncResp->res.jsonValue["Members"] = std::move(entriesArray);
Ed Tanous002d39b2022-05-31 08:59:27 -0700470 });
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500471}
472
Patrick Williams504af5a2025-02-03 14:29:03 -0500473inline void getDumpEntryById(
474 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
475 const std::string& entryID, const std::string& dumpType)
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500476{
Claire Weinanfdd26902022-03-01 14:18:25 -0800477 std::string entriesPath = getDumpEntriesPath(dumpType);
478 if (entriesPath.empty())
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500479 {
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500480 messages::internalError(asyncResp->res);
481 return;
482 }
483
George Liu5eb468d2023-06-20 17:03:24 +0800484 sdbusplus::message::object_path path("/xyz/openbmc_project/dump");
485 dbus::utility::getManagedObjects(
486 "xyz.openbmc_project.Dump.Manager", path,
Claire Weinanfdd26902022-03-01 14:18:25 -0800487 [asyncResp, entryID, dumpType,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800488 entriesPath](const boost::system::error_code& ec,
Ed Tanous02cad962022-06-30 16:50:15 -0700489 const dbus::utility::ManagedObjectType& resp) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400490 if (ec)
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500491 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400492 BMCWEB_LOG_ERROR("DumpEntry resp_handler got error {}", ec);
493 messages::internalError(asyncResp->res);
494 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700495 }
496
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400497 bool foundDumpEntry = false;
498 std::string dumpEntryPath = getDumpPath(dumpType) + "/entry/";
Ed Tanous002d39b2022-05-31 08:59:27 -0700499
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400500 for (const auto& objectPath : resp)
Ed Tanous002d39b2022-05-31 08:59:27 -0700501 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400502 if (objectPath.first.str != dumpEntryPath + entryID)
503 {
504 continue;
505 }
506
507 foundDumpEntry = true;
508 uint64_t timestampUs = 0;
509 uint64_t size = 0;
510 std::string dumpStatus;
511 std::string originatorId;
512 log_entry::OriginatorTypes originatorType =
513 log_entry::OriginatorTypes::Internal;
514
515 parseDumpEntryFromDbusObject(objectPath, dumpStatus, size,
516 timestampUs, originatorId,
517 originatorType, asyncResp);
518
519 if (dumpStatus !=
520 "xyz.openbmc_project.Common.Progress.OperationStatus.Completed" &&
521 !dumpStatus.empty())
522 {
523 // Dump status is not Complete
524 // return not found until status is changed to Completed
525 messages::resourceNotFound(asyncResp->res,
526 dumpType + " dump", entryID);
527 return;
528 }
529
530 asyncResp->res.jsonValue["@odata.type"] =
531 "#LogEntry.v1_11_0.LogEntry";
532 asyncResp->res.jsonValue["@odata.id"] = entriesPath + entryID;
533 asyncResp->res.jsonValue["Id"] = entryID;
534 asyncResp->res.jsonValue["EntryType"] = "Event";
535 asyncResp->res.jsonValue["Name"] = dumpType + " Dump Entry";
536 asyncResp->res.jsonValue["Created"] =
537 redfish::time_utils::getDateTimeUintUs(timestampUs);
538
539 if (!originatorId.empty())
540 {
541 asyncResp->res.jsonValue["Originator"] = originatorId;
542 asyncResp->res.jsonValue["OriginatorType"] = originatorType;
543 }
544
545 if (dumpType == "BMC")
546 {
547 asyncResp->res.jsonValue["DiagnosticDataType"] = "Manager";
548 asyncResp->res.jsonValue["AdditionalDataURI"] =
549 entriesPath + entryID + "/attachment";
550 asyncResp->res.jsonValue["AdditionalDataSizeBytes"] = size;
551 }
552 else if (dumpType == "System")
553 {
554 asyncResp->res.jsonValue["DiagnosticDataType"] = "OEM";
555 asyncResp->res.jsonValue["OEMDiagnosticDataType"] =
556 "System";
557 asyncResp->res.jsonValue["AdditionalDataURI"] =
558 entriesPath + entryID + "/attachment";
559 asyncResp->res.jsonValue["AdditionalDataSizeBytes"] = size;
560 }
561 }
562 if (!foundDumpEntry)
563 {
564 BMCWEB_LOG_WARNING("Can't find Dump Entry {}", entryID);
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +0200565 messages::resourceNotFound(asyncResp->res, dumpType + " dump",
566 entryID);
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500567 return;
568 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400569 });
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500570}
571
zhanghch058d1b46d2021-04-01 11:18:24 +0800572inline void deleteDumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Stanley Chu98782562020-11-04 16:10:24 +0800573 const std::string& entryID,
Asmitha Karunanithib47452b2020-09-25 02:02:19 -0500574 const std::string& dumpType)
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500575{
Patrick Williams5a39f772023-10-20 11:20:21 -0500576 auto respHandler = [asyncResp,
577 entryID](const boost::system::error_code& ec) {
Ed Tanous62598e32023-07-17 17:06:25 -0700578 BMCWEB_LOG_DEBUG("Dump Entry doDelete callback: Done");
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500579 if (ec)
580 {
George Liu3de8d8b2021-03-22 17:49:39 +0800581 if (ec.value() == EBADR)
582 {
583 messages::resourceNotFound(asyncResp->res, "LogEntry", entryID);
584 return;
585 }
Ed Tanous62598e32023-07-17 17:06:25 -0700586 BMCWEB_LOG_ERROR(
587 "Dump (DBus) doDelete respHandler got error {} entryID={}", ec,
588 entryID);
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500589 messages::internalError(asyncResp->res);
590 return;
591 }
592 };
Ed Tanous18f8f602023-07-18 10:07:23 -0700593
Ed Tanous177612a2025-02-14 15:16:09 -0800594 dbus::utility::async_method_call(
595 asyncResp, respHandler, "xyz.openbmc_project.Dump.Manager",
Ed Tanous18f8f602023-07-18 10:07:23 -0700596 std::format("{}/entry/{}", getDumpPath(dumpType), entryID),
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500597 "xyz.openbmc_project.Object.Delete", "Delete");
598}
Carson Labrado168d1b12023-03-27 17:04:46 +0000599
Patrick Williams504af5a2025-02-03 14:29:03 -0500600inline void downloadDumpEntry(
601 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
602 const std::string& entryID, const std::string& dumpType)
Carson Labrado168d1b12023-03-27 17:04:46 +0000603{
604 if (dumpType != "BMC")
605 {
606 BMCWEB_LOG_WARNING("Can't find Dump Entry {}", entryID);
607 messages::resourceNotFound(asyncResp->res, dumpType + " dump", entryID);
608 return;
609 }
610
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400611 std::string dumpEntryPath =
612 std::format("{}/entry/{}", getDumpPath(dumpType), entryID);
Carson Labrado168d1b12023-03-27 17:04:46 +0000613
614 auto downloadDumpEntryHandler =
615 [asyncResp, entryID,
616 dumpType](const boost::system::error_code& ec,
617 const sdbusplus::message::unix_fd& unixfd) {
Oliver Brewkaff35df92025-08-26 08:21:30 +0200618 log_services_utils::downloadEntryCallback(asyncResp, entryID,
619 dumpType, ec, unixfd);
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400620 };
Carson Labrado168d1b12023-03-27 17:04:46 +0000621
Ed Tanous177612a2025-02-14 15:16:09 -0800622 dbus::utility::async_method_call(
623 asyncResp, std::move(downloadDumpEntryHandler),
624 "xyz.openbmc_project.Dump.Manager", dumpEntryPath,
625 "xyz.openbmc_project.Dump.Entry", "GetFileHandle");
Carson Labrado168d1b12023-03-27 17:04:46 +0000626}
627
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400628inline void downloadEventLogEntry(
629 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
630 const std::string& systemName, const std::string& entryID,
631 const std::string& dumpType)
Carson Labrado168d1b12023-03-27 17:04:46 +0000632{
Ed Tanous25b54db2024-04-17 15:40:31 -0700633 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Carson Labrado168d1b12023-03-27 17:04:46 +0000634 {
635 // Option currently returns no systems. TBD
636 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
637 systemName);
638 return;
639 }
Ed Tanous253f11b2024-05-16 09:38:31 -0700640 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Carson Labrado168d1b12023-03-27 17:04:46 +0000641 {
642 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
643 systemName);
644 return;
645 }
646
647 std::string entryPath =
648 sdbusplus::message::object_path("/xyz/openbmc_project/logging/entry") /
649 entryID;
650
651 auto downloadEventLogEntryHandler =
652 [asyncResp, entryID,
653 dumpType](const boost::system::error_code& ec,
654 const sdbusplus::message::unix_fd& unixfd) {
Oliver Brewkaff35df92025-08-26 08:21:30 +0200655 log_services_utils::downloadEntryCallback(asyncResp, entryID,
656 dumpType, ec, unixfd);
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400657 };
Carson Labrado168d1b12023-03-27 17:04:46 +0000658
Ed Tanous177612a2025-02-14 15:16:09 -0800659 dbus::utility::async_method_call(
660 asyncResp, std::move(downloadEventLogEntryHandler),
661 "xyz.openbmc_project.Logging", entryPath,
662 "xyz.openbmc_project.Logging.Entry", "GetEntry");
Carson Labrado168d1b12023-03-27 17:04:46 +0000663}
664
Patrick Williams504af5a2025-02-03 14:29:03 -0500665inline DumpCreationProgress mapDbusStatusToDumpProgress(
666 const std::string& status)
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500667{
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600668 if (status ==
669 "xyz.openbmc_project.Common.Progress.OperationStatus.Failed" ||
670 status == "xyz.openbmc_project.Common.Progress.OperationStatus.Aborted")
671 {
672 return DumpCreationProgress::DUMP_CREATE_FAILED;
673 }
674 if (status ==
675 "xyz.openbmc_project.Common.Progress.OperationStatus.Completed")
676 {
677 return DumpCreationProgress::DUMP_CREATE_SUCCESS;
678 }
679 return DumpCreationProgress::DUMP_CREATE_INPROGRESS;
680}
681
Patrick Williams504af5a2025-02-03 14:29:03 -0500682inline DumpCreationProgress getDumpCompletionStatus(
683 const dbus::utility::DBusPropertiesMap& values)
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600684{
685 for (const auto& [key, val] : values)
686 {
687 if (key == "Status")
Ed Tanous002d39b2022-05-31 08:59:27 -0700688 {
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600689 const std::string* value = std::get_if<std::string>(&val);
690 if (value == nullptr)
691 {
Ed Tanous62598e32023-07-17 17:06:25 -0700692 BMCWEB_LOG_ERROR("Status property value is null");
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600693 return DumpCreationProgress::DUMP_CREATE_FAILED;
694 }
695 return mapDbusStatusToDumpProgress(*value);
696 }
697 }
698 return DumpCreationProgress::DUMP_CREATE_INPROGRESS;
699}
700
701inline std::string getDumpEntryPath(const std::string& dumpPath)
702{
703 if (dumpPath == "/xyz/openbmc_project/dump/bmc/entry")
704 {
Ed Tanous253f11b2024-05-16 09:38:31 -0700705 return std::format("/redfish/v1/Managers/{}/LogServices/Dump/Entries/",
Ed Tanous9f565092024-07-12 22:06:53 -0700706 BMCWEB_REDFISH_MANAGER_URI_NAME);
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600707 }
708 if (dumpPath == "/xyz/openbmc_project/dump/system/entry")
709 {
Ed Tanous253f11b2024-05-16 09:38:31 -0700710 return std::format("/redfish/v1/Systems/{}/LogServices/Dump/Entries/",
711 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600712 }
713 return "";
714}
715
716inline void createDumpTaskCallback(
717 task::Payload&& payload,
718 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
719 const sdbusplus::message::object_path& createdObjPath)
720{
721 const std::string dumpPath = createdObjPath.parent_path().str;
722 const std::string dumpId = createdObjPath.filename();
723
724 std::string dumpEntryPath = getDumpEntryPath(dumpPath);
725
726 if (dumpEntryPath.empty())
727 {
Ed Tanous62598e32023-07-17 17:06:25 -0700728 BMCWEB_LOG_ERROR("Invalid dump type received");
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600729 messages::internalError(asyncResp->res);
730 return;
731 }
732
Ed Tanous177612a2025-02-14 15:16:09 -0800733 dbus::utility::async_method_call(
734 asyncResp,
Ed Tanous8cb2c022024-03-27 16:31:46 -0700735 [asyncResp, payload = std::move(payload), createdObjPath,
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600736 dumpEntryPath{std::move(dumpEntryPath)},
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800737 dumpId](const boost::system::error_code& ec,
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600738 const std::string& introspectXml) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400739 if (ec)
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600740 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400741 BMCWEB_LOG_ERROR("Introspect call failed with error: {}",
742 ec.message());
743 messages::internalError(asyncResp->res);
744 return;
745 }
746
747 // Check if the created dump object has implemented Progress
748 // interface to track dump completion. If yes, fetch the "Status"
749 // property of the interface, modify the task state accordingly.
750 // Else, return task completed.
751 tinyxml2::XMLDocument doc;
752
753 doc.Parse(introspectXml.data(), introspectXml.size());
754 tinyxml2::XMLNode* pRoot = doc.FirstChildElement("node");
755 if (pRoot == nullptr)
756 {
757 BMCWEB_LOG_ERROR("XML document failed to parse");
758 messages::internalError(asyncResp->res);
759 return;
760 }
761 tinyxml2::XMLElement* interfaceNode =
762 pRoot->FirstChildElement("interface");
763
764 bool isProgressIntfPresent = false;
765 while (interfaceNode != nullptr)
766 {
767 const char* thisInterfaceName =
768 interfaceNode->Attribute("name");
769 if (thisInterfaceName != nullptr)
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600770 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400771 if (thisInterfaceName ==
772 std::string_view("xyz.openbmc_project.Common.Progress"))
773 {
774 interfaceNode =
775 interfaceNode->NextSiblingElement("interface");
776 continue;
777 }
778 isProgressIntfPresent = true;
779 break;
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600780 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400781 interfaceNode = interfaceNode->NextSiblingElement("interface");
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600782 }
783
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400784 std::shared_ptr<task::TaskData> task = task::TaskData::createTask(
785 [createdObjPath, dumpEntryPath, dumpId, isProgressIntfPresent](
786 const boost::system::error_code& ec2,
787 sdbusplus::message_t& msg,
788 const std::shared_ptr<task::TaskData>& taskData) {
789 if (ec2)
790 {
791 BMCWEB_LOG_ERROR("{}: Error in creating dump",
792 createdObjPath.str);
793 taskData->messages.emplace_back(
794 messages::internalError());
795 taskData->state = "Cancelled";
796 return task::completed;
797 }
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600798
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400799 if (isProgressIntfPresent)
800 {
801 dbus::utility::DBusPropertiesMap values;
802 std::string prop;
803 msg.read(prop, values);
804
805 DumpCreationProgress dumpStatus =
806 getDumpCompletionStatus(values);
807 if (dumpStatus ==
808 DumpCreationProgress::DUMP_CREATE_FAILED)
809 {
810 BMCWEB_LOG_ERROR("{}: Error in creating dump",
811 createdObjPath.str);
812 taskData->state = "Cancelled";
813 return task::completed;
814 }
815
816 if (dumpStatus ==
817 DumpCreationProgress::DUMP_CREATE_INPROGRESS)
818 {
819 BMCWEB_LOG_DEBUG(
820 "{}: Dump creation task is in progress",
821 createdObjPath.str);
822 return !task::completed;
823 }
824 }
825
826 nlohmann::json retMessage = messages::success();
827 taskData->messages.emplace_back(retMessage);
828
829 boost::urls::url url = boost::urls::format(
830 "/redfish/v1/Managers/{}/LogServices/Dump/Entries/{}",
831 BMCWEB_REDFISH_MANAGER_URI_NAME, dumpId);
832
833 std::string headerLoc = "Location: ";
834 headerLoc += url.buffer();
835
836 taskData->payload->httpHeaders.emplace_back(
837 std::move(headerLoc));
838
839 BMCWEB_LOG_DEBUG("{}: Dump creation task completed",
Ed Tanous62598e32023-07-17 17:06:25 -0700840 createdObjPath.str);
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400841 taskData->state = "Completed";
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600842 return task::completed;
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400843 },
844 "type='signal',interface='org.freedesktop.DBus.Properties',"
845 "member='PropertiesChanged',path='" +
846 createdObjPath.str + "'");
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600847
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400848 // The task timer is set to max time limit within which the
849 // requested dump will be collected.
850 task->startTimer(std::chrono::minutes(6));
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400851 task->payload.emplace(payload);
Chinmay Shripad Hegde29e2bdd2025-06-06 16:23:47 +0530852 task->populateResp(asyncResp->res);
Patrick Williams5a39f772023-10-20 11:20:21 -0500853 },
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600854 "xyz.openbmc_project.Dump.Manager", createdObjPath,
855 "org.freedesktop.DBus.Introspectable", "Introspect");
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500856}
857
zhanghch058d1b46d2021-04-01 11:18:24 +0800858inline void createDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
859 const crow::Request& req, const std::string& dumpType)
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500860{
Claire Weinanfdd26902022-03-01 14:18:25 -0800861 std::string dumpPath = getDumpEntriesPath(dumpType);
862 if (dumpPath.empty())
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500863 {
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500864 messages::internalError(asyncResp->res);
865 return;
866 }
867
868 std::optional<std::string> diagnosticDataType;
869 std::optional<std::string> oemDiagnosticDataType;
870
Patrick Williams504af5a2025-02-03 14:29:03 -0500871 if (!redfish::json_util::readJsonAction( //
872 req, asyncResp->res, //
873 "DiagnosticDataType", diagnosticDataType, //
Myung Baeafc474a2024-10-09 00:53:29 -0700874 "OEMDiagnosticDataType", oemDiagnosticDataType //
875 ))
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500876 {
877 return;
878 }
879
880 if (dumpType == "System")
881 {
882 if (!oemDiagnosticDataType || !diagnosticDataType)
883 {
Ed Tanous62598e32023-07-17 17:06:25 -0700884 BMCWEB_LOG_ERROR(
885 "CreateDump action parameter 'DiagnosticDataType'/'OEMDiagnosticDataType' value not found!");
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500886 messages::actionParameterMissing(
887 asyncResp->res, "CollectDiagnosticData",
888 "DiagnosticDataType & OEMDiagnosticDataType");
889 return;
890 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700891 if ((*oemDiagnosticDataType != "System") ||
892 (*diagnosticDataType != "OEM"))
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500893 {
Ed Tanous62598e32023-07-17 17:06:25 -0700894 BMCWEB_LOG_ERROR("Wrong parameter values passed");
Ed Tanousace85d62021-10-26 12:45:59 -0700895 messages::internalError(asyncResp->res);
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500896 return;
897 }
Ed Tanous253f11b2024-05-16 09:38:31 -0700898 dumpPath = std::format("/redfish/v1/Systems/{}/LogServices/Dump/",
899 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500900 }
901 else if (dumpType == "BMC")
902 {
903 if (!diagnosticDataType)
904 {
Ed Tanous62598e32023-07-17 17:06:25 -0700905 BMCWEB_LOG_ERROR(
906 "CreateDump action parameter 'DiagnosticDataType' not found!");
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500907 messages::actionParameterMissing(
908 asyncResp->res, "CollectDiagnosticData", "DiagnosticDataType");
909 return;
910 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700911 if (*diagnosticDataType != "Manager")
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500912 {
Ed Tanous62598e32023-07-17 17:06:25 -0700913 BMCWEB_LOG_ERROR(
914 "Wrong parameter value passed for 'DiagnosticDataType'");
Ed Tanousace85d62021-10-26 12:45:59 -0700915 messages::internalError(asyncResp->res);
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500916 return;
917 }
Ed Tanous253f11b2024-05-16 09:38:31 -0700918 dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/Dump/",
919 BMCWEB_REDFISH_MANAGER_URI_NAME);
Asmitha Karunanithi59075712021-10-22 01:17:41 -0500920 }
921 else
922 {
Ed Tanous62598e32023-07-17 17:06:25 -0700923 BMCWEB_LOG_ERROR("CreateDump failed. Unknown dump type");
Asmitha Karunanithi59075712021-10-22 01:17:41 -0500924 messages::internalError(asyncResp->res);
925 return;
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500926 }
927
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600928 std::vector<std::pair<std::string, std::variant<std::string, uint64_t>>>
929 createDumpParamVec;
930
Carson Labradof574a8e2023-03-22 02:26:00 +0000931 if (req.session != nullptr)
932 {
933 createDumpParamVec.emplace_back(
934 "xyz.openbmc_project.Dump.Create.CreateParameters.OriginatorId",
935 req.session->clientIp);
936 createDumpParamVec.emplace_back(
937 "xyz.openbmc_project.Dump.Create.CreateParameters.OriginatorType",
938 "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Client");
939 }
Asmitha Karunanithi68dd0752022-11-15 11:33:46 -0600940
Ed Tanous177612a2025-02-14 15:16:09 -0800941 dbus::utility::async_method_call(
942 asyncResp,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800943 [asyncResp, payload(task::Payload(req)),
944 dumpPath](const boost::system::error_code& ec,
945 const sdbusplus::message_t& msg,
946 const sdbusplus::message::object_path& objPath) mutable {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400947 if (ec)
Asmitha Karunanithi59075712021-10-22 01:17:41 -0500948 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400949 BMCWEB_LOG_ERROR("CreateDump resp_handler got error {}", ec);
950 const sd_bus_error* dbusError = msg.get_error();
951 if (dbusError == nullptr)
952 {
953 messages::internalError(asyncResp->res);
954 return;
955 }
956
957 BMCWEB_LOG_ERROR("CreateDump DBus error: {} and error msg: {}",
958 dbusError->name, dbusError->message);
959 if (std::string_view(
960 "xyz.openbmc_project.Common.Error.NotAllowed") ==
961 dbusError->name)
962 {
963 messages::resourceInStandby(asyncResp->res);
964 return;
965 }
966 if (std::string_view(
967 "xyz.openbmc_project.Dump.Create.Error.Disabled") ==
968 dbusError->name)
969 {
970 messages::serviceDisabled(asyncResp->res, dumpPath);
971 return;
972 }
973 if (std::string_view(
974 "xyz.openbmc_project.Common.Error.Unavailable") ==
975 dbusError->name)
976 {
977 messages::resourceInUse(asyncResp->res);
978 return;
979 }
980 // Other Dbus errors such as:
981 // xyz.openbmc_project.Common.Error.InvalidArgument &
982 // org.freedesktop.DBus.Error.InvalidArgs are all related to
983 // the dbus call that is made here in the bmcweb
984 // implementation and has nothing to do with the client's
985 // input in the request. Hence, returning internal error
986 // back to the client.
Asmitha Karunanithi59075712021-10-22 01:17:41 -0500987 messages::internalError(asyncResp->res);
988 return;
989 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400990 BMCWEB_LOG_DEBUG("Dump Created. Path: {}", objPath.str);
991 createDumpTaskCallback(std::move(payload), asyncResp, objPath);
992 },
Ed Tanous18f8f602023-07-18 10:07:23 -0700993 "xyz.openbmc_project.Dump.Manager", getDumpPath(dumpType),
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600994 "xyz.openbmc_project.Dump.Create", "CreateDump", createDumpParamVec);
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500995}
996
zhanghch058d1b46d2021-04-01 11:18:24 +0800997inline void clearDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
998 const std::string& dumpType)
Asmitha Karunanithi80319af2020-05-07 05:30:21 -0500999{
Ed Tanous177612a2025-02-14 15:16:09 -08001000 dbus::utility::async_method_call(
1001 asyncResp,
Claire Weinan0d946212022-07-13 19:40:19 -07001002 [asyncResp](const boost::system::error_code& ec) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001003 if (ec)
1004 {
1005 BMCWEB_LOG_ERROR("clearDump resp_handler got error {}", ec);
1006 messages::internalError(asyncResp->res);
1007 return;
1008 }
Amy Change2460462025-05-06 00:10:13 -07001009 messages::success(asyncResp->res);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001010 },
Ed Tanous18f8f602023-07-18 10:07:23 -07001011 "xyz.openbmc_project.Dump.Manager", getDumpPath(dumpType),
Claire Weinan0d946212022-07-13 19:40:19 -07001012 "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
Asmitha Karunanithi80319af2020-05-07 05:30:21 -05001013}
1014
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001015inline void parseCrashdumpParameters(
1016 const dbus::utility::DBusPropertiesMap& params, std::string& filename,
1017 std::string& timestamp, std::string& logfile)
Johnathan Mantey043a0532020-03-10 17:15:28 -07001018{
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +02001019 const std::string* filenamePtr = nullptr;
1020 const std::string* timestampPtr = nullptr;
1021 const std::string* logfilePtr = nullptr;
1022
1023 const bool success = sdbusplus::unpackPropertiesNoThrow(
1024 dbus_utils::UnpackErrorPrinter(), params, "Timestamp", timestampPtr,
1025 "Filename", filenamePtr, "Log", logfilePtr);
1026
1027 if (!success)
Johnathan Mantey043a0532020-03-10 17:15:28 -07001028 {
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +02001029 return;
1030 }
1031
1032 if (filenamePtr != nullptr)
1033 {
1034 filename = *filenamePtr;
1035 }
1036
1037 if (timestampPtr != nullptr)
1038 {
1039 timestamp = *timestampPtr;
1040 }
1041
1042 if (logfilePtr != nullptr)
1043 {
1044 logfile = *logfilePtr;
Johnathan Mantey043a0532020-03-10 17:15:28 -07001045 }
1046}
1047
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001048inline void requestRoutesSystemLogServiceCollection(App& app)
Ed Tanous1da66f72018-07-27 16:13:37 -07001049{
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001050 /**
1051 * Functions triggers appropriate requests on DBus
1052 */
Ed Tanous22d268c2022-05-19 09:39:07 -07001053 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/")
Ed Tanoused398212021-06-09 17:05:54 -07001054 .privileges(redfish::privileges::getLogServiceCollection)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001055 .methods(
1056 boost::beast::http::verb::
1057 get)([&app](const crow::Request& req,
1058 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1059 const std::string& systemName) {
1060 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07001061 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001062 return;
1063 }
1064 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1065 {
1066 // Option currently returns no systems. TBD
1067 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1068 systemName);
1069 return;
1070 }
1071 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1072 {
1073 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1074 systemName);
Ed Tanous002d39b2022-05-31 08:59:27 -07001075 return;
1076 }
Ed Tanous45ca1b82022-03-25 13:07:27 -07001077
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001078 // Collections don't include the static data added by SubRoute
1079 // because it has a duplicate entry for members
1080 asyncResp->res.jsonValue["@odata.type"] =
1081 "#LogServiceCollection.LogServiceCollection";
1082 asyncResp->res.jsonValue["@odata.id"] =
1083 std::format("/redfish/v1/Systems/{}/LogServices",
1084 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1085 asyncResp->res.jsonValue["Name"] = "System Log Services Collection";
1086 asyncResp->res.jsonValue["Description"] =
1087 "Collection of LogServices for this Computer System";
1088 nlohmann::json& logServiceArray =
1089 asyncResp->res.jsonValue["Members"];
1090 logServiceArray = nlohmann::json::array();
1091 nlohmann::json::object_t eventLog;
1092 eventLog["@odata.id"] =
1093 std::format("/redfish/v1/Systems/{}/LogServices/EventLog",
1094 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1095 logServiceArray.emplace_back(std::move(eventLog));
1096 if constexpr (BMCWEB_REDFISH_DUMP_LOG)
Ed Tanous002d39b2022-05-31 08:59:27 -07001097 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001098 nlohmann::json::object_t dumpLog;
1099 dumpLog["@odata.id"] =
1100 std::format("/redfish/v1/Systems/{}/LogServices/Dump",
1101 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1102 logServiceArray.emplace_back(std::move(dumpLog));
Ed Tanous002d39b2022-05-31 08:59:27 -07001103 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001104
1105 if constexpr (BMCWEB_REDFISH_CPU_LOG)
1106 {
1107 nlohmann::json::object_t crashdump;
1108 crashdump["@odata.id"] =
1109 std::format("/redfish/v1/Systems/{}/LogServices/Crashdump",
1110 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1111 logServiceArray.emplace_back(std::move(crashdump));
1112 }
1113
1114 if constexpr (BMCWEB_REDFISH_HOST_LOGGER)
1115 {
1116 nlohmann::json::object_t hostlogger;
1117 hostlogger["@odata.id"] =
1118 std::format("/redfish/v1/Systems/{}/LogServices/HostLogger",
1119 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1120 logServiceArray.emplace_back(std::move(hostlogger));
1121 }
1122 asyncResp->res.jsonValue["Members@odata.count"] =
1123 logServiceArray.size();
1124
1125 constexpr std::array<std::string_view, 1> interfaces = {
1126 "xyz.openbmc_project.State.Boot.PostCode"};
1127 dbus::utility::getSubTreePaths(
1128 "/", 0, interfaces,
1129 [asyncResp](const boost::system::error_code& ec,
1130 const dbus::utility::MapperGetSubTreePathsResponse&
1131 subtreePath) {
1132 if (ec)
1133 {
1134 BMCWEB_LOG_ERROR("{}", ec);
1135 return;
1136 }
1137
1138 for (const auto& pathStr : subtreePath)
1139 {
1140 if (pathStr.find("PostCode") != std::string::npos)
1141 {
1142 nlohmann::json& logServiceArrayLocal =
1143 asyncResp->res.jsonValue["Members"];
1144 nlohmann::json::object_t member;
1145 member["@odata.id"] = std::format(
1146 "/redfish/v1/Systems/{}/LogServices/PostCodes",
1147 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1148
1149 logServiceArrayLocal.emplace_back(
1150 std::move(member));
1151
1152 asyncResp->res.jsonValue["Members@odata.count"] =
1153 logServiceArrayLocal.size();
1154 return;
1155 }
1156 }
1157 });
Ed Tanous45ca1b82022-03-25 13:07:27 -07001158 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001159}
1160
1161inline void requestRoutesEventLogService(App& app)
1162{
Ed Tanous22d268c2022-05-19 09:39:07 -07001163 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/")
Ed Tanoused398212021-06-09 17:05:54 -07001164 .privileges(redfish::privileges::getLogService)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001165 .methods(
1166 boost::beast::http::verb::
1167 get)([&app](const crow::Request& req,
1168 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1169 const std::string& systemName) {
1170 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1171 {
1172 return;
1173 }
1174 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1175 {
1176 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1177 systemName);
1178 return;
1179 }
1180 asyncResp->res.jsonValue["@odata.id"] =
1181 std::format("/redfish/v1/Systems/{}/LogServices/EventLog",
1182 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1183 asyncResp->res.jsonValue["@odata.type"] =
1184 "#LogService.v1_2_0.LogService";
1185 asyncResp->res.jsonValue["Name"] = "Event Log Service";
1186 asyncResp->res.jsonValue["Description"] =
1187 "System Event Log Service";
1188 asyncResp->res.jsonValue["Id"] = "EventLog";
1189 asyncResp->res.jsonValue["OverWritePolicy"] =
1190 log_service::OverWritePolicy::WrapsWhenFull;
Tejas Patil7c8c4052021-06-04 17:43:14 +05301191
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001192 std::pair<std::string, std::string> redfishDateTimeOffset =
1193 redfish::time_utils::getDateTimeOffsetNow();
Tejas Patil7c8c4052021-06-04 17:43:14 +05301194
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001195 asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
1196 asyncResp->res.jsonValue["DateTimeLocalOffset"] =
1197 redfishDateTimeOffset.second;
Tejas Patil7c8c4052021-06-04 17:43:14 +05301198
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001199 asyncResp->res.jsonValue["Entries"]["@odata.id"] = std::format(
1200 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
Ed Tanous20fa6a22024-05-20 18:02:58 -07001201 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001202 asyncResp->res
1203 .jsonValue["Actions"]["#LogService.ClearLog"]["target"]
1204
1205 = std::format(
1206 "/redfish/v1/Systems/{}/LogServices/EventLog/Actions/LogService.ClearLog",
1207 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1208 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001209}
1210
Alexander Hansen599b9af2024-08-06 15:11:57 +02001211inline void handleSystemsLogServicesEventLogActionsClearPost(
1212 App& app, const crow::Request& req,
1213 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1214 const std::string& systemName)
1215{
1216 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1217 {
1218 return;
1219 }
1220 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1221 {
1222 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1223 systemName);
1224 return;
1225 }
1226
1227 // Clear the EventLog by deleting the log files
1228 std::vector<std::filesystem::path> redfishLogFiles;
1229 if (getRedfishLogFiles(redfishLogFiles))
1230 {
1231 for (const std::filesystem::path& file : redfishLogFiles)
1232 {
1233 std::error_code ec;
1234 std::filesystem::remove(file, ec);
1235 }
1236 }
1237
1238 // Reload rsyslog so it knows to start new log files
Ed Tanous177612a2025-02-14 15:16:09 -08001239 dbus::utility::async_method_call(
1240 asyncResp,
Alexander Hansen599b9af2024-08-06 15:11:57 +02001241 [asyncResp](const boost::system::error_code& ec) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001242 if (ec)
1243 {
1244 BMCWEB_LOG_ERROR("Failed to reload rsyslog: {}", ec);
1245 messages::internalError(asyncResp->res);
1246 return;
1247 }
Alexander Hansen599b9af2024-08-06 15:11:57 +02001248
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001249 messages::success(asyncResp->res);
1250 },
Alexander Hansen599b9af2024-08-06 15:11:57 +02001251 "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
1252 "org.freedesktop.systemd1.Manager", "ReloadUnit", "rsyslog.service",
1253 "replace");
1254}
1255
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001256inline void requestRoutesJournalEventLogClear(App& app)
1257{
Jason M. Bills4978b632022-02-22 14:17:43 -08001258 BMCWEB_ROUTE(
1259 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07001260 "/redfish/v1/Systems/<str>/LogServices/EventLog/Actions/LogService.ClearLog/")
Abhishek Patelfff6a4d2021-07-21 11:29:45 -05001261 .privileges(redfish::privileges::
1262 postLogServiceSubOverComputerSystemLogServiceCollection)
Alexander Hansen599b9af2024-08-06 15:11:57 +02001263 .methods(boost::beast::http::verb::post)(std::bind_front(
1264 handleSystemsLogServicesEventLogActionsClearPost, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001265}
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001266
Jason M. Billsac992cd2022-06-24 13:31:46 -07001267enum class LogParseError
1268{
1269 success,
1270 parseFailed,
1271 messageIdNotInRegistry,
1272};
1273
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001274static LogParseError fillEventLogEntryJson(
1275 const std::string& logEntryID, const std::string& logEntry,
1276 nlohmann::json::object_t& logEntryJson)
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001277{
Jason M. Bills95820182019-04-22 16:25:34 -07001278 // The redfish log format is "<Timestamp> <MessageId>,<MessageArgs>"
Jason M. Billscd225da2019-05-08 15:31:57 -07001279 // First get the Timestamp
Ed Tanousf23b7292020-10-15 09:41:17 -07001280 size_t space = logEntry.find_first_of(' ');
Jason M. Billscd225da2019-05-08 15:31:57 -07001281 if (space == std::string::npos)
Jason M. Bills95820182019-04-22 16:25:34 -07001282 {
Jason M. Billsac992cd2022-06-24 13:31:46 -07001283 return LogParseError::parseFailed;
Jason M. Bills95820182019-04-22 16:25:34 -07001284 }
Jason M. Billscd225da2019-05-08 15:31:57 -07001285 std::string timestamp = logEntry.substr(0, space);
1286 // Then get the log contents
Ed Tanousf23b7292020-10-15 09:41:17 -07001287 size_t entryStart = logEntry.find_first_not_of(' ', space);
Jason M. Billscd225da2019-05-08 15:31:57 -07001288 if (entryStart == std::string::npos)
1289 {
Jason M. Billsac992cd2022-06-24 13:31:46 -07001290 return LogParseError::parseFailed;
Jason M. Billscd225da2019-05-08 15:31:57 -07001291 }
1292 std::string_view entry(logEntry);
1293 entry.remove_prefix(entryStart);
1294 // Use split to separate the entry into its fields
1295 std::vector<std::string> logEntryFields;
Ed Tanous50ebd4a2023-01-19 19:03:17 -08001296 bmcweb::split(logEntryFields, entry, ',');
Jason M. Billscd225da2019-05-08 15:31:57 -07001297 // We need at least a MessageId to be valid
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001298 auto logEntryIter = logEntryFields.begin();
1299 if (logEntryIter == logEntryFields.end())
Jason M. Billscd225da2019-05-08 15:31:57 -07001300 {
Jason M. Billsac992cd2022-06-24 13:31:46 -07001301 return LogParseError::parseFailed;
Jason M. Billscd225da2019-05-08 15:31:57 -07001302 }
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001303 std::string& messageID = *logEntryIter;
Jason M. Bills4851d452019-03-28 11:27:48 -07001304 // Get the Message from the MessageRegistry
Ed Tanousfffb8c12022-02-07 23:53:03 -08001305 const registries::Message* message = registries::getMessage(messageID);
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001306
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001307 logEntryIter++;
Sui Chen54417b02022-03-24 14:59:52 -07001308 if (message == nullptr)
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001309 {
Ed Tanous62598e32023-07-17 17:06:25 -07001310 BMCWEB_LOG_WARNING("Log entry not found in registry: {}", logEntry);
Jason M. Billsac992cd2022-06-24 13:31:46 -07001311 return LogParseError::messageIdNotInRegistry;
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001312 }
1313
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001314 std::vector<std::string_view> messageArgs(logEntryIter,
1315 logEntryFields.end());
Ed Tanousc05bba42023-06-28 08:33:29 -07001316 messageArgs.resize(message->numberOfArgs);
1317
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001318 std::string msg =
1319 redfish::registries::fillMessageArgs(messageArgs, message->message);
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001320 if (msg.empty())
Jason M. Bills4851d452019-03-28 11:27:48 -07001321 {
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001322 return LogParseError::parseFailed;
Jason M. Bills4851d452019-03-28 11:27:48 -07001323 }
1324
Jason M. Bills95820182019-04-22 16:25:34 -07001325 // Get the Created time from the timestamp. The log timestamp is in RFC3339
1326 // format which matches the Redfish format except for the fractional seconds
1327 // between the '.' and the '+', so just remove them.
Ed Tanousf23b7292020-10-15 09:41:17 -07001328 std::size_t dot = timestamp.find_first_of('.');
1329 std::size_t plus = timestamp.find_first_of('+');
Jason M. Bills95820182019-04-22 16:25:34 -07001330 if (dot != std::string::npos && plus != std::string::npos)
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001331 {
Jason M. Bills95820182019-04-22 16:25:34 -07001332 timestamp.erase(dot, plus - dot);
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001333 }
1334
1335 // Fill in the log entry with the gathered data
Vijay Lobo9c11a172021-10-07 16:53:16 -05001336 logEntryJson["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
Ed Tanousef4c65b2023-04-24 15:28:50 -07001337 logEntryJson["@odata.id"] = boost::urls::format(
Ed Tanous253f11b2024-05-16 09:38:31 -07001338 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}",
1339 BMCWEB_REDFISH_SYSTEM_URI_NAME, logEntryID);
Jason M. Bills84afc482022-06-24 12:38:23 -07001340 logEntryJson["Name"] = "System Event Log Entry";
1341 logEntryJson["Id"] = logEntryID;
1342 logEntryJson["Message"] = std::move(msg);
1343 logEntryJson["MessageId"] = std::move(messageID);
1344 logEntryJson["MessageArgs"] = messageArgs;
1345 logEntryJson["EntryType"] = "Event";
1346 logEntryJson["Severity"] = message->messageSeverity;
1347 logEntryJson["Created"] = std::move(timestamp);
Jason M. Billsac992cd2022-06-24 13:31:46 -07001348 return LogParseError::success;
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001349}
1350
Myung Bae7f3726a2025-04-26 15:17:23 -05001351inline void fillEventLogLogEntryFromDbusLogEntry(
1352 const DbusEventLogEntry& entry, nlohmann::json& objectToFillOut)
Ed Tanous898f2aa2024-08-07 12:18:22 -07001353{
Ed Tanous898f2aa2024-08-07 12:18:22 -07001354 objectToFillOut["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
1355 objectToFillOut["@odata.id"] = boost::urls::format(
1356 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}",
Alexander Hansen262dcc12024-09-19 12:04:03 +02001357 BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(entry.Id));
Ed Tanous898f2aa2024-08-07 12:18:22 -07001358 objectToFillOut["Name"] = "System Event Log Entry";
Alexander Hansen262dcc12024-09-19 12:04:03 +02001359 objectToFillOut["Id"] = std::to_string(entry.Id);
1360 objectToFillOut["Message"] = entry.Message;
1361 objectToFillOut["Resolved"] = entry.Resolved;
1362 std::optional<bool> notifyAction =
1363 getProviderNotifyAction(entry.ServiceProviderNotify);
Ed Tanous898f2aa2024-08-07 12:18:22 -07001364 if (notifyAction)
1365 {
1366 objectToFillOut["ServiceProviderNotified"] = *notifyAction;
1367 }
Alexander Hansen262dcc12024-09-19 12:04:03 +02001368 if ((entry.Resolution != nullptr) && !entry.Resolution->empty())
Ed Tanous898f2aa2024-08-07 12:18:22 -07001369 {
Alexander Hansen262dcc12024-09-19 12:04:03 +02001370 objectToFillOut["Resolution"] = *entry.Resolution;
Ed Tanous898f2aa2024-08-07 12:18:22 -07001371 }
1372 objectToFillOut["EntryType"] = "Event";
Alexander Hansen262dcc12024-09-19 12:04:03 +02001373 objectToFillOut["Severity"] =
1374 translateSeverityDbusToRedfish(entry.Severity);
Ed Tanous898f2aa2024-08-07 12:18:22 -07001375 objectToFillOut["Created"] =
Alexander Hansen262dcc12024-09-19 12:04:03 +02001376 redfish::time_utils::getDateTimeUintMs(entry.Timestamp);
Ed Tanous898f2aa2024-08-07 12:18:22 -07001377 objectToFillOut["Modified"] =
Alexander Hansen262dcc12024-09-19 12:04:03 +02001378 redfish::time_utils::getDateTimeUintMs(entry.UpdateTimestamp);
1379 if (entry.Path != nullptr)
Ed Tanous898f2aa2024-08-07 12:18:22 -07001380 {
1381 objectToFillOut["AdditionalDataURI"] = boost::urls::format(
1382 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}/attachment",
Alexander Hansen262dcc12024-09-19 12:04:03 +02001383 BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(entry.Id));
Ed Tanous898f2aa2024-08-07 12:18:22 -07001384 }
1385}
1386
Ed Tanousb7290962024-08-07 11:09:51 -07001387inline void afterLogEntriesGetManagedObjects(
1388 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1389 const boost::system::error_code& ec,
1390 const dbus::utility::ManagedObjectType& resp)
1391{
1392 if (ec)
1393 {
1394 // TODO Handle for specific error code
1395 BMCWEB_LOG_ERROR("getLogEntriesIfaceData resp_handler got error {}",
1396 ec);
1397 messages::internalError(asyncResp->res);
1398 return;
1399 }
1400 nlohmann::json::array_t entriesArray;
1401 for (const auto& objectPath : resp)
1402 {
Ed Tanous898f2aa2024-08-07 12:18:22 -07001403 dbus::utility::DBusPropertiesMap propsFlattened;
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001404 auto isEntry =
1405 std::ranges::find_if(objectPath.second, [](const auto& object) {
1406 return object.first == "xyz.openbmc_project.Logging.Entry";
1407 });
Ed Tanous898f2aa2024-08-07 12:18:22 -07001408 if (isEntry == objectPath.second.end())
Ed Tanousb7290962024-08-07 11:09:51 -07001409 {
1410 continue;
1411 }
Myung Bae7f3726a2025-04-26 15:17:23 -05001412
Ed Tanous898f2aa2024-08-07 12:18:22 -07001413 for (const auto& interfaceMap : objectPath.second)
Ed Tanousb7290962024-08-07 11:09:51 -07001414 {
Ed Tanous898f2aa2024-08-07 12:18:22 -07001415 for (const auto& propertyMap : interfaceMap.second)
Ed Tanousb7290962024-08-07 11:09:51 -07001416 {
Ed Tanous898f2aa2024-08-07 12:18:22 -07001417 propsFlattened.emplace_back(propertyMap.first,
1418 propertyMap.second);
Ed Tanousb7290962024-08-07 11:09:51 -07001419 }
1420 }
Myung Bae7f3726a2025-04-26 15:17:23 -05001421 std::optional<DbusEventLogEntry> optEntry =
1422 fillDbusEventLogEntryFromPropertyMap(propsFlattened);
1423
1424 if (!optEntry.has_value())
Igor Kanyuka90896602025-03-13 08:52:38 +00001425 {
Myung Bae7f3726a2025-04-26 15:17:23 -05001426 messages::internalError(asyncResp->res);
Igor Kanyuka90896602025-03-13 08:52:38 +00001427 return;
1428 }
Myung Bae7f3726a2025-04-26 15:17:23 -05001429 fillEventLogLogEntryFromDbusLogEntry(*optEntry,
1430 entriesArray.emplace_back());
Ed Tanousb7290962024-08-07 11:09:51 -07001431 }
Ed Tanous898f2aa2024-08-07 12:18:22 -07001432
Igor Kanyuka90896602025-03-13 08:52:38 +00001433 redfish::json_util::sortJsonArrayByKey(entriesArray, "Id");
Ed Tanousb7290962024-08-07 11:09:51 -07001434 asyncResp->res.jsonValue["Members@odata.count"] = entriesArray.size();
1435 asyncResp->res.jsonValue["Members"] = std::move(entriesArray);
1436}
1437
Alexander Hansen599b9af2024-08-06 15:11:57 +02001438inline void handleSystemsLogServiceEventLogLogEntryCollection(
1439 App& app, const crow::Request& req,
1440 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1441 const std::string& systemName)
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001442{
Alexander Hansen599b9af2024-08-06 15:11:57 +02001443 query_param::QueryCapabilities capabilities = {
1444 .canDelegateTop = true,
1445 .canDelegateSkip = true,
1446 };
1447 query_param::Query delegatedQuery;
1448 if (!redfish::setUpRedfishRouteWithDelegation(app, req, asyncResp,
1449 delegatedQuery, capabilities))
1450 {
1451 return;
1452 }
1453 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1454 {
1455 // Option currently returns no systems. TBD
1456 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1457 systemName);
1458 return;
1459 }
1460 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1461 {
1462 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1463 systemName);
1464 return;
1465 }
1466
1467 size_t top = delegatedQuery.top.value_or(query_param::Query::maxTop);
1468 size_t skip = delegatedQuery.skip.value_or(0);
1469
1470 // Collections don't include the static data added by SubRoute
1471 // because it has a duplicate entry for members
1472 asyncResp->res.jsonValue["@odata.type"] =
1473 "#LogEntryCollection.LogEntryCollection";
1474 asyncResp->res.jsonValue["@odata.id"] =
1475 std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
1476 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1477 asyncResp->res.jsonValue["Name"] = "System Event Log Entries";
1478 asyncResp->res.jsonValue["Description"] =
1479 "Collection of System Event Log Entries";
1480
1481 nlohmann::json& logEntryArray = asyncResp->res.jsonValue["Members"];
1482 logEntryArray = nlohmann::json::array();
1483 // Go through the log files and create a unique ID for each
1484 // entry
1485 std::vector<std::filesystem::path> redfishLogFiles;
1486 getRedfishLogFiles(redfishLogFiles);
1487 uint64_t entryCount = 0;
1488 std::string logEntry;
1489
1490 // Oldest logs are in the last file, so start there and loop
1491 // backwards
1492 for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend(); it++)
1493 {
1494 std::ifstream logStream(*it);
1495 if (!logStream.is_open())
Ed Tanous002d39b2022-05-31 08:59:27 -07001496 {
Alexander Hansen599b9af2024-08-06 15:11:57 +02001497 continue;
Ed Tanous22d268c2022-05-19 09:39:07 -07001498 }
1499
Alexander Hansen599b9af2024-08-06 15:11:57 +02001500 // Reset the unique ID on the first entry
1501 bool firstEntry = true;
1502 while (std::getline(logStream, logEntry))
Ed Tanous002d39b2022-05-31 08:59:27 -07001503 {
Alexander Hansen599b9af2024-08-06 15:11:57 +02001504 std::string idStr;
1505 if (!getUniqueEntryID(logEntry, idStr, firstEntry))
1506 {
1507 continue;
1508 }
1509 firstEntry = false;
1510
1511 nlohmann::json::object_t bmcLogEntry;
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001512 LogParseError status =
1513 fillEventLogEntryJson(idStr, logEntry, bmcLogEntry);
Alexander Hansen599b9af2024-08-06 15:11:57 +02001514 if (status == LogParseError::messageIdNotInRegistry)
1515 {
1516 continue;
1517 }
1518 if (status != LogParseError::success)
1519 {
1520 messages::internalError(asyncResp->res);
1521 return;
1522 }
1523
1524 entryCount++;
1525 // Handle paging using skip (number of entries to skip from the
1526 // start) and top (number of entries to display)
1527 if (entryCount <= skip || entryCount > skip + top)
Jason M. Bills4978b632022-02-22 14:17:43 -08001528 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001529 continue;
Jason M. Bills4978b632022-02-22 14:17:43 -08001530 }
Jason M. Bills897967d2019-07-29 17:05:30 -07001531
Alexander Hansen599b9af2024-08-06 15:11:57 +02001532 logEntryArray.emplace_back(std::move(bmcLogEntry));
1533 }
1534 }
1535 asyncResp->res.jsonValue["Members@odata.count"] = entryCount;
1536 if (skip + top < entryCount)
1537 {
1538 asyncResp->res.jsonValue["Members@odata.nextLink"] =
1539 boost::urls::format(
1540 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries?$skip={}",
1541 BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(skip + top));
1542 }
1543}
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001544
Alexander Hansen599b9af2024-08-06 15:11:57 +02001545inline void requestRoutesJournalEventLogEntryCollection(App& app)
1546{
1547 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/")
1548 .privileges(redfish::privileges::getLogEntryCollection)
1549 .methods(boost::beast::http::verb::get)(std::bind_front(
1550 handleSystemsLogServiceEventLogLogEntryCollection, std::ref(app)));
1551}
1552
1553inline void handleSystemsLogServiceEventLogEntriesGet(
1554 App& app, const crow::Request& req,
1555 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1556 const std::string& systemName, const std::string& param)
1557{
1558 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1559 {
1560 return;
1561 }
1562 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1563 {
1564 // Option currently returns no systems. TBD
1565 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1566 systemName);
1567 return;
1568 }
1569
1570 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1571 {
1572 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1573 systemName);
1574 return;
1575 }
1576
1577 const std::string& targetID = param;
1578
1579 // Go through the log files and check the unique ID for each
1580 // entry to find the target entry
1581 std::vector<std::filesystem::path> redfishLogFiles;
1582 getRedfishLogFiles(redfishLogFiles);
1583 std::string logEntry;
1584
1585 // Oldest logs are in the last file, so start there and loop
1586 // backwards
1587 for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend(); it++)
1588 {
1589 std::ifstream logStream(*it);
1590 if (!logStream.is_open())
1591 {
1592 continue;
1593 }
1594
1595 // Reset the unique ID on the first entry
1596 bool firstEntry = true;
1597 while (std::getline(logStream, logEntry))
1598 {
1599 std::string idStr;
1600 if (!getUniqueEntryID(logEntry, idStr, firstEntry))
1601 {
1602 continue;
1603 }
1604 firstEntry = false;
1605
1606 if (idStr == targetID)
1607 {
Jason M. Billsde703c52022-06-23 14:19:04 -07001608 nlohmann::json::object_t bmcLogEntry;
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001609 LogParseError status =
1610 fillEventLogEntryJson(idStr, logEntry, bmcLogEntry);
Jason M. Billsac992cd2022-06-24 13:31:46 -07001611 if (status != LogParseError::success)
Ed Tanous002d39b2022-05-31 08:59:27 -07001612 {
1613 messages::internalError(asyncResp->res);
1614 return;
Andrew Geisslercb92c032018-08-17 07:56:14 -07001615 }
Alexander Hansen599b9af2024-08-06 15:11:57 +02001616 asyncResp->res.jsonValue.update(bmcLogEntry);
1617 return;
Jason M. Bills4978b632022-02-22 14:17:43 -08001618 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001619 }
Alexander Hansen599b9af2024-08-06 15:11:57 +02001620 }
1621 // Requested ID was not found
1622 messages::resourceNotFound(asyncResp->res, "LogEntry", targetID);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001623}
Chicago Duan336e96c2019-07-15 14:22:08 +08001624
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001625inline void requestRoutesJournalEventLogEntry(App& app)
1626{
1627 BMCWEB_ROUTE(
Ed Tanous22d268c2022-05-19 09:39:07 -07001628 app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001629 .privileges(redfish::privileges::getLogEntry)
Alexander Hansen599b9af2024-08-06 15:11:57 +02001630 .methods(boost::beast::http::verb::get)(std::bind_front(
1631 handleSystemsLogServiceEventLogEntriesGet, std::ref(app)));
1632}
1633
1634inline void dBusEventLogEntryCollection(
1635 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1636{
1637 // Collections don't include the static data added by SubRoute
1638 // because it has a duplicate entry for members
1639 asyncResp->res.jsonValue["@odata.type"] =
1640 "#LogEntryCollection.LogEntryCollection";
1641 asyncResp->res.jsonValue["@odata.id"] =
1642 std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
1643 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1644 asyncResp->res.jsonValue["Name"] = "System Event Log Entries";
1645 asyncResp->res.jsonValue["Description"] =
1646 "Collection of System Event Log Entries";
1647
1648 // DBus implementation of EventLog/Entries
1649 // Make call to Logging Service to find all log entry objects
1650 sdbusplus::message::object_path path("/xyz/openbmc_project/logging");
1651 dbus::utility::getManagedObjects(
1652 "xyz.openbmc_project.Logging", path,
1653 [asyncResp](const boost::system::error_code& ec,
1654 const dbus::utility::ManagedObjectType& resp) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001655 afterLogEntriesGetManagedObjects(asyncResp, ec, resp);
1656 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001657}
1658
1659inline void requestRoutesDBusEventLogEntryCollection(App& app)
1660{
Ed Tanous22d268c2022-05-19 09:39:07 -07001661 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/")
Ed Tanoused398212021-06-09 17:05:54 -07001662 .privileges(redfish::privileges::getLogEntryCollection)
Ed Tanous002d39b2022-05-31 08:59:27 -07001663 .methods(boost::beast::http::verb::get)(
1664 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07001665 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1666 const std::string& systemName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001667 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1668 {
1669 return;
1670 }
1671 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1672 {
1673 // Option currently returns no systems. TBD
1674 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1675 systemName);
1676 return;
1677 }
1678 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1679 {
1680 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1681 systemName);
1682 return;
1683 }
1684 dBusEventLogEntryCollection(asyncResp);
1685 });
Alexander Hansen599b9af2024-08-06 15:11:57 +02001686}
Ed Tanous22d268c2022-05-19 09:39:07 -07001687
Myung Baec6b7cae2025-06-05 15:46:57 -05001688inline void afterDBusEventLogEntryGet(
1689 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1690 const std::string& entryID, const boost::system::error_code& ec,
1691 const dbus::utility::DBusPropertiesMap& resp)
1692{
1693 if (ec.value() == EBADR)
1694 {
1695 messages::resourceNotFound(asyncResp->res, "EventLogEntry", entryID);
1696 return;
1697 }
1698 if (ec)
1699 {
1700 BMCWEB_LOG_ERROR("EventLogEntry (DBus) resp_handler got error {}", ec);
1701 messages::internalError(asyncResp->res);
1702 return;
1703 }
1704
Myung Bae7f3726a2025-04-26 15:17:23 -05001705 std::optional<DbusEventLogEntry> optEntry =
1706 fillDbusEventLogEntryFromPropertyMap(resp);
1707
1708 if (!optEntry.has_value())
1709 {
1710 messages::internalError(asyncResp->res);
1711 return;
1712 }
1713
1714 fillEventLogLogEntryFromDbusLogEntry(*optEntry, asyncResp->res.jsonValue);
Myung Baec6b7cae2025-06-05 15:46:57 -05001715}
1716
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001717inline void dBusEventLogEntryGet(
1718 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID)
Alexander Hansen599b9af2024-08-06 15:11:57 +02001719{
1720 dbus::utility::escapePathForDbus(entryID);
Ed Tanous002d39b2022-05-31 08:59:27 -07001721
Alexander Hansen599b9af2024-08-06 15:11:57 +02001722 // DBus implementation of EventLog/Entries
1723 // Make call to Logging Service to find all log entry objects
Ed Tanousdeae6a72024-11-11 21:58:57 -08001724 dbus::utility::getAllProperties(
1725 "xyz.openbmc_project.Logging",
Alexander Hansen599b9af2024-08-06 15:11:57 +02001726 "/xyz/openbmc_project/logging/entry/" + entryID, "",
Myung Baec6b7cae2025-06-05 15:46:57 -05001727 std::bind_front(afterDBusEventLogEntryGet, asyncResp, entryID));
Alexander Hansen599b9af2024-08-06 15:11:57 +02001728}
1729
Patrick Williams504af5a2025-02-03 14:29:03 -05001730inline void dBusEventLogEntryPatch(
1731 const crow::Request& req,
1732 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1733 const std::string& entryId)
Alexander Hansen599b9af2024-08-06 15:11:57 +02001734{
1735 std::optional<bool> resolved;
1736
1737 if (!json_util::readJsonPatch(req, asyncResp->res, "Resolved", resolved))
1738 {
1739 return;
1740 }
1741 BMCWEB_LOG_DEBUG("Set Resolved");
1742
1743 setDbusProperty(asyncResp, "Resolved", "xyz.openbmc_project.Logging",
1744 "/xyz/openbmc_project/logging/entry/" + entryId,
1745 "xyz.openbmc_project.Logging.Entry", "Resolved",
1746 resolved.value_or(false));
1747}
1748
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001749inline void dBusEventLogEntryDelete(
1750 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID)
Alexander Hansen599b9af2024-08-06 15:11:57 +02001751{
1752 BMCWEB_LOG_DEBUG("Do delete single event entries.");
1753
1754 dbus::utility::escapePathForDbus(entryID);
1755
1756 // Process response from Logging service.
1757 auto respHandler = [asyncResp,
1758 entryID](const boost::system::error_code& ec) {
1759 BMCWEB_LOG_DEBUG("EventLogEntry (DBus) doDelete callback: Done");
1760 if (ec)
1761 {
1762 if (ec.value() == EBADR)
Ed Tanous45ca1b82022-03-25 13:07:27 -07001763 {
Alexander Hansen599b9af2024-08-06 15:11:57 +02001764 messages::resourceNotFound(asyncResp->res, "LogEntry", entryID);
Ed Tanous45ca1b82022-03-25 13:07:27 -07001765 return;
1766 }
Alexander Hansen599b9af2024-08-06 15:11:57 +02001767 // TODO Handle for specific error code
1768 BMCWEB_LOG_ERROR(
1769 "EventLogEntry (DBus) doDelete respHandler got error {}", ec);
1770 asyncResp->res.result(
1771 boost::beast::http::status::internal_server_error);
1772 return;
1773 }
Abhishek Patel9017faf2021-09-14 22:48:55 -05001774
Alexander Hansen599b9af2024-08-06 15:11:57 +02001775 asyncResp->res.result(boost::beast::http::status::ok);
1776 };
1777
1778 // Make call to Logging service to request Delete Log
Ed Tanous177612a2025-02-14 15:16:09 -08001779 dbus::utility::async_method_call(
1780 asyncResp, respHandler, "xyz.openbmc_project.Logging",
Alexander Hansen599b9af2024-08-06 15:11:57 +02001781 "/xyz/openbmc_project/logging/entry/" + entryID,
1782 "xyz.openbmc_project.Object.Delete", "Delete");
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001783}
Xiaochao Ma75710de2021-01-21 17:56:02 +08001784
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001785inline void requestRoutesDBusEventLogEntry(App& app)
Adriana Kobylak400fd1f2021-01-29 09:01:30 -06001786{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001787 BMCWEB_ROUTE(
Ed Tanous22d268c2022-05-19 09:39:07 -07001788 app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001789 .privileges(redfish::privileges::getLogEntry)
Ed Tanous002d39b2022-05-31 08:59:27 -07001790 .methods(boost::beast::http::verb::get)(
1791 [&app](const crow::Request& req,
1792 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous898f2aa2024-08-07 12:18:22 -07001793 const std::string& systemName, const std::string& entryId) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001794 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1795 {
1796 return;
1797 }
1798 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1799 {
1800 // Option currently returns no systems. TBD
1801 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1802 systemName);
1803 return;
1804 }
1805 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1806 {
1807 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1808 systemName);
1809 return;
1810 }
Ed Tanous22d268c2022-05-19 09:39:07 -07001811
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001812 dBusEventLogEntryGet(asyncResp, entryId);
1813 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001814
1815 BMCWEB_ROUTE(
Ed Tanous22d268c2022-05-19 09:39:07 -07001816 app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001817 .privileges(redfish::privileges::patchLogEntry)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001818 .methods(boost::beast::http::verb::patch)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07001819 [&app](const crow::Request& req,
1820 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -07001821 const std::string& systemName, const std::string& entryId) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001822 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1823 {
1824 return;
1825 }
1826 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1827 {
1828 // Option currently returns no systems. TBD
1829 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1830 systemName);
1831 return;
1832 }
1833 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1834 {
1835 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1836 systemName);
1837 return;
1838 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001839
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001840 dBusEventLogEntryPatch(req, asyncResp, entryId);
1841 });
Adriana Kobylak400fd1f2021-01-29 09:01:30 -06001842
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001843 BMCWEB_ROUTE(
Ed Tanous22d268c2022-05-19 09:39:07 -07001844 app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
Abhishek Patelfff6a4d2021-07-21 11:29:45 -05001845 .privileges(
1846 redfish::privileges::
1847 deleteLogEntrySubOverComputerSystemLogServiceCollectionLogServiceLogEntryCollection)
Ed Tanous002d39b2022-05-31 08:59:27 -07001848 .methods(boost::beast::http::verb::delete_)(
1849 [&app](const crow::Request& req,
1850 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -07001851 const std::string& systemName, const std::string& param) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001852 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1853 {
1854 return;
1855 }
1856 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1857 {
1858 // Option currently returns no systems. TBD
1859 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1860 systemName);
1861 return;
1862 }
1863 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1864 {
1865 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1866 systemName);
1867 return;
1868 }
1869 dBusEventLogEntryDelete(asyncResp, param);
1870 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001871}
1872
Claire Weinandd72e872022-08-15 14:20:06 -07001873inline void handleBMCLogServicesCollectionGet(
Claire Weinanfdd26902022-03-01 14:18:25 -08001874 crow::App& app, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07001875 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1876 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08001877{
1878 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1879 {
1880 return;
1881 }
Ed Tanous253f11b2024-05-16 09:38:31 -07001882
1883 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
1884 {
1885 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
1886 return;
1887 }
1888
Claire Weinanfdd26902022-03-01 14:18:25 -08001889 // Collections don't include the static data added by SubRoute
1890 // because it has a duplicate entry for members
1891 asyncResp->res.jsonValue["@odata.type"] =
1892 "#LogServiceCollection.LogServiceCollection";
Ed Tanous253f11b2024-05-16 09:38:31 -07001893 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
1894 "/redfish/v1/Managers/{}/LogServices", BMCWEB_REDFISH_MANAGER_URI_NAME);
Claire Weinanfdd26902022-03-01 14:18:25 -08001895 asyncResp->res.jsonValue["Name"] = "Open BMC Log Services Collection";
1896 asyncResp->res.jsonValue["Description"] =
1897 "Collection of LogServices for this Manager";
1898 nlohmann::json& logServiceArray = asyncResp->res.jsonValue["Members"];
1899 logServiceArray = nlohmann::json::array();
1900
Ed Tanous25b54db2024-04-17 15:40:31 -07001901 if constexpr (BMCWEB_REDFISH_BMC_JOURNAL)
1902 {
1903 nlohmann::json::object_t journal;
Ed Tanous253f11b2024-05-16 09:38:31 -07001904 journal["@odata.id"] =
1905 boost::urls::format("/redfish/v1/Managers/{}/LogServices/Journal",
1906 BMCWEB_REDFISH_MANAGER_URI_NAME);
Ed Tanous25b54db2024-04-17 15:40:31 -07001907 logServiceArray.emplace_back(std::move(journal));
1908 }
Claire Weinanfdd26902022-03-01 14:18:25 -08001909
1910 asyncResp->res.jsonValue["Members@odata.count"] = logServiceArray.size();
1911
Ed Tanous25b54db2024-04-17 15:40:31 -07001912 if constexpr (BMCWEB_REDFISH_DUMP_LOG)
1913 {
1914 constexpr std::array<std::string_view, 1> interfaces = {
1915 "xyz.openbmc_project.Collection.DeleteAll"};
1916 dbus::utility::getSubTreePaths(
1917 "/xyz/openbmc_project/dump", 0, interfaces,
1918 [asyncResp](const boost::system::error_code& ec,
1919 const dbus::utility::MapperGetSubTreePathsResponse&
1920 subTreePaths) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001921 if (ec)
Ed Tanous25b54db2024-04-17 15:40:31 -07001922 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001923 BMCWEB_LOG_ERROR(
1924 "handleBMCLogServicesCollectionGet respHandler got error {}",
1925 ec);
1926 // Assume that getting an error simply means there are no
1927 // dump LogServices. Return without adding any error
1928 // response.
1929 return;
Ed Tanous25b54db2024-04-17 15:40:31 -07001930 }
Ed Tanous25b54db2024-04-17 15:40:31 -07001931
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001932 nlohmann::json& logServiceArrayLocal =
1933 asyncResp->res.jsonValue["Members"];
1934
1935 for (const std::string& path : subTreePaths)
1936 {
1937 if (path == "/xyz/openbmc_project/dump/bmc")
1938 {
1939 nlohmann::json::object_t member;
1940 member["@odata.id"] = boost::urls::format(
1941 "/redfish/v1/Managers/{}/LogServices/Dump",
1942 BMCWEB_REDFISH_MANAGER_URI_NAME);
1943 logServiceArrayLocal.emplace_back(std::move(member));
1944 }
1945 else if (path == "/xyz/openbmc_project/dump/faultlog")
1946 {
1947 nlohmann::json::object_t member;
1948 member["@odata.id"] = boost::urls::format(
1949 "/redfish/v1/Managers/{}/LogServices/FaultLog",
1950 BMCWEB_REDFISH_MANAGER_URI_NAME);
1951 logServiceArrayLocal.emplace_back(std::move(member));
1952 }
1953 }
1954
1955 asyncResp->res.jsonValue["Members@odata.count"] =
1956 logServiceArrayLocal.size();
1957 });
Ed Tanous25b54db2024-04-17 15:40:31 -07001958 }
Claire Weinanfdd26902022-03-01 14:18:25 -08001959}
1960
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001961inline void requestRoutesBMCLogServiceCollection(App& app)
1962{
Ed Tanous253f11b2024-05-16 09:38:31 -07001963 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/")
Gunnar Millsad89dcf2021-07-30 14:40:11 -05001964 .privileges(redfish::privileges::getLogServiceCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001965 .methods(boost::beast::http::verb::get)(
Claire Weinandd72e872022-08-15 14:20:06 -07001966 std::bind_front(handleBMCLogServicesCollectionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001967}
Ed Tanous1da66f72018-07-27 16:13:37 -07001968
Patrick Williams504af5a2025-02-03 14:29:03 -05001969inline void getDumpServiceInfo(
1970 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1971 const std::string& dumpType)
Claire Weinanfdd26902022-03-01 14:18:25 -08001972{
1973 std::string dumpPath;
Ed Tanous539d8c62024-06-19 14:38:27 -07001974 log_service::OverWritePolicy overWritePolicy =
1975 log_service::OverWritePolicy::Invalid;
Claire Weinanfdd26902022-03-01 14:18:25 -08001976 bool collectDiagnosticDataSupported = false;
1977
1978 if (dumpType == "BMC")
1979 {
Ed Tanous253f11b2024-05-16 09:38:31 -07001980 dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/Dump",
1981 BMCWEB_REDFISH_MANAGER_URI_NAME);
Ed Tanous539d8c62024-06-19 14:38:27 -07001982 overWritePolicy = log_service::OverWritePolicy::WrapsWhenFull;
Claire Weinanfdd26902022-03-01 14:18:25 -08001983 collectDiagnosticDataSupported = true;
1984 }
1985 else if (dumpType == "FaultLog")
1986 {
Ed Tanous253f11b2024-05-16 09:38:31 -07001987 dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/FaultLog",
1988 BMCWEB_REDFISH_MANAGER_URI_NAME);
Ed Tanous539d8c62024-06-19 14:38:27 -07001989 overWritePolicy = log_service::OverWritePolicy::Unknown;
Claire Weinanfdd26902022-03-01 14:18:25 -08001990 collectDiagnosticDataSupported = false;
1991 }
1992 else if (dumpType == "System")
1993 {
Ed Tanous253f11b2024-05-16 09:38:31 -07001994 dumpPath = std::format("/redfish/v1/Systems/{}/LogServices/Dump",
1995 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanous539d8c62024-06-19 14:38:27 -07001996 overWritePolicy = log_service::OverWritePolicy::WrapsWhenFull;
Claire Weinanfdd26902022-03-01 14:18:25 -08001997 collectDiagnosticDataSupported = true;
1998 }
1999 else
2000 {
Ed Tanous62598e32023-07-17 17:06:25 -07002001 BMCWEB_LOG_ERROR("getDumpServiceInfo() invalid dump type: {}",
2002 dumpType);
Claire Weinanfdd26902022-03-01 14:18:25 -08002003 messages::internalError(asyncResp->res);
2004 return;
2005 }
2006
2007 asyncResp->res.jsonValue["@odata.id"] = dumpPath;
2008 asyncResp->res.jsonValue["@odata.type"] = "#LogService.v1_2_0.LogService";
2009 asyncResp->res.jsonValue["Name"] = "Dump LogService";
2010 asyncResp->res.jsonValue["Description"] = dumpType + " Dump LogService";
2011 asyncResp->res.jsonValue["Id"] = std::filesystem::path(dumpPath).filename();
Ed Tanous539d8c62024-06-19 14:38:27 -07002012 asyncResp->res.jsonValue["OverWritePolicy"] = overWritePolicy;
Claire Weinanfdd26902022-03-01 14:18:25 -08002013
2014 std::pair<std::string, std::string> redfishDateTimeOffset =
Ed Tanous2b829372022-08-03 14:22:34 -07002015 redfish::time_utils::getDateTimeOffsetNow();
Claire Weinanfdd26902022-03-01 14:18:25 -08002016 asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
2017 asyncResp->res.jsonValue["DateTimeLocalOffset"] =
2018 redfishDateTimeOffset.second;
2019
2020 asyncResp->res.jsonValue["Entries"]["@odata.id"] = dumpPath + "/Entries";
Claire Weinanfdd26902022-03-01 14:18:25 -08002021
2022 if (collectDiagnosticDataSupported)
2023 {
2024 asyncResp->res.jsonValue["Actions"]["#LogService.CollectDiagnosticData"]
2025 ["target"] =
2026 dumpPath + "/Actions/LogService.CollectDiagnosticData";
2027 }
Claire Weinan0d946212022-07-13 19:40:19 -07002028
2029 constexpr std::array<std::string_view, 1> interfaces = {deleteAllInterface};
2030 dbus::utility::getSubTreePaths(
2031 "/xyz/openbmc_project/dump", 0, interfaces,
2032 [asyncResp, dumpType, dumpPath](
2033 const boost::system::error_code& ec,
2034 const dbus::utility::MapperGetSubTreePathsResponse& subTreePaths) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002035 if (ec)
Claire Weinan0d946212022-07-13 19:40:19 -07002036 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002037 BMCWEB_LOG_ERROR("getDumpServiceInfo respHandler got error {}",
2038 ec);
2039 // Assume that getting an error simply means there are no dump
2040 // LogServices. Return without adding any error response.
2041 return;
Claire Weinan0d946212022-07-13 19:40:19 -07002042 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002043 std::string dbusDumpPath = getDumpPath(dumpType);
2044 for (const std::string& path : subTreePaths)
2045 {
2046 if (path == dbusDumpPath)
2047 {
2048 asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"]
2049 ["target"] =
2050 dumpPath + "/Actions/LogService.ClearLog";
2051 break;
2052 }
2053 }
2054 });
Claire Weinanfdd26902022-03-01 14:18:25 -08002055}
2056
2057inline void handleLogServicesDumpServiceGet(
2058 crow::App& app, const std::string& dumpType, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07002059 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2060 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002061{
2062 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2063 {
2064 return;
2065 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002066
2067 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2068 {
2069 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2070 return;
2071 }
2072
Claire Weinanfdd26902022-03-01 14:18:25 -08002073 getDumpServiceInfo(asyncResp, dumpType);
2074}
2075
Ed Tanous22d268c2022-05-19 09:39:07 -07002076inline void handleLogServicesDumpServiceComputerSystemGet(
2077 crow::App& app, const crow::Request& req,
2078 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2079 const std::string& chassisId)
2080{
2081 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2082 {
2083 return;
2084 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002085 if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous22d268c2022-05-19 09:39:07 -07002086 {
2087 messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
2088 return;
2089 }
2090 getDumpServiceInfo(asyncResp, "System");
2091}
2092
Claire Weinanfdd26902022-03-01 14:18:25 -08002093inline void handleLogServicesDumpEntriesCollectionGet(
2094 crow::App& app, const std::string& dumpType, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07002095 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2096 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002097{
2098 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2099 {
2100 return;
2101 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002102
2103 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2104 {
2105 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2106 return;
2107 }
Claire Weinanfdd26902022-03-01 14:18:25 -08002108 getDumpEntryCollection(asyncResp, dumpType);
2109}
2110
Ed Tanous22d268c2022-05-19 09:39:07 -07002111inline void handleLogServicesDumpEntriesCollectionComputerSystemGet(
2112 crow::App& app, const crow::Request& req,
2113 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2114 const std::string& chassisId)
2115{
2116 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2117 {
2118 return;
2119 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002120 if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous22d268c2022-05-19 09:39:07 -07002121 {
2122 messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
2123 return;
2124 }
2125 getDumpEntryCollection(asyncResp, "System");
2126}
2127
Claire Weinanfdd26902022-03-01 14:18:25 -08002128inline void handleLogServicesDumpEntryGet(
2129 crow::App& app, const std::string& dumpType, const crow::Request& req,
2130 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous253f11b2024-05-16 09:38:31 -07002131 const std::string& managerId, const std::string& dumpId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002132{
2133 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2134 {
2135 return;
2136 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002137 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2138 {
2139 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2140 return;
2141 }
Claire Weinanfdd26902022-03-01 14:18:25 -08002142 getDumpEntryById(asyncResp, dumpId, dumpType);
2143}
Carson Labrado168d1b12023-03-27 17:04:46 +00002144
Ed Tanous22d268c2022-05-19 09:39:07 -07002145inline void handleLogServicesDumpEntryComputerSystemGet(
2146 crow::App& app, const crow::Request& req,
2147 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2148 const std::string& chassisId, const std::string& dumpId)
2149{
2150 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2151 {
2152 return;
2153 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002154 if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous22d268c2022-05-19 09:39:07 -07002155 {
2156 messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
2157 return;
2158 }
2159 getDumpEntryById(asyncResp, dumpId, "System");
2160}
Claire Weinanfdd26902022-03-01 14:18:25 -08002161
2162inline void handleLogServicesDumpEntryDelete(
2163 crow::App& app, const std::string& dumpType, const crow::Request& req,
2164 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous253f11b2024-05-16 09:38:31 -07002165 const std::string& managerId, const std::string& dumpId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002166{
2167 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2168 {
2169 return;
2170 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002171
2172 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2173 {
2174 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2175 return;
2176 }
Claire Weinanfdd26902022-03-01 14:18:25 -08002177 deleteDumpEntry(asyncResp, dumpId, dumpType);
2178}
2179
Ed Tanous22d268c2022-05-19 09:39:07 -07002180inline void handleLogServicesDumpEntryComputerSystemDelete(
2181 crow::App& app, const crow::Request& req,
2182 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2183 const std::string& chassisId, const std::string& dumpId)
2184{
2185 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2186 {
2187 return;
2188 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002189 if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous22d268c2022-05-19 09:39:07 -07002190 {
2191 messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
2192 return;
2193 }
2194 deleteDumpEntry(asyncResp, dumpId, "System");
2195}
2196
Carson Labrado168d1b12023-03-27 17:04:46 +00002197inline void handleLogServicesDumpEntryDownloadGet(
2198 crow::App& app, const std::string& dumpType, const crow::Request& req,
2199 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous253f11b2024-05-16 09:38:31 -07002200 const std::string& managerId, const std::string& dumpId)
Carson Labrado168d1b12023-03-27 17:04:46 +00002201{
2202 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2203 {
2204 return;
2205 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002206
2207 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2208 {
2209 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2210 return;
2211 }
Carson Labrado168d1b12023-03-27 17:04:46 +00002212 downloadDumpEntry(asyncResp, dumpId, dumpType);
2213}
2214
2215inline void handleDBusEventLogEntryDownloadGet(
2216 crow::App& app, const std::string& dumpType, const crow::Request& req,
2217 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2218 const std::string& systemName, const std::string& entryID)
2219{
2220 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2221 {
2222 return;
2223 }
2224 if (!http_helpers::isContentTypeAllowed(
2225 req.getHeaderValue("Accept"),
2226 http_helpers::ContentType::OctetStream, true))
2227 {
2228 asyncResp->res.result(boost::beast::http::status::bad_request);
2229 return;
2230 }
2231 downloadEventLogEntry(asyncResp, systemName, entryID, dumpType);
2232}
2233
Claire Weinanfdd26902022-03-01 14:18:25 -08002234inline void handleLogServicesDumpCollectDiagnosticDataPost(
2235 crow::App& app, const std::string& dumpType, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07002236 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2237 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002238{
2239 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2240 {
2241 return;
2242 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002243 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2244 {
2245 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2246 return;
2247 }
2248
Claire Weinanfdd26902022-03-01 14:18:25 -08002249 createDump(asyncResp, req, dumpType);
2250}
2251
Ed Tanous22d268c2022-05-19 09:39:07 -07002252inline void handleLogServicesDumpCollectDiagnosticDataComputerSystemPost(
2253 crow::App& app, const crow::Request& req,
2254 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002255 const std::string& systemName)
Ed Tanous22d268c2022-05-19 09:39:07 -07002256{
2257 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2258 {
2259 return;
2260 }
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002261
Ed Tanous25b54db2024-04-17 15:40:31 -07002262 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous22d268c2022-05-19 09:39:07 -07002263 {
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002264 // Option currently returns no systems. TBD
2265 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2266 systemName);
2267 return;
2268 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002269 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002270 {
2271 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2272 systemName);
Ed Tanous22d268c2022-05-19 09:39:07 -07002273 return;
2274 }
2275 createDump(asyncResp, req, "System");
2276}
2277
Claire Weinanfdd26902022-03-01 14:18:25 -08002278inline void handleLogServicesDumpClearLogPost(
2279 crow::App& app, const std::string& dumpType, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07002280 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2281 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002282{
2283 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2284 {
2285 return;
2286 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002287
2288 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2289 {
2290 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2291 return;
2292 }
Claire Weinanfdd26902022-03-01 14:18:25 -08002293 clearDump(asyncResp, dumpType);
2294}
2295
Ed Tanous22d268c2022-05-19 09:39:07 -07002296inline void handleLogServicesDumpClearLogComputerSystemPost(
2297 crow::App& app, const crow::Request& req,
2298 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002299 const std::string& systemName)
Ed Tanous22d268c2022-05-19 09:39:07 -07002300{
2301 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2302 {
2303 return;
2304 }
Ed Tanous25b54db2024-04-17 15:40:31 -07002305 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous22d268c2022-05-19 09:39:07 -07002306 {
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002307 // Option currently returns no systems. TBD
2308 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2309 systemName);
2310 return;
2311 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002312 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002313 {
2314 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2315 systemName);
Ed Tanous22d268c2022-05-19 09:39:07 -07002316 return;
2317 }
2318 clearDump(asyncResp, "System");
2319}
2320
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002321inline void requestRoutesBMCDumpService(App& app)
2322{
Ed Tanous253f11b2024-05-16 09:38:31 -07002323 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/Dump/")
Ed Tanoused398212021-06-09 17:05:54 -07002324 .privileges(redfish::privileges::getLogService)
Claire Weinanfdd26902022-03-01 14:18:25 -08002325 .methods(boost::beast::http::verb::get)(std::bind_front(
2326 handleLogServicesDumpServiceGet, std::ref(app), "BMC"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002327}
2328
2329inline void requestRoutesBMCDumpEntryCollection(App& app)
2330{
Ed Tanous253f11b2024-05-16 09:38:31 -07002331 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/")
Ed Tanoused398212021-06-09 17:05:54 -07002332 .privileges(redfish::privileges::getLogEntryCollection)
Claire Weinanfdd26902022-03-01 14:18:25 -08002333 .methods(boost::beast::http::verb::get)(std::bind_front(
2334 handleLogServicesDumpEntriesCollectionGet, std::ref(app), "BMC"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002335}
2336
2337inline void requestRoutesBMCDumpEntry(App& app)
2338{
2339 BMCWEB_ROUTE(app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002340 "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002341 .privileges(redfish::privileges::getLogEntry)
Claire Weinanfdd26902022-03-01 14:18:25 -08002342 .methods(boost::beast::http::verb::get)(std::bind_front(
2343 handleLogServicesDumpEntryGet, std::ref(app), "BMC"));
2344
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002345 BMCWEB_ROUTE(app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002346 "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002347 .privileges(redfish::privileges::deleteLogEntry)
Claire Weinanfdd26902022-03-01 14:18:25 -08002348 .methods(boost::beast::http::verb::delete_)(std::bind_front(
2349 handleLogServicesDumpEntryDelete, std::ref(app), "BMC"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002350}
2351
Carson Labrado168d1b12023-03-27 17:04:46 +00002352inline void requestRoutesBMCDumpEntryDownload(App& app)
2353{
2354 BMCWEB_ROUTE(
2355 app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002356 "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/attachment/")
Carson Labrado168d1b12023-03-27 17:04:46 +00002357 .privileges(redfish::privileges::getLogEntry)
2358 .methods(boost::beast::http::verb::get)(std::bind_front(
2359 handleLogServicesDumpEntryDownloadGet, std::ref(app), "BMC"));
2360}
2361
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002362inline void requestRoutesBMCDumpCreate(App& app)
2363{
George Liu0fda0f12021-11-16 10:06:17 +08002364 BMCWEB_ROUTE(
2365 app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002366 "/redfish/v1/Managers/<str>/LogServices/Dump/Actions/LogService.CollectDiagnosticData/")
Ed Tanoused398212021-06-09 17:05:54 -07002367 .privileges(redfish::privileges::postLogService)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002368 .methods(boost::beast::http::verb::post)(
Claire Weinanfdd26902022-03-01 14:18:25 -08002369 std::bind_front(handleLogServicesDumpCollectDiagnosticDataPost,
2370 std::ref(app), "BMC"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002371}
2372
2373inline void requestRoutesBMCDumpClear(App& app)
2374{
George Liu0fda0f12021-11-16 10:06:17 +08002375 BMCWEB_ROUTE(
2376 app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002377 "/redfish/v1/Managers/<str>/LogServices/Dump/Actions/LogService.ClearLog/")
Ed Tanoused398212021-06-09 17:05:54 -07002378 .privileges(redfish::privileges::postLogService)
Claire Weinanfdd26902022-03-01 14:18:25 -08002379 .methods(boost::beast::http::verb::post)(std::bind_front(
2380 handleLogServicesDumpClearLogPost, std::ref(app), "BMC"));
2381}
2382
Carson Labrado168d1b12023-03-27 17:04:46 +00002383inline void requestRoutesDBusEventLogEntryDownload(App& app)
2384{
2385 BMCWEB_ROUTE(
2386 app,
Ravi Teja9e9d99d2023-11-08 05:33:59 -06002387 "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/attachment/")
Carson Labrado168d1b12023-03-27 17:04:46 +00002388 .privileges(redfish::privileges::getLogEntry)
2389 .methods(boost::beast::http::verb::get)(std::bind_front(
2390 handleDBusEventLogEntryDownloadGet, std::ref(app), "System"));
2391}
2392
Claire Weinanfdd26902022-03-01 14:18:25 -08002393inline void requestRoutesFaultLogDumpService(App& app)
2394{
Ed Tanous253f11b2024-05-16 09:38:31 -07002395 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/")
Claire Weinanfdd26902022-03-01 14:18:25 -08002396 .privileges(redfish::privileges::getLogService)
2397 .methods(boost::beast::http::verb::get)(std::bind_front(
2398 handleLogServicesDumpServiceGet, std::ref(app), "FaultLog"));
2399}
2400
2401inline void requestRoutesFaultLogDumpEntryCollection(App& app)
2402{
Ed Tanous253f11b2024-05-16 09:38:31 -07002403 BMCWEB_ROUTE(app,
2404 "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/")
Claire Weinanfdd26902022-03-01 14:18:25 -08002405 .privileges(redfish::privileges::getLogEntryCollection)
2406 .methods(boost::beast::http::verb::get)(
2407 std::bind_front(handleLogServicesDumpEntriesCollectionGet,
2408 std::ref(app), "FaultLog"));
2409}
2410
2411inline void requestRoutesFaultLogDumpEntry(App& app)
2412{
Ed Tanous253f11b2024-05-16 09:38:31 -07002413 BMCWEB_ROUTE(
2414 app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/<str>/")
Claire Weinanfdd26902022-03-01 14:18:25 -08002415 .privileges(redfish::privileges::getLogEntry)
2416 .methods(boost::beast::http::verb::get)(std::bind_front(
2417 handleLogServicesDumpEntryGet, std::ref(app), "FaultLog"));
2418
Ed Tanous253f11b2024-05-16 09:38:31 -07002419 BMCWEB_ROUTE(
2420 app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/<str>/")
Claire Weinanfdd26902022-03-01 14:18:25 -08002421 .privileges(redfish::privileges::deleteLogEntry)
2422 .methods(boost::beast::http::verb::delete_)(std::bind_front(
2423 handleLogServicesDumpEntryDelete, std::ref(app), "FaultLog"));
2424}
2425
2426inline void requestRoutesFaultLogDumpClear(App& app)
2427{
2428 BMCWEB_ROUTE(
2429 app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002430 "/redfish/v1/Managers/<str>/LogServices/FaultLog/Actions/LogService.ClearLog/")
Claire Weinanfdd26902022-03-01 14:18:25 -08002431 .privileges(redfish::privileges::postLogService)
2432 .methods(boost::beast::http::verb::post)(std::bind_front(
2433 handleLogServicesDumpClearLogPost, std::ref(app), "FaultLog"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002434}
2435
2436inline void requestRoutesSystemDumpService(App& app)
2437{
Ed Tanous22d268c2022-05-19 09:39:07 -07002438 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Dump/")
Ed Tanoused398212021-06-09 17:05:54 -07002439 .privileges(redfish::privileges::getLogService)
Claire Weinan6ab9ad52022-08-12 18:20:17 -07002440 .methods(boost::beast::http::verb::get)(std::bind_front(
Ed Tanous22d268c2022-05-19 09:39:07 -07002441 handleLogServicesDumpServiceComputerSystemGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002442}
2443
2444inline void requestRoutesSystemDumpEntryCollection(App& app)
2445{
Ed Tanous22d268c2022-05-19 09:39:07 -07002446 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/")
Ed Tanoused398212021-06-09 17:05:54 -07002447 .privileges(redfish::privileges::getLogEntryCollection)
Ed Tanous22d268c2022-05-19 09:39:07 -07002448 .methods(boost::beast::http::verb::get)(std::bind_front(
2449 handleLogServicesDumpEntriesCollectionComputerSystemGet,
2450 std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002451}
2452
2453inline void requestRoutesSystemDumpEntry(App& app)
2454{
2455 BMCWEB_ROUTE(app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002456 "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002457 .privileges(redfish::privileges::getLogEntry)
Claire Weinan6ab9ad52022-08-12 18:20:17 -07002458 .methods(boost::beast::http::verb::get)(std::bind_front(
Ed Tanous22d268c2022-05-19 09:39:07 -07002459 handleLogServicesDumpEntryComputerSystemGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002460
2461 BMCWEB_ROUTE(app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002462 "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002463 .privileges(redfish::privileges::deleteLogEntry)
Claire Weinan6ab9ad52022-08-12 18:20:17 -07002464 .methods(boost::beast::http::verb::delete_)(std::bind_front(
Ed Tanous22d268c2022-05-19 09:39:07 -07002465 handleLogServicesDumpEntryComputerSystemDelete, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002466}
2467
2468inline void requestRoutesSystemDumpCreate(App& app)
2469{
George Liu0fda0f12021-11-16 10:06:17 +08002470 BMCWEB_ROUTE(
2471 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002472 "/redfish/v1/Systems/<str>/LogServices/Dump/Actions/LogService.CollectDiagnosticData/")
Abhishek Patelfff6a4d2021-07-21 11:29:45 -05002473 .privileges(redfish::privileges::
2474 postLogServiceSubOverComputerSystemLogServiceCollection)
Ed Tanous22d268c2022-05-19 09:39:07 -07002475 .methods(boost::beast::http::verb::post)(std::bind_front(
2476 handleLogServicesDumpCollectDiagnosticDataComputerSystemPost,
2477 std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002478}
2479
2480inline void requestRoutesSystemDumpClear(App& app)
2481{
George Liu0fda0f12021-11-16 10:06:17 +08002482 BMCWEB_ROUTE(
2483 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002484 "/redfish/v1/Systems/<str>/LogServices/Dump/Actions/LogService.ClearLog/")
Abhishek Patelfff6a4d2021-07-21 11:29:45 -05002485 .privileges(redfish::privileges::
2486 postLogServiceSubOverComputerSystemLogServiceCollection)
Claire Weinan6ab9ad52022-08-12 18:20:17 -07002487 .methods(boost::beast::http::verb::post)(std::bind_front(
Ed Tanous22d268c2022-05-19 09:39:07 -07002488 handleLogServicesDumpClearLogComputerSystemPost, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002489}
2490
2491inline void requestRoutesCrashdumpService(App& app)
2492{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002493 /**
2494 * Functions triggers appropriate requests on DBus
2495 */
Ed Tanous22d268c2022-05-19 09:39:07 -07002496 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Crashdump/")
Myung Bae50d9f382025-06-13 09:40:18 -04002497 .privileges(redfish::privileges::getLogService)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002498 .methods(
2499 boost::beast::http::verb::
2500 get)([&app](const crow::Request& req,
2501 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2502 const std::string& systemName) {
2503 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2504 {
2505 return;
2506 }
2507 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
2508 {
2509 // Option currently returns no systems. TBD
2510 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2511 systemName);
2512 return;
2513 }
2514 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2515 {
2516 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2517 systemName);
2518 return;
2519 }
Ed Tanous22d268c2022-05-19 09:39:07 -07002520
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002521 // Copy over the static data to include the entries added by
2522 // SubRoute
2523 asyncResp->res.jsonValue["@odata.id"] =
2524 std::format("/redfish/v1/Systems/{}/LogServices/Crashdump",
2525 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2526 asyncResp->res.jsonValue["@odata.type"] =
2527 "#LogService.v1_2_0.LogService";
2528 asyncResp->res.jsonValue["Name"] = "Open BMC Oem Crashdump Service";
2529 asyncResp->res.jsonValue["Description"] = "Oem Crashdump Service";
2530 asyncResp->res.jsonValue["Id"] = "Crashdump";
2531 asyncResp->res.jsonValue["OverWritePolicy"] =
2532 log_service::OverWritePolicy::WrapsWhenFull;
2533 asyncResp->res.jsonValue["MaxNumberOfRecords"] = 3;
Tejas Patil7c8c4052021-06-04 17:43:14 +05302534
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002535 std::pair<std::string, std::string> redfishDateTimeOffset =
2536 redfish::time_utils::getDateTimeOffsetNow();
2537 asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
2538 asyncResp->res.jsonValue["DateTimeLocalOffset"] =
2539 redfishDateTimeOffset.second;
Tejas Patil7c8c4052021-06-04 17:43:14 +05302540
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002541 asyncResp->res.jsonValue["Entries"]["@odata.id"] = std::format(
2542 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries",
2543 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2544 asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"]
2545 ["target"] = std::format(
2546 "/redfish/v1/Systems/{}/LogServices/Crashdump/Actions/LogService.ClearLog",
2547 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2548 asyncResp->res
2549 .jsonValue["Actions"]["#LogService.CollectDiagnosticData"]
2550 ["target"] = std::format(
2551 "/redfish/v1/Systems/{}/LogServices/Crashdump/Actions/LogService.CollectDiagnosticData",
2552 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2553 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002554}
2555
Ed Tanous8e4736b2025-08-19 10:14:02 -07002556inline void requestRoutesCrashdumpClear(App& app)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002557{
George Liu0fda0f12021-11-16 10:06:17 +08002558 BMCWEB_ROUTE(
2559 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002560 "/redfish/v1/Systems/<str>/LogServices/Crashdump/Actions/LogService.ClearLog/")
Myung Bae50d9f382025-06-13 09:40:18 -04002561 .privileges(redfish::privileges::
2562 postLogServiceSubOverComputerSystemLogServiceCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002563 .methods(boost::beast::http::verb::post)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07002564 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07002565 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2566 const std::string& systemName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002567 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2568 {
2569 return;
2570 }
2571 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
2572 {
2573 // Option currently returns no systems. TBD
2574 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2575 systemName);
2576 return;
2577 }
2578 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2579 {
2580 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2581 systemName);
2582 return;
2583 }
Ed Tanous177612a2025-02-14 15:16:09 -08002584 dbus::utility::async_method_call(
2585 asyncResp,
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002586 [asyncResp](const boost::system::error_code& ec,
2587 const std::string&) {
2588 if (ec)
2589 {
2590 messages::internalError(asyncResp->res);
2591 return;
2592 }
2593 messages::success(asyncResp->res);
2594 },
2595 crashdumpObject, crashdumpPath, deleteAllInterface,
2596 "DeleteAll");
2597 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002598}
Jason M. Bills5b61b5e2019-10-16 10:59:02 -07002599
Patrick Williams504af5a2025-02-03 14:29:03 -05002600inline void logCrashdumpEntry(
2601 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2602 const std::string& logID, nlohmann::json& logEntryJson)
Jason M. Billse855dd22019-10-08 11:37:48 -07002603{
Johnathan Mantey043a0532020-03-10 17:15:28 -07002604 auto getStoredLogCallback =
Ed Tanousb9d36b42022-02-26 21:42:46 -08002605 [asyncResp, logID,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002606 &logEntryJson](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002607 const dbus::utility::DBusPropertiesMap& params) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002608 if (ec)
2609 {
2610 BMCWEB_LOG_DEBUG("failed to get log ec: {}", ec.message());
2611 if (ec.value() ==
2612 boost::system::linux_error::bad_request_descriptor)
2613 {
2614 messages::resourceNotFound(asyncResp->res, "LogEntry",
2615 logID);
2616 }
2617 else
2618 {
2619 messages::internalError(asyncResp->res);
2620 }
2621 return;
2622 }
2623
2624 std::string timestamp{};
2625 std::string filename{};
2626 std::string logfile{};
2627 parseCrashdumpParameters(params, filename, timestamp, logfile);
2628
2629 if (filename.empty() || timestamp.empty())
Jason M. Bills1ddcf012019-11-26 14:59:21 -08002630 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002631 messages::resourceNotFound(asyncResp->res, "LogEntry", logID);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002632 return;
2633 }
2634
2635 std::string crashdumpURI =
2636 std::format(
2637 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries/",
2638 BMCWEB_REDFISH_SYSTEM_URI_NAME) +
2639 logID + "/" + filename;
2640 nlohmann::json::object_t logEntry;
2641 logEntry["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
2642 logEntry["@odata.id"] = boost::urls::format(
2643 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries/{}",
2644 BMCWEB_REDFISH_SYSTEM_URI_NAME, logID);
2645 logEntry["Name"] = "CPU Crashdump";
2646 logEntry["Id"] = logID;
2647 logEntry["EntryType"] = log_entry::LogEntryType::Oem;
2648 logEntry["AdditionalDataURI"] = std::move(crashdumpURI);
2649 logEntry["DiagnosticDataType"] = "OEM";
2650 logEntry["OEMDiagnosticDataType"] = "PECICrashdump";
2651 logEntry["Created"] = std::move(timestamp);
2652
2653 // If logEntryJson references an array of LogEntry resources
2654 // ('Members' list), then push this as a new entry, otherwise set it
2655 // directly
2656 if (logEntryJson.is_array())
2657 {
2658 logEntryJson.push_back(logEntry);
2659 asyncResp->res.jsonValue["Members@odata.count"] =
2660 logEntryJson.size();
Jason M. Bills2b20ef62022-01-06 15:48:07 -08002661 }
2662 else
2663 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002664 logEntryJson.update(logEntry);
Jason M. Bills2b20ef62022-01-06 15:48:07 -08002665 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002666 };
Ed Tanousdeae6a72024-11-11 21:58:57 -08002667 dbus::utility::getAllProperties(
2668 crashdumpObject, crashdumpPath + std::string("/") + logID,
2669 crashdumpInterface, std::move(getStoredLogCallback));
Jason M. Billse855dd22019-10-08 11:37:48 -07002670}
2671
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002672inline void requestRoutesCrashdumpEntryCollection(App& app)
Ed Tanous1da66f72018-07-27 16:13:37 -07002673{
Ed Tanous1da66f72018-07-27 16:13:37 -07002674 /**
2675 * Functions triggers appropriate requests on DBus
2676 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002677 BMCWEB_ROUTE(app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002678 "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/")
Myung Bae50d9f382025-06-13 09:40:18 -04002679 .privileges(redfish::privileges::getLogEntryCollection)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002680 .methods(
2681 boost::beast::http::verb::
2682 get)([&app](const crow::Request& req,
2683 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2684 const std::string& systemName) {
2685 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous45ca1b82022-03-25 13:07:27 -07002686 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002687 return;
Ed Tanous45ca1b82022-03-25 13:07:27 -07002688 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002689 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous002d39b2022-05-31 08:59:27 -07002690 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002691 // Option currently returns no systems. TBD
2692 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2693 systemName);
2694 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07002695 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002696 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2697 {
2698 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2699 systemName);
2700 return;
2701 }
2702
2703 constexpr std::array<std::string_view, 1> interfaces = {
2704 crashdumpInterface};
2705 dbus::utility::getSubTreePaths(
2706 "/", 0, interfaces,
2707 [asyncResp](const boost::system::error_code& ec,
2708 const std::vector<std::string>& resp) {
2709 if (ec)
2710 {
2711 if (ec.value() !=
2712 boost::system::errc::no_such_file_or_directory)
2713 {
2714 BMCWEB_LOG_DEBUG("failed to get entries ec: {}",
2715 ec.message());
2716 messages::internalError(asyncResp->res);
2717 return;
2718 }
2719 }
2720 asyncResp->res.jsonValue["@odata.type"] =
2721 "#LogEntryCollection.LogEntryCollection";
2722 asyncResp->res.jsonValue["@odata.id"] = std::format(
2723 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries",
2724 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2725 asyncResp->res.jsonValue["Name"] =
2726 "Open BMC Crashdump Entries";
2727 asyncResp->res.jsonValue["Description"] =
2728 "Collection of Crashdump Entries";
2729 asyncResp->res.jsonValue["Members"] =
2730 nlohmann::json::array();
2731 asyncResp->res.jsonValue["Members@odata.count"] = 0;
2732
2733 for (const std::string& path : resp)
2734 {
2735 const sdbusplus::message::object_path objPath(path);
2736 // Get the log ID
2737 std::string logID = objPath.filename();
2738 if (logID.empty())
2739 {
2740 continue;
2741 }
2742 // Add the log entry to the array
2743 logCrashdumpEntry(asyncResp, logID,
2744 asyncResp->res.jsonValue["Members"]);
2745 }
2746 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002747 });
2748}
Ed Tanous1da66f72018-07-27 16:13:37 -07002749
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002750inline void requestRoutesCrashdumpEntry(App& app)
Ed Tanous1da66f72018-07-27 16:13:37 -07002751{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002752 BMCWEB_ROUTE(
Ed Tanous22d268c2022-05-19 09:39:07 -07002753 app, "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/<str>/")
Myung Bae50d9f382025-06-13 09:40:18 -04002754 .privileges(redfish::privileges::getLogEntry)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002755 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07002756 [&app](const crow::Request& req,
2757 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -07002758 const std::string& systemName, const std::string& param) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002759 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2760 {
2761 return;
2762 }
2763 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
2764 {
2765 // Option currently returns no systems. TBD
2766 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2767 systemName);
2768 return;
2769 }
2770 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2771 {
2772 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2773 systemName);
2774 return;
2775 }
2776 const std::string& logID = param;
2777 logCrashdumpEntry(asyncResp, logID, asyncResp->res.jsonValue);
2778 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002779}
Ed Tanous1da66f72018-07-27 16:13:37 -07002780
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002781inline void requestRoutesCrashdumpFile(App& app)
2782{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002783 BMCWEB_ROUTE(
2784 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002785 "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/<str>/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002786 .privileges(redfish::privileges::getLogEntry)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002787 .methods(boost::beast::http::verb::get)(
Nan Zhoua4ce1142022-08-02 18:45:25 +00002788 [](const crow::Request& req,
2789 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -07002790 const std::string& systemName, const std::string& logID,
2791 const std::string& fileName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002792 // Do not call getRedfishRoute here since the crashdump file is
2793 // not a Redfish resource.
Ed Tanous22d268c2022-05-19 09:39:07 -07002794
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002795 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
2796 {
2797 // Option currently returns no systems. TBD
2798 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2799 systemName);
2800 return;
2801 }
2802 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2803 {
2804 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2805 systemName);
2806 return;
2807 }
Ed Tanous22d268c2022-05-19 09:39:07 -07002808
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002809 auto getStoredLogCallback =
2810 [asyncResp, logID, fileName,
2811 url(boost::urls::url(req.url()))](
2812 const boost::system::error_code& ec,
2813 const std::vector<std::pair<
2814 std::string, dbus::utility::DbusVariantType>>&
2815 resp) {
2816 if (ec)
2817 {
2818 BMCWEB_LOG_DEBUG("failed to get log ec: {}",
2819 ec.message());
2820 messages::internalError(asyncResp->res);
2821 return;
2822 }
Jason M. Bills8e6c0992021-03-11 16:26:53 -08002823
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002824 std::string dbusFilename{};
2825 std::string dbusTimestamp{};
2826 std::string dbusFilepath{};
Jason M. Bills8e6c0992021-03-11 16:26:53 -08002827
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002828 parseCrashdumpParameters(resp, dbusFilename,
2829 dbusTimestamp, dbusFilepath);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002830
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002831 if (dbusFilename.empty() || dbusTimestamp.empty() ||
2832 dbusFilepath.empty())
2833 {
2834 messages::resourceNotFound(asyncResp->res,
2835 "LogEntry", logID);
2836 return;
2837 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002838
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002839 // Verify the file name parameter is correct
2840 if (fileName != dbusFilename)
2841 {
2842 messages::resourceNotFound(asyncResp->res,
2843 "LogEntry", logID);
2844 return;
2845 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002846
Myung Baed51c61b2024-09-13 10:35:34 -05002847 if (asyncResp->res.openFile(dbusFilepath) !=
2848 crow::OpenCode::Success)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002849 {
2850 messages::resourceNotFound(asyncResp->res,
2851 "LogEntry", logID);
2852 return;
2853 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002854
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002855 // Configure this to be a file download when accessed
2856 // from a browser
2857 asyncResp->res.addHeader(
2858 boost::beast::http::field::content_disposition,
2859 "attachment");
2860 };
Ed Tanousdeae6a72024-11-11 21:58:57 -08002861 dbus::utility::getAllProperties(
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002862 *crow::connections::systemBus, crashdumpObject,
2863 crashdumpPath + std::string("/") + logID,
2864 crashdumpInterface, std::move(getStoredLogCallback));
2865 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002866}
2867
Jason M. Billsc5a4c822022-01-06 15:51:23 -08002868enum class OEMDiagnosticType
2869{
2870 onDemand,
2871 telemetry,
2872 invalid,
2873};
2874
Ed Tanous26ccae32023-02-16 10:28:44 -08002875inline OEMDiagnosticType getOEMDiagnosticType(std::string_view oemDiagStr)
Jason M. Billsc5a4c822022-01-06 15:51:23 -08002876{
2877 if (oemDiagStr == "OnDemand")
2878 {
2879 return OEMDiagnosticType::onDemand;
2880 }
2881 if (oemDiagStr == "Telemetry")
2882 {
2883 return OEMDiagnosticType::telemetry;
2884 }
2885
2886 return OEMDiagnosticType::invalid;
2887}
2888
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002889inline void requestRoutesCrashdumpCollect(App& app)
2890{
George Liu0fda0f12021-11-16 10:06:17 +08002891 BMCWEB_ROUTE(
2892 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002893 "/redfish/v1/Systems/<str>/LogServices/Crashdump/Actions/LogService.CollectDiagnosticData/")
Myung Bae50d9f382025-06-13 09:40:18 -04002894 .privileges(redfish::privileges::
2895 postLogServiceSubOverComputerSystemLogServiceCollection)
Ed Tanous002d39b2022-05-31 08:59:27 -07002896 .methods(boost::beast::http::verb::post)(
2897 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07002898 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2899 const std::string& systemName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002900 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07002901 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002902 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07002903 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002904
2905 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous002d39b2022-05-31 08:59:27 -07002906 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002907 // Option currently returns no systems. TBD
2908 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2909 systemName);
2910 return;
2911 }
2912 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2913 {
2914 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2915 systemName);
2916 return;
2917 }
2918
2919 std::string diagnosticDataType;
2920 std::string oemDiagnosticDataType;
Patrick Williams504af5a2025-02-03 14:29:03 -05002921 if (!redfish::json_util::readJsonAction( //
2922 req, asyncResp->res, //
2923 "DiagnosticDataType", diagnosticDataType, //
Myung Baeafc474a2024-10-09 00:53:29 -07002924 "OEMDiagnosticDataType", oemDiagnosticDataType //
2925 ))
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002926 {
2927 return;
2928 }
2929
2930 if (diagnosticDataType != "OEM")
2931 {
2932 BMCWEB_LOG_ERROR(
2933 "Only OEM DiagnosticDataType supported for Crashdump");
2934 messages::actionParameterValueFormatError(
2935 asyncResp->res, diagnosticDataType,
2936 "DiagnosticDataType", "CollectDiagnosticData");
2937 return;
2938 }
2939
2940 OEMDiagnosticType oemDiagType =
2941 getOEMDiagnosticType(oemDiagnosticDataType);
2942
2943 std::string iface;
2944 std::string method;
2945 std::string taskMatchStr;
2946 if (oemDiagType == OEMDiagnosticType::onDemand)
2947 {
2948 iface = crashdumpOnDemandInterface;
2949 method = "GenerateOnDemandLog";
2950 taskMatchStr =
2951 "type='signal',"
2952 "interface='org.freedesktop.DBus.Properties',"
2953 "member='PropertiesChanged',"
2954 "arg0namespace='com.intel.crashdump'";
2955 }
2956 else if (oemDiagType == OEMDiagnosticType::telemetry)
2957 {
2958 iface = crashdumpTelemetryInterface;
2959 method = "GenerateTelemetryLog";
2960 taskMatchStr =
2961 "type='signal',"
2962 "interface='org.freedesktop.DBus.Properties',"
2963 "member='PropertiesChanged',"
2964 "arg0namespace='com.intel.crashdump'";
Ed Tanous002d39b2022-05-31 08:59:27 -07002965 }
2966 else
2967 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002968 BMCWEB_LOG_ERROR("Unsupported OEMDiagnosticDataType: {}",
2969 oemDiagnosticDataType);
2970 messages::actionParameterValueFormatError(
2971 asyncResp->res, oemDiagnosticDataType,
2972 "OEMDiagnosticDataType", "CollectDiagnosticData");
2973 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07002974 }
Ed Tanous1da66f72018-07-27 16:13:37 -07002975
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002976 auto collectCrashdumpCallback =
2977 [asyncResp, payload(task::Payload(req)),
2978 taskMatchStr](const boost::system::error_code& ec,
2979 const std::string&) mutable {
2980 if (ec)
2981 {
2982 if (ec.value() ==
2983 boost::system::errc::operation_not_supported)
2984 {
2985 messages::resourceInStandby(asyncResp->res);
2986 }
2987 else if (ec.value() == boost::system::errc::
2988 device_or_resource_busy)
2989 {
2990 messages::serviceTemporarilyUnavailable(
2991 asyncResp->res, "60");
2992 }
2993 else
2994 {
2995 messages::internalError(asyncResp->res);
2996 }
2997 return;
2998 }
2999 std::shared_ptr<task::TaskData> task =
3000 task::TaskData::createTask(
3001 [](const boost::system::error_code& ec2,
3002 sdbusplus::message_t&,
3003 const std::shared_ptr<task::TaskData>&
3004 taskData) {
3005 if (!ec2)
3006 {
3007 taskData->messages.emplace_back(
3008 messages::taskCompletedOK(
3009 std::to_string(
3010 taskData->index)));
3011 taskData->state = "Completed";
3012 }
3013 return task::completed;
3014 },
3015 taskMatchStr);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003016
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003017 task->startTimer(std::chrono::minutes(5));
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003018 task->payload.emplace(std::move(payload));
Chinmay Shripad Hegde29e2bdd2025-06-06 16:23:47 +05303019 task->populateResp(asyncResp->res);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003020 };
3021
Ed Tanous177612a2025-02-14 15:16:09 -08003022 dbus::utility::async_method_call(
3023 asyncResp, std::move(collectCrashdumpCallback),
3024 crashdumpObject, crashdumpPath, iface, method);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003025 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003026}
Kenny L. Ku6eda7682020-06-19 09:48:36 -07003027
Alexander Hansen599b9af2024-08-06 15:11:57 +02003028inline void dBusLogServiceActionsClear(
3029 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
3030{
3031 BMCWEB_LOG_DEBUG("Do delete all entries.");
3032
3033 // Process response from Logging service.
3034 auto respHandler = [asyncResp](const boost::system::error_code& ec) {
3035 BMCWEB_LOG_DEBUG("doClearLog resp_handler callback: Done");
3036 if (ec)
3037 {
3038 // TODO Handle for specific error code
3039 BMCWEB_LOG_ERROR("doClearLog resp_handler got error {}", ec);
3040 asyncResp->res.result(
3041 boost::beast::http::status::internal_server_error);
3042 return;
3043 }
3044
Amy Change2460462025-05-06 00:10:13 -07003045 messages::success(asyncResp->res);
Alexander Hansen599b9af2024-08-06 15:11:57 +02003046 };
3047
3048 // Make call to Logging service to request Clear Log
Ed Tanous177612a2025-02-14 15:16:09 -08003049 dbus::utility::async_method_call(
3050 asyncResp, respHandler, "xyz.openbmc_project.Logging",
Alexander Hansen599b9af2024-08-06 15:11:57 +02003051 "/xyz/openbmc_project/logging",
3052 "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
3053}
3054
Andrew Geisslercb92c032018-08-17 07:56:14 -07003055/**
3056 * DBusLogServiceActionsClear class supports POST method for ClearLog action.
3057 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003058inline void requestRoutesDBusLogServiceActionsClear(App& app)
Andrew Geisslercb92c032018-08-17 07:56:14 -07003059{
Andrew Geisslercb92c032018-08-17 07:56:14 -07003060 /**
3061 * Function handles POST method request.
3062 * The Clear Log actions does not require any parameter.The action deletes
3063 * all entries found in the Entries collection for this Log Service.
3064 */
Andrew Geisslercb92c032018-08-17 07:56:14 -07003065
George Liu0fda0f12021-11-16 10:06:17 +08003066 BMCWEB_ROUTE(
3067 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07003068 "/redfish/v1/Systems/<str>/LogServices/EventLog/Actions/LogService.ClearLog/")
Abhishek Patelfff6a4d2021-07-21 11:29:45 -05003069 .privileges(redfish::privileges::
3070 postLogServiceSubOverComputerSystemLogServiceCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003071 .methods(boost::beast::http::verb::post)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07003072 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07003073 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3074 const std::string& systemName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003075 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3076 {
3077 return;
3078 }
3079 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
3080 {
3081 // Option currently returns no systems. TBD
3082 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3083 systemName);
3084 return;
3085 }
3086 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
3087 {
3088 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3089 systemName);
3090 return;
3091 }
3092 dBusLogServiceActionsClear(asyncResp);
3093 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003094}
ZhikuiRena3316fc2020-01-29 14:58:08 -08003095
Ed Tanous1da66f72018-07-27 16:13:37 -07003096} // namespace redfish