blob: 665e05899687326607b7d7ca9c16e41bf2a73bbd [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 Tanous3ccb3ad2023-01-13 17:40:03 -08006#include "app.hpp"
George Liu7a1dbc42022-12-07 16:03:22 +08007#include "dbus_utility.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -08008#include "error_messages.hpp"
Asmitha Karunanithi68dd0752022-11-15 11:33:46 -06009#include "generated/enums/log_entry.hpp"
Ed Tanous539d8c62024-06-19 14:38:27 -070010#include "generated/enums/log_service.hpp"
George Liu647b3cd2021-07-05 12:43:56 +080011#include "http_utility.hpp"
Spencer Kub7028eb2021-10-26 15:27:35 +080012#include "human_sort.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080013#include "query.hpp"
Jason M. Bills4851d452019-03-28 11:27:48 -070014#include "registries.hpp"
15#include "registries/base_message_registry.hpp"
16#include "registries/openbmc_message_registry.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080017#include "registries/privilege_registry.hpp"
James Feist46229572020-02-19 15:11:58 -080018#include "task.hpp"
Ed Tanous5b904292024-04-16 11:10:17 -070019#include "task_messages.hpp"
Alexander Hansen262dcc12024-09-19 12:04:03 +020020#include "utils/dbus_event_log_entry.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080021#include "utils/dbus_utils.hpp"
Ed Tanous5b904292024-04-16 11:10:17 -070022#include "utils/json_utils.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080023#include "utils/time_utils.hpp"
Ed Tanous1da66f72018-07-27 16:13:37 -070024
Myung Bae75e8e212023-11-30 12:53:46 -080025#include <systemd/sd-id128.h>
Asmitha Karunanithi8e317782020-12-10 03:35:05 -060026#include <tinyxml2.h>
Adriana Kobylak400fd1f2021-01-29 09:01:30 -060027#include <unistd.h>
Jason M. Billse1f26342018-07-18 12:12:00 -070028
Ed Tanous07c8c202022-07-11 10:08:08 -070029#include <boost/beast/http/verb.hpp>
Ed Tanous1da66f72018-07-27 16:13:37 -070030#include <boost/container/flat_map.hpp>
Jason M. Bills1ddcf012019-11-26 14:59:21 -080031#include <boost/system/linux_error.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070032#include <boost/url/format.hpp>
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +020033#include <sdbusplus/asio/property.hpp>
34#include <sdbusplus/unpack_properties.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050035
George Liu7a1dbc42022-12-07 16:03:22 +080036#include <array>
George Liu647b3cd2021-07-05 12:43:56 +080037#include <charconv>
Abhilash Rajub5f288d2023-11-08 22:32:44 -060038#include <cstddef>
James Feist4418c7f2019-04-15 11:09:15 -070039#include <filesystem>
Ed Tanous18f8f602023-07-18 10:07:23 -070040#include <iterator>
Xiaochao Ma75710de2021-01-21 17:56:02 +080041#include <optional>
Ed Tanous3544d2a2023-08-06 18:12:20 -070042#include <ranges>
Ed Tanous26702d02021-11-03 15:02:33 -070043#include <span>
Ed Tanous18f8f602023-07-18 10:07:23 -070044#include <string>
Jason M. Billscd225da2019-05-08 15:31:57 -070045#include <string_view>
Ed Tanousabf2add2019-01-22 16:40:12 -080046#include <variant>
Ed Tanous1da66f72018-07-27 16:13:37 -070047
48namespace redfish
49{
50
Patrick Williams89492a12023-05-10 07:51:34 -050051constexpr const char* crashdumpObject = "com.intel.crashdump";
52constexpr const char* crashdumpPath = "/com/intel/crashdump";
53constexpr const char* crashdumpInterface = "com.intel.crashdump";
54constexpr const char* deleteAllInterface =
Jason M. Bills5b61b5e2019-10-16 10:59:02 -070055 "xyz.openbmc_project.Collection.DeleteAll";
Patrick Williams89492a12023-05-10 07:51:34 -050056constexpr const char* crashdumpOnDemandInterface =
Jason M. Bills424c4172019-03-21 13:50:33 -070057 "com.intel.crashdump.OnDemand";
Patrick Williams89492a12023-05-10 07:51:34 -050058constexpr const char* crashdumpTelemetryInterface =
Kenny L. Ku6eda7682020-06-19 09:48:36 -070059 "com.intel.crashdump.Telemetry";
Ed Tanous1da66f72018-07-27 16:13:37 -070060
Asmitha Karunanithi8e317782020-12-10 03:35:05 -060061enum class DumpCreationProgress
62{
63 DUMP_CREATE_SUCCESS,
64 DUMP_CREATE_FAILED,
65 DUMP_CREATE_INPROGRESS
66};
67
James Feistf6150402019-01-08 10:36:20 -080068namespace fs = std::filesystem;
Ed Tanous1da66f72018-07-27 16:13:37 -070069
Gunnar Mills1214b7e2020-06-04 10:11:30 -050070inline std::string translateSeverityDbusToRedfish(const std::string& s)
Andrew Geisslercb92c032018-08-17 07:56:14 -070071{
Ed Tanousd4d25792020-09-29 15:15:03 -070072 if ((s == "xyz.openbmc_project.Logging.Entry.Level.Alert") ||
73 (s == "xyz.openbmc_project.Logging.Entry.Level.Critical") ||
74 (s == "xyz.openbmc_project.Logging.Entry.Level.Emergency") ||
75 (s == "xyz.openbmc_project.Logging.Entry.Level.Error"))
Andrew Geisslercb92c032018-08-17 07:56:14 -070076 {
77 return "Critical";
78 }
Ed Tanous3174e4d2020-10-07 11:41:22 -070079 if ((s == "xyz.openbmc_project.Logging.Entry.Level.Debug") ||
80 (s == "xyz.openbmc_project.Logging.Entry.Level.Informational") ||
81 (s == "xyz.openbmc_project.Logging.Entry.Level.Notice"))
Andrew Geisslercb92c032018-08-17 07:56:14 -070082 {
83 return "OK";
84 }
Ed Tanous3174e4d2020-10-07 11:41:22 -070085 if (s == "xyz.openbmc_project.Logging.Entry.Level.Warning")
Andrew Geisslercb92c032018-08-17 07:56:14 -070086 {
87 return "Warning";
88 }
89 return "";
90}
91
Abhishek Patel9017faf2021-09-14 22:48:55 -050092inline std::optional<bool> getProviderNotifyAction(const std::string& notify)
93{
94 std::optional<bool> notifyAction;
95 if (notify == "xyz.openbmc_project.Logging.Entry.Notify.Notify")
96 {
97 notifyAction = true;
98 }
99 else if (notify == "xyz.openbmc_project.Logging.Entry.Notify.Inhibit")
100 {
101 notifyAction = false;
102 }
103
104 return notifyAction;
105}
106
Ed Tanous18f8f602023-07-18 10:07:23 -0700107inline std::string getDumpPath(std::string_view dumpType)
108{
109 std::string dbusDumpPath = "/xyz/openbmc_project/dump/";
110 std::ranges::transform(dumpType, std::back_inserter(dbusDumpPath),
111 bmcweb::asciiToLower);
112
113 return dbusDumpPath;
114}
115
Ed Tanous055713e2024-07-17 17:19:36 -0700116inline bool getUniqueEntryID(const std::string& logEntry, std::string& entryID,
Jason M. Billse85d6b12019-07-29 17:01:15 -0700117 const bool firstEntry = true)
Jason M. Bills95820182019-04-22 16:25:34 -0700118{
Ed Tanous271584a2019-07-09 16:24:22 -0700119 static time_t prevTs = 0;
Jason M. Bills95820182019-04-22 16:25:34 -0700120 static int index = 0;
Jason M. Billse85d6b12019-07-29 17:01:15 -0700121 if (firstEntry)
122 {
123 prevTs = 0;
124 }
125
Jason M. Bills95820182019-04-22 16:25:34 -0700126 // Get the entry timestamp
Ed Tanous271584a2019-07-09 16:24:22 -0700127 std::time_t curTs = 0;
Jason M. Bills95820182019-04-22 16:25:34 -0700128 std::tm timeStruct = {};
129 std::istringstream entryStream(logEntry);
130 if (entryStream >> std::get_time(&timeStruct, "%Y-%m-%dT%H:%M:%S"))
131 {
132 curTs = std::mktime(&timeStruct);
133 }
134 // If the timestamp isn't unique, increment the index
135 if (curTs == prevTs)
136 {
137 index++;
138 }
139 else
140 {
141 // Otherwise, reset it
142 index = 0;
143 }
144 // Save the timestamp
145 prevTs = curTs;
146
147 entryID = std::to_string(curTs);
148 if (index > 0)
149 {
150 entryID += "_" + std::to_string(index);
151 }
152 return true;
153}
154
Ed Tanous4ff0f1f2024-09-04 17:27:37 -0700155inline bool
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500156 getRedfishLogFiles(std::vector<std::filesystem::path>& redfishLogFiles)
Jason M. Bills95820182019-04-22 16:25:34 -0700157{
158 static const std::filesystem::path redfishLogDir = "/var/log";
159 static const std::string redfishLogFilename = "redfish";
160
161 // Loop through the directory looking for redfish log files
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500162 for (const std::filesystem::directory_entry& dirEnt :
Jason M. Bills95820182019-04-22 16:25:34 -0700163 std::filesystem::directory_iterator(redfishLogDir))
164 {
165 // If we find a redfish log file, save the path
166 std::string filename = dirEnt.path().filename();
Ed Tanous11ba3972022-07-11 09:50:41 -0700167 if (filename.starts_with(redfishLogFilename))
Jason M. Bills95820182019-04-22 16:25:34 -0700168 {
169 redfishLogFiles.emplace_back(redfishLogDir / filename);
170 }
171 }
172 // As the log files rotate, they are appended with a ".#" that is higher for
173 // the older logs. Since we don't expect more than 10 log files, we
174 // can just sort the list to get them in order from newest to oldest
Ed Tanous3544d2a2023-08-06 18:12:20 -0700175 std::ranges::sort(redfishLogFiles);
Jason M. Bills95820182019-04-22 16:25:34 -0700176
177 return !redfishLogFiles.empty();
178}
179
Asmitha Karunanithi68dd0752022-11-15 11:33:46 -0600180inline log_entry::OriginatorTypes
181 mapDbusOriginatorTypeToRedfish(const std::string& originatorType)
182{
183 if (originatorType ==
184 "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Client")
185 {
186 return log_entry::OriginatorTypes::Client;
187 }
188 if (originatorType ==
189 "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Internal")
190 {
191 return log_entry::OriginatorTypes::Internal;
192 }
193 if (originatorType ==
194 "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.SupportingService")
195 {
196 return log_entry::OriginatorTypes::SupportingService;
197 }
198 return log_entry::OriginatorTypes::Invalid;
199}
200
Claire Weinanaefe3782022-07-15 19:17:19 -0700201inline void parseDumpEntryFromDbusObject(
Jiaqing Zhao2d613eb2022-08-15 16:03:00 +0800202 const dbus::utility::ManagedObjectType::value_type& object,
Claire Weinanc6fecda2022-07-15 10:43:25 -0700203 std::string& dumpStatus, uint64_t& size, uint64_t& timestampUs,
Asmitha Karunanithi68dd0752022-11-15 11:33:46 -0600204 std::string& originatorId, log_entry::OriginatorTypes& originatorType,
Claire Weinanaefe3782022-07-15 19:17:19 -0700205 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
206{
207 for (const auto& interfaceMap : object.second)
208 {
209 if (interfaceMap.first == "xyz.openbmc_project.Common.Progress")
210 {
211 for (const auto& propertyMap : interfaceMap.second)
212 {
213 if (propertyMap.first == "Status")
214 {
215 const auto* status =
216 std::get_if<std::string>(&propertyMap.second);
217 if (status == nullptr)
218 {
219 messages::internalError(asyncResp->res);
220 break;
221 }
222 dumpStatus = *status;
223 }
224 }
225 }
226 else if (interfaceMap.first == "xyz.openbmc_project.Dump.Entry")
227 {
228 for (const auto& propertyMap : interfaceMap.second)
229 {
230 if (propertyMap.first == "Size")
231 {
232 const auto* sizePtr =
233 std::get_if<uint64_t>(&propertyMap.second);
234 if (sizePtr == nullptr)
235 {
236 messages::internalError(asyncResp->res);
237 break;
238 }
239 size = *sizePtr;
240 break;
241 }
242 }
243 }
244 else if (interfaceMap.first == "xyz.openbmc_project.Time.EpochTime")
245 {
246 for (const auto& propertyMap : interfaceMap.second)
247 {
248 if (propertyMap.first == "Elapsed")
249 {
250 const uint64_t* usecsTimeStamp =
251 std::get_if<uint64_t>(&propertyMap.second);
252 if (usecsTimeStamp == nullptr)
253 {
254 messages::internalError(asyncResp->res);
255 break;
256 }
Claire Weinanc6fecda2022-07-15 10:43:25 -0700257 timestampUs = *usecsTimeStamp;
Claire Weinanaefe3782022-07-15 19:17:19 -0700258 break;
259 }
260 }
261 }
Asmitha Karunanithi68dd0752022-11-15 11:33:46 -0600262 else if (interfaceMap.first ==
263 "xyz.openbmc_project.Common.OriginatedBy")
264 {
265 for (const auto& propertyMap : interfaceMap.second)
266 {
267 if (propertyMap.first == "OriginatorId")
268 {
269 const std::string* id =
270 std::get_if<std::string>(&propertyMap.second);
271 if (id == nullptr)
272 {
273 messages::internalError(asyncResp->res);
274 break;
275 }
276 originatorId = *id;
277 }
278
279 if (propertyMap.first == "OriginatorType")
280 {
281 const std::string* type =
282 std::get_if<std::string>(&propertyMap.second);
283 if (type == nullptr)
284 {
285 messages::internalError(asyncResp->res);
286 break;
287 }
288
289 originatorType = mapDbusOriginatorTypeToRedfish(*type);
290 if (originatorType == log_entry::OriginatorTypes::Invalid)
291 {
292 messages::internalError(asyncResp->res);
293 break;
294 }
295 }
296 }
297 }
Claire Weinanaefe3782022-07-15 19:17:19 -0700298 }
299}
300
Nan Zhou21ab4042022-06-26 23:07:40 +0000301static std::string getDumpEntriesPath(const std::string& dumpType)
Claire Weinanfdd26902022-03-01 14:18:25 -0800302{
303 std::string entriesPath;
304
305 if (dumpType == "BMC")
306 {
Ed Tanous253f11b2024-05-16 09:38:31 -0700307 entriesPath =
308 std::format("/redfish/v1/Managers/{}/LogServices/Dump/Entries/",
309 BMCWEB_REDFISH_MANAGER_URI_NAME);
Claire Weinanfdd26902022-03-01 14:18:25 -0800310 }
311 else if (dumpType == "FaultLog")
312 {
Ed Tanous253f11b2024-05-16 09:38:31 -0700313 entriesPath =
314 std::format("/redfish/v1/Managers/{}/LogServices/FaultLog/Entries/",
315 BMCWEB_REDFISH_MANAGER_URI_NAME);
Claire Weinanfdd26902022-03-01 14:18:25 -0800316 }
317 else if (dumpType == "System")
318 {
Ed Tanous253f11b2024-05-16 09:38:31 -0700319 entriesPath =
320 std::format("/redfish/v1/Systems/{}/LogServices/Dump/Entries/",
321 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Claire Weinanfdd26902022-03-01 14:18:25 -0800322 }
323 else
324 {
Ed Tanous62598e32023-07-17 17:06:25 -0700325 BMCWEB_LOG_ERROR("getDumpEntriesPath() invalid dump type: {}",
326 dumpType);
Claire Weinanfdd26902022-03-01 14:18:25 -0800327 }
328
329 // Returns empty string on error
330 return entriesPath;
331}
332
zhanghch058d1b46d2021-04-01 11:18:24 +0800333inline void
334 getDumpEntryCollection(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
335 const std::string& dumpType)
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500336{
Claire Weinanfdd26902022-03-01 14:18:25 -0800337 std::string entriesPath = getDumpEntriesPath(dumpType);
338 if (entriesPath.empty())
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500339 {
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500340 messages::internalError(asyncResp->res);
341 return;
342 }
343
George Liu5eb468d2023-06-20 17:03:24 +0800344 sdbusplus::message::object_path path("/xyz/openbmc_project/dump");
345 dbus::utility::getManagedObjects(
346 "xyz.openbmc_project.Dump.Manager", path,
Claire Weinanfdd26902022-03-01 14:18:25 -0800347 [asyncResp, entriesPath,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800348 dumpType](const boost::system::error_code& ec,
George Liu5eb468d2023-06-20 17:03:24 +0800349 const dbus::utility::ManagedObjectType& objects) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400350 if (ec)
351 {
352 BMCWEB_LOG_ERROR("DumpEntry resp_handler got error {}", ec);
353 messages::internalError(asyncResp->res);
354 return;
355 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700356
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400357 // Remove ending slash
358 std::string odataIdStr = entriesPath;
359 if (!odataIdStr.empty())
360 {
361 odataIdStr.pop_back();
362 }
Claire Weinanfdd26902022-03-01 14:18:25 -0800363
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400364 asyncResp->res.jsonValue["@odata.type"] =
365 "#LogEntryCollection.LogEntryCollection";
366 asyncResp->res.jsonValue["@odata.id"] = std::move(odataIdStr);
367 asyncResp->res.jsonValue["Name"] = dumpType + " Dump Entries";
368 asyncResp->res.jsonValue["Description"] =
369 "Collection of " + dumpType + " Dump Entries";
Claire Weinanfdd26902022-03-01 14:18:25 -0800370
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400371 nlohmann::json::array_t entriesArray;
372 std::string dumpEntryPath = getDumpPath(dumpType) + "/entry/";
Ed Tanous002d39b2022-05-31 08:59:27 -0700373
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400374 dbus::utility::ManagedObjectType resp(objects);
375 std::ranges::sort(resp, [](const auto& l, const auto& r) {
376 return AlphanumLess<std::string>()(l.first.filename(),
377 r.first.filename());
378 });
379
380 for (auto& object : resp)
381 {
382 if (object.first.str.find(dumpEntryPath) == std::string::npos)
383 {
384 continue;
385 }
386 uint64_t timestampUs = 0;
387 uint64_t size = 0;
388 std::string dumpStatus;
389 std::string originatorId;
390 log_entry::OriginatorTypes originatorType =
391 log_entry::OriginatorTypes::Internal;
392 nlohmann::json::object_t thisEntry;
393
394 std::string entryID = object.first.filename();
395 if (entryID.empty())
396 {
397 continue;
398 }
399
400 parseDumpEntryFromDbusObject(object, dumpStatus, size,
401 timestampUs, originatorId,
402 originatorType, asyncResp);
403
404 if (dumpStatus !=
405 "xyz.openbmc_project.Common.Progress.OperationStatus.Completed" &&
406 !dumpStatus.empty())
407 {
408 // Dump status is not Complete, no need to enumerate
409 continue;
410 }
411
412 thisEntry["@odata.type"] = "#LogEntry.v1_11_0.LogEntry";
413 thisEntry["@odata.id"] = entriesPath + entryID;
414 thisEntry["Id"] = entryID;
415 thisEntry["EntryType"] = "Event";
416 thisEntry["Name"] = dumpType + " Dump Entry";
417 thisEntry["Created"] =
418 redfish::time_utils::getDateTimeUintUs(timestampUs);
419
420 if (!originatorId.empty())
421 {
422 thisEntry["Originator"] = originatorId;
423 thisEntry["OriginatorType"] = originatorType;
424 }
425
426 if (dumpType == "BMC")
427 {
428 thisEntry["DiagnosticDataType"] = "Manager";
429 thisEntry["AdditionalDataURI"] =
430 entriesPath + entryID + "/attachment";
431 thisEntry["AdditionalDataSizeBytes"] = size;
432 }
433 else if (dumpType == "System")
434 {
435 thisEntry["DiagnosticDataType"] = "OEM";
436 thisEntry["OEMDiagnosticDataType"] = "System";
437 thisEntry["AdditionalDataURI"] =
438 entriesPath + entryID + "/attachment";
439 thisEntry["AdditionalDataSizeBytes"] = size;
440 }
441 entriesArray.emplace_back(std::move(thisEntry));
442 }
443 asyncResp->res.jsonValue["Members@odata.count"] =
444 entriesArray.size();
445 asyncResp->res.jsonValue["Members"] = std::move(entriesArray);
Ed Tanous002d39b2022-05-31 08:59:27 -0700446 });
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500447}
448
zhanghch058d1b46d2021-04-01 11:18:24 +0800449inline void
Claire Weinanc7a6d662022-06-13 16:36:39 -0700450 getDumpEntryById(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
zhanghch058d1b46d2021-04-01 11:18:24 +0800451 const std::string& entryID, const std::string& dumpType)
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500452{
Claire Weinanfdd26902022-03-01 14:18:25 -0800453 std::string entriesPath = getDumpEntriesPath(dumpType);
454 if (entriesPath.empty())
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500455 {
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500456 messages::internalError(asyncResp->res);
457 return;
458 }
459
George Liu5eb468d2023-06-20 17:03:24 +0800460 sdbusplus::message::object_path path("/xyz/openbmc_project/dump");
461 dbus::utility::getManagedObjects(
462 "xyz.openbmc_project.Dump.Manager", path,
Claire Weinanfdd26902022-03-01 14:18:25 -0800463 [asyncResp, entryID, dumpType,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800464 entriesPath](const boost::system::error_code& ec,
Ed Tanous02cad962022-06-30 16:50:15 -0700465 const dbus::utility::ManagedObjectType& resp) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400466 if (ec)
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500467 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400468 BMCWEB_LOG_ERROR("DumpEntry resp_handler got error {}", ec);
469 messages::internalError(asyncResp->res);
470 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700471 }
472
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400473 bool foundDumpEntry = false;
474 std::string dumpEntryPath = getDumpPath(dumpType) + "/entry/";
Ed Tanous002d39b2022-05-31 08:59:27 -0700475
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400476 for (const auto& objectPath : resp)
Ed Tanous002d39b2022-05-31 08:59:27 -0700477 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400478 if (objectPath.first.str != dumpEntryPath + entryID)
479 {
480 continue;
481 }
482
483 foundDumpEntry = true;
484 uint64_t timestampUs = 0;
485 uint64_t size = 0;
486 std::string dumpStatus;
487 std::string originatorId;
488 log_entry::OriginatorTypes originatorType =
489 log_entry::OriginatorTypes::Internal;
490
491 parseDumpEntryFromDbusObject(objectPath, dumpStatus, size,
492 timestampUs, originatorId,
493 originatorType, asyncResp);
494
495 if (dumpStatus !=
496 "xyz.openbmc_project.Common.Progress.OperationStatus.Completed" &&
497 !dumpStatus.empty())
498 {
499 // Dump status is not Complete
500 // return not found until status is changed to Completed
501 messages::resourceNotFound(asyncResp->res,
502 dumpType + " dump", entryID);
503 return;
504 }
505
506 asyncResp->res.jsonValue["@odata.type"] =
507 "#LogEntry.v1_11_0.LogEntry";
508 asyncResp->res.jsonValue["@odata.id"] = entriesPath + entryID;
509 asyncResp->res.jsonValue["Id"] = entryID;
510 asyncResp->res.jsonValue["EntryType"] = "Event";
511 asyncResp->res.jsonValue["Name"] = dumpType + " Dump Entry";
512 asyncResp->res.jsonValue["Created"] =
513 redfish::time_utils::getDateTimeUintUs(timestampUs);
514
515 if (!originatorId.empty())
516 {
517 asyncResp->res.jsonValue["Originator"] = originatorId;
518 asyncResp->res.jsonValue["OriginatorType"] = originatorType;
519 }
520
521 if (dumpType == "BMC")
522 {
523 asyncResp->res.jsonValue["DiagnosticDataType"] = "Manager";
524 asyncResp->res.jsonValue["AdditionalDataURI"] =
525 entriesPath + entryID + "/attachment";
526 asyncResp->res.jsonValue["AdditionalDataSizeBytes"] = size;
527 }
528 else if (dumpType == "System")
529 {
530 asyncResp->res.jsonValue["DiagnosticDataType"] = "OEM";
531 asyncResp->res.jsonValue["OEMDiagnosticDataType"] =
532 "System";
533 asyncResp->res.jsonValue["AdditionalDataURI"] =
534 entriesPath + entryID + "/attachment";
535 asyncResp->res.jsonValue["AdditionalDataSizeBytes"] = size;
536 }
537 }
538 if (!foundDumpEntry)
539 {
540 BMCWEB_LOG_WARNING("Can't find Dump Entry {}", entryID);
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +0200541 messages::resourceNotFound(asyncResp->res, dumpType + " dump",
542 entryID);
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500543 return;
544 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400545 });
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500546}
547
zhanghch058d1b46d2021-04-01 11:18:24 +0800548inline void deleteDumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Stanley Chu98782562020-11-04 16:10:24 +0800549 const std::string& entryID,
Asmitha Karunanithib47452b2020-09-25 02:02:19 -0500550 const std::string& dumpType)
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500551{
Patrick Williams5a39f772023-10-20 11:20:21 -0500552 auto respHandler = [asyncResp,
553 entryID](const boost::system::error_code& ec) {
Ed Tanous62598e32023-07-17 17:06:25 -0700554 BMCWEB_LOG_DEBUG("Dump Entry doDelete callback: Done");
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500555 if (ec)
556 {
George Liu3de8d8b2021-03-22 17:49:39 +0800557 if (ec.value() == EBADR)
558 {
559 messages::resourceNotFound(asyncResp->res, "LogEntry", entryID);
560 return;
561 }
Ed Tanous62598e32023-07-17 17:06:25 -0700562 BMCWEB_LOG_ERROR(
563 "Dump (DBus) doDelete respHandler got error {} entryID={}", ec,
564 entryID);
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500565 messages::internalError(asyncResp->res);
566 return;
567 }
568 };
Ed Tanous18f8f602023-07-18 10:07:23 -0700569
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500570 crow::connections::systemBus->async_method_call(
571 respHandler, "xyz.openbmc_project.Dump.Manager",
Ed Tanous18f8f602023-07-18 10:07:23 -0700572 std::format("{}/entry/{}", getDumpPath(dumpType), entryID),
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500573 "xyz.openbmc_project.Object.Delete", "Delete");
574}
Abhilash Rajub5f288d2023-11-08 22:32:44 -0600575inline bool checkSizeLimit(int fd, crow::Response& res)
576{
577 long long int size = lseek(fd, 0, SEEK_END);
578 if (size <= 0)
579 {
580 BMCWEB_LOG_ERROR("Failed to get size of file, lseek() returned {}",
581 size);
582 messages::internalError(res);
583 return false;
584 }
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500585
Abhilash Rajub5f288d2023-11-08 22:32:44 -0600586 // Arbitrary max size of 20MB to accommodate BMC dumps
587 constexpr long long int maxFileSize = 20LL * 1024LL * 1024LL;
588 if (size > maxFileSize)
589 {
590 BMCWEB_LOG_ERROR("File size {} exceeds maximum allowed size of {}",
591 size, maxFileSize);
592 messages::internalError(res);
593 return false;
594 }
595 off_t rc = lseek(fd, 0, SEEK_SET);
596 if (rc < 0)
597 {
598 BMCWEB_LOG_ERROR("Failed to reset file offset to 0");
599 messages::internalError(res);
600 return false;
601 }
602 return true;
603}
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400604inline void downloadEntryCallback(
605 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
606 const std::string& entryID, const std::string& downloadEntryType,
607 const boost::system::error_code& ec,
608 const sdbusplus::message::unix_fd& unixfd)
Carson Labrado168d1b12023-03-27 17:04:46 +0000609{
610 if (ec.value() == EBADR)
611 {
612 messages::resourceNotFound(asyncResp->res, "EntryAttachment", entryID);
613 return;
614 }
615 if (ec)
616 {
617 BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
618 messages::internalError(asyncResp->res);
619 return;
620 }
621
622 // Make sure we know how to process the retrieved entry attachment
623 if ((downloadEntryType != "BMC") && (downloadEntryType != "System"))
624 {
625 BMCWEB_LOG_ERROR("downloadEntryCallback() invalid entry type: {}",
626 downloadEntryType);
627 messages::internalError(asyncResp->res);
628 }
629
630 int fd = -1;
631 fd = dup(unixfd);
632 if (fd < 0)
633 {
634 BMCWEB_LOG_ERROR("Failed to open file");
635 messages::internalError(asyncResp->res);
636 return;
637 }
Abhilash Rajub5f288d2023-11-08 22:32:44 -0600638 if (!checkSizeLimit(fd, asyncResp->res))
Carson Labrado168d1b12023-03-27 17:04:46 +0000639 {
Carson Labrado168d1b12023-03-27 17:04:46 +0000640 close(fd);
641 return;
642 }
Carson Labrado168d1b12023-03-27 17:04:46 +0000643 if (downloadEntryType == "System")
644 {
Abhilash Rajub5f288d2023-11-08 22:32:44 -0600645 if (!asyncResp->res.openFd(fd, bmcweb::EncodingType::Base64))
646 {
647 messages::internalError(asyncResp->res);
648 close(fd);
649 return;
650 }
Carson Labrado168d1b12023-03-27 17:04:46 +0000651 asyncResp->res.addHeader(
652 boost::beast::http::field::content_transfer_encoding, "Base64");
Abhilash Rajub5f288d2023-11-08 22:32:44 -0600653 return;
Carson Labrado168d1b12023-03-27 17:04:46 +0000654 }
Abhilash Rajub5f288d2023-11-08 22:32:44 -0600655 if (!asyncResp->res.openFd(fd))
Ed Tanous27b0cf92023-08-07 12:02:40 -0700656 {
Abhilash Rajub5f288d2023-11-08 22:32:44 -0600657 messages::internalError(asyncResp->res);
658 close(fd);
659 return;
Ed Tanous27b0cf92023-08-07 12:02:40 -0700660 }
Carson Labrado168d1b12023-03-27 17:04:46 +0000661 asyncResp->res.addHeader(boost::beast::http::field::content_type,
662 "application/octet-stream");
663}
664
665inline void
666 downloadDumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
667 const std::string& entryID, const std::string& dumpType)
668{
669 if (dumpType != "BMC")
670 {
671 BMCWEB_LOG_WARNING("Can't find Dump Entry {}", entryID);
672 messages::resourceNotFound(asyncResp->res, dumpType + " dump", entryID);
673 return;
674 }
675
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400676 std::string dumpEntryPath =
677 std::format("{}/entry/{}", getDumpPath(dumpType), entryID);
Carson Labrado168d1b12023-03-27 17:04:46 +0000678
679 auto downloadDumpEntryHandler =
680 [asyncResp, entryID,
681 dumpType](const boost::system::error_code& ec,
682 const sdbusplus::message::unix_fd& unixfd) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400683 downloadEntryCallback(asyncResp, entryID, dumpType, ec, unixfd);
684 };
Carson Labrado168d1b12023-03-27 17:04:46 +0000685
686 crow::connections::systemBus->async_method_call(
687 std::move(downloadDumpEntryHandler), "xyz.openbmc_project.Dump.Manager",
688 dumpEntryPath, "xyz.openbmc_project.Dump.Entry", "GetFileHandle");
689}
690
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400691inline void downloadEventLogEntry(
692 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
693 const std::string& systemName, const std::string& entryID,
694 const std::string& dumpType)
Carson Labrado168d1b12023-03-27 17:04:46 +0000695{
Ed Tanous25b54db2024-04-17 15:40:31 -0700696 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Carson Labrado168d1b12023-03-27 17:04:46 +0000697 {
698 // Option currently returns no systems. TBD
699 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
700 systemName);
701 return;
702 }
Ed Tanous253f11b2024-05-16 09:38:31 -0700703 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Carson Labrado168d1b12023-03-27 17:04:46 +0000704 {
705 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
706 systemName);
707 return;
708 }
709
710 std::string entryPath =
711 sdbusplus::message::object_path("/xyz/openbmc_project/logging/entry") /
712 entryID;
713
714 auto downloadEventLogEntryHandler =
715 [asyncResp, entryID,
716 dumpType](const boost::system::error_code& ec,
717 const sdbusplus::message::unix_fd& unixfd) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400718 downloadEntryCallback(asyncResp, entryID, dumpType, ec, unixfd);
719 };
Carson Labrado168d1b12023-03-27 17:04:46 +0000720
721 crow::connections::systemBus->async_method_call(
722 std::move(downloadEventLogEntryHandler), "xyz.openbmc_project.Logging",
723 entryPath, "xyz.openbmc_project.Logging.Entry", "GetEntry");
724}
725
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600726inline DumpCreationProgress
727 mapDbusStatusToDumpProgress(const std::string& status)
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500728{
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600729 if (status ==
730 "xyz.openbmc_project.Common.Progress.OperationStatus.Failed" ||
731 status == "xyz.openbmc_project.Common.Progress.OperationStatus.Aborted")
732 {
733 return DumpCreationProgress::DUMP_CREATE_FAILED;
734 }
735 if (status ==
736 "xyz.openbmc_project.Common.Progress.OperationStatus.Completed")
737 {
738 return DumpCreationProgress::DUMP_CREATE_SUCCESS;
739 }
740 return DumpCreationProgress::DUMP_CREATE_INPROGRESS;
741}
742
743inline DumpCreationProgress
744 getDumpCompletionStatus(const dbus::utility::DBusPropertiesMap& values)
745{
746 for (const auto& [key, val] : values)
747 {
748 if (key == "Status")
Ed Tanous002d39b2022-05-31 08:59:27 -0700749 {
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600750 const std::string* value = std::get_if<std::string>(&val);
751 if (value == nullptr)
752 {
Ed Tanous62598e32023-07-17 17:06:25 -0700753 BMCWEB_LOG_ERROR("Status property value is null");
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600754 return DumpCreationProgress::DUMP_CREATE_FAILED;
755 }
756 return mapDbusStatusToDumpProgress(*value);
757 }
758 }
759 return DumpCreationProgress::DUMP_CREATE_INPROGRESS;
760}
761
762inline std::string getDumpEntryPath(const std::string& dumpPath)
763{
764 if (dumpPath == "/xyz/openbmc_project/dump/bmc/entry")
765 {
Ed Tanous253f11b2024-05-16 09:38:31 -0700766 return std::format("/redfish/v1/Managers/{}/LogServices/Dump/Entries/",
Ed Tanous9f565092024-07-12 22:06:53 -0700767 BMCWEB_REDFISH_MANAGER_URI_NAME);
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600768 }
769 if (dumpPath == "/xyz/openbmc_project/dump/system/entry")
770 {
Ed Tanous253f11b2024-05-16 09:38:31 -0700771 return std::format("/redfish/v1/Systems/{}/LogServices/Dump/Entries/",
772 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600773 }
774 return "";
775}
776
777inline void createDumpTaskCallback(
778 task::Payload&& payload,
779 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
780 const sdbusplus::message::object_path& createdObjPath)
781{
782 const std::string dumpPath = createdObjPath.parent_path().str;
783 const std::string dumpId = createdObjPath.filename();
784
785 std::string dumpEntryPath = getDumpEntryPath(dumpPath);
786
787 if (dumpEntryPath.empty())
788 {
Ed Tanous62598e32023-07-17 17:06:25 -0700789 BMCWEB_LOG_ERROR("Invalid dump type received");
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600790 messages::internalError(asyncResp->res);
791 return;
792 }
793
794 crow::connections::systemBus->async_method_call(
Ed Tanous8cb2c022024-03-27 16:31:46 -0700795 [asyncResp, payload = std::move(payload), createdObjPath,
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600796 dumpEntryPath{std::move(dumpEntryPath)},
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800797 dumpId](const boost::system::error_code& ec,
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600798 const std::string& introspectXml) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400799 if (ec)
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600800 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400801 BMCWEB_LOG_ERROR("Introspect call failed with error: {}",
802 ec.message());
803 messages::internalError(asyncResp->res);
804 return;
805 }
806
807 // Check if the created dump object has implemented Progress
808 // interface to track dump completion. If yes, fetch the "Status"
809 // property of the interface, modify the task state accordingly.
810 // Else, return task completed.
811 tinyxml2::XMLDocument doc;
812
813 doc.Parse(introspectXml.data(), introspectXml.size());
814 tinyxml2::XMLNode* pRoot = doc.FirstChildElement("node");
815 if (pRoot == nullptr)
816 {
817 BMCWEB_LOG_ERROR("XML document failed to parse");
818 messages::internalError(asyncResp->res);
819 return;
820 }
821 tinyxml2::XMLElement* interfaceNode =
822 pRoot->FirstChildElement("interface");
823
824 bool isProgressIntfPresent = false;
825 while (interfaceNode != nullptr)
826 {
827 const char* thisInterfaceName =
828 interfaceNode->Attribute("name");
829 if (thisInterfaceName != nullptr)
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600830 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400831 if (thisInterfaceName ==
832 std::string_view("xyz.openbmc_project.Common.Progress"))
833 {
834 interfaceNode =
835 interfaceNode->NextSiblingElement("interface");
836 continue;
837 }
838 isProgressIntfPresent = true;
839 break;
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600840 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400841 interfaceNode = interfaceNode->NextSiblingElement("interface");
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600842 }
843
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400844 std::shared_ptr<task::TaskData> task = task::TaskData::createTask(
845 [createdObjPath, dumpEntryPath, dumpId, isProgressIntfPresent](
846 const boost::system::error_code& ec2,
847 sdbusplus::message_t& msg,
848 const std::shared_ptr<task::TaskData>& taskData) {
849 if (ec2)
850 {
851 BMCWEB_LOG_ERROR("{}: Error in creating dump",
852 createdObjPath.str);
853 taskData->messages.emplace_back(
854 messages::internalError());
855 taskData->state = "Cancelled";
856 return task::completed;
857 }
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600858
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400859 if (isProgressIntfPresent)
860 {
861 dbus::utility::DBusPropertiesMap values;
862 std::string prop;
863 msg.read(prop, values);
864
865 DumpCreationProgress dumpStatus =
866 getDumpCompletionStatus(values);
867 if (dumpStatus ==
868 DumpCreationProgress::DUMP_CREATE_FAILED)
869 {
870 BMCWEB_LOG_ERROR("{}: Error in creating dump",
871 createdObjPath.str);
872 taskData->state = "Cancelled";
873 return task::completed;
874 }
875
876 if (dumpStatus ==
877 DumpCreationProgress::DUMP_CREATE_INPROGRESS)
878 {
879 BMCWEB_LOG_DEBUG(
880 "{}: Dump creation task is in progress",
881 createdObjPath.str);
882 return !task::completed;
883 }
884 }
885
886 nlohmann::json retMessage = messages::success();
887 taskData->messages.emplace_back(retMessage);
888
889 boost::urls::url url = boost::urls::format(
890 "/redfish/v1/Managers/{}/LogServices/Dump/Entries/{}",
891 BMCWEB_REDFISH_MANAGER_URI_NAME, dumpId);
892
893 std::string headerLoc = "Location: ";
894 headerLoc += url.buffer();
895
896 taskData->payload->httpHeaders.emplace_back(
897 std::move(headerLoc));
898
899 BMCWEB_LOG_DEBUG("{}: Dump creation task completed",
Ed Tanous62598e32023-07-17 17:06:25 -0700900 createdObjPath.str);
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400901 taskData->state = "Completed";
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600902 return task::completed;
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400903 },
904 "type='signal',interface='org.freedesktop.DBus.Properties',"
905 "member='PropertiesChanged',path='" +
906 createdObjPath.str + "'");
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600907
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400908 // The task timer is set to max time limit within which the
909 // requested dump will be collected.
910 task->startTimer(std::chrono::minutes(6));
911 task->populateResp(asyncResp->res);
912 task->payload.emplace(payload);
Patrick Williams5a39f772023-10-20 11:20:21 -0500913 },
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600914 "xyz.openbmc_project.Dump.Manager", createdObjPath,
915 "org.freedesktop.DBus.Introspectable", "Introspect");
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500916}
917
zhanghch058d1b46d2021-04-01 11:18:24 +0800918inline void createDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
919 const crow::Request& req, const std::string& dumpType)
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500920{
Claire Weinanfdd26902022-03-01 14:18:25 -0800921 std::string dumpPath = getDumpEntriesPath(dumpType);
922 if (dumpPath.empty())
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500923 {
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500924 messages::internalError(asyncResp->res);
925 return;
926 }
927
928 std::optional<std::string> diagnosticDataType;
929 std::optional<std::string> oemDiagnosticDataType;
930
Myung Baeafc474a2024-10-09 00:53:29 -0700931 if (!redfish::json_util::readJsonAction( //
932 req, asyncResp->res, //
933 "DiagnosticDataType", diagnosticDataType, //
934 "OEMDiagnosticDataType", oemDiagnosticDataType //
935 ))
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500936 {
937 return;
938 }
939
940 if (dumpType == "System")
941 {
942 if (!oemDiagnosticDataType || !diagnosticDataType)
943 {
Ed Tanous62598e32023-07-17 17:06:25 -0700944 BMCWEB_LOG_ERROR(
945 "CreateDump action parameter 'DiagnosticDataType'/'OEMDiagnosticDataType' value not found!");
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500946 messages::actionParameterMissing(
947 asyncResp->res, "CollectDiagnosticData",
948 "DiagnosticDataType & OEMDiagnosticDataType");
949 return;
950 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700951 if ((*oemDiagnosticDataType != "System") ||
952 (*diagnosticDataType != "OEM"))
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500953 {
Ed Tanous62598e32023-07-17 17:06:25 -0700954 BMCWEB_LOG_ERROR("Wrong parameter values passed");
Ed Tanousace85d62021-10-26 12:45:59 -0700955 messages::internalError(asyncResp->res);
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500956 return;
957 }
Ed Tanous253f11b2024-05-16 09:38:31 -0700958 dumpPath = std::format("/redfish/v1/Systems/{}/LogServices/Dump/",
959 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500960 }
961 else if (dumpType == "BMC")
962 {
963 if (!diagnosticDataType)
964 {
Ed Tanous62598e32023-07-17 17:06:25 -0700965 BMCWEB_LOG_ERROR(
966 "CreateDump action parameter 'DiagnosticDataType' not found!");
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500967 messages::actionParameterMissing(
968 asyncResp->res, "CollectDiagnosticData", "DiagnosticDataType");
969 return;
970 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700971 if (*diagnosticDataType != "Manager")
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500972 {
Ed Tanous62598e32023-07-17 17:06:25 -0700973 BMCWEB_LOG_ERROR(
974 "Wrong parameter value passed for 'DiagnosticDataType'");
Ed Tanousace85d62021-10-26 12:45:59 -0700975 messages::internalError(asyncResp->res);
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500976 return;
977 }
Ed Tanous253f11b2024-05-16 09:38:31 -0700978 dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/Dump/",
979 BMCWEB_REDFISH_MANAGER_URI_NAME);
Asmitha Karunanithi59075712021-10-22 01:17:41 -0500980 }
981 else
982 {
Ed Tanous62598e32023-07-17 17:06:25 -0700983 BMCWEB_LOG_ERROR("CreateDump failed. Unknown dump type");
Asmitha Karunanithi59075712021-10-22 01:17:41 -0500984 messages::internalError(asyncResp->res);
985 return;
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500986 }
987
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600988 std::vector<std::pair<std::string, std::variant<std::string, uint64_t>>>
989 createDumpParamVec;
990
Carson Labradof574a8e2023-03-22 02:26:00 +0000991 if (req.session != nullptr)
992 {
993 createDumpParamVec.emplace_back(
994 "xyz.openbmc_project.Dump.Create.CreateParameters.OriginatorId",
995 req.session->clientIp);
996 createDumpParamVec.emplace_back(
997 "xyz.openbmc_project.Dump.Create.CreateParameters.OriginatorType",
998 "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Client");
999 }
Asmitha Karunanithi68dd0752022-11-15 11:33:46 -06001000
Asmitha Karunanithia43be802020-05-07 05:05:36 -05001001 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001002 [asyncResp, payload(task::Payload(req)),
1003 dumpPath](const boost::system::error_code& ec,
1004 const sdbusplus::message_t& msg,
1005 const sdbusplus::message::object_path& objPath) mutable {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001006 if (ec)
Asmitha Karunanithi59075712021-10-22 01:17:41 -05001007 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001008 BMCWEB_LOG_ERROR("CreateDump resp_handler got error {}", ec);
1009 const sd_bus_error* dbusError = msg.get_error();
1010 if (dbusError == nullptr)
1011 {
1012 messages::internalError(asyncResp->res);
1013 return;
1014 }
1015
1016 BMCWEB_LOG_ERROR("CreateDump DBus error: {} and error msg: {}",
1017 dbusError->name, dbusError->message);
1018 if (std::string_view(
1019 "xyz.openbmc_project.Common.Error.NotAllowed") ==
1020 dbusError->name)
1021 {
1022 messages::resourceInStandby(asyncResp->res);
1023 return;
1024 }
1025 if (std::string_view(
1026 "xyz.openbmc_project.Dump.Create.Error.Disabled") ==
1027 dbusError->name)
1028 {
1029 messages::serviceDisabled(asyncResp->res, dumpPath);
1030 return;
1031 }
1032 if (std::string_view(
1033 "xyz.openbmc_project.Common.Error.Unavailable") ==
1034 dbusError->name)
1035 {
1036 messages::resourceInUse(asyncResp->res);
1037 return;
1038 }
1039 // Other Dbus errors such as:
1040 // xyz.openbmc_project.Common.Error.InvalidArgument &
1041 // org.freedesktop.DBus.Error.InvalidArgs are all related to
1042 // the dbus call that is made here in the bmcweb
1043 // implementation and has nothing to do with the client's
1044 // input in the request. Hence, returning internal error
1045 // back to the client.
Asmitha Karunanithi59075712021-10-22 01:17:41 -05001046 messages::internalError(asyncResp->res);
1047 return;
1048 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001049 BMCWEB_LOG_DEBUG("Dump Created. Path: {}", objPath.str);
1050 createDumpTaskCallback(std::move(payload), asyncResp, objPath);
1051 },
Ed Tanous18f8f602023-07-18 10:07:23 -07001052 "xyz.openbmc_project.Dump.Manager", getDumpPath(dumpType),
Asmitha Karunanithi8e317782020-12-10 03:35:05 -06001053 "xyz.openbmc_project.Dump.Create", "CreateDump", createDumpParamVec);
Asmitha Karunanithia43be802020-05-07 05:05:36 -05001054}
1055
zhanghch058d1b46d2021-04-01 11:18:24 +08001056inline void clearDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1057 const std::string& dumpType)
Asmitha Karunanithi80319af2020-05-07 05:30:21 -05001058{
Claire Weinan0d946212022-07-13 19:40:19 -07001059 crow::connections::systemBus->async_method_call(
1060 [asyncResp](const boost::system::error_code& ec) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001061 if (ec)
1062 {
1063 BMCWEB_LOG_ERROR("clearDump resp_handler got error {}", ec);
1064 messages::internalError(asyncResp->res);
1065 return;
1066 }
1067 },
Ed Tanous18f8f602023-07-18 10:07:23 -07001068 "xyz.openbmc_project.Dump.Manager", getDumpPath(dumpType),
Claire Weinan0d946212022-07-13 19:40:19 -07001069 "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
Asmitha Karunanithi80319af2020-05-07 05:30:21 -05001070}
1071
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001072inline void parseCrashdumpParameters(
1073 const dbus::utility::DBusPropertiesMap& params, std::string& filename,
1074 std::string& timestamp, std::string& logfile)
Johnathan Mantey043a0532020-03-10 17:15:28 -07001075{
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +02001076 const std::string* filenamePtr = nullptr;
1077 const std::string* timestampPtr = nullptr;
1078 const std::string* logfilePtr = nullptr;
1079
1080 const bool success = sdbusplus::unpackPropertiesNoThrow(
1081 dbus_utils::UnpackErrorPrinter(), params, "Timestamp", timestampPtr,
1082 "Filename", filenamePtr, "Log", logfilePtr);
1083
1084 if (!success)
Johnathan Mantey043a0532020-03-10 17:15:28 -07001085 {
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +02001086 return;
1087 }
1088
1089 if (filenamePtr != nullptr)
1090 {
1091 filename = *filenamePtr;
1092 }
1093
1094 if (timestampPtr != nullptr)
1095 {
1096 timestamp = *timestampPtr;
1097 }
1098
1099 if (logfilePtr != nullptr)
1100 {
1101 logfile = *logfilePtr;
Johnathan Mantey043a0532020-03-10 17:15:28 -07001102 }
1103}
1104
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001105inline void requestRoutesSystemLogServiceCollection(App& app)
Ed Tanous1da66f72018-07-27 16:13:37 -07001106{
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001107 /**
1108 * Functions triggers appropriate requests on DBus
1109 */
Ed Tanous22d268c2022-05-19 09:39:07 -07001110 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/")
Ed Tanoused398212021-06-09 17:05:54 -07001111 .privileges(redfish::privileges::getLogServiceCollection)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001112 .methods(
1113 boost::beast::http::verb::
1114 get)([&app](const crow::Request& req,
1115 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1116 const std::string& systemName) {
1117 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07001118 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001119 return;
1120 }
1121 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1122 {
1123 // Option currently returns no systems. TBD
1124 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1125 systemName);
1126 return;
1127 }
1128 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1129 {
1130 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1131 systemName);
Ed Tanous002d39b2022-05-31 08:59:27 -07001132 return;
1133 }
Ed Tanous45ca1b82022-03-25 13:07:27 -07001134
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001135 // Collections don't include the static data added by SubRoute
1136 // because it has a duplicate entry for members
1137 asyncResp->res.jsonValue["@odata.type"] =
1138 "#LogServiceCollection.LogServiceCollection";
1139 asyncResp->res.jsonValue["@odata.id"] =
1140 std::format("/redfish/v1/Systems/{}/LogServices",
1141 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1142 asyncResp->res.jsonValue["Name"] = "System Log Services Collection";
1143 asyncResp->res.jsonValue["Description"] =
1144 "Collection of LogServices for this Computer System";
1145 nlohmann::json& logServiceArray =
1146 asyncResp->res.jsonValue["Members"];
1147 logServiceArray = nlohmann::json::array();
1148 nlohmann::json::object_t eventLog;
1149 eventLog["@odata.id"] =
1150 std::format("/redfish/v1/Systems/{}/LogServices/EventLog",
1151 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1152 logServiceArray.emplace_back(std::move(eventLog));
1153 if constexpr (BMCWEB_REDFISH_DUMP_LOG)
Ed Tanous002d39b2022-05-31 08:59:27 -07001154 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001155 nlohmann::json::object_t dumpLog;
1156 dumpLog["@odata.id"] =
1157 std::format("/redfish/v1/Systems/{}/LogServices/Dump",
1158 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1159 logServiceArray.emplace_back(std::move(dumpLog));
Ed Tanous002d39b2022-05-31 08:59:27 -07001160 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001161
1162 if constexpr (BMCWEB_REDFISH_CPU_LOG)
1163 {
1164 nlohmann::json::object_t crashdump;
1165 crashdump["@odata.id"] =
1166 std::format("/redfish/v1/Systems/{}/LogServices/Crashdump",
1167 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1168 logServiceArray.emplace_back(std::move(crashdump));
1169 }
1170
1171 if constexpr (BMCWEB_REDFISH_HOST_LOGGER)
1172 {
1173 nlohmann::json::object_t hostlogger;
1174 hostlogger["@odata.id"] =
1175 std::format("/redfish/v1/Systems/{}/LogServices/HostLogger",
1176 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1177 logServiceArray.emplace_back(std::move(hostlogger));
1178 }
1179 asyncResp->res.jsonValue["Members@odata.count"] =
1180 logServiceArray.size();
1181
1182 constexpr std::array<std::string_view, 1> interfaces = {
1183 "xyz.openbmc_project.State.Boot.PostCode"};
1184 dbus::utility::getSubTreePaths(
1185 "/", 0, interfaces,
1186 [asyncResp](const boost::system::error_code& ec,
1187 const dbus::utility::MapperGetSubTreePathsResponse&
1188 subtreePath) {
1189 if (ec)
1190 {
1191 BMCWEB_LOG_ERROR("{}", ec);
1192 return;
1193 }
1194
1195 for (const auto& pathStr : subtreePath)
1196 {
1197 if (pathStr.find("PostCode") != std::string::npos)
1198 {
1199 nlohmann::json& logServiceArrayLocal =
1200 asyncResp->res.jsonValue["Members"];
1201 nlohmann::json::object_t member;
1202 member["@odata.id"] = std::format(
1203 "/redfish/v1/Systems/{}/LogServices/PostCodes",
1204 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1205
1206 logServiceArrayLocal.emplace_back(
1207 std::move(member));
1208
1209 asyncResp->res.jsonValue["Members@odata.count"] =
1210 logServiceArrayLocal.size();
1211 return;
1212 }
1213 }
1214 });
Ed Tanous45ca1b82022-03-25 13:07:27 -07001215 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001216}
1217
1218inline void requestRoutesEventLogService(App& app)
1219{
Ed Tanous22d268c2022-05-19 09:39:07 -07001220 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/")
Ed Tanoused398212021-06-09 17:05:54 -07001221 .privileges(redfish::privileges::getLogService)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001222 .methods(
1223 boost::beast::http::verb::
1224 get)([&app](const crow::Request& req,
1225 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1226 const std::string& systemName) {
1227 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1228 {
1229 return;
1230 }
1231 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1232 {
1233 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1234 systemName);
1235 return;
1236 }
1237 asyncResp->res.jsonValue["@odata.id"] =
1238 std::format("/redfish/v1/Systems/{}/LogServices/EventLog",
1239 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1240 asyncResp->res.jsonValue["@odata.type"] =
1241 "#LogService.v1_2_0.LogService";
1242 asyncResp->res.jsonValue["Name"] = "Event Log Service";
1243 asyncResp->res.jsonValue["Description"] =
1244 "System Event Log Service";
1245 asyncResp->res.jsonValue["Id"] = "EventLog";
1246 asyncResp->res.jsonValue["OverWritePolicy"] =
1247 log_service::OverWritePolicy::WrapsWhenFull;
Tejas Patil7c8c4052021-06-04 17:43:14 +05301248
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001249 std::pair<std::string, std::string> redfishDateTimeOffset =
1250 redfish::time_utils::getDateTimeOffsetNow();
Tejas Patil7c8c4052021-06-04 17:43:14 +05301251
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001252 asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
1253 asyncResp->res.jsonValue["DateTimeLocalOffset"] =
1254 redfishDateTimeOffset.second;
Tejas Patil7c8c4052021-06-04 17:43:14 +05301255
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001256 asyncResp->res.jsonValue["Entries"]["@odata.id"] = std::format(
1257 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
Ed Tanous20fa6a22024-05-20 18:02:58 -07001258 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001259 asyncResp->res
1260 .jsonValue["Actions"]["#LogService.ClearLog"]["target"]
1261
1262 = std::format(
1263 "/redfish/v1/Systems/{}/LogServices/EventLog/Actions/LogService.ClearLog",
1264 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1265 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001266}
1267
Alexander Hansen599b9af2024-08-06 15:11:57 +02001268inline void handleSystemsLogServicesEventLogActionsClearPost(
1269 App& app, const crow::Request& req,
1270 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1271 const std::string& systemName)
1272{
1273 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1274 {
1275 return;
1276 }
1277 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1278 {
1279 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1280 systemName);
1281 return;
1282 }
1283
1284 // Clear the EventLog by deleting the log files
1285 std::vector<std::filesystem::path> redfishLogFiles;
1286 if (getRedfishLogFiles(redfishLogFiles))
1287 {
1288 for (const std::filesystem::path& file : redfishLogFiles)
1289 {
1290 std::error_code ec;
1291 std::filesystem::remove(file, ec);
1292 }
1293 }
1294
1295 // Reload rsyslog so it knows to start new log files
1296 crow::connections::systemBus->async_method_call(
1297 [asyncResp](const boost::system::error_code& ec) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001298 if (ec)
1299 {
1300 BMCWEB_LOG_ERROR("Failed to reload rsyslog: {}", ec);
1301 messages::internalError(asyncResp->res);
1302 return;
1303 }
Alexander Hansen599b9af2024-08-06 15:11:57 +02001304
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001305 messages::success(asyncResp->res);
1306 },
Alexander Hansen599b9af2024-08-06 15:11:57 +02001307 "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
1308 "org.freedesktop.systemd1.Manager", "ReloadUnit", "rsyslog.service",
1309 "replace");
1310}
1311
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001312inline void requestRoutesJournalEventLogClear(App& app)
1313{
Jason M. Bills4978b632022-02-22 14:17:43 -08001314 BMCWEB_ROUTE(
1315 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07001316 "/redfish/v1/Systems/<str>/LogServices/EventLog/Actions/LogService.ClearLog/")
Ed Tanous432a8902021-06-14 15:28:56 -07001317 .privileges({{"ConfigureComponents"}})
Alexander Hansen599b9af2024-08-06 15:11:57 +02001318 .methods(boost::beast::http::verb::post)(std::bind_front(
1319 handleSystemsLogServicesEventLogActionsClearPost, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001320}
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001321
Jason M. Billsac992cd2022-06-24 13:31:46 -07001322enum class LogParseError
1323{
1324 success,
1325 parseFailed,
1326 messageIdNotInRegistry,
1327};
1328
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001329static LogParseError fillEventLogEntryJson(
1330 const std::string& logEntryID, const std::string& logEntry,
1331 nlohmann::json::object_t& logEntryJson)
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001332{
Jason M. Bills95820182019-04-22 16:25:34 -07001333 // The redfish log format is "<Timestamp> <MessageId>,<MessageArgs>"
Jason M. Billscd225da2019-05-08 15:31:57 -07001334 // First get the Timestamp
Ed Tanousf23b7292020-10-15 09:41:17 -07001335 size_t space = logEntry.find_first_of(' ');
Jason M. Billscd225da2019-05-08 15:31:57 -07001336 if (space == std::string::npos)
Jason M. Bills95820182019-04-22 16:25:34 -07001337 {
Jason M. Billsac992cd2022-06-24 13:31:46 -07001338 return LogParseError::parseFailed;
Jason M. Bills95820182019-04-22 16:25:34 -07001339 }
Jason M. Billscd225da2019-05-08 15:31:57 -07001340 std::string timestamp = logEntry.substr(0, space);
1341 // Then get the log contents
Ed Tanousf23b7292020-10-15 09:41:17 -07001342 size_t entryStart = logEntry.find_first_not_of(' ', space);
Jason M. Billscd225da2019-05-08 15:31:57 -07001343 if (entryStart == std::string::npos)
1344 {
Jason M. Billsac992cd2022-06-24 13:31:46 -07001345 return LogParseError::parseFailed;
Jason M. Billscd225da2019-05-08 15:31:57 -07001346 }
1347 std::string_view entry(logEntry);
1348 entry.remove_prefix(entryStart);
1349 // Use split to separate the entry into its fields
1350 std::vector<std::string> logEntryFields;
Ed Tanous50ebd4a2023-01-19 19:03:17 -08001351 bmcweb::split(logEntryFields, entry, ',');
Jason M. Billscd225da2019-05-08 15:31:57 -07001352 // We need at least a MessageId to be valid
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001353 auto logEntryIter = logEntryFields.begin();
1354 if (logEntryIter == logEntryFields.end())
Jason M. Billscd225da2019-05-08 15:31:57 -07001355 {
Jason M. Billsac992cd2022-06-24 13:31:46 -07001356 return LogParseError::parseFailed;
Jason M. Billscd225da2019-05-08 15:31:57 -07001357 }
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001358 std::string& messageID = *logEntryIter;
Jason M. Bills4851d452019-03-28 11:27:48 -07001359 // Get the Message from the MessageRegistry
Ed Tanousfffb8c12022-02-07 23:53:03 -08001360 const registries::Message* message = registries::getMessage(messageID);
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001361
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001362 logEntryIter++;
Sui Chen54417b02022-03-24 14:59:52 -07001363 if (message == nullptr)
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001364 {
Ed Tanous62598e32023-07-17 17:06:25 -07001365 BMCWEB_LOG_WARNING("Log entry not found in registry: {}", logEntry);
Jason M. Billsac992cd2022-06-24 13:31:46 -07001366 return LogParseError::messageIdNotInRegistry;
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001367 }
1368
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001369 std::vector<std::string_view> messageArgs(logEntryIter,
1370 logEntryFields.end());
Ed Tanousc05bba42023-06-28 08:33:29 -07001371 messageArgs.resize(message->numberOfArgs);
1372
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001373 std::string msg =
1374 redfish::registries::fillMessageArgs(messageArgs, message->message);
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001375 if (msg.empty())
Jason M. Bills4851d452019-03-28 11:27:48 -07001376 {
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001377 return LogParseError::parseFailed;
Jason M. Bills4851d452019-03-28 11:27:48 -07001378 }
1379
Jason M. Bills95820182019-04-22 16:25:34 -07001380 // Get the Created time from the timestamp. The log timestamp is in RFC3339
1381 // format which matches the Redfish format except for the fractional seconds
1382 // between the '.' and the '+', so just remove them.
Ed Tanousf23b7292020-10-15 09:41:17 -07001383 std::size_t dot = timestamp.find_first_of('.');
1384 std::size_t plus = timestamp.find_first_of('+');
Jason M. Bills95820182019-04-22 16:25:34 -07001385 if (dot != std::string::npos && plus != std::string::npos)
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001386 {
Jason M. Bills95820182019-04-22 16:25:34 -07001387 timestamp.erase(dot, plus - dot);
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001388 }
1389
1390 // Fill in the log entry with the gathered data
Vijay Lobo9c11a172021-10-07 16:53:16 -05001391 logEntryJson["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
Ed Tanousef4c65b2023-04-24 15:28:50 -07001392 logEntryJson["@odata.id"] = boost::urls::format(
Ed Tanous253f11b2024-05-16 09:38:31 -07001393 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}",
1394 BMCWEB_REDFISH_SYSTEM_URI_NAME, logEntryID);
Jason M. Bills84afc482022-06-24 12:38:23 -07001395 logEntryJson["Name"] = "System Event Log Entry";
1396 logEntryJson["Id"] = logEntryID;
1397 logEntryJson["Message"] = std::move(msg);
1398 logEntryJson["MessageId"] = std::move(messageID);
1399 logEntryJson["MessageArgs"] = messageArgs;
1400 logEntryJson["EntryType"] = "Event";
1401 logEntryJson["Severity"] = message->messageSeverity;
1402 logEntryJson["Created"] = std::move(timestamp);
Jason M. Billsac992cd2022-06-24 13:31:46 -07001403 return LogParseError::success;
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001404}
1405
Ed Tanous898f2aa2024-08-07 12:18:22 -07001406inline void fillEventLogLogEntryFromPropertyMap(
1407 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1408 const dbus::utility::DBusPropertiesMap& resp,
1409 nlohmann::json& objectToFillOut)
1410{
Alexander Hansen262dcc12024-09-19 12:04:03 +02001411 std::optional<DbusEventLogEntry> optEntry =
1412 fillDbusEventLogEntryFromPropertyMap(resp);
Ed Tanous898f2aa2024-08-07 12:18:22 -07001413
Alexander Hansen262dcc12024-09-19 12:04:03 +02001414 if (!optEntry.has_value())
Ed Tanous898f2aa2024-08-07 12:18:22 -07001415 {
1416 messages::internalError(asyncResp->res);
1417 return;
1418 }
Alexander Hansen262dcc12024-09-19 12:04:03 +02001419 DbusEventLogEntry entry = optEntry.value();
Ed Tanous898f2aa2024-08-07 12:18:22 -07001420
1421 objectToFillOut["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
1422 objectToFillOut["@odata.id"] = boost::urls::format(
1423 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}",
Alexander Hansen262dcc12024-09-19 12:04:03 +02001424 BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(entry.Id));
Ed Tanous898f2aa2024-08-07 12:18:22 -07001425 objectToFillOut["Name"] = "System Event Log Entry";
Alexander Hansen262dcc12024-09-19 12:04:03 +02001426 objectToFillOut["Id"] = std::to_string(entry.Id);
1427 objectToFillOut["Message"] = entry.Message;
1428 objectToFillOut["Resolved"] = entry.Resolved;
1429 std::optional<bool> notifyAction =
1430 getProviderNotifyAction(entry.ServiceProviderNotify);
Ed Tanous898f2aa2024-08-07 12:18:22 -07001431 if (notifyAction)
1432 {
1433 objectToFillOut["ServiceProviderNotified"] = *notifyAction;
1434 }
Alexander Hansen262dcc12024-09-19 12:04:03 +02001435 if ((entry.Resolution != nullptr) && !entry.Resolution->empty())
Ed Tanous898f2aa2024-08-07 12:18:22 -07001436 {
Alexander Hansen262dcc12024-09-19 12:04:03 +02001437 objectToFillOut["Resolution"] = *entry.Resolution;
Ed Tanous898f2aa2024-08-07 12:18:22 -07001438 }
1439 objectToFillOut["EntryType"] = "Event";
Alexander Hansen262dcc12024-09-19 12:04:03 +02001440 objectToFillOut["Severity"] =
1441 translateSeverityDbusToRedfish(entry.Severity);
Ed Tanous898f2aa2024-08-07 12:18:22 -07001442 objectToFillOut["Created"] =
Alexander Hansen262dcc12024-09-19 12:04:03 +02001443 redfish::time_utils::getDateTimeUintMs(entry.Timestamp);
Ed Tanous898f2aa2024-08-07 12:18:22 -07001444 objectToFillOut["Modified"] =
Alexander Hansen262dcc12024-09-19 12:04:03 +02001445 redfish::time_utils::getDateTimeUintMs(entry.UpdateTimestamp);
1446 if (entry.Path != nullptr)
Ed Tanous898f2aa2024-08-07 12:18:22 -07001447 {
1448 objectToFillOut["AdditionalDataURI"] = boost::urls::format(
1449 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}/attachment",
Alexander Hansen262dcc12024-09-19 12:04:03 +02001450 BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(entry.Id));
Ed Tanous898f2aa2024-08-07 12:18:22 -07001451 }
1452}
1453
Ed Tanousb7290962024-08-07 11:09:51 -07001454inline void afterLogEntriesGetManagedObjects(
1455 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1456 const boost::system::error_code& ec,
1457 const dbus::utility::ManagedObjectType& resp)
1458{
1459 if (ec)
1460 {
1461 // TODO Handle for specific error code
1462 BMCWEB_LOG_ERROR("getLogEntriesIfaceData resp_handler got error {}",
1463 ec);
1464 messages::internalError(asyncResp->res);
1465 return;
1466 }
1467 nlohmann::json::array_t entriesArray;
1468 for (const auto& objectPath : resp)
1469 {
Ed Tanous898f2aa2024-08-07 12:18:22 -07001470 dbus::utility::DBusPropertiesMap propsFlattened;
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001471 auto isEntry =
1472 std::ranges::find_if(objectPath.second, [](const auto& object) {
1473 return object.first == "xyz.openbmc_project.Logging.Entry";
1474 });
Ed Tanous898f2aa2024-08-07 12:18:22 -07001475 if (isEntry == objectPath.second.end())
Ed Tanousb7290962024-08-07 11:09:51 -07001476 {
1477 continue;
1478 }
Ed Tanous898f2aa2024-08-07 12:18:22 -07001479 for (const auto& interfaceMap : objectPath.second)
Ed Tanousb7290962024-08-07 11:09:51 -07001480 {
Ed Tanous898f2aa2024-08-07 12:18:22 -07001481 for (const auto& propertyMap : interfaceMap.second)
Ed Tanousb7290962024-08-07 11:09:51 -07001482 {
Ed Tanous898f2aa2024-08-07 12:18:22 -07001483 propsFlattened.emplace_back(propertyMap.first,
1484 propertyMap.second);
Ed Tanousb7290962024-08-07 11:09:51 -07001485 }
1486 }
Ed Tanous898f2aa2024-08-07 12:18:22 -07001487 fillEventLogLogEntryFromPropertyMap(asyncResp, propsFlattened,
1488 entriesArray.emplace_back());
Ed Tanousb7290962024-08-07 11:09:51 -07001489 }
Ed Tanous898f2aa2024-08-07 12:18:22 -07001490
Ed Tanousb7290962024-08-07 11:09:51 -07001491 std::ranges::sort(entriesArray, [](const nlohmann::json& left,
1492 const nlohmann::json& right) {
1493 return (left["Id"] <= right["Id"]);
1494 });
1495 asyncResp->res.jsonValue["Members@odata.count"] = entriesArray.size();
1496 asyncResp->res.jsonValue["Members"] = std::move(entriesArray);
1497}
1498
Alexander Hansen599b9af2024-08-06 15:11:57 +02001499inline void handleSystemsLogServiceEventLogLogEntryCollection(
1500 App& app, const crow::Request& req,
1501 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1502 const std::string& systemName)
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001503{
Alexander Hansen599b9af2024-08-06 15:11:57 +02001504 query_param::QueryCapabilities capabilities = {
1505 .canDelegateTop = true,
1506 .canDelegateSkip = true,
1507 };
1508 query_param::Query delegatedQuery;
1509 if (!redfish::setUpRedfishRouteWithDelegation(app, req, asyncResp,
1510 delegatedQuery, capabilities))
1511 {
1512 return;
1513 }
1514 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1515 {
1516 // Option currently returns no systems. TBD
1517 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1518 systemName);
1519 return;
1520 }
1521 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1522 {
1523 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1524 systemName);
1525 return;
1526 }
1527
1528 size_t top = delegatedQuery.top.value_or(query_param::Query::maxTop);
1529 size_t skip = delegatedQuery.skip.value_or(0);
1530
1531 // Collections don't include the static data added by SubRoute
1532 // because it has a duplicate entry for members
1533 asyncResp->res.jsonValue["@odata.type"] =
1534 "#LogEntryCollection.LogEntryCollection";
1535 asyncResp->res.jsonValue["@odata.id"] =
1536 std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
1537 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1538 asyncResp->res.jsonValue["Name"] = "System Event Log Entries";
1539 asyncResp->res.jsonValue["Description"] =
1540 "Collection of System Event Log Entries";
1541
1542 nlohmann::json& logEntryArray = asyncResp->res.jsonValue["Members"];
1543 logEntryArray = nlohmann::json::array();
1544 // Go through the log files and create a unique ID for each
1545 // entry
1546 std::vector<std::filesystem::path> redfishLogFiles;
1547 getRedfishLogFiles(redfishLogFiles);
1548 uint64_t entryCount = 0;
1549 std::string logEntry;
1550
1551 // Oldest logs are in the last file, so start there and loop
1552 // backwards
1553 for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend(); it++)
1554 {
1555 std::ifstream logStream(*it);
1556 if (!logStream.is_open())
Ed Tanous002d39b2022-05-31 08:59:27 -07001557 {
Alexander Hansen599b9af2024-08-06 15:11:57 +02001558 continue;
Ed Tanous22d268c2022-05-19 09:39:07 -07001559 }
1560
Alexander Hansen599b9af2024-08-06 15:11:57 +02001561 // Reset the unique ID on the first entry
1562 bool firstEntry = true;
1563 while (std::getline(logStream, logEntry))
Ed Tanous002d39b2022-05-31 08:59:27 -07001564 {
Alexander Hansen599b9af2024-08-06 15:11:57 +02001565 std::string idStr;
1566 if (!getUniqueEntryID(logEntry, idStr, firstEntry))
1567 {
1568 continue;
1569 }
1570 firstEntry = false;
1571
1572 nlohmann::json::object_t bmcLogEntry;
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001573 LogParseError status =
1574 fillEventLogEntryJson(idStr, logEntry, bmcLogEntry);
Alexander Hansen599b9af2024-08-06 15:11:57 +02001575 if (status == LogParseError::messageIdNotInRegistry)
1576 {
1577 continue;
1578 }
1579 if (status != LogParseError::success)
1580 {
1581 messages::internalError(asyncResp->res);
1582 return;
1583 }
1584
1585 entryCount++;
1586 // Handle paging using skip (number of entries to skip from the
1587 // start) and top (number of entries to display)
1588 if (entryCount <= skip || entryCount > skip + top)
Jason M. Bills4978b632022-02-22 14:17:43 -08001589 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001590 continue;
Jason M. Bills4978b632022-02-22 14:17:43 -08001591 }
Jason M. Bills897967d2019-07-29 17:05:30 -07001592
Alexander Hansen599b9af2024-08-06 15:11:57 +02001593 logEntryArray.emplace_back(std::move(bmcLogEntry));
1594 }
1595 }
1596 asyncResp->res.jsonValue["Members@odata.count"] = entryCount;
1597 if (skip + top < entryCount)
1598 {
1599 asyncResp->res.jsonValue["Members@odata.nextLink"] =
1600 boost::urls::format(
1601 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries?$skip={}",
1602 BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(skip + top));
1603 }
1604}
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001605
Alexander Hansen599b9af2024-08-06 15:11:57 +02001606inline void requestRoutesJournalEventLogEntryCollection(App& app)
1607{
1608 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/")
1609 .privileges(redfish::privileges::getLogEntryCollection)
1610 .methods(boost::beast::http::verb::get)(std::bind_front(
1611 handleSystemsLogServiceEventLogLogEntryCollection, std::ref(app)));
1612}
1613
1614inline void handleSystemsLogServiceEventLogEntriesGet(
1615 App& app, const crow::Request& req,
1616 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1617 const std::string& systemName, const std::string& param)
1618{
1619 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1620 {
1621 return;
1622 }
1623 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1624 {
1625 // Option currently returns no systems. TBD
1626 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1627 systemName);
1628 return;
1629 }
1630
1631 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1632 {
1633 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1634 systemName);
1635 return;
1636 }
1637
1638 const std::string& targetID = param;
1639
1640 // Go through the log files and check the unique ID for each
1641 // entry to find the target entry
1642 std::vector<std::filesystem::path> redfishLogFiles;
1643 getRedfishLogFiles(redfishLogFiles);
1644 std::string logEntry;
1645
1646 // Oldest logs are in the last file, so start there and loop
1647 // backwards
1648 for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend(); it++)
1649 {
1650 std::ifstream logStream(*it);
1651 if (!logStream.is_open())
1652 {
1653 continue;
1654 }
1655
1656 // Reset the unique ID on the first entry
1657 bool firstEntry = true;
1658 while (std::getline(logStream, logEntry))
1659 {
1660 std::string idStr;
1661 if (!getUniqueEntryID(logEntry, idStr, firstEntry))
1662 {
1663 continue;
1664 }
1665 firstEntry = false;
1666
1667 if (idStr == targetID)
1668 {
Jason M. Billsde703c52022-06-23 14:19:04 -07001669 nlohmann::json::object_t bmcLogEntry;
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001670 LogParseError status =
1671 fillEventLogEntryJson(idStr, logEntry, bmcLogEntry);
Jason M. Billsac992cd2022-06-24 13:31:46 -07001672 if (status != LogParseError::success)
Ed Tanous002d39b2022-05-31 08:59:27 -07001673 {
1674 messages::internalError(asyncResp->res);
1675 return;
Andrew Geisslercb92c032018-08-17 07:56:14 -07001676 }
Alexander Hansen599b9af2024-08-06 15:11:57 +02001677 asyncResp->res.jsonValue.update(bmcLogEntry);
1678 return;
Jason M. Bills4978b632022-02-22 14:17:43 -08001679 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001680 }
Alexander Hansen599b9af2024-08-06 15:11:57 +02001681 }
1682 // Requested ID was not found
1683 messages::resourceNotFound(asyncResp->res, "LogEntry", targetID);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001684}
Chicago Duan336e96c2019-07-15 14:22:08 +08001685
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001686inline void requestRoutesJournalEventLogEntry(App& app)
1687{
1688 BMCWEB_ROUTE(
Ed Tanous22d268c2022-05-19 09:39:07 -07001689 app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001690 .privileges(redfish::privileges::getLogEntry)
Alexander Hansen599b9af2024-08-06 15:11:57 +02001691 .methods(boost::beast::http::verb::get)(std::bind_front(
1692 handleSystemsLogServiceEventLogEntriesGet, std::ref(app)));
1693}
1694
1695inline void dBusEventLogEntryCollection(
1696 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1697{
1698 // Collections don't include the static data added by SubRoute
1699 // because it has a duplicate entry for members
1700 asyncResp->res.jsonValue["@odata.type"] =
1701 "#LogEntryCollection.LogEntryCollection";
1702 asyncResp->res.jsonValue["@odata.id"] =
1703 std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
1704 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1705 asyncResp->res.jsonValue["Name"] = "System Event Log Entries";
1706 asyncResp->res.jsonValue["Description"] =
1707 "Collection of System Event Log Entries";
1708
1709 // DBus implementation of EventLog/Entries
1710 // Make call to Logging Service to find all log entry objects
1711 sdbusplus::message::object_path path("/xyz/openbmc_project/logging");
1712 dbus::utility::getManagedObjects(
1713 "xyz.openbmc_project.Logging", path,
1714 [asyncResp](const boost::system::error_code& ec,
1715 const dbus::utility::ManagedObjectType& resp) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001716 afterLogEntriesGetManagedObjects(asyncResp, ec, resp);
1717 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001718}
1719
1720inline void requestRoutesDBusEventLogEntryCollection(App& app)
1721{
Ed Tanous22d268c2022-05-19 09:39:07 -07001722 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/")
Ed Tanoused398212021-06-09 17:05:54 -07001723 .privileges(redfish::privileges::getLogEntryCollection)
Ed Tanous002d39b2022-05-31 08:59:27 -07001724 .methods(boost::beast::http::verb::get)(
1725 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07001726 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1727 const std::string& systemName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001728 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1729 {
1730 return;
1731 }
1732 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1733 {
1734 // Option currently returns no systems. TBD
1735 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1736 systemName);
1737 return;
1738 }
1739 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1740 {
1741 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1742 systemName);
1743 return;
1744 }
1745 dBusEventLogEntryCollection(asyncResp);
1746 });
Alexander Hansen599b9af2024-08-06 15:11:57 +02001747}
Ed Tanous22d268c2022-05-19 09:39:07 -07001748
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001749inline void dBusEventLogEntryGet(
1750 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID)
Alexander Hansen599b9af2024-08-06 15:11:57 +02001751{
1752 dbus::utility::escapePathForDbus(entryID);
Ed Tanous002d39b2022-05-31 08:59:27 -07001753
Alexander Hansen599b9af2024-08-06 15:11:57 +02001754 // DBus implementation of EventLog/Entries
1755 // Make call to Logging Service to find all log entry objects
Ed Tanousdeae6a72024-11-11 21:58:57 -08001756 dbus::utility::getAllProperties(
1757 "xyz.openbmc_project.Logging",
Alexander Hansen599b9af2024-08-06 15:11:57 +02001758 "/xyz/openbmc_project/logging/entry/" + entryID, "",
1759 [asyncResp, entryID](const boost::system::error_code& ec,
1760 const dbus::utility::DBusPropertiesMap& resp) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001761 if (ec.value() == EBADR)
1762 {
1763 messages::resourceNotFound(asyncResp->res, "EventLogEntry",
1764 entryID);
1765 return;
1766 }
1767 if (ec)
1768 {
1769 BMCWEB_LOG_ERROR(
1770 "EventLogEntry (DBus) resp_handler got error {}", ec);
1771 messages::internalError(asyncResp->res);
1772 return;
1773 }
Alexander Hansen599b9af2024-08-06 15:11:57 +02001774
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001775 fillEventLogLogEntryFromPropertyMap(asyncResp, resp,
1776 asyncResp->res.jsonValue);
1777 });
Alexander Hansen599b9af2024-08-06 15:11:57 +02001778}
1779
1780inline void
1781 dBusEventLogEntryPatch(const crow::Request& req,
1782 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1783 const std::string& entryId)
1784{
1785 std::optional<bool> resolved;
1786
1787 if (!json_util::readJsonPatch(req, asyncResp->res, "Resolved", resolved))
1788 {
1789 return;
1790 }
1791 BMCWEB_LOG_DEBUG("Set Resolved");
1792
1793 setDbusProperty(asyncResp, "Resolved", "xyz.openbmc_project.Logging",
1794 "/xyz/openbmc_project/logging/entry/" + entryId,
1795 "xyz.openbmc_project.Logging.Entry", "Resolved",
1796 resolved.value_or(false));
1797}
1798
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001799inline void dBusEventLogEntryDelete(
1800 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID)
Alexander Hansen599b9af2024-08-06 15:11:57 +02001801{
1802 BMCWEB_LOG_DEBUG("Do delete single event entries.");
1803
1804 dbus::utility::escapePathForDbus(entryID);
1805
1806 // Process response from Logging service.
1807 auto respHandler = [asyncResp,
1808 entryID](const boost::system::error_code& ec) {
1809 BMCWEB_LOG_DEBUG("EventLogEntry (DBus) doDelete callback: Done");
1810 if (ec)
1811 {
1812 if (ec.value() == EBADR)
Ed Tanous45ca1b82022-03-25 13:07:27 -07001813 {
Alexander Hansen599b9af2024-08-06 15:11:57 +02001814 messages::resourceNotFound(asyncResp->res, "LogEntry", entryID);
Ed Tanous45ca1b82022-03-25 13:07:27 -07001815 return;
1816 }
Alexander Hansen599b9af2024-08-06 15:11:57 +02001817 // TODO Handle for specific error code
1818 BMCWEB_LOG_ERROR(
1819 "EventLogEntry (DBus) doDelete respHandler got error {}", ec);
1820 asyncResp->res.result(
1821 boost::beast::http::status::internal_server_error);
1822 return;
1823 }
Abhishek Patel9017faf2021-09-14 22:48:55 -05001824
Alexander Hansen599b9af2024-08-06 15:11:57 +02001825 asyncResp->res.result(boost::beast::http::status::ok);
1826 };
1827
1828 // Make call to Logging service to request Delete Log
1829 crow::connections::systemBus->async_method_call(
1830 respHandler, "xyz.openbmc_project.Logging",
1831 "/xyz/openbmc_project/logging/entry/" + entryID,
1832 "xyz.openbmc_project.Object.Delete", "Delete");
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001833}
Xiaochao Ma75710de2021-01-21 17:56:02 +08001834
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001835inline void requestRoutesDBusEventLogEntry(App& app)
Adriana Kobylak400fd1f2021-01-29 09:01:30 -06001836{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001837 BMCWEB_ROUTE(
Ed Tanous22d268c2022-05-19 09:39:07 -07001838 app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001839 .privileges(redfish::privileges::getLogEntry)
Ed Tanous002d39b2022-05-31 08:59:27 -07001840 .methods(boost::beast::http::verb::get)(
1841 [&app](const crow::Request& req,
1842 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous898f2aa2024-08-07 12:18:22 -07001843 const std::string& systemName, const std::string& entryId) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001844 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1845 {
1846 return;
1847 }
1848 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1849 {
1850 // Option currently returns no systems. TBD
1851 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1852 systemName);
1853 return;
1854 }
1855 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1856 {
1857 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1858 systemName);
1859 return;
1860 }
Ed Tanous22d268c2022-05-19 09:39:07 -07001861
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001862 dBusEventLogEntryGet(asyncResp, entryId);
1863 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001864
1865 BMCWEB_ROUTE(
Ed Tanous22d268c2022-05-19 09:39:07 -07001866 app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001867 .privileges(redfish::privileges::patchLogEntry)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001868 .methods(boost::beast::http::verb::patch)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07001869 [&app](const crow::Request& req,
1870 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -07001871 const std::string& systemName, const std::string& entryId) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001872 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1873 {
1874 return;
1875 }
1876 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1877 {
1878 // Option currently returns no systems. TBD
1879 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1880 systemName);
1881 return;
1882 }
1883 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1884 {
1885 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1886 systemName);
1887 return;
1888 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001889
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001890 dBusEventLogEntryPatch(req, asyncResp, entryId);
1891 });
Adriana Kobylak400fd1f2021-01-29 09:01:30 -06001892
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001893 BMCWEB_ROUTE(
Ed Tanous22d268c2022-05-19 09:39:07 -07001894 app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001895 .privileges(redfish::privileges::deleteLogEntry)
1896
Ed Tanous002d39b2022-05-31 08:59:27 -07001897 .methods(boost::beast::http::verb::delete_)(
1898 [&app](const crow::Request& req,
1899 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -07001900 const std::string& systemName, const std::string& param) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001901 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1902 {
1903 return;
1904 }
1905 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1906 {
1907 // Option currently returns no systems. TBD
1908 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1909 systemName);
1910 return;
1911 }
1912 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1913 {
1914 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1915 systemName);
1916 return;
1917 }
1918 dBusEventLogEntryDelete(asyncResp, param);
1919 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001920}
1921
Claire Weinandd72e872022-08-15 14:20:06 -07001922inline void handleBMCLogServicesCollectionGet(
Claire Weinanfdd26902022-03-01 14:18:25 -08001923 crow::App& app, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07001924 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1925 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08001926{
1927 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1928 {
1929 return;
1930 }
Ed Tanous253f11b2024-05-16 09:38:31 -07001931
1932 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
1933 {
1934 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
1935 return;
1936 }
1937
Claire Weinanfdd26902022-03-01 14:18:25 -08001938 // Collections don't include the static data added by SubRoute
1939 // because it has a duplicate entry for members
1940 asyncResp->res.jsonValue["@odata.type"] =
1941 "#LogServiceCollection.LogServiceCollection";
Ed Tanous253f11b2024-05-16 09:38:31 -07001942 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
1943 "/redfish/v1/Managers/{}/LogServices", BMCWEB_REDFISH_MANAGER_URI_NAME);
Claire Weinanfdd26902022-03-01 14:18:25 -08001944 asyncResp->res.jsonValue["Name"] = "Open BMC Log Services Collection";
1945 asyncResp->res.jsonValue["Description"] =
1946 "Collection of LogServices for this Manager";
1947 nlohmann::json& logServiceArray = asyncResp->res.jsonValue["Members"];
1948 logServiceArray = nlohmann::json::array();
1949
Ed Tanous25b54db2024-04-17 15:40:31 -07001950 if constexpr (BMCWEB_REDFISH_BMC_JOURNAL)
1951 {
1952 nlohmann::json::object_t journal;
Ed Tanous253f11b2024-05-16 09:38:31 -07001953 journal["@odata.id"] =
1954 boost::urls::format("/redfish/v1/Managers/{}/LogServices/Journal",
1955 BMCWEB_REDFISH_MANAGER_URI_NAME);
Ed Tanous25b54db2024-04-17 15:40:31 -07001956 logServiceArray.emplace_back(std::move(journal));
1957 }
Claire Weinanfdd26902022-03-01 14:18:25 -08001958
1959 asyncResp->res.jsonValue["Members@odata.count"] = logServiceArray.size();
1960
Ed Tanous25b54db2024-04-17 15:40:31 -07001961 if constexpr (BMCWEB_REDFISH_DUMP_LOG)
1962 {
1963 constexpr std::array<std::string_view, 1> interfaces = {
1964 "xyz.openbmc_project.Collection.DeleteAll"};
1965 dbus::utility::getSubTreePaths(
1966 "/xyz/openbmc_project/dump", 0, interfaces,
1967 [asyncResp](const boost::system::error_code& ec,
1968 const dbus::utility::MapperGetSubTreePathsResponse&
1969 subTreePaths) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001970 if (ec)
Ed Tanous25b54db2024-04-17 15:40:31 -07001971 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001972 BMCWEB_LOG_ERROR(
1973 "handleBMCLogServicesCollectionGet respHandler got error {}",
1974 ec);
1975 // Assume that getting an error simply means there are no
1976 // dump LogServices. Return without adding any error
1977 // response.
1978 return;
Ed Tanous25b54db2024-04-17 15:40:31 -07001979 }
Ed Tanous25b54db2024-04-17 15:40:31 -07001980
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001981 nlohmann::json& logServiceArrayLocal =
1982 asyncResp->res.jsonValue["Members"];
1983
1984 for (const std::string& path : subTreePaths)
1985 {
1986 if (path == "/xyz/openbmc_project/dump/bmc")
1987 {
1988 nlohmann::json::object_t member;
1989 member["@odata.id"] = boost::urls::format(
1990 "/redfish/v1/Managers/{}/LogServices/Dump",
1991 BMCWEB_REDFISH_MANAGER_URI_NAME);
1992 logServiceArrayLocal.emplace_back(std::move(member));
1993 }
1994 else if (path == "/xyz/openbmc_project/dump/faultlog")
1995 {
1996 nlohmann::json::object_t member;
1997 member["@odata.id"] = boost::urls::format(
1998 "/redfish/v1/Managers/{}/LogServices/FaultLog",
1999 BMCWEB_REDFISH_MANAGER_URI_NAME);
2000 logServiceArrayLocal.emplace_back(std::move(member));
2001 }
2002 }
2003
2004 asyncResp->res.jsonValue["Members@odata.count"] =
2005 logServiceArrayLocal.size();
2006 });
Ed Tanous25b54db2024-04-17 15:40:31 -07002007 }
Claire Weinanfdd26902022-03-01 14:18:25 -08002008}
2009
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002010inline void requestRoutesBMCLogServiceCollection(App& app)
2011{
Ed Tanous253f11b2024-05-16 09:38:31 -07002012 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/")
Gunnar Millsad89dcf2021-07-30 14:40:11 -05002013 .privileges(redfish::privileges::getLogServiceCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002014 .methods(boost::beast::http::verb::get)(
Claire Weinandd72e872022-08-15 14:20:06 -07002015 std::bind_front(handleBMCLogServicesCollectionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002016}
Ed Tanous1da66f72018-07-27 16:13:37 -07002017
Claire Weinanfdd26902022-03-01 14:18:25 -08002018inline void
2019 getDumpServiceInfo(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2020 const std::string& dumpType)
2021{
2022 std::string dumpPath;
Ed Tanous539d8c62024-06-19 14:38:27 -07002023 log_service::OverWritePolicy overWritePolicy =
2024 log_service::OverWritePolicy::Invalid;
Claire Weinanfdd26902022-03-01 14:18:25 -08002025 bool collectDiagnosticDataSupported = false;
2026
2027 if (dumpType == "BMC")
2028 {
Ed Tanous253f11b2024-05-16 09:38:31 -07002029 dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/Dump",
2030 BMCWEB_REDFISH_MANAGER_URI_NAME);
Ed Tanous539d8c62024-06-19 14:38:27 -07002031 overWritePolicy = log_service::OverWritePolicy::WrapsWhenFull;
Claire Weinanfdd26902022-03-01 14:18:25 -08002032 collectDiagnosticDataSupported = true;
2033 }
2034 else if (dumpType == "FaultLog")
2035 {
Ed Tanous253f11b2024-05-16 09:38:31 -07002036 dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/FaultLog",
2037 BMCWEB_REDFISH_MANAGER_URI_NAME);
Ed Tanous539d8c62024-06-19 14:38:27 -07002038 overWritePolicy = log_service::OverWritePolicy::Unknown;
Claire Weinanfdd26902022-03-01 14:18:25 -08002039 collectDiagnosticDataSupported = false;
2040 }
2041 else if (dumpType == "System")
2042 {
Ed Tanous253f11b2024-05-16 09:38:31 -07002043 dumpPath = std::format("/redfish/v1/Systems/{}/LogServices/Dump",
2044 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanous539d8c62024-06-19 14:38:27 -07002045 overWritePolicy = log_service::OverWritePolicy::WrapsWhenFull;
Claire Weinanfdd26902022-03-01 14:18:25 -08002046 collectDiagnosticDataSupported = true;
2047 }
2048 else
2049 {
Ed Tanous62598e32023-07-17 17:06:25 -07002050 BMCWEB_LOG_ERROR("getDumpServiceInfo() invalid dump type: {}",
2051 dumpType);
Claire Weinanfdd26902022-03-01 14:18:25 -08002052 messages::internalError(asyncResp->res);
2053 return;
2054 }
2055
2056 asyncResp->res.jsonValue["@odata.id"] = dumpPath;
2057 asyncResp->res.jsonValue["@odata.type"] = "#LogService.v1_2_0.LogService";
2058 asyncResp->res.jsonValue["Name"] = "Dump LogService";
2059 asyncResp->res.jsonValue["Description"] = dumpType + " Dump LogService";
2060 asyncResp->res.jsonValue["Id"] = std::filesystem::path(dumpPath).filename();
Ed Tanous539d8c62024-06-19 14:38:27 -07002061 asyncResp->res.jsonValue["OverWritePolicy"] = overWritePolicy;
Claire Weinanfdd26902022-03-01 14:18:25 -08002062
2063 std::pair<std::string, std::string> redfishDateTimeOffset =
Ed Tanous2b829372022-08-03 14:22:34 -07002064 redfish::time_utils::getDateTimeOffsetNow();
Claire Weinanfdd26902022-03-01 14:18:25 -08002065 asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
2066 asyncResp->res.jsonValue["DateTimeLocalOffset"] =
2067 redfishDateTimeOffset.second;
2068
2069 asyncResp->res.jsonValue["Entries"]["@odata.id"] = dumpPath + "/Entries";
Claire Weinanfdd26902022-03-01 14:18:25 -08002070
2071 if (collectDiagnosticDataSupported)
2072 {
2073 asyncResp->res.jsonValue["Actions"]["#LogService.CollectDiagnosticData"]
2074 ["target"] =
2075 dumpPath + "/Actions/LogService.CollectDiagnosticData";
2076 }
Claire Weinan0d946212022-07-13 19:40:19 -07002077
2078 constexpr std::array<std::string_view, 1> interfaces = {deleteAllInterface};
2079 dbus::utility::getSubTreePaths(
2080 "/xyz/openbmc_project/dump", 0, interfaces,
2081 [asyncResp, dumpType, dumpPath](
2082 const boost::system::error_code& ec,
2083 const dbus::utility::MapperGetSubTreePathsResponse& subTreePaths) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002084 if (ec)
Claire Weinan0d946212022-07-13 19:40:19 -07002085 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002086 BMCWEB_LOG_ERROR("getDumpServiceInfo respHandler got error {}",
2087 ec);
2088 // Assume that getting an error simply means there are no dump
2089 // LogServices. Return without adding any error response.
2090 return;
Claire Weinan0d946212022-07-13 19:40:19 -07002091 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002092 std::string dbusDumpPath = getDumpPath(dumpType);
2093 for (const std::string& path : subTreePaths)
2094 {
2095 if (path == dbusDumpPath)
2096 {
2097 asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"]
2098 ["target"] =
2099 dumpPath + "/Actions/LogService.ClearLog";
2100 break;
2101 }
2102 }
2103 });
Claire Weinanfdd26902022-03-01 14:18:25 -08002104}
2105
2106inline void handleLogServicesDumpServiceGet(
2107 crow::App& app, const std::string& dumpType, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07002108 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2109 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002110{
2111 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2112 {
2113 return;
2114 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002115
2116 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2117 {
2118 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2119 return;
2120 }
2121
Claire Weinanfdd26902022-03-01 14:18:25 -08002122 getDumpServiceInfo(asyncResp, dumpType);
2123}
2124
Ed Tanous22d268c2022-05-19 09:39:07 -07002125inline void handleLogServicesDumpServiceComputerSystemGet(
2126 crow::App& app, const crow::Request& req,
2127 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2128 const std::string& chassisId)
2129{
2130 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2131 {
2132 return;
2133 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002134 if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous22d268c2022-05-19 09:39:07 -07002135 {
2136 messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
2137 return;
2138 }
2139 getDumpServiceInfo(asyncResp, "System");
2140}
2141
Claire Weinanfdd26902022-03-01 14:18:25 -08002142inline void handleLogServicesDumpEntriesCollectionGet(
2143 crow::App& app, const std::string& dumpType, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07002144 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2145 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002146{
2147 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2148 {
2149 return;
2150 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002151
2152 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2153 {
2154 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2155 return;
2156 }
Claire Weinanfdd26902022-03-01 14:18:25 -08002157 getDumpEntryCollection(asyncResp, dumpType);
2158}
2159
Ed Tanous22d268c2022-05-19 09:39:07 -07002160inline void handleLogServicesDumpEntriesCollectionComputerSystemGet(
2161 crow::App& app, const crow::Request& req,
2162 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2163 const std::string& chassisId)
2164{
2165 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2166 {
2167 return;
2168 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002169 if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous22d268c2022-05-19 09:39:07 -07002170 {
2171 messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
2172 return;
2173 }
2174 getDumpEntryCollection(asyncResp, "System");
2175}
2176
Claire Weinanfdd26902022-03-01 14:18:25 -08002177inline void handleLogServicesDumpEntryGet(
2178 crow::App& app, const std::string& dumpType, const crow::Request& req,
2179 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous253f11b2024-05-16 09:38:31 -07002180 const std::string& managerId, const std::string& dumpId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002181{
2182 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2183 {
2184 return;
2185 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002186 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2187 {
2188 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2189 return;
2190 }
Claire Weinanfdd26902022-03-01 14:18:25 -08002191 getDumpEntryById(asyncResp, dumpId, dumpType);
2192}
Carson Labrado168d1b12023-03-27 17:04:46 +00002193
Ed Tanous22d268c2022-05-19 09:39:07 -07002194inline void handleLogServicesDumpEntryComputerSystemGet(
2195 crow::App& app, const crow::Request& req,
2196 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2197 const std::string& chassisId, const std::string& dumpId)
2198{
2199 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2200 {
2201 return;
2202 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002203 if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous22d268c2022-05-19 09:39:07 -07002204 {
2205 messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
2206 return;
2207 }
2208 getDumpEntryById(asyncResp, dumpId, "System");
2209}
Claire Weinanfdd26902022-03-01 14:18:25 -08002210
2211inline void handleLogServicesDumpEntryDelete(
2212 crow::App& app, const std::string& dumpType, const crow::Request& req,
2213 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous253f11b2024-05-16 09:38:31 -07002214 const std::string& managerId, const std::string& dumpId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002215{
2216 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2217 {
2218 return;
2219 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002220
2221 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2222 {
2223 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2224 return;
2225 }
Claire Weinanfdd26902022-03-01 14:18:25 -08002226 deleteDumpEntry(asyncResp, dumpId, dumpType);
2227}
2228
Ed Tanous22d268c2022-05-19 09:39:07 -07002229inline void handleLogServicesDumpEntryComputerSystemDelete(
2230 crow::App& app, const crow::Request& req,
2231 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2232 const std::string& chassisId, const std::string& dumpId)
2233{
2234 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2235 {
2236 return;
2237 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002238 if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous22d268c2022-05-19 09:39:07 -07002239 {
2240 messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
2241 return;
2242 }
2243 deleteDumpEntry(asyncResp, dumpId, "System");
2244}
2245
Carson Labrado168d1b12023-03-27 17:04:46 +00002246inline void handleLogServicesDumpEntryDownloadGet(
2247 crow::App& app, const std::string& dumpType, const crow::Request& req,
2248 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous253f11b2024-05-16 09:38:31 -07002249 const std::string& managerId, const std::string& dumpId)
Carson Labrado168d1b12023-03-27 17:04:46 +00002250{
2251 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2252 {
2253 return;
2254 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002255
2256 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2257 {
2258 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2259 return;
2260 }
Carson Labrado168d1b12023-03-27 17:04:46 +00002261 downloadDumpEntry(asyncResp, dumpId, dumpType);
2262}
2263
2264inline void handleDBusEventLogEntryDownloadGet(
2265 crow::App& app, const std::string& dumpType, const crow::Request& req,
2266 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2267 const std::string& systemName, const std::string& entryID)
2268{
2269 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2270 {
2271 return;
2272 }
2273 if (!http_helpers::isContentTypeAllowed(
2274 req.getHeaderValue("Accept"),
2275 http_helpers::ContentType::OctetStream, true))
2276 {
2277 asyncResp->res.result(boost::beast::http::status::bad_request);
2278 return;
2279 }
2280 downloadEventLogEntry(asyncResp, systemName, entryID, dumpType);
2281}
2282
Claire Weinanfdd26902022-03-01 14:18:25 -08002283inline void handleLogServicesDumpCollectDiagnosticDataPost(
2284 crow::App& app, const std::string& dumpType, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07002285 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2286 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002287{
2288 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2289 {
2290 return;
2291 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002292 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2293 {
2294 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2295 return;
2296 }
2297
Claire Weinanfdd26902022-03-01 14:18:25 -08002298 createDump(asyncResp, req, dumpType);
2299}
2300
Ed Tanous22d268c2022-05-19 09:39:07 -07002301inline void handleLogServicesDumpCollectDiagnosticDataComputerSystemPost(
2302 crow::App& app, const crow::Request& req,
2303 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002304 const std::string& systemName)
Ed Tanous22d268c2022-05-19 09:39:07 -07002305{
2306 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2307 {
2308 return;
2309 }
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002310
Ed Tanous25b54db2024-04-17 15:40:31 -07002311 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous22d268c2022-05-19 09:39:07 -07002312 {
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002313 // Option currently returns no systems. TBD
2314 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2315 systemName);
2316 return;
2317 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002318 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002319 {
2320 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2321 systemName);
Ed Tanous22d268c2022-05-19 09:39:07 -07002322 return;
2323 }
2324 createDump(asyncResp, req, "System");
2325}
2326
Claire Weinanfdd26902022-03-01 14:18:25 -08002327inline void handleLogServicesDumpClearLogPost(
2328 crow::App& app, const std::string& dumpType, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07002329 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2330 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002331{
2332 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2333 {
2334 return;
2335 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002336
2337 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2338 {
2339 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2340 return;
2341 }
Claire Weinanfdd26902022-03-01 14:18:25 -08002342 clearDump(asyncResp, dumpType);
2343}
2344
Ed Tanous22d268c2022-05-19 09:39:07 -07002345inline void handleLogServicesDumpClearLogComputerSystemPost(
2346 crow::App& app, const crow::Request& req,
2347 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002348 const std::string& systemName)
Ed Tanous22d268c2022-05-19 09:39:07 -07002349{
2350 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2351 {
2352 return;
2353 }
Ed Tanous25b54db2024-04-17 15:40:31 -07002354 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous22d268c2022-05-19 09:39:07 -07002355 {
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002356 // Option currently returns no systems. TBD
2357 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2358 systemName);
2359 return;
2360 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002361 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002362 {
2363 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2364 systemName);
Ed Tanous22d268c2022-05-19 09:39:07 -07002365 return;
2366 }
2367 clearDump(asyncResp, "System");
2368}
2369
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002370inline void requestRoutesBMCDumpService(App& app)
2371{
Ed Tanous253f11b2024-05-16 09:38:31 -07002372 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/Dump/")
Ed Tanoused398212021-06-09 17:05:54 -07002373 .privileges(redfish::privileges::getLogService)
Claire Weinanfdd26902022-03-01 14:18:25 -08002374 .methods(boost::beast::http::verb::get)(std::bind_front(
2375 handleLogServicesDumpServiceGet, std::ref(app), "BMC"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002376}
2377
2378inline void requestRoutesBMCDumpEntryCollection(App& app)
2379{
Ed Tanous253f11b2024-05-16 09:38:31 -07002380 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/")
Ed Tanoused398212021-06-09 17:05:54 -07002381 .privileges(redfish::privileges::getLogEntryCollection)
Claire Weinanfdd26902022-03-01 14:18:25 -08002382 .methods(boost::beast::http::verb::get)(std::bind_front(
2383 handleLogServicesDumpEntriesCollectionGet, std::ref(app), "BMC"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002384}
2385
2386inline void requestRoutesBMCDumpEntry(App& app)
2387{
2388 BMCWEB_ROUTE(app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002389 "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002390 .privileges(redfish::privileges::getLogEntry)
Claire Weinanfdd26902022-03-01 14:18:25 -08002391 .methods(boost::beast::http::verb::get)(std::bind_front(
2392 handleLogServicesDumpEntryGet, std::ref(app), "BMC"));
2393
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002394 BMCWEB_ROUTE(app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002395 "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002396 .privileges(redfish::privileges::deleteLogEntry)
Claire Weinanfdd26902022-03-01 14:18:25 -08002397 .methods(boost::beast::http::verb::delete_)(std::bind_front(
2398 handleLogServicesDumpEntryDelete, std::ref(app), "BMC"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002399}
2400
Carson Labrado168d1b12023-03-27 17:04:46 +00002401inline void requestRoutesBMCDumpEntryDownload(App& app)
2402{
2403 BMCWEB_ROUTE(
2404 app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002405 "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/attachment/")
Carson Labrado168d1b12023-03-27 17:04:46 +00002406 .privileges(redfish::privileges::getLogEntry)
2407 .methods(boost::beast::http::verb::get)(std::bind_front(
2408 handleLogServicesDumpEntryDownloadGet, std::ref(app), "BMC"));
2409}
2410
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002411inline void requestRoutesBMCDumpCreate(App& app)
2412{
George Liu0fda0f12021-11-16 10:06:17 +08002413 BMCWEB_ROUTE(
2414 app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002415 "/redfish/v1/Managers/<str>/LogServices/Dump/Actions/LogService.CollectDiagnosticData/")
Ed Tanoused398212021-06-09 17:05:54 -07002416 .privileges(redfish::privileges::postLogService)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002417 .methods(boost::beast::http::verb::post)(
Claire Weinanfdd26902022-03-01 14:18:25 -08002418 std::bind_front(handleLogServicesDumpCollectDiagnosticDataPost,
2419 std::ref(app), "BMC"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002420}
2421
2422inline void requestRoutesBMCDumpClear(App& app)
2423{
George Liu0fda0f12021-11-16 10:06:17 +08002424 BMCWEB_ROUTE(
2425 app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002426 "/redfish/v1/Managers/<str>/LogServices/Dump/Actions/LogService.ClearLog/")
Ed Tanoused398212021-06-09 17:05:54 -07002427 .privileges(redfish::privileges::postLogService)
Claire Weinanfdd26902022-03-01 14:18:25 -08002428 .methods(boost::beast::http::verb::post)(std::bind_front(
2429 handleLogServicesDumpClearLogPost, std::ref(app), "BMC"));
2430}
2431
Carson Labrado168d1b12023-03-27 17:04:46 +00002432inline void requestRoutesDBusEventLogEntryDownload(App& app)
2433{
2434 BMCWEB_ROUTE(
2435 app,
Ravi Teja9e9d99d2023-11-08 05:33:59 -06002436 "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/attachment/")
Carson Labrado168d1b12023-03-27 17:04:46 +00002437 .privileges(redfish::privileges::getLogEntry)
2438 .methods(boost::beast::http::verb::get)(std::bind_front(
2439 handleDBusEventLogEntryDownloadGet, std::ref(app), "System"));
2440}
2441
Claire Weinanfdd26902022-03-01 14:18:25 -08002442inline void requestRoutesFaultLogDumpService(App& app)
2443{
Ed Tanous253f11b2024-05-16 09:38:31 -07002444 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/")
Claire Weinanfdd26902022-03-01 14:18:25 -08002445 .privileges(redfish::privileges::getLogService)
2446 .methods(boost::beast::http::verb::get)(std::bind_front(
2447 handleLogServicesDumpServiceGet, std::ref(app), "FaultLog"));
2448}
2449
2450inline void requestRoutesFaultLogDumpEntryCollection(App& app)
2451{
Ed Tanous253f11b2024-05-16 09:38:31 -07002452 BMCWEB_ROUTE(app,
2453 "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/")
Claire Weinanfdd26902022-03-01 14:18:25 -08002454 .privileges(redfish::privileges::getLogEntryCollection)
2455 .methods(boost::beast::http::verb::get)(
2456 std::bind_front(handleLogServicesDumpEntriesCollectionGet,
2457 std::ref(app), "FaultLog"));
2458}
2459
2460inline void requestRoutesFaultLogDumpEntry(App& app)
2461{
Ed Tanous253f11b2024-05-16 09:38:31 -07002462 BMCWEB_ROUTE(
2463 app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/<str>/")
Claire Weinanfdd26902022-03-01 14:18:25 -08002464 .privileges(redfish::privileges::getLogEntry)
2465 .methods(boost::beast::http::verb::get)(std::bind_front(
2466 handleLogServicesDumpEntryGet, std::ref(app), "FaultLog"));
2467
Ed Tanous253f11b2024-05-16 09:38:31 -07002468 BMCWEB_ROUTE(
2469 app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/<str>/")
Claire Weinanfdd26902022-03-01 14:18:25 -08002470 .privileges(redfish::privileges::deleteLogEntry)
2471 .methods(boost::beast::http::verb::delete_)(std::bind_front(
2472 handleLogServicesDumpEntryDelete, std::ref(app), "FaultLog"));
2473}
2474
2475inline void requestRoutesFaultLogDumpClear(App& app)
2476{
2477 BMCWEB_ROUTE(
2478 app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002479 "/redfish/v1/Managers/<str>/LogServices/FaultLog/Actions/LogService.ClearLog/")
Claire Weinanfdd26902022-03-01 14:18:25 -08002480 .privileges(redfish::privileges::postLogService)
2481 .methods(boost::beast::http::verb::post)(std::bind_front(
2482 handleLogServicesDumpClearLogPost, std::ref(app), "FaultLog"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002483}
2484
2485inline void requestRoutesSystemDumpService(App& app)
2486{
Ed Tanous22d268c2022-05-19 09:39:07 -07002487 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Dump/")
Ed Tanoused398212021-06-09 17:05:54 -07002488 .privileges(redfish::privileges::getLogService)
Claire Weinan6ab9ad52022-08-12 18:20:17 -07002489 .methods(boost::beast::http::verb::get)(std::bind_front(
Ed Tanous22d268c2022-05-19 09:39:07 -07002490 handleLogServicesDumpServiceComputerSystemGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002491}
2492
2493inline void requestRoutesSystemDumpEntryCollection(App& app)
2494{
Ed Tanous22d268c2022-05-19 09:39:07 -07002495 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/")
Ed Tanoused398212021-06-09 17:05:54 -07002496 .privileges(redfish::privileges::getLogEntryCollection)
Ed Tanous22d268c2022-05-19 09:39:07 -07002497 .methods(boost::beast::http::verb::get)(std::bind_front(
2498 handleLogServicesDumpEntriesCollectionComputerSystemGet,
2499 std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002500}
2501
2502inline void requestRoutesSystemDumpEntry(App& app)
2503{
2504 BMCWEB_ROUTE(app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002505 "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002506 .privileges(redfish::privileges::getLogEntry)
Claire Weinan6ab9ad52022-08-12 18:20:17 -07002507 .methods(boost::beast::http::verb::get)(std::bind_front(
Ed Tanous22d268c2022-05-19 09:39:07 -07002508 handleLogServicesDumpEntryComputerSystemGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002509
2510 BMCWEB_ROUTE(app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002511 "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002512 .privileges(redfish::privileges::deleteLogEntry)
Claire Weinan6ab9ad52022-08-12 18:20:17 -07002513 .methods(boost::beast::http::verb::delete_)(std::bind_front(
Ed Tanous22d268c2022-05-19 09:39:07 -07002514 handleLogServicesDumpEntryComputerSystemDelete, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002515}
2516
2517inline void requestRoutesSystemDumpCreate(App& app)
2518{
George Liu0fda0f12021-11-16 10:06:17 +08002519 BMCWEB_ROUTE(
2520 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002521 "/redfish/v1/Systems/<str>/LogServices/Dump/Actions/LogService.CollectDiagnosticData/")
Ed Tanoused398212021-06-09 17:05:54 -07002522 .privileges(redfish::privileges::postLogService)
Ed Tanous22d268c2022-05-19 09:39:07 -07002523 .methods(boost::beast::http::verb::post)(std::bind_front(
2524 handleLogServicesDumpCollectDiagnosticDataComputerSystemPost,
2525 std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002526}
2527
2528inline void requestRoutesSystemDumpClear(App& app)
2529{
George Liu0fda0f12021-11-16 10:06:17 +08002530 BMCWEB_ROUTE(
2531 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002532 "/redfish/v1/Systems/<str>/LogServices/Dump/Actions/LogService.ClearLog/")
Ed Tanoused398212021-06-09 17:05:54 -07002533 .privileges(redfish::privileges::postLogService)
Claire Weinan6ab9ad52022-08-12 18:20:17 -07002534 .methods(boost::beast::http::verb::post)(std::bind_front(
Ed Tanous22d268c2022-05-19 09:39:07 -07002535 handleLogServicesDumpClearLogComputerSystemPost, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002536}
2537
2538inline void requestRoutesCrashdumpService(App& app)
2539{
2540 // Note: Deviated from redfish privilege registry for GET & HEAD
2541 // method for security reasons.
2542 /**
2543 * Functions triggers appropriate requests on DBus
2544 */
Ed Tanous22d268c2022-05-19 09:39:07 -07002545 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Crashdump/")
Ed Tanoused398212021-06-09 17:05:54 -07002546 // This is incorrect, should be:
2547 //.privileges(redfish::privileges::getLogService)
Ed Tanous432a8902021-06-14 15:28:56 -07002548 .privileges({{"ConfigureManager"}})
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002549 .methods(
2550 boost::beast::http::verb::
2551 get)([&app](const crow::Request& req,
2552 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2553 const std::string& systemName) {
2554 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2555 {
2556 return;
2557 }
2558 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
2559 {
2560 // Option currently returns no systems. TBD
2561 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2562 systemName);
2563 return;
2564 }
2565 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2566 {
2567 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2568 systemName);
2569 return;
2570 }
Ed Tanous22d268c2022-05-19 09:39:07 -07002571
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002572 // Copy over the static data to include the entries added by
2573 // SubRoute
2574 asyncResp->res.jsonValue["@odata.id"] =
2575 std::format("/redfish/v1/Systems/{}/LogServices/Crashdump",
2576 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2577 asyncResp->res.jsonValue["@odata.type"] =
2578 "#LogService.v1_2_0.LogService";
2579 asyncResp->res.jsonValue["Name"] = "Open BMC Oem Crashdump Service";
2580 asyncResp->res.jsonValue["Description"] = "Oem Crashdump Service";
2581 asyncResp->res.jsonValue["Id"] = "Crashdump";
2582 asyncResp->res.jsonValue["OverWritePolicy"] =
2583 log_service::OverWritePolicy::WrapsWhenFull;
2584 asyncResp->res.jsonValue["MaxNumberOfRecords"] = 3;
Tejas Patil7c8c4052021-06-04 17:43:14 +05302585
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002586 std::pair<std::string, std::string> redfishDateTimeOffset =
2587 redfish::time_utils::getDateTimeOffsetNow();
2588 asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
2589 asyncResp->res.jsonValue["DateTimeLocalOffset"] =
2590 redfishDateTimeOffset.second;
Tejas Patil7c8c4052021-06-04 17:43:14 +05302591
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002592 asyncResp->res.jsonValue["Entries"]["@odata.id"] = std::format(
2593 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries",
2594 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2595 asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"]
2596 ["target"] = std::format(
2597 "/redfish/v1/Systems/{}/LogServices/Crashdump/Actions/LogService.ClearLog",
2598 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2599 asyncResp->res
2600 .jsonValue["Actions"]["#LogService.CollectDiagnosticData"]
2601 ["target"] = std::format(
2602 "/redfish/v1/Systems/{}/LogServices/Crashdump/Actions/LogService.CollectDiagnosticData",
2603 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2604 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002605}
2606
2607void inline requestRoutesCrashdumpClear(App& app)
2608{
George Liu0fda0f12021-11-16 10:06:17 +08002609 BMCWEB_ROUTE(
2610 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002611 "/redfish/v1/Systems/<str>/LogServices/Crashdump/Actions/LogService.ClearLog/")
Ed Tanoused398212021-06-09 17:05:54 -07002612 // This is incorrect, should be:
2613 //.privileges(redfish::privileges::postLogService)
Ed Tanous432a8902021-06-14 15:28:56 -07002614 .privileges({{"ConfigureComponents"}})
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002615 .methods(boost::beast::http::verb::post)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07002616 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07002617 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2618 const std::string& systemName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002619 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2620 {
2621 return;
2622 }
2623 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
2624 {
2625 // Option currently returns no systems. TBD
2626 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2627 systemName);
2628 return;
2629 }
2630 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2631 {
2632 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2633 systemName);
2634 return;
2635 }
2636 crow::connections::systemBus->async_method_call(
2637 [asyncResp](const boost::system::error_code& ec,
2638 const std::string&) {
2639 if (ec)
2640 {
2641 messages::internalError(asyncResp->res);
2642 return;
2643 }
2644 messages::success(asyncResp->res);
2645 },
2646 crashdumpObject, crashdumpPath, deleteAllInterface,
2647 "DeleteAll");
2648 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002649}
Jason M. Bills5b61b5e2019-10-16 10:59:02 -07002650
Ed Tanous4ff0f1f2024-09-04 17:27:37 -07002651inline void
zhanghch058d1b46d2021-04-01 11:18:24 +08002652 logCrashdumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2653 const std::string& logID, nlohmann::json& logEntryJson)
Jason M. Billse855dd22019-10-08 11:37:48 -07002654{
Johnathan Mantey043a0532020-03-10 17:15:28 -07002655 auto getStoredLogCallback =
Ed Tanousb9d36b42022-02-26 21:42:46 -08002656 [asyncResp, logID,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002657 &logEntryJson](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002658 const dbus::utility::DBusPropertiesMap& params) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002659 if (ec)
2660 {
2661 BMCWEB_LOG_DEBUG("failed to get log ec: {}", ec.message());
2662 if (ec.value() ==
2663 boost::system::linux_error::bad_request_descriptor)
2664 {
2665 messages::resourceNotFound(asyncResp->res, "LogEntry",
2666 logID);
2667 }
2668 else
2669 {
2670 messages::internalError(asyncResp->res);
2671 }
2672 return;
2673 }
2674
2675 std::string timestamp{};
2676 std::string filename{};
2677 std::string logfile{};
2678 parseCrashdumpParameters(params, filename, timestamp, logfile);
2679
2680 if (filename.empty() || timestamp.empty())
Jason M. Bills1ddcf012019-11-26 14:59:21 -08002681 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002682 messages::resourceNotFound(asyncResp->res, "LogEntry", logID);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002683 return;
2684 }
2685
2686 std::string crashdumpURI =
2687 std::format(
2688 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries/",
2689 BMCWEB_REDFISH_SYSTEM_URI_NAME) +
2690 logID + "/" + filename;
2691 nlohmann::json::object_t logEntry;
2692 logEntry["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
2693 logEntry["@odata.id"] = boost::urls::format(
2694 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries/{}",
2695 BMCWEB_REDFISH_SYSTEM_URI_NAME, logID);
2696 logEntry["Name"] = "CPU Crashdump";
2697 logEntry["Id"] = logID;
2698 logEntry["EntryType"] = log_entry::LogEntryType::Oem;
2699 logEntry["AdditionalDataURI"] = std::move(crashdumpURI);
2700 logEntry["DiagnosticDataType"] = "OEM";
2701 logEntry["OEMDiagnosticDataType"] = "PECICrashdump";
2702 logEntry["Created"] = std::move(timestamp);
2703
2704 // If logEntryJson references an array of LogEntry resources
2705 // ('Members' list), then push this as a new entry, otherwise set it
2706 // directly
2707 if (logEntryJson.is_array())
2708 {
2709 logEntryJson.push_back(logEntry);
2710 asyncResp->res.jsonValue["Members@odata.count"] =
2711 logEntryJson.size();
Jason M. Bills2b20ef62022-01-06 15:48:07 -08002712 }
2713 else
2714 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002715 logEntryJson.update(logEntry);
Jason M. Bills2b20ef62022-01-06 15:48:07 -08002716 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002717 };
Ed Tanousdeae6a72024-11-11 21:58:57 -08002718 dbus::utility::getAllProperties(
2719 crashdumpObject, crashdumpPath + std::string("/") + logID,
2720 crashdumpInterface, std::move(getStoredLogCallback));
Jason M. Billse855dd22019-10-08 11:37:48 -07002721}
2722
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002723inline void requestRoutesCrashdumpEntryCollection(App& app)
Ed Tanous1da66f72018-07-27 16:13:37 -07002724{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002725 // Note: Deviated from redfish privilege registry for GET & HEAD
2726 // method for security reasons.
Ed Tanous1da66f72018-07-27 16:13:37 -07002727 /**
2728 * Functions triggers appropriate requests on DBus
2729 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002730 BMCWEB_ROUTE(app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002731 "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/")
Ed Tanoused398212021-06-09 17:05:54 -07002732 // This is incorrect, should be.
2733 //.privileges(redfish::privileges::postLogEntryCollection)
Ed Tanous432a8902021-06-14 15:28:56 -07002734 .privileges({{"ConfigureComponents"}})
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002735 .methods(
2736 boost::beast::http::verb::
2737 get)([&app](const crow::Request& req,
2738 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2739 const std::string& systemName) {
2740 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous45ca1b82022-03-25 13:07:27 -07002741 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002742 return;
Ed Tanous45ca1b82022-03-25 13:07:27 -07002743 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002744 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous002d39b2022-05-31 08:59:27 -07002745 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002746 // Option currently returns no systems. TBD
2747 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2748 systemName);
2749 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07002750 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002751 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2752 {
2753 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2754 systemName);
2755 return;
2756 }
2757
2758 constexpr std::array<std::string_view, 1> interfaces = {
2759 crashdumpInterface};
2760 dbus::utility::getSubTreePaths(
2761 "/", 0, interfaces,
2762 [asyncResp](const boost::system::error_code& ec,
2763 const std::vector<std::string>& resp) {
2764 if (ec)
2765 {
2766 if (ec.value() !=
2767 boost::system::errc::no_such_file_or_directory)
2768 {
2769 BMCWEB_LOG_DEBUG("failed to get entries ec: {}",
2770 ec.message());
2771 messages::internalError(asyncResp->res);
2772 return;
2773 }
2774 }
2775 asyncResp->res.jsonValue["@odata.type"] =
2776 "#LogEntryCollection.LogEntryCollection";
2777 asyncResp->res.jsonValue["@odata.id"] = std::format(
2778 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries",
2779 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2780 asyncResp->res.jsonValue["Name"] =
2781 "Open BMC Crashdump Entries";
2782 asyncResp->res.jsonValue["Description"] =
2783 "Collection of Crashdump Entries";
2784 asyncResp->res.jsonValue["Members"] =
2785 nlohmann::json::array();
2786 asyncResp->res.jsonValue["Members@odata.count"] = 0;
2787
2788 for (const std::string& path : resp)
2789 {
2790 const sdbusplus::message::object_path objPath(path);
2791 // Get the log ID
2792 std::string logID = objPath.filename();
2793 if (logID.empty())
2794 {
2795 continue;
2796 }
2797 // Add the log entry to the array
2798 logCrashdumpEntry(asyncResp, logID,
2799 asyncResp->res.jsonValue["Members"]);
2800 }
2801 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002802 });
2803}
Ed Tanous1da66f72018-07-27 16:13:37 -07002804
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002805inline void requestRoutesCrashdumpEntry(App& app)
Ed Tanous1da66f72018-07-27 16:13:37 -07002806{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002807 // Note: Deviated from redfish privilege registry for GET & HEAD
2808 // method for security reasons.
Ed Tanous1da66f72018-07-27 16:13:37 -07002809
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002810 BMCWEB_ROUTE(
Ed Tanous22d268c2022-05-19 09:39:07 -07002811 app, "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002812 // this is incorrect, should be
2813 // .privileges(redfish::privileges::getLogEntry)
Ed Tanous432a8902021-06-14 15:28:56 -07002814 .privileges({{"ConfigureComponents"}})
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002815 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07002816 [&app](const crow::Request& req,
2817 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -07002818 const std::string& systemName, const std::string& param) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002819 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2820 {
2821 return;
2822 }
2823 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
2824 {
2825 // Option currently returns no systems. TBD
2826 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2827 systemName);
2828 return;
2829 }
2830 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2831 {
2832 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2833 systemName);
2834 return;
2835 }
2836 const std::string& logID = param;
2837 logCrashdumpEntry(asyncResp, logID, asyncResp->res.jsonValue);
2838 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002839}
Ed Tanous1da66f72018-07-27 16:13:37 -07002840
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002841inline void requestRoutesCrashdumpFile(App& app)
2842{
2843 // Note: Deviated from redfish privilege registry for GET & HEAD
2844 // method for security reasons.
2845 BMCWEB_ROUTE(
2846 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002847 "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/<str>/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002848 .privileges(redfish::privileges::getLogEntry)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002849 .methods(boost::beast::http::verb::get)(
Nan Zhoua4ce1142022-08-02 18:45:25 +00002850 [](const crow::Request& req,
2851 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -07002852 const std::string& systemName, const std::string& logID,
2853 const std::string& fileName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002854 // Do not call getRedfishRoute here since the crashdump file is
2855 // not a Redfish resource.
Ed Tanous22d268c2022-05-19 09:39:07 -07002856
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002857 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
2858 {
2859 // Option currently returns no systems. TBD
2860 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2861 systemName);
2862 return;
2863 }
2864 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2865 {
2866 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2867 systemName);
2868 return;
2869 }
Ed Tanous22d268c2022-05-19 09:39:07 -07002870
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002871 auto getStoredLogCallback =
2872 [asyncResp, logID, fileName,
2873 url(boost::urls::url(req.url()))](
2874 const boost::system::error_code& ec,
2875 const std::vector<std::pair<
2876 std::string, dbus::utility::DbusVariantType>>&
2877 resp) {
2878 if (ec)
2879 {
2880 BMCWEB_LOG_DEBUG("failed to get log ec: {}",
2881 ec.message());
2882 messages::internalError(asyncResp->res);
2883 return;
2884 }
Jason M. Bills8e6c0992021-03-11 16:26:53 -08002885
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002886 std::string dbusFilename{};
2887 std::string dbusTimestamp{};
2888 std::string dbusFilepath{};
Jason M. Bills8e6c0992021-03-11 16:26:53 -08002889
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002890 parseCrashdumpParameters(resp, dbusFilename,
2891 dbusTimestamp, dbusFilepath);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002892
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002893 if (dbusFilename.empty() || dbusTimestamp.empty() ||
2894 dbusFilepath.empty())
2895 {
2896 messages::resourceNotFound(asyncResp->res,
2897 "LogEntry", logID);
2898 return;
2899 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002900
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002901 // Verify the file name parameter is correct
2902 if (fileName != dbusFilename)
2903 {
2904 messages::resourceNotFound(asyncResp->res,
2905 "LogEntry", logID);
2906 return;
2907 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002908
Myung Baed51c61b2024-09-13 10:35:34 -05002909 if (asyncResp->res.openFile(dbusFilepath) !=
2910 crow::OpenCode::Success)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002911 {
2912 messages::resourceNotFound(asyncResp->res,
2913 "LogEntry", logID);
2914 return;
2915 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002916
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002917 // Configure this to be a file download when accessed
2918 // from a browser
2919 asyncResp->res.addHeader(
2920 boost::beast::http::field::content_disposition,
2921 "attachment");
2922 };
Ed Tanousdeae6a72024-11-11 21:58:57 -08002923 dbus::utility::getAllProperties(
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002924 *crow::connections::systemBus, crashdumpObject,
2925 crashdumpPath + std::string("/") + logID,
2926 crashdumpInterface, std::move(getStoredLogCallback));
2927 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002928}
2929
Jason M. Billsc5a4c822022-01-06 15:51:23 -08002930enum class OEMDiagnosticType
2931{
2932 onDemand,
2933 telemetry,
2934 invalid,
2935};
2936
Ed Tanous26ccae32023-02-16 10:28:44 -08002937inline OEMDiagnosticType getOEMDiagnosticType(std::string_view oemDiagStr)
Jason M. Billsc5a4c822022-01-06 15:51:23 -08002938{
2939 if (oemDiagStr == "OnDemand")
2940 {
2941 return OEMDiagnosticType::onDemand;
2942 }
2943 if (oemDiagStr == "Telemetry")
2944 {
2945 return OEMDiagnosticType::telemetry;
2946 }
2947
2948 return OEMDiagnosticType::invalid;
2949}
2950
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002951inline void requestRoutesCrashdumpCollect(App& app)
2952{
2953 // Note: Deviated from redfish privilege registry for GET & HEAD
2954 // method for security reasons.
George Liu0fda0f12021-11-16 10:06:17 +08002955 BMCWEB_ROUTE(
2956 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002957 "/redfish/v1/Systems/<str>/LogServices/Crashdump/Actions/LogService.CollectDiagnosticData/")
Ed Tanoused398212021-06-09 17:05:54 -07002958 // The below is incorrect; Should be ConfigureManager
2959 //.privileges(redfish::privileges::postLogService)
Ed Tanous432a8902021-06-14 15:28:56 -07002960 .privileges({{"ConfigureComponents"}})
Ed Tanous002d39b2022-05-31 08:59:27 -07002961 .methods(boost::beast::http::verb::post)(
2962 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07002963 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2964 const std::string& systemName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002965 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07002966 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002967 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07002968 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002969
2970 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous002d39b2022-05-31 08:59:27 -07002971 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002972 // Option currently returns no systems. TBD
2973 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2974 systemName);
2975 return;
2976 }
2977 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2978 {
2979 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2980 systemName);
2981 return;
2982 }
2983
2984 std::string diagnosticDataType;
2985 std::string oemDiagnosticDataType;
Myung Baeafc474a2024-10-09 00:53:29 -07002986 if (!redfish::json_util::readJsonAction( //
2987 req, asyncResp->res, //
2988 "DiagnosticDataType", diagnosticDataType, //
2989 "OEMDiagnosticDataType", oemDiagnosticDataType //
2990 ))
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002991 {
2992 return;
2993 }
2994
2995 if (diagnosticDataType != "OEM")
2996 {
2997 BMCWEB_LOG_ERROR(
2998 "Only OEM DiagnosticDataType supported for Crashdump");
2999 messages::actionParameterValueFormatError(
3000 asyncResp->res, diagnosticDataType,
3001 "DiagnosticDataType", "CollectDiagnosticData");
3002 return;
3003 }
3004
3005 OEMDiagnosticType oemDiagType =
3006 getOEMDiagnosticType(oemDiagnosticDataType);
3007
3008 std::string iface;
3009 std::string method;
3010 std::string taskMatchStr;
3011 if (oemDiagType == OEMDiagnosticType::onDemand)
3012 {
3013 iface = crashdumpOnDemandInterface;
3014 method = "GenerateOnDemandLog";
3015 taskMatchStr =
3016 "type='signal',"
3017 "interface='org.freedesktop.DBus.Properties',"
3018 "member='PropertiesChanged',"
3019 "arg0namespace='com.intel.crashdump'";
3020 }
3021 else if (oemDiagType == OEMDiagnosticType::telemetry)
3022 {
3023 iface = crashdumpTelemetryInterface;
3024 method = "GenerateTelemetryLog";
3025 taskMatchStr =
3026 "type='signal',"
3027 "interface='org.freedesktop.DBus.Properties',"
3028 "member='PropertiesChanged',"
3029 "arg0namespace='com.intel.crashdump'";
Ed Tanous002d39b2022-05-31 08:59:27 -07003030 }
3031 else
3032 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003033 BMCWEB_LOG_ERROR("Unsupported OEMDiagnosticDataType: {}",
3034 oemDiagnosticDataType);
3035 messages::actionParameterValueFormatError(
3036 asyncResp->res, oemDiagnosticDataType,
3037 "OEMDiagnosticDataType", "CollectDiagnosticData");
3038 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07003039 }
Ed Tanous1da66f72018-07-27 16:13:37 -07003040
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003041 auto collectCrashdumpCallback =
3042 [asyncResp, payload(task::Payload(req)),
3043 taskMatchStr](const boost::system::error_code& ec,
3044 const std::string&) mutable {
3045 if (ec)
3046 {
3047 if (ec.value() ==
3048 boost::system::errc::operation_not_supported)
3049 {
3050 messages::resourceInStandby(asyncResp->res);
3051 }
3052 else if (ec.value() == boost::system::errc::
3053 device_or_resource_busy)
3054 {
3055 messages::serviceTemporarilyUnavailable(
3056 asyncResp->res, "60");
3057 }
3058 else
3059 {
3060 messages::internalError(asyncResp->res);
3061 }
3062 return;
3063 }
3064 std::shared_ptr<task::TaskData> task =
3065 task::TaskData::createTask(
3066 [](const boost::system::error_code& ec2,
3067 sdbusplus::message_t&,
3068 const std::shared_ptr<task::TaskData>&
3069 taskData) {
3070 if (!ec2)
3071 {
3072 taskData->messages.emplace_back(
3073 messages::taskCompletedOK(
3074 std::to_string(
3075 taskData->index)));
3076 taskData->state = "Completed";
3077 }
3078 return task::completed;
3079 },
3080 taskMatchStr);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003081
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003082 task->startTimer(std::chrono::minutes(5));
3083 task->populateResp(asyncResp->res);
3084 task->payload.emplace(std::move(payload));
3085 };
3086
3087 crow::connections::systemBus->async_method_call(
3088 std::move(collectCrashdumpCallback), crashdumpObject,
3089 crashdumpPath, iface, method);
3090 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003091}
Kenny L. Ku6eda7682020-06-19 09:48:36 -07003092
Alexander Hansen599b9af2024-08-06 15:11:57 +02003093inline void dBusLogServiceActionsClear(
3094 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
3095{
3096 BMCWEB_LOG_DEBUG("Do delete all entries.");
3097
3098 // Process response from Logging service.
3099 auto respHandler = [asyncResp](const boost::system::error_code& ec) {
3100 BMCWEB_LOG_DEBUG("doClearLog resp_handler callback: Done");
3101 if (ec)
3102 {
3103 // TODO Handle for specific error code
3104 BMCWEB_LOG_ERROR("doClearLog resp_handler got error {}", ec);
3105 asyncResp->res.result(
3106 boost::beast::http::status::internal_server_error);
3107 return;
3108 }
3109
3110 asyncResp->res.result(boost::beast::http::status::no_content);
3111 };
3112
3113 // Make call to Logging service to request Clear Log
3114 crow::connections::systemBus->async_method_call(
3115 respHandler, "xyz.openbmc_project.Logging",
3116 "/xyz/openbmc_project/logging",
3117 "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
3118}
3119
Andrew Geisslercb92c032018-08-17 07:56:14 -07003120/**
3121 * DBusLogServiceActionsClear class supports POST method for ClearLog action.
3122 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003123inline void requestRoutesDBusLogServiceActionsClear(App& app)
Andrew Geisslercb92c032018-08-17 07:56:14 -07003124{
Andrew Geisslercb92c032018-08-17 07:56:14 -07003125 /**
3126 * Function handles POST method request.
3127 * The Clear Log actions does not require any parameter.The action deletes
3128 * all entries found in the Entries collection for this Log Service.
3129 */
Andrew Geisslercb92c032018-08-17 07:56:14 -07003130
George Liu0fda0f12021-11-16 10:06:17 +08003131 BMCWEB_ROUTE(
3132 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07003133 "/redfish/v1/Systems/<str>/LogServices/EventLog/Actions/LogService.ClearLog/")
Ed Tanoused398212021-06-09 17:05:54 -07003134 .privileges(redfish::privileges::postLogService)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003135 .methods(boost::beast::http::verb::post)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07003136 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07003137 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3138 const std::string& systemName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003139 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3140 {
3141 return;
3142 }
3143 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
3144 {
3145 // Option currently returns no systems. TBD
3146 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3147 systemName);
3148 return;
3149 }
3150 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
3151 {
3152 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3153 systemName);
3154 return;
3155 }
3156 dBusLogServiceActionsClear(asyncResp);
3157 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003158}
ZhikuiRena3316fc2020-01-29 14:58:08 -08003159
Ed Tanous1da66f72018-07-27 16:13:37 -07003160} // namespace redfish