blob: cde992b507421a811e9c597b7f15eaf954cd4476 [file] [log] [blame]
Ed Tanous40e9b922024-09-10 13:50:16 -07001// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright OpenBMC Authors
3// SPDX-FileCopyrightText: Copyright 2018 Intel Corporation
Ed Tanous1da66f72018-07-27 16:13:37 -07004#pragma once
5
Ed Tanousd7857202025-01-28 15:32:26 -08006#include "bmcweb_config.h"
7
Ed Tanous3ccb3ad2023-01-13 17:40:03 -08008#include "app.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -08009#include "async_resp.hpp"
10#include "dbus_singleton.hpp"
George Liu7a1dbc42022-12-07 16:03:22 +080011#include "dbus_utility.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080012#include "error_messages.hpp"
Asmitha Karunanithi68dd0752022-11-15 11:33:46 -060013#include "generated/enums/log_entry.hpp"
Ed Tanous539d8c62024-06-19 14:38:27 -070014#include "generated/enums/log_service.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080015#include "http_body.hpp"
16#include "http_request.hpp"
17#include "http_response.hpp"
George Liu647b3cd2021-07-05 12:43:56 +080018#include "http_utility.hpp"
Spencer Kub7028eb2021-10-26 15:27:35 +080019#include "human_sort.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080020#include "logging.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080021#include "query.hpp"
Jason M. Bills4851d452019-03-28 11:27:48 -070022#include "registries.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080023#include "registries/privilege_registry.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080024#include "str_utility.hpp"
James Feist46229572020-02-19 15:11:58 -080025#include "task.hpp"
Ed Tanous5b904292024-04-16 11:10:17 -070026#include "task_messages.hpp"
Alexander Hansen262dcc12024-09-19 12:04:03 +020027#include "utils/dbus_event_log_entry.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080028#include "utils/dbus_utils.hpp"
Ed Tanous5b904292024-04-16 11:10:17 -070029#include "utils/json_utils.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080030#include "utils/query_param.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080031#include "utils/time_utils.hpp"
Ed Tanous1da66f72018-07-27 16:13:37 -070032
Ed Tanousd7857202025-01-28 15:32:26 -080033#include <asm-generic/errno.h>
34#include <systemd/sd-bus.h>
Asmitha Karunanithi8e317782020-12-10 03:35:05 -060035#include <tinyxml2.h>
Adriana Kobylak400fd1f2021-01-29 09:01:30 -060036#include <unistd.h>
Jason M. Billse1f26342018-07-18 12:12:00 -070037
Ed Tanousd7857202025-01-28 15:32:26 -080038#include <boost/beast/http/field.hpp>
39#include <boost/beast/http/status.hpp>
Ed Tanous07c8c202022-07-11 10:08:08 -070040#include <boost/beast/http/verb.hpp>
Jason M. Bills1ddcf012019-11-26 14:59:21 -080041#include <boost/system/linux_error.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070042#include <boost/url/format.hpp>
Ed Tanousd7857202025-01-28 15:32:26 -080043#include <boost/url/url.hpp>
44#include <sdbusplus/message.hpp>
45#include <sdbusplus/message/native_types.hpp>
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +020046#include <sdbusplus/unpack_properties.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050047
Ed Tanousd7857202025-01-28 15:32:26 -080048#include <algorithm>
George Liu7a1dbc42022-12-07 16:03:22 +080049#include <array>
Ed Tanousd7857202025-01-28 15:32:26 -080050#include <chrono>
Abhilash Rajub5f288d2023-11-08 22:32:44 -060051#include <cstddef>
Ed Tanousd7857202025-01-28 15:32:26 -080052#include <cstdint>
53#include <cstdio>
54#include <ctime>
James Feist4418c7f2019-04-15 11:09:15 -070055#include <filesystem>
Ed Tanousd7857202025-01-28 15:32:26 -080056#include <format>
57#include <fstream>
58#include <functional>
59#include <iomanip>
Ed Tanous18f8f602023-07-18 10:07:23 -070060#include <iterator>
Ed Tanousd7857202025-01-28 15:32:26 -080061#include <memory>
Xiaochao Ma75710de2021-01-21 17:56:02 +080062#include <optional>
Ed Tanous3544d2a2023-08-06 18:12:20 -070063#include <ranges>
Ed Tanous26702d02021-11-03 15:02:33 -070064#include <span>
Ed Tanousd7857202025-01-28 15:32:26 -080065#include <sstream>
Ed Tanous18f8f602023-07-18 10:07:23 -070066#include <string>
Jason M. Billscd225da2019-05-08 15:31:57 -070067#include <string_view>
Ed Tanousd7857202025-01-28 15:32:26 -080068#include <system_error>
69#include <utility>
Ed Tanousabf2add2019-01-22 16:40:12 -080070#include <variant>
Ed Tanousd7857202025-01-28 15:32:26 -080071#include <vector>
Ed Tanous1da66f72018-07-27 16:13:37 -070072
73namespace redfish
74{
75
Patrick Williams89492a12023-05-10 07:51:34 -050076constexpr const char* crashdumpObject = "com.intel.crashdump";
77constexpr const char* crashdumpPath = "/com/intel/crashdump";
78constexpr const char* crashdumpInterface = "com.intel.crashdump";
79constexpr const char* deleteAllInterface =
Jason M. Bills5b61b5e2019-10-16 10:59:02 -070080 "xyz.openbmc_project.Collection.DeleteAll";
Patrick Williams89492a12023-05-10 07:51:34 -050081constexpr const char* crashdumpOnDemandInterface =
Jason M. Bills424c4172019-03-21 13:50:33 -070082 "com.intel.crashdump.OnDemand";
Patrick Williams89492a12023-05-10 07:51:34 -050083constexpr const char* crashdumpTelemetryInterface =
Kenny L. Ku6eda7682020-06-19 09:48:36 -070084 "com.intel.crashdump.Telemetry";
Ed Tanous1da66f72018-07-27 16:13:37 -070085
Asmitha Karunanithi8e317782020-12-10 03:35:05 -060086enum class DumpCreationProgress
87{
88 DUMP_CREATE_SUCCESS,
89 DUMP_CREATE_FAILED,
90 DUMP_CREATE_INPROGRESS
91};
92
Gunnar Mills1214b7e2020-06-04 10:11:30 -050093inline std::string translateSeverityDbusToRedfish(const std::string& s)
Andrew Geisslercb92c032018-08-17 07:56:14 -070094{
Ed Tanousd4d25792020-09-29 15:15:03 -070095 if ((s == "xyz.openbmc_project.Logging.Entry.Level.Alert") ||
96 (s == "xyz.openbmc_project.Logging.Entry.Level.Critical") ||
97 (s == "xyz.openbmc_project.Logging.Entry.Level.Emergency") ||
98 (s == "xyz.openbmc_project.Logging.Entry.Level.Error"))
Andrew Geisslercb92c032018-08-17 07:56:14 -070099 {
100 return "Critical";
101 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700102 if ((s == "xyz.openbmc_project.Logging.Entry.Level.Debug") ||
103 (s == "xyz.openbmc_project.Logging.Entry.Level.Informational") ||
104 (s == "xyz.openbmc_project.Logging.Entry.Level.Notice"))
Andrew Geisslercb92c032018-08-17 07:56:14 -0700105 {
106 return "OK";
107 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700108 if (s == "xyz.openbmc_project.Logging.Entry.Level.Warning")
Andrew Geisslercb92c032018-08-17 07:56:14 -0700109 {
110 return "Warning";
111 }
112 return "";
113}
114
Abhishek Patel9017faf2021-09-14 22:48:55 -0500115inline std::optional<bool> getProviderNotifyAction(const std::string& notify)
116{
117 std::optional<bool> notifyAction;
118 if (notify == "xyz.openbmc_project.Logging.Entry.Notify.Notify")
119 {
120 notifyAction = true;
121 }
122 else if (notify == "xyz.openbmc_project.Logging.Entry.Notify.Inhibit")
123 {
124 notifyAction = false;
125 }
126
127 return notifyAction;
128}
129
Ed Tanous18f8f602023-07-18 10:07:23 -0700130inline std::string getDumpPath(std::string_view dumpType)
131{
132 std::string dbusDumpPath = "/xyz/openbmc_project/dump/";
133 std::ranges::transform(dumpType, std::back_inserter(dbusDumpPath),
134 bmcweb::asciiToLower);
135
136 return dbusDumpPath;
137}
138
Ed Tanous055713e2024-07-17 17:19:36 -0700139inline bool getUniqueEntryID(const std::string& logEntry, std::string& entryID,
Jason M. Billse85d6b12019-07-29 17:01:15 -0700140 const bool firstEntry = true)
Jason M. Bills95820182019-04-22 16:25:34 -0700141{
Ed Tanous271584a2019-07-09 16:24:22 -0700142 static time_t prevTs = 0;
Jason M. Bills95820182019-04-22 16:25:34 -0700143 static int index = 0;
Jason M. Billse85d6b12019-07-29 17:01:15 -0700144 if (firstEntry)
145 {
146 prevTs = 0;
147 }
148
Jason M. Bills95820182019-04-22 16:25:34 -0700149 // Get the entry timestamp
Ed Tanous271584a2019-07-09 16:24:22 -0700150 std::time_t curTs = 0;
Jason M. Bills95820182019-04-22 16:25:34 -0700151 std::tm timeStruct = {};
152 std::istringstream entryStream(logEntry);
153 if (entryStream >> std::get_time(&timeStruct, "%Y-%m-%dT%H:%M:%S"))
154 {
155 curTs = std::mktime(&timeStruct);
156 }
157 // If the timestamp isn't unique, increment the index
158 if (curTs == prevTs)
159 {
160 index++;
161 }
162 else
163 {
164 // Otherwise, reset it
165 index = 0;
166 }
167 // Save the timestamp
168 prevTs = curTs;
169
170 entryID = std::to_string(curTs);
171 if (index > 0)
172 {
173 entryID += "_" + std::to_string(index);
174 }
175 return true;
176}
177
Patrick Williams504af5a2025-02-03 14:29:03 -0500178inline bool getRedfishLogFiles(
179 std::vector<std::filesystem::path>& redfishLogFiles)
Jason M. Bills95820182019-04-22 16:25:34 -0700180{
181 static const std::filesystem::path redfishLogDir = "/var/log";
182 static const std::string redfishLogFilename = "redfish";
183
184 // Loop through the directory looking for redfish log files
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500185 for (const std::filesystem::directory_entry& dirEnt :
Jason M. Bills95820182019-04-22 16:25:34 -0700186 std::filesystem::directory_iterator(redfishLogDir))
187 {
188 // If we find a redfish log file, save the path
189 std::string filename = dirEnt.path().filename();
Ed Tanous11ba3972022-07-11 09:50:41 -0700190 if (filename.starts_with(redfishLogFilename))
Jason M. Bills95820182019-04-22 16:25:34 -0700191 {
192 redfishLogFiles.emplace_back(redfishLogDir / filename);
193 }
194 }
195 // As the log files rotate, they are appended with a ".#" that is higher for
196 // the older logs. Since we don't expect more than 10 log files, we
197 // can just sort the list to get them in order from newest to oldest
Ed Tanous3544d2a2023-08-06 18:12:20 -0700198 std::ranges::sort(redfishLogFiles);
Jason M. Bills95820182019-04-22 16:25:34 -0700199
200 return !redfishLogFiles.empty();
201}
202
Patrick Williams504af5a2025-02-03 14:29:03 -0500203inline log_entry::OriginatorTypes mapDbusOriginatorTypeToRedfish(
204 const std::string& originatorType)
Asmitha Karunanithi68dd0752022-11-15 11:33:46 -0600205{
206 if (originatorType ==
207 "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Client")
208 {
209 return log_entry::OriginatorTypes::Client;
210 }
211 if (originatorType ==
212 "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Internal")
213 {
214 return log_entry::OriginatorTypes::Internal;
215 }
216 if (originatorType ==
217 "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.SupportingService")
218 {
219 return log_entry::OriginatorTypes::SupportingService;
220 }
221 return log_entry::OriginatorTypes::Invalid;
222}
223
Claire Weinanaefe3782022-07-15 19:17:19 -0700224inline void parseDumpEntryFromDbusObject(
Jiaqing Zhao2d613eb2022-08-15 16:03:00 +0800225 const dbus::utility::ManagedObjectType::value_type& object,
Claire Weinanc6fecda2022-07-15 10:43:25 -0700226 std::string& dumpStatus, uint64_t& size, uint64_t& timestampUs,
Asmitha Karunanithi68dd0752022-11-15 11:33:46 -0600227 std::string& originatorId, log_entry::OriginatorTypes& originatorType,
Claire Weinanaefe3782022-07-15 19:17:19 -0700228 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
229{
230 for (const auto& interfaceMap : object.second)
231 {
232 if (interfaceMap.first == "xyz.openbmc_project.Common.Progress")
233 {
234 for (const auto& propertyMap : interfaceMap.second)
235 {
236 if (propertyMap.first == "Status")
237 {
238 const auto* status =
239 std::get_if<std::string>(&propertyMap.second);
240 if (status == nullptr)
241 {
242 messages::internalError(asyncResp->res);
243 break;
244 }
245 dumpStatus = *status;
246 }
247 }
248 }
249 else if (interfaceMap.first == "xyz.openbmc_project.Dump.Entry")
250 {
251 for (const auto& propertyMap : interfaceMap.second)
252 {
253 if (propertyMap.first == "Size")
254 {
255 const auto* sizePtr =
256 std::get_if<uint64_t>(&propertyMap.second);
257 if (sizePtr == nullptr)
258 {
259 messages::internalError(asyncResp->res);
260 break;
261 }
262 size = *sizePtr;
263 break;
264 }
265 }
266 }
267 else if (interfaceMap.first == "xyz.openbmc_project.Time.EpochTime")
268 {
269 for (const auto& propertyMap : interfaceMap.second)
270 {
271 if (propertyMap.first == "Elapsed")
272 {
273 const uint64_t* usecsTimeStamp =
274 std::get_if<uint64_t>(&propertyMap.second);
275 if (usecsTimeStamp == nullptr)
276 {
277 messages::internalError(asyncResp->res);
278 break;
279 }
Claire Weinanc6fecda2022-07-15 10:43:25 -0700280 timestampUs = *usecsTimeStamp;
Claire Weinanaefe3782022-07-15 19:17:19 -0700281 break;
282 }
283 }
284 }
Asmitha Karunanithi68dd0752022-11-15 11:33:46 -0600285 else if (interfaceMap.first ==
286 "xyz.openbmc_project.Common.OriginatedBy")
287 {
288 for (const auto& propertyMap : interfaceMap.second)
289 {
290 if (propertyMap.first == "OriginatorId")
291 {
292 const std::string* id =
293 std::get_if<std::string>(&propertyMap.second);
294 if (id == nullptr)
295 {
296 messages::internalError(asyncResp->res);
297 break;
298 }
299 originatorId = *id;
300 }
301
302 if (propertyMap.first == "OriginatorType")
303 {
304 const std::string* type =
305 std::get_if<std::string>(&propertyMap.second);
306 if (type == nullptr)
307 {
308 messages::internalError(asyncResp->res);
309 break;
310 }
311
312 originatorType = mapDbusOriginatorTypeToRedfish(*type);
313 if (originatorType == log_entry::OriginatorTypes::Invalid)
314 {
315 messages::internalError(asyncResp->res);
316 break;
317 }
318 }
319 }
320 }
Claire Weinanaefe3782022-07-15 19:17:19 -0700321 }
322}
323
Nan Zhou21ab4042022-06-26 23:07:40 +0000324static std::string getDumpEntriesPath(const std::string& dumpType)
Claire Weinanfdd26902022-03-01 14:18:25 -0800325{
326 std::string entriesPath;
327
328 if (dumpType == "BMC")
329 {
Ed Tanous253f11b2024-05-16 09:38:31 -0700330 entriesPath =
331 std::format("/redfish/v1/Managers/{}/LogServices/Dump/Entries/",
332 BMCWEB_REDFISH_MANAGER_URI_NAME);
Claire Weinanfdd26902022-03-01 14:18:25 -0800333 }
334 else if (dumpType == "FaultLog")
335 {
Ed Tanous253f11b2024-05-16 09:38:31 -0700336 entriesPath =
337 std::format("/redfish/v1/Managers/{}/LogServices/FaultLog/Entries/",
338 BMCWEB_REDFISH_MANAGER_URI_NAME);
Claire Weinanfdd26902022-03-01 14:18:25 -0800339 }
340 else if (dumpType == "System")
341 {
Ed Tanous253f11b2024-05-16 09:38:31 -0700342 entriesPath =
343 std::format("/redfish/v1/Systems/{}/LogServices/Dump/Entries/",
344 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Claire Weinanfdd26902022-03-01 14:18:25 -0800345 }
346 else
347 {
Ed Tanous62598e32023-07-17 17:06:25 -0700348 BMCWEB_LOG_ERROR("getDumpEntriesPath() invalid dump type: {}",
349 dumpType);
Claire Weinanfdd26902022-03-01 14:18:25 -0800350 }
351
352 // Returns empty string on error
353 return entriesPath;
354}
355
Patrick Williams504af5a2025-02-03 14:29:03 -0500356inline void getDumpEntryCollection(
357 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
358 const std::string& dumpType)
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500359{
Claire Weinanfdd26902022-03-01 14:18:25 -0800360 std::string entriesPath = getDumpEntriesPath(dumpType);
361 if (entriesPath.empty())
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500362 {
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500363 messages::internalError(asyncResp->res);
364 return;
365 }
366
George Liu5eb468d2023-06-20 17:03:24 +0800367 sdbusplus::message::object_path path("/xyz/openbmc_project/dump");
368 dbus::utility::getManagedObjects(
369 "xyz.openbmc_project.Dump.Manager", path,
Claire Weinanfdd26902022-03-01 14:18:25 -0800370 [asyncResp, entriesPath,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800371 dumpType](const boost::system::error_code& ec,
George Liu5eb468d2023-06-20 17:03:24 +0800372 const dbus::utility::ManagedObjectType& objects) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400373 if (ec)
374 {
375 BMCWEB_LOG_ERROR("DumpEntry resp_handler got error {}", ec);
376 messages::internalError(asyncResp->res);
377 return;
378 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700379
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400380 // Remove ending slash
381 std::string odataIdStr = entriesPath;
382 if (!odataIdStr.empty())
383 {
384 odataIdStr.pop_back();
385 }
Claire Weinanfdd26902022-03-01 14:18:25 -0800386
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400387 asyncResp->res.jsonValue["@odata.type"] =
388 "#LogEntryCollection.LogEntryCollection";
389 asyncResp->res.jsonValue["@odata.id"] = std::move(odataIdStr);
390 asyncResp->res.jsonValue["Name"] = dumpType + " Dump Entries";
391 asyncResp->res.jsonValue["Description"] =
392 "Collection of " + dumpType + " Dump Entries";
Claire Weinanfdd26902022-03-01 14:18:25 -0800393
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400394 nlohmann::json::array_t entriesArray;
395 std::string dumpEntryPath = getDumpPath(dumpType) + "/entry/";
Ed Tanous002d39b2022-05-31 08:59:27 -0700396
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400397 dbus::utility::ManagedObjectType resp(objects);
398 std::ranges::sort(resp, [](const auto& l, const auto& r) {
399 return AlphanumLess<std::string>()(l.first.filename(),
400 r.first.filename());
401 });
402
403 for (auto& object : resp)
404 {
405 if (object.first.str.find(dumpEntryPath) == std::string::npos)
406 {
407 continue;
408 }
409 uint64_t timestampUs = 0;
410 uint64_t size = 0;
411 std::string dumpStatus;
412 std::string originatorId;
413 log_entry::OriginatorTypes originatorType =
414 log_entry::OriginatorTypes::Internal;
415 nlohmann::json::object_t thisEntry;
416
417 std::string entryID = object.first.filename();
418 if (entryID.empty())
419 {
420 continue;
421 }
422
423 parseDumpEntryFromDbusObject(object, dumpStatus, size,
424 timestampUs, originatorId,
425 originatorType, asyncResp);
426
427 if (dumpStatus !=
428 "xyz.openbmc_project.Common.Progress.OperationStatus.Completed" &&
429 !dumpStatus.empty())
430 {
431 // Dump status is not Complete, no need to enumerate
432 continue;
433 }
434
435 thisEntry["@odata.type"] = "#LogEntry.v1_11_0.LogEntry";
436 thisEntry["@odata.id"] = entriesPath + entryID;
437 thisEntry["Id"] = entryID;
438 thisEntry["EntryType"] = "Event";
439 thisEntry["Name"] = dumpType + " Dump Entry";
440 thisEntry["Created"] =
441 redfish::time_utils::getDateTimeUintUs(timestampUs);
442
443 if (!originatorId.empty())
444 {
445 thisEntry["Originator"] = originatorId;
446 thisEntry["OriginatorType"] = originatorType;
447 }
448
449 if (dumpType == "BMC")
450 {
451 thisEntry["DiagnosticDataType"] = "Manager";
452 thisEntry["AdditionalDataURI"] =
453 entriesPath + entryID + "/attachment";
454 thisEntry["AdditionalDataSizeBytes"] = size;
455 }
456 else if (dumpType == "System")
457 {
458 thisEntry["DiagnosticDataType"] = "OEM";
459 thisEntry["OEMDiagnosticDataType"] = "System";
460 thisEntry["AdditionalDataURI"] =
461 entriesPath + entryID + "/attachment";
462 thisEntry["AdditionalDataSizeBytes"] = size;
463 }
464 entriesArray.emplace_back(std::move(thisEntry));
465 }
466 asyncResp->res.jsonValue["Members@odata.count"] =
467 entriesArray.size();
468 asyncResp->res.jsonValue["Members"] = std::move(entriesArray);
Ed Tanous002d39b2022-05-31 08:59:27 -0700469 });
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500470}
471
Patrick Williams504af5a2025-02-03 14:29:03 -0500472inline void getDumpEntryById(
473 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
474 const std::string& entryID, const std::string& dumpType)
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500475{
Claire Weinanfdd26902022-03-01 14:18:25 -0800476 std::string entriesPath = getDumpEntriesPath(dumpType);
477 if (entriesPath.empty())
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500478 {
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500479 messages::internalError(asyncResp->res);
480 return;
481 }
482
George Liu5eb468d2023-06-20 17:03:24 +0800483 sdbusplus::message::object_path path("/xyz/openbmc_project/dump");
484 dbus::utility::getManagedObjects(
485 "xyz.openbmc_project.Dump.Manager", path,
Claire Weinanfdd26902022-03-01 14:18:25 -0800486 [asyncResp, entryID, dumpType,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800487 entriesPath](const boost::system::error_code& ec,
Ed Tanous02cad962022-06-30 16:50:15 -0700488 const dbus::utility::ManagedObjectType& resp) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400489 if (ec)
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500490 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400491 BMCWEB_LOG_ERROR("DumpEntry resp_handler got error {}", ec);
492 messages::internalError(asyncResp->res);
493 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700494 }
495
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400496 bool foundDumpEntry = false;
497 std::string dumpEntryPath = getDumpPath(dumpType) + "/entry/";
Ed Tanous002d39b2022-05-31 08:59:27 -0700498
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400499 for (const auto& objectPath : resp)
Ed Tanous002d39b2022-05-31 08:59:27 -0700500 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400501 if (objectPath.first.str != dumpEntryPath + entryID)
502 {
503 continue;
504 }
505
506 foundDumpEntry = true;
507 uint64_t timestampUs = 0;
508 uint64_t size = 0;
509 std::string dumpStatus;
510 std::string originatorId;
511 log_entry::OriginatorTypes originatorType =
512 log_entry::OriginatorTypes::Internal;
513
514 parseDumpEntryFromDbusObject(objectPath, dumpStatus, size,
515 timestampUs, originatorId,
516 originatorType, asyncResp);
517
518 if (dumpStatus !=
519 "xyz.openbmc_project.Common.Progress.OperationStatus.Completed" &&
520 !dumpStatus.empty())
521 {
522 // Dump status is not Complete
523 // return not found until status is changed to Completed
524 messages::resourceNotFound(asyncResp->res,
525 dumpType + " dump", entryID);
526 return;
527 }
528
529 asyncResp->res.jsonValue["@odata.type"] =
530 "#LogEntry.v1_11_0.LogEntry";
531 asyncResp->res.jsonValue["@odata.id"] = entriesPath + entryID;
532 asyncResp->res.jsonValue["Id"] = entryID;
533 asyncResp->res.jsonValue["EntryType"] = "Event";
534 asyncResp->res.jsonValue["Name"] = dumpType + " Dump Entry";
535 asyncResp->res.jsonValue["Created"] =
536 redfish::time_utils::getDateTimeUintUs(timestampUs);
537
538 if (!originatorId.empty())
539 {
540 asyncResp->res.jsonValue["Originator"] = originatorId;
541 asyncResp->res.jsonValue["OriginatorType"] = originatorType;
542 }
543
544 if (dumpType == "BMC")
545 {
546 asyncResp->res.jsonValue["DiagnosticDataType"] = "Manager";
547 asyncResp->res.jsonValue["AdditionalDataURI"] =
548 entriesPath + entryID + "/attachment";
549 asyncResp->res.jsonValue["AdditionalDataSizeBytes"] = size;
550 }
551 else if (dumpType == "System")
552 {
553 asyncResp->res.jsonValue["DiagnosticDataType"] = "OEM";
554 asyncResp->res.jsonValue["OEMDiagnosticDataType"] =
555 "System";
556 asyncResp->res.jsonValue["AdditionalDataURI"] =
557 entriesPath + entryID + "/attachment";
558 asyncResp->res.jsonValue["AdditionalDataSizeBytes"] = size;
559 }
560 }
561 if (!foundDumpEntry)
562 {
563 BMCWEB_LOG_WARNING("Can't find Dump Entry {}", entryID);
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +0200564 messages::resourceNotFound(asyncResp->res, dumpType + " dump",
565 entryID);
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500566 return;
567 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400568 });
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500569}
570
zhanghch058d1b46d2021-04-01 11:18:24 +0800571inline void deleteDumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Stanley Chu98782562020-11-04 16:10:24 +0800572 const std::string& entryID,
Asmitha Karunanithib47452b2020-09-25 02:02:19 -0500573 const std::string& dumpType)
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500574{
Patrick Williams5a39f772023-10-20 11:20:21 -0500575 auto respHandler = [asyncResp,
576 entryID](const boost::system::error_code& ec) {
Ed Tanous62598e32023-07-17 17:06:25 -0700577 BMCWEB_LOG_DEBUG("Dump Entry doDelete callback: Done");
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500578 if (ec)
579 {
George Liu3de8d8b2021-03-22 17:49:39 +0800580 if (ec.value() == EBADR)
581 {
582 messages::resourceNotFound(asyncResp->res, "LogEntry", entryID);
583 return;
584 }
Ed Tanous62598e32023-07-17 17:06:25 -0700585 BMCWEB_LOG_ERROR(
586 "Dump (DBus) doDelete respHandler got error {} entryID={}", ec,
587 entryID);
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500588 messages::internalError(asyncResp->res);
589 return;
590 }
591 };
Ed Tanous18f8f602023-07-18 10:07:23 -0700592
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500593 crow::connections::systemBus->async_method_call(
594 respHandler, "xyz.openbmc_project.Dump.Manager",
Ed Tanous18f8f602023-07-18 10:07:23 -0700595 std::format("{}/entry/{}", getDumpPath(dumpType), entryID),
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500596 "xyz.openbmc_project.Object.Delete", "Delete");
597}
Abhilash Rajub5f288d2023-11-08 22:32:44 -0600598inline bool checkSizeLimit(int fd, crow::Response& res)
599{
600 long long int size = lseek(fd, 0, SEEK_END);
601 if (size <= 0)
602 {
603 BMCWEB_LOG_ERROR("Failed to get size of file, lseek() returned {}",
604 size);
605 messages::internalError(res);
606 return false;
607 }
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500608
Abhilash Rajub5f288d2023-11-08 22:32:44 -0600609 // Arbitrary max size of 20MB to accommodate BMC dumps
610 constexpr long long int maxFileSize = 20LL * 1024LL * 1024LL;
611 if (size > maxFileSize)
612 {
613 BMCWEB_LOG_ERROR("File size {} exceeds maximum allowed size of {}",
614 size, maxFileSize);
615 messages::internalError(res);
616 return false;
617 }
618 off_t rc = lseek(fd, 0, SEEK_SET);
619 if (rc < 0)
620 {
621 BMCWEB_LOG_ERROR("Failed to reset file offset to 0");
622 messages::internalError(res);
623 return false;
624 }
625 return true;
626}
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400627inline void downloadEntryCallback(
628 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
629 const std::string& entryID, const std::string& downloadEntryType,
630 const boost::system::error_code& ec,
631 const sdbusplus::message::unix_fd& unixfd)
Carson Labrado168d1b12023-03-27 17:04:46 +0000632{
633 if (ec.value() == EBADR)
634 {
635 messages::resourceNotFound(asyncResp->res, "EntryAttachment", entryID);
636 return;
637 }
638 if (ec)
639 {
640 BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
641 messages::internalError(asyncResp->res);
642 return;
643 }
644
645 // Make sure we know how to process the retrieved entry attachment
646 if ((downloadEntryType != "BMC") && (downloadEntryType != "System"))
647 {
648 BMCWEB_LOG_ERROR("downloadEntryCallback() invalid entry type: {}",
649 downloadEntryType);
650 messages::internalError(asyncResp->res);
651 }
652
653 int fd = -1;
654 fd = dup(unixfd);
655 if (fd < 0)
656 {
657 BMCWEB_LOG_ERROR("Failed to open file");
658 messages::internalError(asyncResp->res);
659 return;
660 }
Abhilash Rajub5f288d2023-11-08 22:32:44 -0600661 if (!checkSizeLimit(fd, asyncResp->res))
Carson Labrado168d1b12023-03-27 17:04:46 +0000662 {
Carson Labrado168d1b12023-03-27 17:04:46 +0000663 close(fd);
664 return;
665 }
Carson Labrado168d1b12023-03-27 17:04:46 +0000666 if (downloadEntryType == "System")
667 {
Abhilash Rajub5f288d2023-11-08 22:32:44 -0600668 if (!asyncResp->res.openFd(fd, bmcweb::EncodingType::Base64))
669 {
670 messages::internalError(asyncResp->res);
671 close(fd);
672 return;
673 }
Carson Labrado168d1b12023-03-27 17:04:46 +0000674 asyncResp->res.addHeader(
675 boost::beast::http::field::content_transfer_encoding, "Base64");
Abhilash Rajub5f288d2023-11-08 22:32:44 -0600676 return;
Carson Labrado168d1b12023-03-27 17:04:46 +0000677 }
Abhilash Rajub5f288d2023-11-08 22:32:44 -0600678 if (!asyncResp->res.openFd(fd))
Ed Tanous27b0cf92023-08-07 12:02:40 -0700679 {
Abhilash Rajub5f288d2023-11-08 22:32:44 -0600680 messages::internalError(asyncResp->res);
681 close(fd);
682 return;
Ed Tanous27b0cf92023-08-07 12:02:40 -0700683 }
Carson Labrado168d1b12023-03-27 17:04:46 +0000684 asyncResp->res.addHeader(boost::beast::http::field::content_type,
685 "application/octet-stream");
686}
687
Patrick Williams504af5a2025-02-03 14:29:03 -0500688inline void downloadDumpEntry(
689 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
690 const std::string& entryID, const std::string& dumpType)
Carson Labrado168d1b12023-03-27 17:04:46 +0000691{
692 if (dumpType != "BMC")
693 {
694 BMCWEB_LOG_WARNING("Can't find Dump Entry {}", entryID);
695 messages::resourceNotFound(asyncResp->res, dumpType + " dump", entryID);
696 return;
697 }
698
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400699 std::string dumpEntryPath =
700 std::format("{}/entry/{}", getDumpPath(dumpType), entryID);
Carson Labrado168d1b12023-03-27 17:04:46 +0000701
702 auto downloadDumpEntryHandler =
703 [asyncResp, entryID,
704 dumpType](const boost::system::error_code& ec,
705 const sdbusplus::message::unix_fd& unixfd) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400706 downloadEntryCallback(asyncResp, entryID, dumpType, ec, unixfd);
707 };
Carson Labrado168d1b12023-03-27 17:04:46 +0000708
709 crow::connections::systemBus->async_method_call(
710 std::move(downloadDumpEntryHandler), "xyz.openbmc_project.Dump.Manager",
711 dumpEntryPath, "xyz.openbmc_project.Dump.Entry", "GetFileHandle");
712}
713
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400714inline void downloadEventLogEntry(
715 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
716 const std::string& systemName, const std::string& entryID,
717 const std::string& dumpType)
Carson Labrado168d1b12023-03-27 17:04:46 +0000718{
Ed Tanous25b54db2024-04-17 15:40:31 -0700719 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Carson Labrado168d1b12023-03-27 17:04:46 +0000720 {
721 // Option currently returns no systems. TBD
722 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
723 systemName);
724 return;
725 }
Ed Tanous253f11b2024-05-16 09:38:31 -0700726 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Carson Labrado168d1b12023-03-27 17:04:46 +0000727 {
728 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
729 systemName);
730 return;
731 }
732
733 std::string entryPath =
734 sdbusplus::message::object_path("/xyz/openbmc_project/logging/entry") /
735 entryID;
736
737 auto downloadEventLogEntryHandler =
738 [asyncResp, entryID,
739 dumpType](const boost::system::error_code& ec,
740 const sdbusplus::message::unix_fd& unixfd) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400741 downloadEntryCallback(asyncResp, entryID, dumpType, ec, unixfd);
742 };
Carson Labrado168d1b12023-03-27 17:04:46 +0000743
744 crow::connections::systemBus->async_method_call(
745 std::move(downloadEventLogEntryHandler), "xyz.openbmc_project.Logging",
746 entryPath, "xyz.openbmc_project.Logging.Entry", "GetEntry");
747}
748
Patrick Williams504af5a2025-02-03 14:29:03 -0500749inline DumpCreationProgress mapDbusStatusToDumpProgress(
750 const std::string& status)
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500751{
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600752 if (status ==
753 "xyz.openbmc_project.Common.Progress.OperationStatus.Failed" ||
754 status == "xyz.openbmc_project.Common.Progress.OperationStatus.Aborted")
755 {
756 return DumpCreationProgress::DUMP_CREATE_FAILED;
757 }
758 if (status ==
759 "xyz.openbmc_project.Common.Progress.OperationStatus.Completed")
760 {
761 return DumpCreationProgress::DUMP_CREATE_SUCCESS;
762 }
763 return DumpCreationProgress::DUMP_CREATE_INPROGRESS;
764}
765
Patrick Williams504af5a2025-02-03 14:29:03 -0500766inline DumpCreationProgress getDumpCompletionStatus(
767 const dbus::utility::DBusPropertiesMap& values)
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600768{
769 for (const auto& [key, val] : values)
770 {
771 if (key == "Status")
Ed Tanous002d39b2022-05-31 08:59:27 -0700772 {
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600773 const std::string* value = std::get_if<std::string>(&val);
774 if (value == nullptr)
775 {
Ed Tanous62598e32023-07-17 17:06:25 -0700776 BMCWEB_LOG_ERROR("Status property value is null");
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600777 return DumpCreationProgress::DUMP_CREATE_FAILED;
778 }
779 return mapDbusStatusToDumpProgress(*value);
780 }
781 }
782 return DumpCreationProgress::DUMP_CREATE_INPROGRESS;
783}
784
785inline std::string getDumpEntryPath(const std::string& dumpPath)
786{
787 if (dumpPath == "/xyz/openbmc_project/dump/bmc/entry")
788 {
Ed Tanous253f11b2024-05-16 09:38:31 -0700789 return std::format("/redfish/v1/Managers/{}/LogServices/Dump/Entries/",
Ed Tanous9f565092024-07-12 22:06:53 -0700790 BMCWEB_REDFISH_MANAGER_URI_NAME);
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600791 }
792 if (dumpPath == "/xyz/openbmc_project/dump/system/entry")
793 {
Ed Tanous253f11b2024-05-16 09:38:31 -0700794 return std::format("/redfish/v1/Systems/{}/LogServices/Dump/Entries/",
795 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600796 }
797 return "";
798}
799
800inline void createDumpTaskCallback(
801 task::Payload&& payload,
802 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
803 const sdbusplus::message::object_path& createdObjPath)
804{
805 const std::string dumpPath = createdObjPath.parent_path().str;
806 const std::string dumpId = createdObjPath.filename();
807
808 std::string dumpEntryPath = getDumpEntryPath(dumpPath);
809
810 if (dumpEntryPath.empty())
811 {
Ed Tanous62598e32023-07-17 17:06:25 -0700812 BMCWEB_LOG_ERROR("Invalid dump type received");
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600813 messages::internalError(asyncResp->res);
814 return;
815 }
816
817 crow::connections::systemBus->async_method_call(
Ed Tanous8cb2c022024-03-27 16:31:46 -0700818 [asyncResp, payload = std::move(payload), createdObjPath,
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600819 dumpEntryPath{std::move(dumpEntryPath)},
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800820 dumpId](const boost::system::error_code& ec,
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600821 const std::string& introspectXml) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400822 if (ec)
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600823 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400824 BMCWEB_LOG_ERROR("Introspect call failed with error: {}",
825 ec.message());
826 messages::internalError(asyncResp->res);
827 return;
828 }
829
830 // Check if the created dump object has implemented Progress
831 // interface to track dump completion. If yes, fetch the "Status"
832 // property of the interface, modify the task state accordingly.
833 // Else, return task completed.
834 tinyxml2::XMLDocument doc;
835
836 doc.Parse(introspectXml.data(), introspectXml.size());
837 tinyxml2::XMLNode* pRoot = doc.FirstChildElement("node");
838 if (pRoot == nullptr)
839 {
840 BMCWEB_LOG_ERROR("XML document failed to parse");
841 messages::internalError(asyncResp->res);
842 return;
843 }
844 tinyxml2::XMLElement* interfaceNode =
845 pRoot->FirstChildElement("interface");
846
847 bool isProgressIntfPresent = false;
848 while (interfaceNode != nullptr)
849 {
850 const char* thisInterfaceName =
851 interfaceNode->Attribute("name");
852 if (thisInterfaceName != nullptr)
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600853 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400854 if (thisInterfaceName ==
855 std::string_view("xyz.openbmc_project.Common.Progress"))
856 {
857 interfaceNode =
858 interfaceNode->NextSiblingElement("interface");
859 continue;
860 }
861 isProgressIntfPresent = true;
862 break;
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600863 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400864 interfaceNode = interfaceNode->NextSiblingElement("interface");
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600865 }
866
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400867 std::shared_ptr<task::TaskData> task = task::TaskData::createTask(
868 [createdObjPath, dumpEntryPath, dumpId, isProgressIntfPresent](
869 const boost::system::error_code& ec2,
870 sdbusplus::message_t& msg,
871 const std::shared_ptr<task::TaskData>& taskData) {
872 if (ec2)
873 {
874 BMCWEB_LOG_ERROR("{}: Error in creating dump",
875 createdObjPath.str);
876 taskData->messages.emplace_back(
877 messages::internalError());
878 taskData->state = "Cancelled";
879 return task::completed;
880 }
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600881
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400882 if (isProgressIntfPresent)
883 {
884 dbus::utility::DBusPropertiesMap values;
885 std::string prop;
886 msg.read(prop, values);
887
888 DumpCreationProgress dumpStatus =
889 getDumpCompletionStatus(values);
890 if (dumpStatus ==
891 DumpCreationProgress::DUMP_CREATE_FAILED)
892 {
893 BMCWEB_LOG_ERROR("{}: Error in creating dump",
894 createdObjPath.str);
895 taskData->state = "Cancelled";
896 return task::completed;
897 }
898
899 if (dumpStatus ==
900 DumpCreationProgress::DUMP_CREATE_INPROGRESS)
901 {
902 BMCWEB_LOG_DEBUG(
903 "{}: Dump creation task is in progress",
904 createdObjPath.str);
905 return !task::completed;
906 }
907 }
908
909 nlohmann::json retMessage = messages::success();
910 taskData->messages.emplace_back(retMessage);
911
912 boost::urls::url url = boost::urls::format(
913 "/redfish/v1/Managers/{}/LogServices/Dump/Entries/{}",
914 BMCWEB_REDFISH_MANAGER_URI_NAME, dumpId);
915
916 std::string headerLoc = "Location: ";
917 headerLoc += url.buffer();
918
919 taskData->payload->httpHeaders.emplace_back(
920 std::move(headerLoc));
921
922 BMCWEB_LOG_DEBUG("{}: Dump creation task completed",
Ed Tanous62598e32023-07-17 17:06:25 -0700923 createdObjPath.str);
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400924 taskData->state = "Completed";
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600925 return task::completed;
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400926 },
927 "type='signal',interface='org.freedesktop.DBus.Properties',"
928 "member='PropertiesChanged',path='" +
929 createdObjPath.str + "'");
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600930
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400931 // The task timer is set to max time limit within which the
932 // requested dump will be collected.
933 task->startTimer(std::chrono::minutes(6));
934 task->populateResp(asyncResp->res);
935 task->payload.emplace(payload);
Patrick Williams5a39f772023-10-20 11:20:21 -0500936 },
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600937 "xyz.openbmc_project.Dump.Manager", createdObjPath,
938 "org.freedesktop.DBus.Introspectable", "Introspect");
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500939}
940
zhanghch058d1b46d2021-04-01 11:18:24 +0800941inline void createDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
942 const crow::Request& req, const std::string& dumpType)
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500943{
Claire Weinanfdd26902022-03-01 14:18:25 -0800944 std::string dumpPath = getDumpEntriesPath(dumpType);
945 if (dumpPath.empty())
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500946 {
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500947 messages::internalError(asyncResp->res);
948 return;
949 }
950
951 std::optional<std::string> diagnosticDataType;
952 std::optional<std::string> oemDiagnosticDataType;
953
Patrick Williams504af5a2025-02-03 14:29:03 -0500954 if (!redfish::json_util::readJsonAction( //
955 req, asyncResp->res, //
956 "DiagnosticDataType", diagnosticDataType, //
Myung Baeafc474a2024-10-09 00:53:29 -0700957 "OEMDiagnosticDataType", oemDiagnosticDataType //
958 ))
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500959 {
960 return;
961 }
962
963 if (dumpType == "System")
964 {
965 if (!oemDiagnosticDataType || !diagnosticDataType)
966 {
Ed Tanous62598e32023-07-17 17:06:25 -0700967 BMCWEB_LOG_ERROR(
968 "CreateDump action parameter 'DiagnosticDataType'/'OEMDiagnosticDataType' value not found!");
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500969 messages::actionParameterMissing(
970 asyncResp->res, "CollectDiagnosticData",
971 "DiagnosticDataType & OEMDiagnosticDataType");
972 return;
973 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700974 if ((*oemDiagnosticDataType != "System") ||
975 (*diagnosticDataType != "OEM"))
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500976 {
Ed Tanous62598e32023-07-17 17:06:25 -0700977 BMCWEB_LOG_ERROR("Wrong parameter values passed");
Ed Tanousace85d62021-10-26 12:45:59 -0700978 messages::internalError(asyncResp->res);
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500979 return;
980 }
Ed Tanous253f11b2024-05-16 09:38:31 -0700981 dumpPath = std::format("/redfish/v1/Systems/{}/LogServices/Dump/",
982 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500983 }
984 else if (dumpType == "BMC")
985 {
986 if (!diagnosticDataType)
987 {
Ed Tanous62598e32023-07-17 17:06:25 -0700988 BMCWEB_LOG_ERROR(
989 "CreateDump action parameter 'DiagnosticDataType' not found!");
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500990 messages::actionParameterMissing(
991 asyncResp->res, "CollectDiagnosticData", "DiagnosticDataType");
992 return;
993 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700994 if (*diagnosticDataType != "Manager")
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500995 {
Ed Tanous62598e32023-07-17 17:06:25 -0700996 BMCWEB_LOG_ERROR(
997 "Wrong parameter value passed for 'DiagnosticDataType'");
Ed Tanousace85d62021-10-26 12:45:59 -0700998 messages::internalError(asyncResp->res);
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500999 return;
1000 }
Ed Tanous253f11b2024-05-16 09:38:31 -07001001 dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/Dump/",
1002 BMCWEB_REDFISH_MANAGER_URI_NAME);
Asmitha Karunanithi59075712021-10-22 01:17:41 -05001003 }
1004 else
1005 {
Ed Tanous62598e32023-07-17 17:06:25 -07001006 BMCWEB_LOG_ERROR("CreateDump failed. Unknown dump type");
Asmitha Karunanithi59075712021-10-22 01:17:41 -05001007 messages::internalError(asyncResp->res);
1008 return;
Asmitha Karunanithia43be802020-05-07 05:05:36 -05001009 }
1010
Asmitha Karunanithi8e317782020-12-10 03:35:05 -06001011 std::vector<std::pair<std::string, std::variant<std::string, uint64_t>>>
1012 createDumpParamVec;
1013
Carson Labradof574a8e2023-03-22 02:26:00 +00001014 if (req.session != nullptr)
1015 {
1016 createDumpParamVec.emplace_back(
1017 "xyz.openbmc_project.Dump.Create.CreateParameters.OriginatorId",
1018 req.session->clientIp);
1019 createDumpParamVec.emplace_back(
1020 "xyz.openbmc_project.Dump.Create.CreateParameters.OriginatorType",
1021 "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Client");
1022 }
Asmitha Karunanithi68dd0752022-11-15 11:33:46 -06001023
Asmitha Karunanithia43be802020-05-07 05:05:36 -05001024 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001025 [asyncResp, payload(task::Payload(req)),
1026 dumpPath](const boost::system::error_code& ec,
1027 const sdbusplus::message_t& msg,
1028 const sdbusplus::message::object_path& objPath) mutable {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001029 if (ec)
Asmitha Karunanithi59075712021-10-22 01:17:41 -05001030 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001031 BMCWEB_LOG_ERROR("CreateDump resp_handler got error {}", ec);
1032 const sd_bus_error* dbusError = msg.get_error();
1033 if (dbusError == nullptr)
1034 {
1035 messages::internalError(asyncResp->res);
1036 return;
1037 }
1038
1039 BMCWEB_LOG_ERROR("CreateDump DBus error: {} and error msg: {}",
1040 dbusError->name, dbusError->message);
1041 if (std::string_view(
1042 "xyz.openbmc_project.Common.Error.NotAllowed") ==
1043 dbusError->name)
1044 {
1045 messages::resourceInStandby(asyncResp->res);
1046 return;
1047 }
1048 if (std::string_view(
1049 "xyz.openbmc_project.Dump.Create.Error.Disabled") ==
1050 dbusError->name)
1051 {
1052 messages::serviceDisabled(asyncResp->res, dumpPath);
1053 return;
1054 }
1055 if (std::string_view(
1056 "xyz.openbmc_project.Common.Error.Unavailable") ==
1057 dbusError->name)
1058 {
1059 messages::resourceInUse(asyncResp->res);
1060 return;
1061 }
1062 // Other Dbus errors such as:
1063 // xyz.openbmc_project.Common.Error.InvalidArgument &
1064 // org.freedesktop.DBus.Error.InvalidArgs are all related to
1065 // the dbus call that is made here in the bmcweb
1066 // implementation and has nothing to do with the client's
1067 // input in the request. Hence, returning internal error
1068 // back to the client.
Asmitha Karunanithi59075712021-10-22 01:17:41 -05001069 messages::internalError(asyncResp->res);
1070 return;
1071 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001072 BMCWEB_LOG_DEBUG("Dump Created. Path: {}", objPath.str);
1073 createDumpTaskCallback(std::move(payload), asyncResp, objPath);
1074 },
Ed Tanous18f8f602023-07-18 10:07:23 -07001075 "xyz.openbmc_project.Dump.Manager", getDumpPath(dumpType),
Asmitha Karunanithi8e317782020-12-10 03:35:05 -06001076 "xyz.openbmc_project.Dump.Create", "CreateDump", createDumpParamVec);
Asmitha Karunanithia43be802020-05-07 05:05:36 -05001077}
1078
zhanghch058d1b46d2021-04-01 11:18:24 +08001079inline void clearDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1080 const std::string& dumpType)
Asmitha Karunanithi80319af2020-05-07 05:30:21 -05001081{
Claire Weinan0d946212022-07-13 19:40:19 -07001082 crow::connections::systemBus->async_method_call(
1083 [asyncResp](const boost::system::error_code& ec) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001084 if (ec)
1085 {
1086 BMCWEB_LOG_ERROR("clearDump resp_handler got error {}", ec);
1087 messages::internalError(asyncResp->res);
1088 return;
1089 }
1090 },
Ed Tanous18f8f602023-07-18 10:07:23 -07001091 "xyz.openbmc_project.Dump.Manager", getDumpPath(dumpType),
Claire Weinan0d946212022-07-13 19:40:19 -07001092 "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
Asmitha Karunanithi80319af2020-05-07 05:30:21 -05001093}
1094
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001095inline void parseCrashdumpParameters(
1096 const dbus::utility::DBusPropertiesMap& params, std::string& filename,
1097 std::string& timestamp, std::string& logfile)
Johnathan Mantey043a0532020-03-10 17:15:28 -07001098{
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +02001099 const std::string* filenamePtr = nullptr;
1100 const std::string* timestampPtr = nullptr;
1101 const std::string* logfilePtr = nullptr;
1102
1103 const bool success = sdbusplus::unpackPropertiesNoThrow(
1104 dbus_utils::UnpackErrorPrinter(), params, "Timestamp", timestampPtr,
1105 "Filename", filenamePtr, "Log", logfilePtr);
1106
1107 if (!success)
Johnathan Mantey043a0532020-03-10 17:15:28 -07001108 {
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +02001109 return;
1110 }
1111
1112 if (filenamePtr != nullptr)
1113 {
1114 filename = *filenamePtr;
1115 }
1116
1117 if (timestampPtr != nullptr)
1118 {
1119 timestamp = *timestampPtr;
1120 }
1121
1122 if (logfilePtr != nullptr)
1123 {
1124 logfile = *logfilePtr;
Johnathan Mantey043a0532020-03-10 17:15:28 -07001125 }
1126}
1127
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001128inline void requestRoutesSystemLogServiceCollection(App& app)
Ed Tanous1da66f72018-07-27 16:13:37 -07001129{
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001130 /**
1131 * Functions triggers appropriate requests on DBus
1132 */
Ed Tanous22d268c2022-05-19 09:39:07 -07001133 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/")
Ed Tanoused398212021-06-09 17:05:54 -07001134 .privileges(redfish::privileges::getLogServiceCollection)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001135 .methods(
1136 boost::beast::http::verb::
1137 get)([&app](const crow::Request& req,
1138 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1139 const std::string& systemName) {
1140 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07001141 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001142 return;
1143 }
1144 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1145 {
1146 // Option currently returns no systems. TBD
1147 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1148 systemName);
1149 return;
1150 }
1151 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1152 {
1153 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1154 systemName);
Ed Tanous002d39b2022-05-31 08:59:27 -07001155 return;
1156 }
Ed Tanous45ca1b82022-03-25 13:07:27 -07001157
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001158 // Collections don't include the static data added by SubRoute
1159 // because it has a duplicate entry for members
1160 asyncResp->res.jsonValue["@odata.type"] =
1161 "#LogServiceCollection.LogServiceCollection";
1162 asyncResp->res.jsonValue["@odata.id"] =
1163 std::format("/redfish/v1/Systems/{}/LogServices",
1164 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1165 asyncResp->res.jsonValue["Name"] = "System Log Services Collection";
1166 asyncResp->res.jsonValue["Description"] =
1167 "Collection of LogServices for this Computer System";
1168 nlohmann::json& logServiceArray =
1169 asyncResp->res.jsonValue["Members"];
1170 logServiceArray = nlohmann::json::array();
1171 nlohmann::json::object_t eventLog;
1172 eventLog["@odata.id"] =
1173 std::format("/redfish/v1/Systems/{}/LogServices/EventLog",
1174 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1175 logServiceArray.emplace_back(std::move(eventLog));
1176 if constexpr (BMCWEB_REDFISH_DUMP_LOG)
Ed Tanous002d39b2022-05-31 08:59:27 -07001177 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001178 nlohmann::json::object_t dumpLog;
1179 dumpLog["@odata.id"] =
1180 std::format("/redfish/v1/Systems/{}/LogServices/Dump",
1181 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1182 logServiceArray.emplace_back(std::move(dumpLog));
Ed Tanous002d39b2022-05-31 08:59:27 -07001183 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001184
1185 if constexpr (BMCWEB_REDFISH_CPU_LOG)
1186 {
1187 nlohmann::json::object_t crashdump;
1188 crashdump["@odata.id"] =
1189 std::format("/redfish/v1/Systems/{}/LogServices/Crashdump",
1190 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1191 logServiceArray.emplace_back(std::move(crashdump));
1192 }
1193
1194 if constexpr (BMCWEB_REDFISH_HOST_LOGGER)
1195 {
1196 nlohmann::json::object_t hostlogger;
1197 hostlogger["@odata.id"] =
1198 std::format("/redfish/v1/Systems/{}/LogServices/HostLogger",
1199 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1200 logServiceArray.emplace_back(std::move(hostlogger));
1201 }
1202 asyncResp->res.jsonValue["Members@odata.count"] =
1203 logServiceArray.size();
1204
1205 constexpr std::array<std::string_view, 1> interfaces = {
1206 "xyz.openbmc_project.State.Boot.PostCode"};
1207 dbus::utility::getSubTreePaths(
1208 "/", 0, interfaces,
1209 [asyncResp](const boost::system::error_code& ec,
1210 const dbus::utility::MapperGetSubTreePathsResponse&
1211 subtreePath) {
1212 if (ec)
1213 {
1214 BMCWEB_LOG_ERROR("{}", ec);
1215 return;
1216 }
1217
1218 for (const auto& pathStr : subtreePath)
1219 {
1220 if (pathStr.find("PostCode") != std::string::npos)
1221 {
1222 nlohmann::json& logServiceArrayLocal =
1223 asyncResp->res.jsonValue["Members"];
1224 nlohmann::json::object_t member;
1225 member["@odata.id"] = std::format(
1226 "/redfish/v1/Systems/{}/LogServices/PostCodes",
1227 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1228
1229 logServiceArrayLocal.emplace_back(
1230 std::move(member));
1231
1232 asyncResp->res.jsonValue["Members@odata.count"] =
1233 logServiceArrayLocal.size();
1234 return;
1235 }
1236 }
1237 });
Ed Tanous45ca1b82022-03-25 13:07:27 -07001238 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001239}
1240
1241inline void requestRoutesEventLogService(App& app)
1242{
Ed Tanous22d268c2022-05-19 09:39:07 -07001243 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/")
Ed Tanoused398212021-06-09 17:05:54 -07001244 .privileges(redfish::privileges::getLogService)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001245 .methods(
1246 boost::beast::http::verb::
1247 get)([&app](const crow::Request& req,
1248 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1249 const std::string& systemName) {
1250 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1251 {
1252 return;
1253 }
1254 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1255 {
1256 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1257 systemName);
1258 return;
1259 }
1260 asyncResp->res.jsonValue["@odata.id"] =
1261 std::format("/redfish/v1/Systems/{}/LogServices/EventLog",
1262 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1263 asyncResp->res.jsonValue["@odata.type"] =
1264 "#LogService.v1_2_0.LogService";
1265 asyncResp->res.jsonValue["Name"] = "Event Log Service";
1266 asyncResp->res.jsonValue["Description"] =
1267 "System Event Log Service";
1268 asyncResp->res.jsonValue["Id"] = "EventLog";
1269 asyncResp->res.jsonValue["OverWritePolicy"] =
1270 log_service::OverWritePolicy::WrapsWhenFull;
Tejas Patil7c8c4052021-06-04 17:43:14 +05301271
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001272 std::pair<std::string, std::string> redfishDateTimeOffset =
1273 redfish::time_utils::getDateTimeOffsetNow();
Tejas Patil7c8c4052021-06-04 17:43:14 +05301274
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001275 asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
1276 asyncResp->res.jsonValue["DateTimeLocalOffset"] =
1277 redfishDateTimeOffset.second;
Tejas Patil7c8c4052021-06-04 17:43:14 +05301278
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001279 asyncResp->res.jsonValue["Entries"]["@odata.id"] = std::format(
1280 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
Ed Tanous20fa6a22024-05-20 18:02:58 -07001281 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001282 asyncResp->res
1283 .jsonValue["Actions"]["#LogService.ClearLog"]["target"]
1284
1285 = std::format(
1286 "/redfish/v1/Systems/{}/LogServices/EventLog/Actions/LogService.ClearLog",
1287 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1288 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001289}
1290
Alexander Hansen599b9af2024-08-06 15:11:57 +02001291inline void handleSystemsLogServicesEventLogActionsClearPost(
1292 App& app, const crow::Request& req,
1293 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1294 const std::string& systemName)
1295{
1296 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1297 {
1298 return;
1299 }
1300 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1301 {
1302 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1303 systemName);
1304 return;
1305 }
1306
1307 // Clear the EventLog by deleting the log files
1308 std::vector<std::filesystem::path> redfishLogFiles;
1309 if (getRedfishLogFiles(redfishLogFiles))
1310 {
1311 for (const std::filesystem::path& file : redfishLogFiles)
1312 {
1313 std::error_code ec;
1314 std::filesystem::remove(file, ec);
1315 }
1316 }
1317
1318 // Reload rsyslog so it knows to start new log files
1319 crow::connections::systemBus->async_method_call(
1320 [asyncResp](const boost::system::error_code& ec) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001321 if (ec)
1322 {
1323 BMCWEB_LOG_ERROR("Failed to reload rsyslog: {}", ec);
1324 messages::internalError(asyncResp->res);
1325 return;
1326 }
Alexander Hansen599b9af2024-08-06 15:11:57 +02001327
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001328 messages::success(asyncResp->res);
1329 },
Alexander Hansen599b9af2024-08-06 15:11:57 +02001330 "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
1331 "org.freedesktop.systemd1.Manager", "ReloadUnit", "rsyslog.service",
1332 "replace");
1333}
1334
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001335inline void requestRoutesJournalEventLogClear(App& app)
1336{
Jason M. Bills4978b632022-02-22 14:17:43 -08001337 BMCWEB_ROUTE(
1338 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07001339 "/redfish/v1/Systems/<str>/LogServices/EventLog/Actions/LogService.ClearLog/")
Ed Tanous432a8902021-06-14 15:28:56 -07001340 .privileges({{"ConfigureComponents"}})
Alexander Hansen599b9af2024-08-06 15:11:57 +02001341 .methods(boost::beast::http::verb::post)(std::bind_front(
1342 handleSystemsLogServicesEventLogActionsClearPost, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001343}
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001344
Jason M. Billsac992cd2022-06-24 13:31:46 -07001345enum class LogParseError
1346{
1347 success,
1348 parseFailed,
1349 messageIdNotInRegistry,
1350};
1351
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001352static LogParseError fillEventLogEntryJson(
1353 const std::string& logEntryID, const std::string& logEntry,
1354 nlohmann::json::object_t& logEntryJson)
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001355{
Jason M. Bills95820182019-04-22 16:25:34 -07001356 // The redfish log format is "<Timestamp> <MessageId>,<MessageArgs>"
Jason M. Billscd225da2019-05-08 15:31:57 -07001357 // First get the Timestamp
Ed Tanousf23b7292020-10-15 09:41:17 -07001358 size_t space = logEntry.find_first_of(' ');
Jason M. Billscd225da2019-05-08 15:31:57 -07001359 if (space == std::string::npos)
Jason M. Bills95820182019-04-22 16:25:34 -07001360 {
Jason M. Billsac992cd2022-06-24 13:31:46 -07001361 return LogParseError::parseFailed;
Jason M. Bills95820182019-04-22 16:25:34 -07001362 }
Jason M. Billscd225da2019-05-08 15:31:57 -07001363 std::string timestamp = logEntry.substr(0, space);
1364 // Then get the log contents
Ed Tanousf23b7292020-10-15 09:41:17 -07001365 size_t entryStart = logEntry.find_first_not_of(' ', space);
Jason M. Billscd225da2019-05-08 15:31:57 -07001366 if (entryStart == std::string::npos)
1367 {
Jason M. Billsac992cd2022-06-24 13:31:46 -07001368 return LogParseError::parseFailed;
Jason M. Billscd225da2019-05-08 15:31:57 -07001369 }
1370 std::string_view entry(logEntry);
1371 entry.remove_prefix(entryStart);
1372 // Use split to separate the entry into its fields
1373 std::vector<std::string> logEntryFields;
Ed Tanous50ebd4a2023-01-19 19:03:17 -08001374 bmcweb::split(logEntryFields, entry, ',');
Jason M. Billscd225da2019-05-08 15:31:57 -07001375 // We need at least a MessageId to be valid
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001376 auto logEntryIter = logEntryFields.begin();
1377 if (logEntryIter == logEntryFields.end())
Jason M. Billscd225da2019-05-08 15:31:57 -07001378 {
Jason M. Billsac992cd2022-06-24 13:31:46 -07001379 return LogParseError::parseFailed;
Jason M. Billscd225da2019-05-08 15:31:57 -07001380 }
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001381 std::string& messageID = *logEntryIter;
Jason M. Bills4851d452019-03-28 11:27:48 -07001382 // Get the Message from the MessageRegistry
Ed Tanousfffb8c12022-02-07 23:53:03 -08001383 const registries::Message* message = registries::getMessage(messageID);
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001384
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001385 logEntryIter++;
Sui Chen54417b02022-03-24 14:59:52 -07001386 if (message == nullptr)
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001387 {
Ed Tanous62598e32023-07-17 17:06:25 -07001388 BMCWEB_LOG_WARNING("Log entry not found in registry: {}", logEntry);
Jason M. Billsac992cd2022-06-24 13:31:46 -07001389 return LogParseError::messageIdNotInRegistry;
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001390 }
1391
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001392 std::vector<std::string_view> messageArgs(logEntryIter,
1393 logEntryFields.end());
Ed Tanousc05bba42023-06-28 08:33:29 -07001394 messageArgs.resize(message->numberOfArgs);
1395
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001396 std::string msg =
1397 redfish::registries::fillMessageArgs(messageArgs, message->message);
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001398 if (msg.empty())
Jason M. Bills4851d452019-03-28 11:27:48 -07001399 {
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001400 return LogParseError::parseFailed;
Jason M. Bills4851d452019-03-28 11:27:48 -07001401 }
1402
Jason M. Bills95820182019-04-22 16:25:34 -07001403 // Get the Created time from the timestamp. The log timestamp is in RFC3339
1404 // format which matches the Redfish format except for the fractional seconds
1405 // between the '.' and the '+', so just remove them.
Ed Tanousf23b7292020-10-15 09:41:17 -07001406 std::size_t dot = timestamp.find_first_of('.');
1407 std::size_t plus = timestamp.find_first_of('+');
Jason M. Bills95820182019-04-22 16:25:34 -07001408 if (dot != std::string::npos && plus != std::string::npos)
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001409 {
Jason M. Bills95820182019-04-22 16:25:34 -07001410 timestamp.erase(dot, plus - dot);
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001411 }
1412
1413 // Fill in the log entry with the gathered data
Vijay Lobo9c11a172021-10-07 16:53:16 -05001414 logEntryJson["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
Ed Tanousef4c65b2023-04-24 15:28:50 -07001415 logEntryJson["@odata.id"] = boost::urls::format(
Ed Tanous253f11b2024-05-16 09:38:31 -07001416 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}",
1417 BMCWEB_REDFISH_SYSTEM_URI_NAME, logEntryID);
Jason M. Bills84afc482022-06-24 12:38:23 -07001418 logEntryJson["Name"] = "System Event Log Entry";
1419 logEntryJson["Id"] = logEntryID;
1420 logEntryJson["Message"] = std::move(msg);
1421 logEntryJson["MessageId"] = std::move(messageID);
1422 logEntryJson["MessageArgs"] = messageArgs;
1423 logEntryJson["EntryType"] = "Event";
1424 logEntryJson["Severity"] = message->messageSeverity;
1425 logEntryJson["Created"] = std::move(timestamp);
Jason M. Billsac992cd2022-06-24 13:31:46 -07001426 return LogParseError::success;
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001427}
1428
Igor Kanyuka90896602025-03-13 08:52:38 +00001429inline bool fillEventLogLogEntryFromPropertyMap(
Ed Tanous898f2aa2024-08-07 12:18:22 -07001430 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1431 const dbus::utility::DBusPropertiesMap& resp,
1432 nlohmann::json& objectToFillOut)
1433{
Alexander Hansen262dcc12024-09-19 12:04:03 +02001434 std::optional<DbusEventLogEntry> optEntry =
1435 fillDbusEventLogEntryFromPropertyMap(resp);
Ed Tanous898f2aa2024-08-07 12:18:22 -07001436
Alexander Hansen262dcc12024-09-19 12:04:03 +02001437 if (!optEntry.has_value())
Ed Tanous898f2aa2024-08-07 12:18:22 -07001438 {
1439 messages::internalError(asyncResp->res);
Igor Kanyuka90896602025-03-13 08:52:38 +00001440 return false;
Ed Tanous898f2aa2024-08-07 12:18:22 -07001441 }
Alexander Hansen262dcc12024-09-19 12:04:03 +02001442 DbusEventLogEntry entry = optEntry.value();
Ed Tanous898f2aa2024-08-07 12:18:22 -07001443
1444 objectToFillOut["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
1445 objectToFillOut["@odata.id"] = boost::urls::format(
1446 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}",
Alexander Hansen262dcc12024-09-19 12:04:03 +02001447 BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(entry.Id));
Ed Tanous898f2aa2024-08-07 12:18:22 -07001448 objectToFillOut["Name"] = "System Event Log Entry";
Alexander Hansen262dcc12024-09-19 12:04:03 +02001449 objectToFillOut["Id"] = std::to_string(entry.Id);
1450 objectToFillOut["Message"] = entry.Message;
1451 objectToFillOut["Resolved"] = entry.Resolved;
1452 std::optional<bool> notifyAction =
1453 getProviderNotifyAction(entry.ServiceProviderNotify);
Ed Tanous898f2aa2024-08-07 12:18:22 -07001454 if (notifyAction)
1455 {
1456 objectToFillOut["ServiceProviderNotified"] = *notifyAction;
1457 }
Alexander Hansen262dcc12024-09-19 12:04:03 +02001458 if ((entry.Resolution != nullptr) && !entry.Resolution->empty())
Ed Tanous898f2aa2024-08-07 12:18:22 -07001459 {
Alexander Hansen262dcc12024-09-19 12:04:03 +02001460 objectToFillOut["Resolution"] = *entry.Resolution;
Ed Tanous898f2aa2024-08-07 12:18:22 -07001461 }
1462 objectToFillOut["EntryType"] = "Event";
Alexander Hansen262dcc12024-09-19 12:04:03 +02001463 objectToFillOut["Severity"] =
1464 translateSeverityDbusToRedfish(entry.Severity);
Ed Tanous898f2aa2024-08-07 12:18:22 -07001465 objectToFillOut["Created"] =
Alexander Hansen262dcc12024-09-19 12:04:03 +02001466 redfish::time_utils::getDateTimeUintMs(entry.Timestamp);
Ed Tanous898f2aa2024-08-07 12:18:22 -07001467 objectToFillOut["Modified"] =
Alexander Hansen262dcc12024-09-19 12:04:03 +02001468 redfish::time_utils::getDateTimeUintMs(entry.UpdateTimestamp);
1469 if (entry.Path != nullptr)
Ed Tanous898f2aa2024-08-07 12:18:22 -07001470 {
1471 objectToFillOut["AdditionalDataURI"] = boost::urls::format(
1472 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}/attachment",
Alexander Hansen262dcc12024-09-19 12:04:03 +02001473 BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(entry.Id));
Ed Tanous898f2aa2024-08-07 12:18:22 -07001474 }
Igor Kanyuka90896602025-03-13 08:52:38 +00001475 return true;
Ed Tanous898f2aa2024-08-07 12:18:22 -07001476}
1477
Ed Tanousb7290962024-08-07 11:09:51 -07001478inline void afterLogEntriesGetManagedObjects(
1479 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1480 const boost::system::error_code& ec,
1481 const dbus::utility::ManagedObjectType& resp)
1482{
1483 if (ec)
1484 {
1485 // TODO Handle for specific error code
1486 BMCWEB_LOG_ERROR("getLogEntriesIfaceData resp_handler got error {}",
1487 ec);
1488 messages::internalError(asyncResp->res);
1489 return;
1490 }
1491 nlohmann::json::array_t entriesArray;
1492 for (const auto& objectPath : resp)
1493 {
Ed Tanous898f2aa2024-08-07 12:18:22 -07001494 dbus::utility::DBusPropertiesMap propsFlattened;
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001495 auto isEntry =
1496 std::ranges::find_if(objectPath.second, [](const auto& object) {
1497 return object.first == "xyz.openbmc_project.Logging.Entry";
1498 });
Ed Tanous898f2aa2024-08-07 12:18:22 -07001499 if (isEntry == objectPath.second.end())
Ed Tanousb7290962024-08-07 11:09:51 -07001500 {
1501 continue;
1502 }
Ed Tanous898f2aa2024-08-07 12:18:22 -07001503 for (const auto& interfaceMap : objectPath.second)
Ed Tanousb7290962024-08-07 11:09:51 -07001504 {
Ed Tanous898f2aa2024-08-07 12:18:22 -07001505 for (const auto& propertyMap : interfaceMap.second)
Ed Tanousb7290962024-08-07 11:09:51 -07001506 {
Ed Tanous898f2aa2024-08-07 12:18:22 -07001507 propsFlattened.emplace_back(propertyMap.first,
1508 propertyMap.second);
Ed Tanousb7290962024-08-07 11:09:51 -07001509 }
1510 }
Igor Kanyuka90896602025-03-13 08:52:38 +00001511 bool success = fillEventLogLogEntryFromPropertyMap(
1512 asyncResp, propsFlattened, entriesArray.emplace_back());
1513 if (!success)
1514 {
1515 return;
1516 }
Ed Tanousb7290962024-08-07 11:09:51 -07001517 }
Ed Tanous898f2aa2024-08-07 12:18:22 -07001518
Igor Kanyuka90896602025-03-13 08:52:38 +00001519 redfish::json_util::sortJsonArrayByKey(entriesArray, "Id");
Ed Tanousb7290962024-08-07 11:09:51 -07001520 asyncResp->res.jsonValue["Members@odata.count"] = entriesArray.size();
1521 asyncResp->res.jsonValue["Members"] = std::move(entriesArray);
1522}
1523
Alexander Hansen599b9af2024-08-06 15:11:57 +02001524inline void handleSystemsLogServiceEventLogLogEntryCollection(
1525 App& app, const crow::Request& req,
1526 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1527 const std::string& systemName)
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001528{
Alexander Hansen599b9af2024-08-06 15:11:57 +02001529 query_param::QueryCapabilities capabilities = {
1530 .canDelegateTop = true,
1531 .canDelegateSkip = true,
1532 };
1533 query_param::Query delegatedQuery;
1534 if (!redfish::setUpRedfishRouteWithDelegation(app, req, asyncResp,
1535 delegatedQuery, capabilities))
1536 {
1537 return;
1538 }
1539 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1540 {
1541 // Option currently returns no systems. TBD
1542 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1543 systemName);
1544 return;
1545 }
1546 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1547 {
1548 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1549 systemName);
1550 return;
1551 }
1552
1553 size_t top = delegatedQuery.top.value_or(query_param::Query::maxTop);
1554 size_t skip = delegatedQuery.skip.value_or(0);
1555
1556 // Collections don't include the static data added by SubRoute
1557 // because it has a duplicate entry for members
1558 asyncResp->res.jsonValue["@odata.type"] =
1559 "#LogEntryCollection.LogEntryCollection";
1560 asyncResp->res.jsonValue["@odata.id"] =
1561 std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
1562 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1563 asyncResp->res.jsonValue["Name"] = "System Event Log Entries";
1564 asyncResp->res.jsonValue["Description"] =
1565 "Collection of System Event Log Entries";
1566
1567 nlohmann::json& logEntryArray = asyncResp->res.jsonValue["Members"];
1568 logEntryArray = nlohmann::json::array();
1569 // Go through the log files and create a unique ID for each
1570 // entry
1571 std::vector<std::filesystem::path> redfishLogFiles;
1572 getRedfishLogFiles(redfishLogFiles);
1573 uint64_t entryCount = 0;
1574 std::string logEntry;
1575
1576 // Oldest logs are in the last file, so start there and loop
1577 // backwards
1578 for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend(); it++)
1579 {
1580 std::ifstream logStream(*it);
1581 if (!logStream.is_open())
Ed Tanous002d39b2022-05-31 08:59:27 -07001582 {
Alexander Hansen599b9af2024-08-06 15:11:57 +02001583 continue;
Ed Tanous22d268c2022-05-19 09:39:07 -07001584 }
1585
Alexander Hansen599b9af2024-08-06 15:11:57 +02001586 // Reset the unique ID on the first entry
1587 bool firstEntry = true;
1588 while (std::getline(logStream, logEntry))
Ed Tanous002d39b2022-05-31 08:59:27 -07001589 {
Alexander Hansen599b9af2024-08-06 15:11:57 +02001590 std::string idStr;
1591 if (!getUniqueEntryID(logEntry, idStr, firstEntry))
1592 {
1593 continue;
1594 }
1595 firstEntry = false;
1596
1597 nlohmann::json::object_t bmcLogEntry;
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001598 LogParseError status =
1599 fillEventLogEntryJson(idStr, logEntry, bmcLogEntry);
Alexander Hansen599b9af2024-08-06 15:11:57 +02001600 if (status == LogParseError::messageIdNotInRegistry)
1601 {
1602 continue;
1603 }
1604 if (status != LogParseError::success)
1605 {
1606 messages::internalError(asyncResp->res);
1607 return;
1608 }
1609
1610 entryCount++;
1611 // Handle paging using skip (number of entries to skip from the
1612 // start) and top (number of entries to display)
1613 if (entryCount <= skip || entryCount > skip + top)
Jason M. Bills4978b632022-02-22 14:17:43 -08001614 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001615 continue;
Jason M. Bills4978b632022-02-22 14:17:43 -08001616 }
Jason M. Bills897967d2019-07-29 17:05:30 -07001617
Alexander Hansen599b9af2024-08-06 15:11:57 +02001618 logEntryArray.emplace_back(std::move(bmcLogEntry));
1619 }
1620 }
1621 asyncResp->res.jsonValue["Members@odata.count"] = entryCount;
1622 if (skip + top < entryCount)
1623 {
1624 asyncResp->res.jsonValue["Members@odata.nextLink"] =
1625 boost::urls::format(
1626 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries?$skip={}",
1627 BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(skip + top));
1628 }
1629}
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001630
Alexander Hansen599b9af2024-08-06 15:11:57 +02001631inline void requestRoutesJournalEventLogEntryCollection(App& app)
1632{
1633 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/")
1634 .privileges(redfish::privileges::getLogEntryCollection)
1635 .methods(boost::beast::http::verb::get)(std::bind_front(
1636 handleSystemsLogServiceEventLogLogEntryCollection, std::ref(app)));
1637}
1638
1639inline void handleSystemsLogServiceEventLogEntriesGet(
1640 App& app, const crow::Request& req,
1641 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1642 const std::string& systemName, const std::string& param)
1643{
1644 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1645 {
1646 return;
1647 }
1648 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1649 {
1650 // Option currently returns no systems. TBD
1651 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1652 systemName);
1653 return;
1654 }
1655
1656 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1657 {
1658 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1659 systemName);
1660 return;
1661 }
1662
1663 const std::string& targetID = param;
1664
1665 // Go through the log files and check the unique ID for each
1666 // entry to find the target entry
1667 std::vector<std::filesystem::path> redfishLogFiles;
1668 getRedfishLogFiles(redfishLogFiles);
1669 std::string logEntry;
1670
1671 // Oldest logs are in the last file, so start there and loop
1672 // backwards
1673 for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend(); it++)
1674 {
1675 std::ifstream logStream(*it);
1676 if (!logStream.is_open())
1677 {
1678 continue;
1679 }
1680
1681 // Reset the unique ID on the first entry
1682 bool firstEntry = true;
1683 while (std::getline(logStream, logEntry))
1684 {
1685 std::string idStr;
1686 if (!getUniqueEntryID(logEntry, idStr, firstEntry))
1687 {
1688 continue;
1689 }
1690 firstEntry = false;
1691
1692 if (idStr == targetID)
1693 {
Jason M. Billsde703c52022-06-23 14:19:04 -07001694 nlohmann::json::object_t bmcLogEntry;
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001695 LogParseError status =
1696 fillEventLogEntryJson(idStr, logEntry, bmcLogEntry);
Jason M. Billsac992cd2022-06-24 13:31:46 -07001697 if (status != LogParseError::success)
Ed Tanous002d39b2022-05-31 08:59:27 -07001698 {
1699 messages::internalError(asyncResp->res);
1700 return;
Andrew Geisslercb92c032018-08-17 07:56:14 -07001701 }
Alexander Hansen599b9af2024-08-06 15:11:57 +02001702 asyncResp->res.jsonValue.update(bmcLogEntry);
1703 return;
Jason M. Bills4978b632022-02-22 14:17:43 -08001704 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001705 }
Alexander Hansen599b9af2024-08-06 15:11:57 +02001706 }
1707 // Requested ID was not found
1708 messages::resourceNotFound(asyncResp->res, "LogEntry", targetID);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001709}
Chicago Duan336e96c2019-07-15 14:22:08 +08001710
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001711inline void requestRoutesJournalEventLogEntry(App& app)
1712{
1713 BMCWEB_ROUTE(
Ed Tanous22d268c2022-05-19 09:39:07 -07001714 app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001715 .privileges(redfish::privileges::getLogEntry)
Alexander Hansen599b9af2024-08-06 15:11:57 +02001716 .methods(boost::beast::http::verb::get)(std::bind_front(
1717 handleSystemsLogServiceEventLogEntriesGet, std::ref(app)));
1718}
1719
1720inline void dBusEventLogEntryCollection(
1721 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1722{
1723 // Collections don't include the static data added by SubRoute
1724 // because it has a duplicate entry for members
1725 asyncResp->res.jsonValue["@odata.type"] =
1726 "#LogEntryCollection.LogEntryCollection";
1727 asyncResp->res.jsonValue["@odata.id"] =
1728 std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
1729 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1730 asyncResp->res.jsonValue["Name"] = "System Event Log Entries";
1731 asyncResp->res.jsonValue["Description"] =
1732 "Collection of System Event Log Entries";
1733
1734 // DBus implementation of EventLog/Entries
1735 // Make call to Logging Service to find all log entry objects
1736 sdbusplus::message::object_path path("/xyz/openbmc_project/logging");
1737 dbus::utility::getManagedObjects(
1738 "xyz.openbmc_project.Logging", path,
1739 [asyncResp](const boost::system::error_code& ec,
1740 const dbus::utility::ManagedObjectType& resp) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001741 afterLogEntriesGetManagedObjects(asyncResp, ec, resp);
1742 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001743}
1744
1745inline void requestRoutesDBusEventLogEntryCollection(App& app)
1746{
Ed Tanous22d268c2022-05-19 09:39:07 -07001747 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/")
Ed Tanoused398212021-06-09 17:05:54 -07001748 .privileges(redfish::privileges::getLogEntryCollection)
Ed Tanous002d39b2022-05-31 08:59:27 -07001749 .methods(boost::beast::http::verb::get)(
1750 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07001751 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1752 const std::string& systemName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001753 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1754 {
1755 return;
1756 }
1757 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1758 {
1759 // Option currently returns no systems. TBD
1760 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1761 systemName);
1762 return;
1763 }
1764 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1765 {
1766 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1767 systemName);
1768 return;
1769 }
1770 dBusEventLogEntryCollection(asyncResp);
1771 });
Alexander Hansen599b9af2024-08-06 15:11:57 +02001772}
Ed Tanous22d268c2022-05-19 09:39:07 -07001773
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001774inline void dBusEventLogEntryGet(
1775 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID)
Alexander Hansen599b9af2024-08-06 15:11:57 +02001776{
1777 dbus::utility::escapePathForDbus(entryID);
Ed Tanous002d39b2022-05-31 08:59:27 -07001778
Alexander Hansen599b9af2024-08-06 15:11:57 +02001779 // DBus implementation of EventLog/Entries
1780 // Make call to Logging Service to find all log entry objects
Ed Tanousdeae6a72024-11-11 21:58:57 -08001781 dbus::utility::getAllProperties(
1782 "xyz.openbmc_project.Logging",
Alexander Hansen599b9af2024-08-06 15:11:57 +02001783 "/xyz/openbmc_project/logging/entry/" + entryID, "",
1784 [asyncResp, entryID](const boost::system::error_code& ec,
1785 const dbus::utility::DBusPropertiesMap& resp) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001786 if (ec.value() == EBADR)
1787 {
1788 messages::resourceNotFound(asyncResp->res, "EventLogEntry",
1789 entryID);
1790 return;
1791 }
1792 if (ec)
1793 {
1794 BMCWEB_LOG_ERROR(
1795 "EventLogEntry (DBus) resp_handler got error {}", ec);
1796 messages::internalError(asyncResp->res);
1797 return;
1798 }
Alexander Hansen599b9af2024-08-06 15:11:57 +02001799
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001800 fillEventLogLogEntryFromPropertyMap(asyncResp, resp,
1801 asyncResp->res.jsonValue);
1802 });
Alexander Hansen599b9af2024-08-06 15:11:57 +02001803}
1804
Patrick Williams504af5a2025-02-03 14:29:03 -05001805inline void dBusEventLogEntryPatch(
1806 const crow::Request& req,
1807 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1808 const std::string& entryId)
Alexander Hansen599b9af2024-08-06 15:11:57 +02001809{
1810 std::optional<bool> resolved;
1811
1812 if (!json_util::readJsonPatch(req, asyncResp->res, "Resolved", resolved))
1813 {
1814 return;
1815 }
1816 BMCWEB_LOG_DEBUG("Set Resolved");
1817
1818 setDbusProperty(asyncResp, "Resolved", "xyz.openbmc_project.Logging",
1819 "/xyz/openbmc_project/logging/entry/" + entryId,
1820 "xyz.openbmc_project.Logging.Entry", "Resolved",
1821 resolved.value_or(false));
1822}
1823
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001824inline void dBusEventLogEntryDelete(
1825 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID)
Alexander Hansen599b9af2024-08-06 15:11:57 +02001826{
1827 BMCWEB_LOG_DEBUG("Do delete single event entries.");
1828
1829 dbus::utility::escapePathForDbus(entryID);
1830
1831 // Process response from Logging service.
1832 auto respHandler = [asyncResp,
1833 entryID](const boost::system::error_code& ec) {
1834 BMCWEB_LOG_DEBUG("EventLogEntry (DBus) doDelete callback: Done");
1835 if (ec)
1836 {
1837 if (ec.value() == EBADR)
Ed Tanous45ca1b82022-03-25 13:07:27 -07001838 {
Alexander Hansen599b9af2024-08-06 15:11:57 +02001839 messages::resourceNotFound(asyncResp->res, "LogEntry", entryID);
Ed Tanous45ca1b82022-03-25 13:07:27 -07001840 return;
1841 }
Alexander Hansen599b9af2024-08-06 15:11:57 +02001842 // TODO Handle for specific error code
1843 BMCWEB_LOG_ERROR(
1844 "EventLogEntry (DBus) doDelete respHandler got error {}", ec);
1845 asyncResp->res.result(
1846 boost::beast::http::status::internal_server_error);
1847 return;
1848 }
Abhishek Patel9017faf2021-09-14 22:48:55 -05001849
Alexander Hansen599b9af2024-08-06 15:11:57 +02001850 asyncResp->res.result(boost::beast::http::status::ok);
1851 };
1852
1853 // Make call to Logging service to request Delete Log
1854 crow::connections::systemBus->async_method_call(
1855 respHandler, "xyz.openbmc_project.Logging",
1856 "/xyz/openbmc_project/logging/entry/" + entryID,
1857 "xyz.openbmc_project.Object.Delete", "Delete");
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001858}
Xiaochao Ma75710de2021-01-21 17:56:02 +08001859
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001860inline void requestRoutesDBusEventLogEntry(App& app)
Adriana Kobylak400fd1f2021-01-29 09:01:30 -06001861{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001862 BMCWEB_ROUTE(
Ed Tanous22d268c2022-05-19 09:39:07 -07001863 app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001864 .privileges(redfish::privileges::getLogEntry)
Ed Tanous002d39b2022-05-31 08:59:27 -07001865 .methods(boost::beast::http::verb::get)(
1866 [&app](const crow::Request& req,
1867 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous898f2aa2024-08-07 12:18:22 -07001868 const std::string& systemName, const std::string& entryId) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001869 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1870 {
1871 return;
1872 }
1873 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1874 {
1875 // Option currently returns no systems. TBD
1876 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1877 systemName);
1878 return;
1879 }
1880 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1881 {
1882 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1883 systemName);
1884 return;
1885 }
Ed Tanous22d268c2022-05-19 09:39:07 -07001886
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001887 dBusEventLogEntryGet(asyncResp, entryId);
1888 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001889
1890 BMCWEB_ROUTE(
Ed Tanous22d268c2022-05-19 09:39:07 -07001891 app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001892 .privileges(redfish::privileges::patchLogEntry)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001893 .methods(boost::beast::http::verb::patch)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07001894 [&app](const crow::Request& req,
1895 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -07001896 const std::string& systemName, const std::string& entryId) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001897 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1898 {
1899 return;
1900 }
1901 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1902 {
1903 // Option currently returns no systems. TBD
1904 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1905 systemName);
1906 return;
1907 }
1908 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1909 {
1910 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1911 systemName);
1912 return;
1913 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001914
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001915 dBusEventLogEntryPatch(req, asyncResp, entryId);
1916 });
Adriana Kobylak400fd1f2021-01-29 09:01:30 -06001917
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001918 BMCWEB_ROUTE(
Ed Tanous22d268c2022-05-19 09:39:07 -07001919 app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001920 .privileges(redfish::privileges::deleteLogEntry)
1921
Ed Tanous002d39b2022-05-31 08:59:27 -07001922 .methods(boost::beast::http::verb::delete_)(
1923 [&app](const crow::Request& req,
1924 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -07001925 const std::string& systemName, const std::string& param) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001926 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1927 {
1928 return;
1929 }
1930 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1931 {
1932 // Option currently returns no systems. TBD
1933 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1934 systemName);
1935 return;
1936 }
1937 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1938 {
1939 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1940 systemName);
1941 return;
1942 }
1943 dBusEventLogEntryDelete(asyncResp, param);
1944 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001945}
1946
Claire Weinandd72e872022-08-15 14:20:06 -07001947inline void handleBMCLogServicesCollectionGet(
Claire Weinanfdd26902022-03-01 14:18:25 -08001948 crow::App& app, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07001949 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1950 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08001951{
1952 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1953 {
1954 return;
1955 }
Ed Tanous253f11b2024-05-16 09:38:31 -07001956
1957 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
1958 {
1959 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
1960 return;
1961 }
1962
Claire Weinanfdd26902022-03-01 14:18:25 -08001963 // Collections don't include the static data added by SubRoute
1964 // because it has a duplicate entry for members
1965 asyncResp->res.jsonValue["@odata.type"] =
1966 "#LogServiceCollection.LogServiceCollection";
Ed Tanous253f11b2024-05-16 09:38:31 -07001967 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
1968 "/redfish/v1/Managers/{}/LogServices", BMCWEB_REDFISH_MANAGER_URI_NAME);
Claire Weinanfdd26902022-03-01 14:18:25 -08001969 asyncResp->res.jsonValue["Name"] = "Open BMC Log Services Collection";
1970 asyncResp->res.jsonValue["Description"] =
1971 "Collection of LogServices for this Manager";
1972 nlohmann::json& logServiceArray = asyncResp->res.jsonValue["Members"];
1973 logServiceArray = nlohmann::json::array();
1974
Ed Tanous25b54db2024-04-17 15:40:31 -07001975 if constexpr (BMCWEB_REDFISH_BMC_JOURNAL)
1976 {
1977 nlohmann::json::object_t journal;
Ed Tanous253f11b2024-05-16 09:38:31 -07001978 journal["@odata.id"] =
1979 boost::urls::format("/redfish/v1/Managers/{}/LogServices/Journal",
1980 BMCWEB_REDFISH_MANAGER_URI_NAME);
Ed Tanous25b54db2024-04-17 15:40:31 -07001981 logServiceArray.emplace_back(std::move(journal));
1982 }
Claire Weinanfdd26902022-03-01 14:18:25 -08001983
1984 asyncResp->res.jsonValue["Members@odata.count"] = logServiceArray.size();
1985
Ed Tanous25b54db2024-04-17 15:40:31 -07001986 if constexpr (BMCWEB_REDFISH_DUMP_LOG)
1987 {
1988 constexpr std::array<std::string_view, 1> interfaces = {
1989 "xyz.openbmc_project.Collection.DeleteAll"};
1990 dbus::utility::getSubTreePaths(
1991 "/xyz/openbmc_project/dump", 0, interfaces,
1992 [asyncResp](const boost::system::error_code& ec,
1993 const dbus::utility::MapperGetSubTreePathsResponse&
1994 subTreePaths) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001995 if (ec)
Ed Tanous25b54db2024-04-17 15:40:31 -07001996 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001997 BMCWEB_LOG_ERROR(
1998 "handleBMCLogServicesCollectionGet respHandler got error {}",
1999 ec);
2000 // Assume that getting an error simply means there are no
2001 // dump LogServices. Return without adding any error
2002 // response.
2003 return;
Ed Tanous25b54db2024-04-17 15:40:31 -07002004 }
Ed Tanous25b54db2024-04-17 15:40:31 -07002005
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002006 nlohmann::json& logServiceArrayLocal =
2007 asyncResp->res.jsonValue["Members"];
2008
2009 for (const std::string& path : subTreePaths)
2010 {
2011 if (path == "/xyz/openbmc_project/dump/bmc")
2012 {
2013 nlohmann::json::object_t member;
2014 member["@odata.id"] = boost::urls::format(
2015 "/redfish/v1/Managers/{}/LogServices/Dump",
2016 BMCWEB_REDFISH_MANAGER_URI_NAME);
2017 logServiceArrayLocal.emplace_back(std::move(member));
2018 }
2019 else if (path == "/xyz/openbmc_project/dump/faultlog")
2020 {
2021 nlohmann::json::object_t member;
2022 member["@odata.id"] = boost::urls::format(
2023 "/redfish/v1/Managers/{}/LogServices/FaultLog",
2024 BMCWEB_REDFISH_MANAGER_URI_NAME);
2025 logServiceArrayLocal.emplace_back(std::move(member));
2026 }
2027 }
2028
2029 asyncResp->res.jsonValue["Members@odata.count"] =
2030 logServiceArrayLocal.size();
2031 });
Ed Tanous25b54db2024-04-17 15:40:31 -07002032 }
Claire Weinanfdd26902022-03-01 14:18:25 -08002033}
2034
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002035inline void requestRoutesBMCLogServiceCollection(App& app)
2036{
Ed Tanous253f11b2024-05-16 09:38:31 -07002037 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/")
Gunnar Millsad89dcf2021-07-30 14:40:11 -05002038 .privileges(redfish::privileges::getLogServiceCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002039 .methods(boost::beast::http::verb::get)(
Claire Weinandd72e872022-08-15 14:20:06 -07002040 std::bind_front(handleBMCLogServicesCollectionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002041}
Ed Tanous1da66f72018-07-27 16:13:37 -07002042
Patrick Williams504af5a2025-02-03 14:29:03 -05002043inline void getDumpServiceInfo(
2044 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2045 const std::string& dumpType)
Claire Weinanfdd26902022-03-01 14:18:25 -08002046{
2047 std::string dumpPath;
Ed Tanous539d8c62024-06-19 14:38:27 -07002048 log_service::OverWritePolicy overWritePolicy =
2049 log_service::OverWritePolicy::Invalid;
Claire Weinanfdd26902022-03-01 14:18:25 -08002050 bool collectDiagnosticDataSupported = false;
2051
2052 if (dumpType == "BMC")
2053 {
Ed Tanous253f11b2024-05-16 09:38:31 -07002054 dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/Dump",
2055 BMCWEB_REDFISH_MANAGER_URI_NAME);
Ed Tanous539d8c62024-06-19 14:38:27 -07002056 overWritePolicy = log_service::OverWritePolicy::WrapsWhenFull;
Claire Weinanfdd26902022-03-01 14:18:25 -08002057 collectDiagnosticDataSupported = true;
2058 }
2059 else if (dumpType == "FaultLog")
2060 {
Ed Tanous253f11b2024-05-16 09:38:31 -07002061 dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/FaultLog",
2062 BMCWEB_REDFISH_MANAGER_URI_NAME);
Ed Tanous539d8c62024-06-19 14:38:27 -07002063 overWritePolicy = log_service::OverWritePolicy::Unknown;
Claire Weinanfdd26902022-03-01 14:18:25 -08002064 collectDiagnosticDataSupported = false;
2065 }
2066 else if (dumpType == "System")
2067 {
Ed Tanous253f11b2024-05-16 09:38:31 -07002068 dumpPath = std::format("/redfish/v1/Systems/{}/LogServices/Dump",
2069 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanous539d8c62024-06-19 14:38:27 -07002070 overWritePolicy = log_service::OverWritePolicy::WrapsWhenFull;
Claire Weinanfdd26902022-03-01 14:18:25 -08002071 collectDiagnosticDataSupported = true;
2072 }
2073 else
2074 {
Ed Tanous62598e32023-07-17 17:06:25 -07002075 BMCWEB_LOG_ERROR("getDumpServiceInfo() invalid dump type: {}",
2076 dumpType);
Claire Weinanfdd26902022-03-01 14:18:25 -08002077 messages::internalError(asyncResp->res);
2078 return;
2079 }
2080
2081 asyncResp->res.jsonValue["@odata.id"] = dumpPath;
2082 asyncResp->res.jsonValue["@odata.type"] = "#LogService.v1_2_0.LogService";
2083 asyncResp->res.jsonValue["Name"] = "Dump LogService";
2084 asyncResp->res.jsonValue["Description"] = dumpType + " Dump LogService";
2085 asyncResp->res.jsonValue["Id"] = std::filesystem::path(dumpPath).filename();
Ed Tanous539d8c62024-06-19 14:38:27 -07002086 asyncResp->res.jsonValue["OverWritePolicy"] = overWritePolicy;
Claire Weinanfdd26902022-03-01 14:18:25 -08002087
2088 std::pair<std::string, std::string> redfishDateTimeOffset =
Ed Tanous2b829372022-08-03 14:22:34 -07002089 redfish::time_utils::getDateTimeOffsetNow();
Claire Weinanfdd26902022-03-01 14:18:25 -08002090 asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
2091 asyncResp->res.jsonValue["DateTimeLocalOffset"] =
2092 redfishDateTimeOffset.second;
2093
2094 asyncResp->res.jsonValue["Entries"]["@odata.id"] = dumpPath + "/Entries";
Claire Weinanfdd26902022-03-01 14:18:25 -08002095
2096 if (collectDiagnosticDataSupported)
2097 {
2098 asyncResp->res.jsonValue["Actions"]["#LogService.CollectDiagnosticData"]
2099 ["target"] =
2100 dumpPath + "/Actions/LogService.CollectDiagnosticData";
2101 }
Claire Weinan0d946212022-07-13 19:40:19 -07002102
2103 constexpr std::array<std::string_view, 1> interfaces = {deleteAllInterface};
2104 dbus::utility::getSubTreePaths(
2105 "/xyz/openbmc_project/dump", 0, interfaces,
2106 [asyncResp, dumpType, dumpPath](
2107 const boost::system::error_code& ec,
2108 const dbus::utility::MapperGetSubTreePathsResponse& subTreePaths) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002109 if (ec)
Claire Weinan0d946212022-07-13 19:40:19 -07002110 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002111 BMCWEB_LOG_ERROR("getDumpServiceInfo respHandler got error {}",
2112 ec);
2113 // Assume that getting an error simply means there are no dump
2114 // LogServices. Return without adding any error response.
2115 return;
Claire Weinan0d946212022-07-13 19:40:19 -07002116 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002117 std::string dbusDumpPath = getDumpPath(dumpType);
2118 for (const std::string& path : subTreePaths)
2119 {
2120 if (path == dbusDumpPath)
2121 {
2122 asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"]
2123 ["target"] =
2124 dumpPath + "/Actions/LogService.ClearLog";
2125 break;
2126 }
2127 }
2128 });
Claire Weinanfdd26902022-03-01 14:18:25 -08002129}
2130
2131inline void handleLogServicesDumpServiceGet(
2132 crow::App& app, const std::string& dumpType, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07002133 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2134 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002135{
2136 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2137 {
2138 return;
2139 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002140
2141 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2142 {
2143 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2144 return;
2145 }
2146
Claire Weinanfdd26902022-03-01 14:18:25 -08002147 getDumpServiceInfo(asyncResp, dumpType);
2148}
2149
Ed Tanous22d268c2022-05-19 09:39:07 -07002150inline void handleLogServicesDumpServiceComputerSystemGet(
2151 crow::App& app, const crow::Request& req,
2152 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2153 const std::string& chassisId)
2154{
2155 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2156 {
2157 return;
2158 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002159 if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous22d268c2022-05-19 09:39:07 -07002160 {
2161 messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
2162 return;
2163 }
2164 getDumpServiceInfo(asyncResp, "System");
2165}
2166
Claire Weinanfdd26902022-03-01 14:18:25 -08002167inline void handleLogServicesDumpEntriesCollectionGet(
2168 crow::App& app, const std::string& dumpType, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07002169 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2170 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002171{
2172 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2173 {
2174 return;
2175 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002176
2177 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2178 {
2179 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2180 return;
2181 }
Claire Weinanfdd26902022-03-01 14:18:25 -08002182 getDumpEntryCollection(asyncResp, dumpType);
2183}
2184
Ed Tanous22d268c2022-05-19 09:39:07 -07002185inline void handleLogServicesDumpEntriesCollectionComputerSystemGet(
2186 crow::App& app, const crow::Request& req,
2187 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2188 const std::string& chassisId)
2189{
2190 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2191 {
2192 return;
2193 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002194 if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous22d268c2022-05-19 09:39:07 -07002195 {
2196 messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
2197 return;
2198 }
2199 getDumpEntryCollection(asyncResp, "System");
2200}
2201
Claire Weinanfdd26902022-03-01 14:18:25 -08002202inline void handleLogServicesDumpEntryGet(
2203 crow::App& app, const std::string& dumpType, const crow::Request& req,
2204 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous253f11b2024-05-16 09:38:31 -07002205 const std::string& managerId, const std::string& dumpId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002206{
2207 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2208 {
2209 return;
2210 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002211 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2212 {
2213 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2214 return;
2215 }
Claire Weinanfdd26902022-03-01 14:18:25 -08002216 getDumpEntryById(asyncResp, dumpId, dumpType);
2217}
Carson Labrado168d1b12023-03-27 17:04:46 +00002218
Ed Tanous22d268c2022-05-19 09:39:07 -07002219inline void handleLogServicesDumpEntryComputerSystemGet(
2220 crow::App& app, const crow::Request& req,
2221 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2222 const std::string& chassisId, const std::string& dumpId)
2223{
2224 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2225 {
2226 return;
2227 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002228 if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous22d268c2022-05-19 09:39:07 -07002229 {
2230 messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
2231 return;
2232 }
2233 getDumpEntryById(asyncResp, dumpId, "System");
2234}
Claire Weinanfdd26902022-03-01 14:18:25 -08002235
2236inline void handleLogServicesDumpEntryDelete(
2237 crow::App& app, const std::string& dumpType, const crow::Request& req,
2238 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous253f11b2024-05-16 09:38:31 -07002239 const std::string& managerId, const std::string& dumpId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002240{
2241 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2242 {
2243 return;
2244 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002245
2246 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2247 {
2248 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2249 return;
2250 }
Claire Weinanfdd26902022-03-01 14:18:25 -08002251 deleteDumpEntry(asyncResp, dumpId, dumpType);
2252}
2253
Ed Tanous22d268c2022-05-19 09:39:07 -07002254inline void handleLogServicesDumpEntryComputerSystemDelete(
2255 crow::App& app, const crow::Request& req,
2256 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2257 const std::string& chassisId, const std::string& dumpId)
2258{
2259 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2260 {
2261 return;
2262 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002263 if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous22d268c2022-05-19 09:39:07 -07002264 {
2265 messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
2266 return;
2267 }
2268 deleteDumpEntry(asyncResp, dumpId, "System");
2269}
2270
Carson Labrado168d1b12023-03-27 17:04:46 +00002271inline void handleLogServicesDumpEntryDownloadGet(
2272 crow::App& app, const std::string& dumpType, const crow::Request& req,
2273 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous253f11b2024-05-16 09:38:31 -07002274 const std::string& managerId, const std::string& dumpId)
Carson Labrado168d1b12023-03-27 17:04:46 +00002275{
2276 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2277 {
2278 return;
2279 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002280
2281 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2282 {
2283 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2284 return;
2285 }
Carson Labrado168d1b12023-03-27 17:04:46 +00002286 downloadDumpEntry(asyncResp, dumpId, dumpType);
2287}
2288
2289inline void handleDBusEventLogEntryDownloadGet(
2290 crow::App& app, const std::string& dumpType, const crow::Request& req,
2291 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2292 const std::string& systemName, const std::string& entryID)
2293{
2294 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2295 {
2296 return;
2297 }
2298 if (!http_helpers::isContentTypeAllowed(
2299 req.getHeaderValue("Accept"),
2300 http_helpers::ContentType::OctetStream, true))
2301 {
2302 asyncResp->res.result(boost::beast::http::status::bad_request);
2303 return;
2304 }
2305 downloadEventLogEntry(asyncResp, systemName, entryID, dumpType);
2306}
2307
Claire Weinanfdd26902022-03-01 14:18:25 -08002308inline void handleLogServicesDumpCollectDiagnosticDataPost(
2309 crow::App& app, const std::string& dumpType, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07002310 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2311 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002312{
2313 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2314 {
2315 return;
2316 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002317 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2318 {
2319 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2320 return;
2321 }
2322
Claire Weinanfdd26902022-03-01 14:18:25 -08002323 createDump(asyncResp, req, dumpType);
2324}
2325
Ed Tanous22d268c2022-05-19 09:39:07 -07002326inline void handleLogServicesDumpCollectDiagnosticDataComputerSystemPost(
2327 crow::App& app, const crow::Request& req,
2328 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002329 const std::string& systemName)
Ed Tanous22d268c2022-05-19 09:39:07 -07002330{
2331 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2332 {
2333 return;
2334 }
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002335
Ed Tanous25b54db2024-04-17 15:40:31 -07002336 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous22d268c2022-05-19 09:39:07 -07002337 {
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002338 // Option currently returns no systems. TBD
2339 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2340 systemName);
2341 return;
2342 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002343 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002344 {
2345 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2346 systemName);
Ed Tanous22d268c2022-05-19 09:39:07 -07002347 return;
2348 }
2349 createDump(asyncResp, req, "System");
2350}
2351
Claire Weinanfdd26902022-03-01 14:18:25 -08002352inline void handleLogServicesDumpClearLogPost(
2353 crow::App& app, const std::string& dumpType, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07002354 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2355 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002356{
2357 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2358 {
2359 return;
2360 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002361
2362 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2363 {
2364 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2365 return;
2366 }
Claire Weinanfdd26902022-03-01 14:18:25 -08002367 clearDump(asyncResp, dumpType);
2368}
2369
Ed Tanous22d268c2022-05-19 09:39:07 -07002370inline void handleLogServicesDumpClearLogComputerSystemPost(
2371 crow::App& app, const crow::Request& req,
2372 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002373 const std::string& systemName)
Ed Tanous22d268c2022-05-19 09:39:07 -07002374{
2375 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2376 {
2377 return;
2378 }
Ed Tanous25b54db2024-04-17 15:40:31 -07002379 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous22d268c2022-05-19 09:39:07 -07002380 {
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002381 // Option currently returns no systems. TBD
2382 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2383 systemName);
2384 return;
2385 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002386 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002387 {
2388 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2389 systemName);
Ed Tanous22d268c2022-05-19 09:39:07 -07002390 return;
2391 }
2392 clearDump(asyncResp, "System");
2393}
2394
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002395inline void requestRoutesBMCDumpService(App& app)
2396{
Ed Tanous253f11b2024-05-16 09:38:31 -07002397 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/Dump/")
Ed Tanoused398212021-06-09 17:05:54 -07002398 .privileges(redfish::privileges::getLogService)
Claire Weinanfdd26902022-03-01 14:18:25 -08002399 .methods(boost::beast::http::verb::get)(std::bind_front(
2400 handleLogServicesDumpServiceGet, std::ref(app), "BMC"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002401}
2402
2403inline void requestRoutesBMCDumpEntryCollection(App& app)
2404{
Ed Tanous253f11b2024-05-16 09:38:31 -07002405 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/")
Ed Tanoused398212021-06-09 17:05:54 -07002406 .privileges(redfish::privileges::getLogEntryCollection)
Claire Weinanfdd26902022-03-01 14:18:25 -08002407 .methods(boost::beast::http::verb::get)(std::bind_front(
2408 handleLogServicesDumpEntriesCollectionGet, std::ref(app), "BMC"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002409}
2410
2411inline void requestRoutesBMCDumpEntry(App& app)
2412{
2413 BMCWEB_ROUTE(app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002414 "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002415 .privileges(redfish::privileges::getLogEntry)
Claire Weinanfdd26902022-03-01 14:18:25 -08002416 .methods(boost::beast::http::verb::get)(std::bind_front(
2417 handleLogServicesDumpEntryGet, std::ref(app), "BMC"));
2418
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002419 BMCWEB_ROUTE(app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002420 "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002421 .privileges(redfish::privileges::deleteLogEntry)
Claire Weinanfdd26902022-03-01 14:18:25 -08002422 .methods(boost::beast::http::verb::delete_)(std::bind_front(
2423 handleLogServicesDumpEntryDelete, std::ref(app), "BMC"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002424}
2425
Carson Labrado168d1b12023-03-27 17:04:46 +00002426inline void requestRoutesBMCDumpEntryDownload(App& app)
2427{
2428 BMCWEB_ROUTE(
2429 app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002430 "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/attachment/")
Carson Labrado168d1b12023-03-27 17:04:46 +00002431 .privileges(redfish::privileges::getLogEntry)
2432 .methods(boost::beast::http::verb::get)(std::bind_front(
2433 handleLogServicesDumpEntryDownloadGet, std::ref(app), "BMC"));
2434}
2435
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002436inline void requestRoutesBMCDumpCreate(App& app)
2437{
George Liu0fda0f12021-11-16 10:06:17 +08002438 BMCWEB_ROUTE(
2439 app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002440 "/redfish/v1/Managers/<str>/LogServices/Dump/Actions/LogService.CollectDiagnosticData/")
Ed Tanoused398212021-06-09 17:05:54 -07002441 .privileges(redfish::privileges::postLogService)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002442 .methods(boost::beast::http::verb::post)(
Claire Weinanfdd26902022-03-01 14:18:25 -08002443 std::bind_front(handleLogServicesDumpCollectDiagnosticDataPost,
2444 std::ref(app), "BMC"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002445}
2446
2447inline void requestRoutesBMCDumpClear(App& app)
2448{
George Liu0fda0f12021-11-16 10:06:17 +08002449 BMCWEB_ROUTE(
2450 app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002451 "/redfish/v1/Managers/<str>/LogServices/Dump/Actions/LogService.ClearLog/")
Ed Tanoused398212021-06-09 17:05:54 -07002452 .privileges(redfish::privileges::postLogService)
Claire Weinanfdd26902022-03-01 14:18:25 -08002453 .methods(boost::beast::http::verb::post)(std::bind_front(
2454 handleLogServicesDumpClearLogPost, std::ref(app), "BMC"));
2455}
2456
Carson Labrado168d1b12023-03-27 17:04:46 +00002457inline void requestRoutesDBusEventLogEntryDownload(App& app)
2458{
2459 BMCWEB_ROUTE(
2460 app,
Ravi Teja9e9d99d2023-11-08 05:33:59 -06002461 "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/attachment/")
Carson Labrado168d1b12023-03-27 17:04:46 +00002462 .privileges(redfish::privileges::getLogEntry)
2463 .methods(boost::beast::http::verb::get)(std::bind_front(
2464 handleDBusEventLogEntryDownloadGet, std::ref(app), "System"));
2465}
2466
Claire Weinanfdd26902022-03-01 14:18:25 -08002467inline void requestRoutesFaultLogDumpService(App& app)
2468{
Ed Tanous253f11b2024-05-16 09:38:31 -07002469 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/")
Claire Weinanfdd26902022-03-01 14:18:25 -08002470 .privileges(redfish::privileges::getLogService)
2471 .methods(boost::beast::http::verb::get)(std::bind_front(
2472 handleLogServicesDumpServiceGet, std::ref(app), "FaultLog"));
2473}
2474
2475inline void requestRoutesFaultLogDumpEntryCollection(App& app)
2476{
Ed Tanous253f11b2024-05-16 09:38:31 -07002477 BMCWEB_ROUTE(app,
2478 "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/")
Claire Weinanfdd26902022-03-01 14:18:25 -08002479 .privileges(redfish::privileges::getLogEntryCollection)
2480 .methods(boost::beast::http::verb::get)(
2481 std::bind_front(handleLogServicesDumpEntriesCollectionGet,
2482 std::ref(app), "FaultLog"));
2483}
2484
2485inline void requestRoutesFaultLogDumpEntry(App& app)
2486{
Ed Tanous253f11b2024-05-16 09:38:31 -07002487 BMCWEB_ROUTE(
2488 app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/<str>/")
Claire Weinanfdd26902022-03-01 14:18:25 -08002489 .privileges(redfish::privileges::getLogEntry)
2490 .methods(boost::beast::http::verb::get)(std::bind_front(
2491 handleLogServicesDumpEntryGet, std::ref(app), "FaultLog"));
2492
Ed Tanous253f11b2024-05-16 09:38:31 -07002493 BMCWEB_ROUTE(
2494 app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/<str>/")
Claire Weinanfdd26902022-03-01 14:18:25 -08002495 .privileges(redfish::privileges::deleteLogEntry)
2496 .methods(boost::beast::http::verb::delete_)(std::bind_front(
2497 handleLogServicesDumpEntryDelete, std::ref(app), "FaultLog"));
2498}
2499
2500inline void requestRoutesFaultLogDumpClear(App& app)
2501{
2502 BMCWEB_ROUTE(
2503 app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002504 "/redfish/v1/Managers/<str>/LogServices/FaultLog/Actions/LogService.ClearLog/")
Claire Weinanfdd26902022-03-01 14:18:25 -08002505 .privileges(redfish::privileges::postLogService)
2506 .methods(boost::beast::http::verb::post)(std::bind_front(
2507 handleLogServicesDumpClearLogPost, std::ref(app), "FaultLog"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002508}
2509
2510inline void requestRoutesSystemDumpService(App& app)
2511{
Ed Tanous22d268c2022-05-19 09:39:07 -07002512 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Dump/")
Ed Tanoused398212021-06-09 17:05:54 -07002513 .privileges(redfish::privileges::getLogService)
Claire Weinan6ab9ad52022-08-12 18:20:17 -07002514 .methods(boost::beast::http::verb::get)(std::bind_front(
Ed Tanous22d268c2022-05-19 09:39:07 -07002515 handleLogServicesDumpServiceComputerSystemGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002516}
2517
2518inline void requestRoutesSystemDumpEntryCollection(App& app)
2519{
Ed Tanous22d268c2022-05-19 09:39:07 -07002520 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/")
Ed Tanoused398212021-06-09 17:05:54 -07002521 .privileges(redfish::privileges::getLogEntryCollection)
Ed Tanous22d268c2022-05-19 09:39:07 -07002522 .methods(boost::beast::http::verb::get)(std::bind_front(
2523 handleLogServicesDumpEntriesCollectionComputerSystemGet,
2524 std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002525}
2526
2527inline void requestRoutesSystemDumpEntry(App& app)
2528{
2529 BMCWEB_ROUTE(app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002530 "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002531 .privileges(redfish::privileges::getLogEntry)
Claire Weinan6ab9ad52022-08-12 18:20:17 -07002532 .methods(boost::beast::http::verb::get)(std::bind_front(
Ed Tanous22d268c2022-05-19 09:39:07 -07002533 handleLogServicesDumpEntryComputerSystemGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002534
2535 BMCWEB_ROUTE(app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002536 "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002537 .privileges(redfish::privileges::deleteLogEntry)
Claire Weinan6ab9ad52022-08-12 18:20:17 -07002538 .methods(boost::beast::http::verb::delete_)(std::bind_front(
Ed Tanous22d268c2022-05-19 09:39:07 -07002539 handleLogServicesDumpEntryComputerSystemDelete, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002540}
2541
2542inline void requestRoutesSystemDumpCreate(App& app)
2543{
George Liu0fda0f12021-11-16 10:06:17 +08002544 BMCWEB_ROUTE(
2545 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002546 "/redfish/v1/Systems/<str>/LogServices/Dump/Actions/LogService.CollectDiagnosticData/")
Ed Tanoused398212021-06-09 17:05:54 -07002547 .privileges(redfish::privileges::postLogService)
Ed Tanous22d268c2022-05-19 09:39:07 -07002548 .methods(boost::beast::http::verb::post)(std::bind_front(
2549 handleLogServicesDumpCollectDiagnosticDataComputerSystemPost,
2550 std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002551}
2552
2553inline void requestRoutesSystemDumpClear(App& app)
2554{
George Liu0fda0f12021-11-16 10:06:17 +08002555 BMCWEB_ROUTE(
2556 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002557 "/redfish/v1/Systems/<str>/LogServices/Dump/Actions/LogService.ClearLog/")
Ed Tanoused398212021-06-09 17:05:54 -07002558 .privileges(redfish::privileges::postLogService)
Claire Weinan6ab9ad52022-08-12 18:20:17 -07002559 .methods(boost::beast::http::verb::post)(std::bind_front(
Ed Tanous22d268c2022-05-19 09:39:07 -07002560 handleLogServicesDumpClearLogComputerSystemPost, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002561}
2562
2563inline void requestRoutesCrashdumpService(App& app)
2564{
2565 // Note: Deviated from redfish privilege registry for GET & HEAD
2566 // method for security reasons.
2567 /**
2568 * Functions triggers appropriate requests on DBus
2569 */
Ed Tanous22d268c2022-05-19 09:39:07 -07002570 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Crashdump/")
Ed Tanoused398212021-06-09 17:05:54 -07002571 // This is incorrect, should be:
2572 //.privileges(redfish::privileges::getLogService)
Ed Tanous432a8902021-06-14 15:28:56 -07002573 .privileges({{"ConfigureManager"}})
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002574 .methods(
2575 boost::beast::http::verb::
2576 get)([&app](const crow::Request& req,
2577 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2578 const std::string& systemName) {
2579 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2580 {
2581 return;
2582 }
2583 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
2584 {
2585 // Option currently returns no systems. TBD
2586 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2587 systemName);
2588 return;
2589 }
2590 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2591 {
2592 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2593 systemName);
2594 return;
2595 }
Ed Tanous22d268c2022-05-19 09:39:07 -07002596
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002597 // Copy over the static data to include the entries added by
2598 // SubRoute
2599 asyncResp->res.jsonValue["@odata.id"] =
2600 std::format("/redfish/v1/Systems/{}/LogServices/Crashdump",
2601 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2602 asyncResp->res.jsonValue["@odata.type"] =
2603 "#LogService.v1_2_0.LogService";
2604 asyncResp->res.jsonValue["Name"] = "Open BMC Oem Crashdump Service";
2605 asyncResp->res.jsonValue["Description"] = "Oem Crashdump Service";
2606 asyncResp->res.jsonValue["Id"] = "Crashdump";
2607 asyncResp->res.jsonValue["OverWritePolicy"] =
2608 log_service::OverWritePolicy::WrapsWhenFull;
2609 asyncResp->res.jsonValue["MaxNumberOfRecords"] = 3;
Tejas Patil7c8c4052021-06-04 17:43:14 +05302610
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002611 std::pair<std::string, std::string> redfishDateTimeOffset =
2612 redfish::time_utils::getDateTimeOffsetNow();
2613 asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
2614 asyncResp->res.jsonValue["DateTimeLocalOffset"] =
2615 redfishDateTimeOffset.second;
Tejas Patil7c8c4052021-06-04 17:43:14 +05302616
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002617 asyncResp->res.jsonValue["Entries"]["@odata.id"] = std::format(
2618 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries",
2619 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2620 asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"]
2621 ["target"] = std::format(
2622 "/redfish/v1/Systems/{}/LogServices/Crashdump/Actions/LogService.ClearLog",
2623 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2624 asyncResp->res
2625 .jsonValue["Actions"]["#LogService.CollectDiagnosticData"]
2626 ["target"] = std::format(
2627 "/redfish/v1/Systems/{}/LogServices/Crashdump/Actions/LogService.CollectDiagnosticData",
2628 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2629 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002630}
2631
2632void inline requestRoutesCrashdumpClear(App& app)
2633{
George Liu0fda0f12021-11-16 10:06:17 +08002634 BMCWEB_ROUTE(
2635 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002636 "/redfish/v1/Systems/<str>/LogServices/Crashdump/Actions/LogService.ClearLog/")
Ed Tanoused398212021-06-09 17:05:54 -07002637 // This is incorrect, should be:
2638 //.privileges(redfish::privileges::postLogService)
Ed Tanous432a8902021-06-14 15:28:56 -07002639 .privileges({{"ConfigureComponents"}})
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002640 .methods(boost::beast::http::verb::post)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07002641 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07002642 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2643 const std::string& systemName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002644 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2645 {
2646 return;
2647 }
2648 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
2649 {
2650 // Option currently returns no systems. TBD
2651 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2652 systemName);
2653 return;
2654 }
2655 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2656 {
2657 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2658 systemName);
2659 return;
2660 }
2661 crow::connections::systemBus->async_method_call(
2662 [asyncResp](const boost::system::error_code& ec,
2663 const std::string&) {
2664 if (ec)
2665 {
2666 messages::internalError(asyncResp->res);
2667 return;
2668 }
2669 messages::success(asyncResp->res);
2670 },
2671 crashdumpObject, crashdumpPath, deleteAllInterface,
2672 "DeleteAll");
2673 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002674}
Jason M. Bills5b61b5e2019-10-16 10:59:02 -07002675
Patrick Williams504af5a2025-02-03 14:29:03 -05002676inline void logCrashdumpEntry(
2677 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2678 const std::string& logID, nlohmann::json& logEntryJson)
Jason M. Billse855dd22019-10-08 11:37:48 -07002679{
Johnathan Mantey043a0532020-03-10 17:15:28 -07002680 auto getStoredLogCallback =
Ed Tanousb9d36b42022-02-26 21:42:46 -08002681 [asyncResp, logID,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002682 &logEntryJson](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002683 const dbus::utility::DBusPropertiesMap& params) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002684 if (ec)
2685 {
2686 BMCWEB_LOG_DEBUG("failed to get log ec: {}", ec.message());
2687 if (ec.value() ==
2688 boost::system::linux_error::bad_request_descriptor)
2689 {
2690 messages::resourceNotFound(asyncResp->res, "LogEntry",
2691 logID);
2692 }
2693 else
2694 {
2695 messages::internalError(asyncResp->res);
2696 }
2697 return;
2698 }
2699
2700 std::string timestamp{};
2701 std::string filename{};
2702 std::string logfile{};
2703 parseCrashdumpParameters(params, filename, timestamp, logfile);
2704
2705 if (filename.empty() || timestamp.empty())
Jason M. Bills1ddcf012019-11-26 14:59:21 -08002706 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002707 messages::resourceNotFound(asyncResp->res, "LogEntry", logID);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002708 return;
2709 }
2710
2711 std::string crashdumpURI =
2712 std::format(
2713 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries/",
2714 BMCWEB_REDFISH_SYSTEM_URI_NAME) +
2715 logID + "/" + filename;
2716 nlohmann::json::object_t logEntry;
2717 logEntry["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
2718 logEntry["@odata.id"] = boost::urls::format(
2719 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries/{}",
2720 BMCWEB_REDFISH_SYSTEM_URI_NAME, logID);
2721 logEntry["Name"] = "CPU Crashdump";
2722 logEntry["Id"] = logID;
2723 logEntry["EntryType"] = log_entry::LogEntryType::Oem;
2724 logEntry["AdditionalDataURI"] = std::move(crashdumpURI);
2725 logEntry["DiagnosticDataType"] = "OEM";
2726 logEntry["OEMDiagnosticDataType"] = "PECICrashdump";
2727 logEntry["Created"] = std::move(timestamp);
2728
2729 // If logEntryJson references an array of LogEntry resources
2730 // ('Members' list), then push this as a new entry, otherwise set it
2731 // directly
2732 if (logEntryJson.is_array())
2733 {
2734 logEntryJson.push_back(logEntry);
2735 asyncResp->res.jsonValue["Members@odata.count"] =
2736 logEntryJson.size();
Jason M. Bills2b20ef62022-01-06 15:48:07 -08002737 }
2738 else
2739 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002740 logEntryJson.update(logEntry);
Jason M. Bills2b20ef62022-01-06 15:48:07 -08002741 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002742 };
Ed Tanousdeae6a72024-11-11 21:58:57 -08002743 dbus::utility::getAllProperties(
2744 crashdumpObject, crashdumpPath + std::string("/") + logID,
2745 crashdumpInterface, std::move(getStoredLogCallback));
Jason M. Billse855dd22019-10-08 11:37:48 -07002746}
2747
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002748inline void requestRoutesCrashdumpEntryCollection(App& app)
Ed Tanous1da66f72018-07-27 16:13:37 -07002749{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002750 // Note: Deviated from redfish privilege registry for GET & HEAD
2751 // method for security reasons.
Ed Tanous1da66f72018-07-27 16:13:37 -07002752 /**
2753 * Functions triggers appropriate requests on DBus
2754 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002755 BMCWEB_ROUTE(app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002756 "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/")
Ed Tanoused398212021-06-09 17:05:54 -07002757 // This is incorrect, should be.
2758 //.privileges(redfish::privileges::postLogEntryCollection)
Ed Tanous432a8902021-06-14 15:28:56 -07002759 .privileges({{"ConfigureComponents"}})
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002760 .methods(
2761 boost::beast::http::verb::
2762 get)([&app](const crow::Request& req,
2763 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2764 const std::string& systemName) {
2765 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous45ca1b82022-03-25 13:07:27 -07002766 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002767 return;
Ed Tanous45ca1b82022-03-25 13:07:27 -07002768 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002769 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous002d39b2022-05-31 08:59:27 -07002770 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002771 // Option currently returns no systems. TBD
2772 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2773 systemName);
2774 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07002775 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002776 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2777 {
2778 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2779 systemName);
2780 return;
2781 }
2782
2783 constexpr std::array<std::string_view, 1> interfaces = {
2784 crashdumpInterface};
2785 dbus::utility::getSubTreePaths(
2786 "/", 0, interfaces,
2787 [asyncResp](const boost::system::error_code& ec,
2788 const std::vector<std::string>& resp) {
2789 if (ec)
2790 {
2791 if (ec.value() !=
2792 boost::system::errc::no_such_file_or_directory)
2793 {
2794 BMCWEB_LOG_DEBUG("failed to get entries ec: {}",
2795 ec.message());
2796 messages::internalError(asyncResp->res);
2797 return;
2798 }
2799 }
2800 asyncResp->res.jsonValue["@odata.type"] =
2801 "#LogEntryCollection.LogEntryCollection";
2802 asyncResp->res.jsonValue["@odata.id"] = std::format(
2803 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries",
2804 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2805 asyncResp->res.jsonValue["Name"] =
2806 "Open BMC Crashdump Entries";
2807 asyncResp->res.jsonValue["Description"] =
2808 "Collection of Crashdump Entries";
2809 asyncResp->res.jsonValue["Members"] =
2810 nlohmann::json::array();
2811 asyncResp->res.jsonValue["Members@odata.count"] = 0;
2812
2813 for (const std::string& path : resp)
2814 {
2815 const sdbusplus::message::object_path objPath(path);
2816 // Get the log ID
2817 std::string logID = objPath.filename();
2818 if (logID.empty())
2819 {
2820 continue;
2821 }
2822 // Add the log entry to the array
2823 logCrashdumpEntry(asyncResp, logID,
2824 asyncResp->res.jsonValue["Members"]);
2825 }
2826 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002827 });
2828}
Ed Tanous1da66f72018-07-27 16:13:37 -07002829
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002830inline void requestRoutesCrashdumpEntry(App& app)
Ed Tanous1da66f72018-07-27 16:13:37 -07002831{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002832 // Note: Deviated from redfish privilege registry for GET & HEAD
2833 // method for security reasons.
Ed Tanous1da66f72018-07-27 16:13:37 -07002834
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002835 BMCWEB_ROUTE(
Ed Tanous22d268c2022-05-19 09:39:07 -07002836 app, "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002837 // this is incorrect, should be
2838 // .privileges(redfish::privileges::getLogEntry)
Ed Tanous432a8902021-06-14 15:28:56 -07002839 .privileges({{"ConfigureComponents"}})
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002840 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07002841 [&app](const crow::Request& req,
2842 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -07002843 const std::string& systemName, const std::string& param) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002844 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2845 {
2846 return;
2847 }
2848 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
2849 {
2850 // Option currently returns no systems. TBD
2851 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2852 systemName);
2853 return;
2854 }
2855 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2856 {
2857 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2858 systemName);
2859 return;
2860 }
2861 const std::string& logID = param;
2862 logCrashdumpEntry(asyncResp, logID, asyncResp->res.jsonValue);
2863 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002864}
Ed Tanous1da66f72018-07-27 16:13:37 -07002865
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002866inline void requestRoutesCrashdumpFile(App& app)
2867{
2868 // Note: Deviated from redfish privilege registry for GET & HEAD
2869 // method for security reasons.
2870 BMCWEB_ROUTE(
2871 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002872 "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/<str>/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002873 .privileges(redfish::privileges::getLogEntry)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002874 .methods(boost::beast::http::verb::get)(
Nan Zhoua4ce1142022-08-02 18:45:25 +00002875 [](const crow::Request& req,
2876 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -07002877 const std::string& systemName, const std::string& logID,
2878 const std::string& fileName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002879 // Do not call getRedfishRoute here since the crashdump file is
2880 // not a Redfish resource.
Ed Tanous22d268c2022-05-19 09:39:07 -07002881
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002882 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
2883 {
2884 // Option currently returns no systems. TBD
2885 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2886 systemName);
2887 return;
2888 }
2889 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2890 {
2891 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2892 systemName);
2893 return;
2894 }
Ed Tanous22d268c2022-05-19 09:39:07 -07002895
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002896 auto getStoredLogCallback =
2897 [asyncResp, logID, fileName,
2898 url(boost::urls::url(req.url()))](
2899 const boost::system::error_code& ec,
2900 const std::vector<std::pair<
2901 std::string, dbus::utility::DbusVariantType>>&
2902 resp) {
2903 if (ec)
2904 {
2905 BMCWEB_LOG_DEBUG("failed to get log ec: {}",
2906 ec.message());
2907 messages::internalError(asyncResp->res);
2908 return;
2909 }
Jason M. Bills8e6c0992021-03-11 16:26:53 -08002910
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002911 std::string dbusFilename{};
2912 std::string dbusTimestamp{};
2913 std::string dbusFilepath{};
Jason M. Bills8e6c0992021-03-11 16:26:53 -08002914
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002915 parseCrashdumpParameters(resp, dbusFilename,
2916 dbusTimestamp, dbusFilepath);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002917
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002918 if (dbusFilename.empty() || dbusTimestamp.empty() ||
2919 dbusFilepath.empty())
2920 {
2921 messages::resourceNotFound(asyncResp->res,
2922 "LogEntry", logID);
2923 return;
2924 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002925
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002926 // Verify the file name parameter is correct
2927 if (fileName != dbusFilename)
2928 {
2929 messages::resourceNotFound(asyncResp->res,
2930 "LogEntry", logID);
2931 return;
2932 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002933
Myung Baed51c61b2024-09-13 10:35:34 -05002934 if (asyncResp->res.openFile(dbusFilepath) !=
2935 crow::OpenCode::Success)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002936 {
2937 messages::resourceNotFound(asyncResp->res,
2938 "LogEntry", logID);
2939 return;
2940 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002941
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002942 // Configure this to be a file download when accessed
2943 // from a browser
2944 asyncResp->res.addHeader(
2945 boost::beast::http::field::content_disposition,
2946 "attachment");
2947 };
Ed Tanousdeae6a72024-11-11 21:58:57 -08002948 dbus::utility::getAllProperties(
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002949 *crow::connections::systemBus, crashdumpObject,
2950 crashdumpPath + std::string("/") + logID,
2951 crashdumpInterface, std::move(getStoredLogCallback));
2952 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002953}
2954
Jason M. Billsc5a4c822022-01-06 15:51:23 -08002955enum class OEMDiagnosticType
2956{
2957 onDemand,
2958 telemetry,
2959 invalid,
2960};
2961
Ed Tanous26ccae32023-02-16 10:28:44 -08002962inline OEMDiagnosticType getOEMDiagnosticType(std::string_view oemDiagStr)
Jason M. Billsc5a4c822022-01-06 15:51:23 -08002963{
2964 if (oemDiagStr == "OnDemand")
2965 {
2966 return OEMDiagnosticType::onDemand;
2967 }
2968 if (oemDiagStr == "Telemetry")
2969 {
2970 return OEMDiagnosticType::telemetry;
2971 }
2972
2973 return OEMDiagnosticType::invalid;
2974}
2975
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002976inline void requestRoutesCrashdumpCollect(App& app)
2977{
2978 // Note: Deviated from redfish privilege registry for GET & HEAD
2979 // method for security reasons.
George Liu0fda0f12021-11-16 10:06:17 +08002980 BMCWEB_ROUTE(
2981 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002982 "/redfish/v1/Systems/<str>/LogServices/Crashdump/Actions/LogService.CollectDiagnosticData/")
Ed Tanoused398212021-06-09 17:05:54 -07002983 // The below is incorrect; Should be ConfigureManager
2984 //.privileges(redfish::privileges::postLogService)
Ed Tanous432a8902021-06-14 15:28:56 -07002985 .privileges({{"ConfigureComponents"}})
Ed Tanous002d39b2022-05-31 08:59:27 -07002986 .methods(boost::beast::http::verb::post)(
2987 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07002988 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2989 const std::string& systemName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002990 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07002991 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002992 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07002993 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002994
2995 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous002d39b2022-05-31 08:59:27 -07002996 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002997 // Option currently returns no systems. TBD
2998 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2999 systemName);
3000 return;
3001 }
3002 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
3003 {
3004 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3005 systemName);
3006 return;
3007 }
3008
3009 std::string diagnosticDataType;
3010 std::string oemDiagnosticDataType;
Patrick Williams504af5a2025-02-03 14:29:03 -05003011 if (!redfish::json_util::readJsonAction( //
3012 req, asyncResp->res, //
3013 "DiagnosticDataType", diagnosticDataType, //
Myung Baeafc474a2024-10-09 00:53:29 -07003014 "OEMDiagnosticDataType", oemDiagnosticDataType //
3015 ))
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003016 {
3017 return;
3018 }
3019
3020 if (diagnosticDataType != "OEM")
3021 {
3022 BMCWEB_LOG_ERROR(
3023 "Only OEM DiagnosticDataType supported for Crashdump");
3024 messages::actionParameterValueFormatError(
3025 asyncResp->res, diagnosticDataType,
3026 "DiagnosticDataType", "CollectDiagnosticData");
3027 return;
3028 }
3029
3030 OEMDiagnosticType oemDiagType =
3031 getOEMDiagnosticType(oemDiagnosticDataType);
3032
3033 std::string iface;
3034 std::string method;
3035 std::string taskMatchStr;
3036 if (oemDiagType == OEMDiagnosticType::onDemand)
3037 {
3038 iface = crashdumpOnDemandInterface;
3039 method = "GenerateOnDemandLog";
3040 taskMatchStr =
3041 "type='signal',"
3042 "interface='org.freedesktop.DBus.Properties',"
3043 "member='PropertiesChanged',"
3044 "arg0namespace='com.intel.crashdump'";
3045 }
3046 else if (oemDiagType == OEMDiagnosticType::telemetry)
3047 {
3048 iface = crashdumpTelemetryInterface;
3049 method = "GenerateTelemetryLog";
3050 taskMatchStr =
3051 "type='signal',"
3052 "interface='org.freedesktop.DBus.Properties',"
3053 "member='PropertiesChanged',"
3054 "arg0namespace='com.intel.crashdump'";
Ed Tanous002d39b2022-05-31 08:59:27 -07003055 }
3056 else
3057 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003058 BMCWEB_LOG_ERROR("Unsupported OEMDiagnosticDataType: {}",
3059 oemDiagnosticDataType);
3060 messages::actionParameterValueFormatError(
3061 asyncResp->res, oemDiagnosticDataType,
3062 "OEMDiagnosticDataType", "CollectDiagnosticData");
3063 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07003064 }
Ed Tanous1da66f72018-07-27 16:13:37 -07003065
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003066 auto collectCrashdumpCallback =
3067 [asyncResp, payload(task::Payload(req)),
3068 taskMatchStr](const boost::system::error_code& ec,
3069 const std::string&) mutable {
3070 if (ec)
3071 {
3072 if (ec.value() ==
3073 boost::system::errc::operation_not_supported)
3074 {
3075 messages::resourceInStandby(asyncResp->res);
3076 }
3077 else if (ec.value() == boost::system::errc::
3078 device_or_resource_busy)
3079 {
3080 messages::serviceTemporarilyUnavailable(
3081 asyncResp->res, "60");
3082 }
3083 else
3084 {
3085 messages::internalError(asyncResp->res);
3086 }
3087 return;
3088 }
3089 std::shared_ptr<task::TaskData> task =
3090 task::TaskData::createTask(
3091 [](const boost::system::error_code& ec2,
3092 sdbusplus::message_t&,
3093 const std::shared_ptr<task::TaskData>&
3094 taskData) {
3095 if (!ec2)
3096 {
3097 taskData->messages.emplace_back(
3098 messages::taskCompletedOK(
3099 std::to_string(
3100 taskData->index)));
3101 taskData->state = "Completed";
3102 }
3103 return task::completed;
3104 },
3105 taskMatchStr);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003106
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003107 task->startTimer(std::chrono::minutes(5));
3108 task->populateResp(asyncResp->res);
3109 task->payload.emplace(std::move(payload));
3110 };
3111
3112 crow::connections::systemBus->async_method_call(
3113 std::move(collectCrashdumpCallback), crashdumpObject,
3114 crashdumpPath, iface, method);
3115 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003116}
Kenny L. Ku6eda7682020-06-19 09:48:36 -07003117
Alexander Hansen599b9af2024-08-06 15:11:57 +02003118inline void dBusLogServiceActionsClear(
3119 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
3120{
3121 BMCWEB_LOG_DEBUG("Do delete all entries.");
3122
3123 // Process response from Logging service.
3124 auto respHandler = [asyncResp](const boost::system::error_code& ec) {
3125 BMCWEB_LOG_DEBUG("doClearLog resp_handler callback: Done");
3126 if (ec)
3127 {
3128 // TODO Handle for specific error code
3129 BMCWEB_LOG_ERROR("doClearLog resp_handler got error {}", ec);
3130 asyncResp->res.result(
3131 boost::beast::http::status::internal_server_error);
3132 return;
3133 }
3134
3135 asyncResp->res.result(boost::beast::http::status::no_content);
3136 };
3137
3138 // Make call to Logging service to request Clear Log
3139 crow::connections::systemBus->async_method_call(
3140 respHandler, "xyz.openbmc_project.Logging",
3141 "/xyz/openbmc_project/logging",
3142 "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
3143}
3144
Andrew Geisslercb92c032018-08-17 07:56:14 -07003145/**
3146 * DBusLogServiceActionsClear class supports POST method for ClearLog action.
3147 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003148inline void requestRoutesDBusLogServiceActionsClear(App& app)
Andrew Geisslercb92c032018-08-17 07:56:14 -07003149{
Andrew Geisslercb92c032018-08-17 07:56:14 -07003150 /**
3151 * Function handles POST method request.
3152 * The Clear Log actions does not require any parameter.The action deletes
3153 * all entries found in the Entries collection for this Log Service.
3154 */
Andrew Geisslercb92c032018-08-17 07:56:14 -07003155
George Liu0fda0f12021-11-16 10:06:17 +08003156 BMCWEB_ROUTE(
3157 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07003158 "/redfish/v1/Systems/<str>/LogServices/EventLog/Actions/LogService.ClearLog/")
Ed Tanoused398212021-06-09 17:05:54 -07003159 .privileges(redfish::privileges::postLogService)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003160 .methods(boost::beast::http::verb::post)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07003161 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07003162 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3163 const std::string& systemName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003164 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3165 {
3166 return;
3167 }
3168 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
3169 {
3170 // Option currently returns no systems. TBD
3171 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3172 systemName);
3173 return;
3174 }
3175 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
3176 {
3177 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3178 systemName);
3179 return;
3180 }
3181 dBusLogServiceActionsClear(asyncResp);
3182 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003183}
ZhikuiRena3316fc2020-01-29 14:58:08 -08003184
Ed Tanous1da66f72018-07-27 16:13:37 -07003185} // namespace redfish