blob: 4b6d7af2866be7af38e600d89f68dbd1d6f58bf3 [file] [log] [blame]
Ed Tanous40e9b922024-09-10 13:50:16 -07001// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright OpenBMC Authors
3// SPDX-FileCopyrightText: Copyright 2018 Intel Corporation
Ed Tanous1da66f72018-07-27 16:13:37 -07004#pragma once
5
Ed Tanous3ccb3ad2023-01-13 17:40:03 -08006#include "app.hpp"
George Liu7a1dbc42022-12-07 16:03:22 +08007#include "dbus_utility.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -08008#include "error_messages.hpp"
Asmitha Karunanithi68dd0752022-11-15 11:33:46 -06009#include "generated/enums/log_entry.hpp"
Ed Tanous539d8c62024-06-19 14:38:27 -070010#include "generated/enums/log_service.hpp"
Spencer Kub7028eb2021-10-26 15:27:35 +080011#include "gzfile.hpp"
George Liu647b3cd2021-07-05 12:43:56 +080012#include "http_utility.hpp"
Spencer Kub7028eb2021-10-26 15:27:35 +080013#include "human_sort.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080014#include "query.hpp"
Jason M. Bills4851d452019-03-28 11:27:48 -070015#include "registries.hpp"
16#include "registries/base_message_registry.hpp"
17#include "registries/openbmc_message_registry.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080018#include "registries/privilege_registry.hpp"
James Feist46229572020-02-19 15:11:58 -080019#include "task.hpp"
Ed Tanous5b904292024-04-16 11:10:17 -070020#include "task_messages.hpp"
Alexander Hansen262dcc12024-09-19 12:04:03 +020021#include "utils/dbus_event_log_entry.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080022#include "utils/dbus_utils.hpp"
Ed Tanous5b904292024-04-16 11:10:17 -070023#include "utils/json_utils.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080024#include "utils/time_utils.hpp"
Ed Tanous1da66f72018-07-27 16:13:37 -070025
Myung Bae75e8e212023-11-30 12:53:46 -080026#include <systemd/sd-id128.h>
Asmitha Karunanithi8e317782020-12-10 03:35:05 -060027#include <tinyxml2.h>
Adriana Kobylak400fd1f2021-01-29 09:01:30 -060028#include <unistd.h>
Jason M. Billse1f26342018-07-18 12:12:00 -070029
Ed Tanous07c8c202022-07-11 10:08:08 -070030#include <boost/beast/http/verb.hpp>
Ed Tanous1da66f72018-07-27 16:13:37 -070031#include <boost/container/flat_map.hpp>
Jason M. Bills1ddcf012019-11-26 14:59:21 -080032#include <boost/system/linux_error.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070033#include <boost/url/format.hpp>
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +020034#include <sdbusplus/asio/property.hpp>
35#include <sdbusplus/unpack_properties.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050036
George Liu7a1dbc42022-12-07 16:03:22 +080037#include <array>
George Liu647b3cd2021-07-05 12:43:56 +080038#include <charconv>
Abhilash Rajub5f288d2023-11-08 22:32:44 -060039#include <cstddef>
James Feist4418c7f2019-04-15 11:09:15 -070040#include <filesystem>
Ed Tanous18f8f602023-07-18 10:07:23 -070041#include <iterator>
Xiaochao Ma75710de2021-01-21 17:56:02 +080042#include <optional>
Ed Tanous3544d2a2023-08-06 18:12:20 -070043#include <ranges>
Ed Tanous26702d02021-11-03 15:02:33 -070044#include <span>
Ed Tanous18f8f602023-07-18 10:07:23 -070045#include <string>
Jason M. Billscd225da2019-05-08 15:31:57 -070046#include <string_view>
Ed Tanousabf2add2019-01-22 16:40:12 -080047#include <variant>
Ed Tanous1da66f72018-07-27 16:13:37 -070048
49namespace redfish
50{
51
Patrick Williams89492a12023-05-10 07:51:34 -050052constexpr const char* crashdumpObject = "com.intel.crashdump";
53constexpr const char* crashdumpPath = "/com/intel/crashdump";
54constexpr const char* crashdumpInterface = "com.intel.crashdump";
55constexpr const char* deleteAllInterface =
Jason M. Bills5b61b5e2019-10-16 10:59:02 -070056 "xyz.openbmc_project.Collection.DeleteAll";
Patrick Williams89492a12023-05-10 07:51:34 -050057constexpr const char* crashdumpOnDemandInterface =
Jason M. Bills424c4172019-03-21 13:50:33 -070058 "com.intel.crashdump.OnDemand";
Patrick Williams89492a12023-05-10 07:51:34 -050059constexpr const char* crashdumpTelemetryInterface =
Kenny L. Ku6eda7682020-06-19 09:48:36 -070060 "com.intel.crashdump.Telemetry";
Ed Tanous1da66f72018-07-27 16:13:37 -070061
Asmitha Karunanithi8e317782020-12-10 03:35:05 -060062enum class DumpCreationProgress
63{
64 DUMP_CREATE_SUCCESS,
65 DUMP_CREATE_FAILED,
66 DUMP_CREATE_INPROGRESS
67};
68
James Feistf6150402019-01-08 10:36:20 -080069namespace fs = std::filesystem;
Ed Tanous1da66f72018-07-27 16:13:37 -070070
Gunnar Mills1214b7e2020-06-04 10:11:30 -050071inline std::string translateSeverityDbusToRedfish(const std::string& s)
Andrew Geisslercb92c032018-08-17 07:56:14 -070072{
Ed Tanousd4d25792020-09-29 15:15:03 -070073 if ((s == "xyz.openbmc_project.Logging.Entry.Level.Alert") ||
74 (s == "xyz.openbmc_project.Logging.Entry.Level.Critical") ||
75 (s == "xyz.openbmc_project.Logging.Entry.Level.Emergency") ||
76 (s == "xyz.openbmc_project.Logging.Entry.Level.Error"))
Andrew Geisslercb92c032018-08-17 07:56:14 -070077 {
78 return "Critical";
79 }
Ed Tanous3174e4d2020-10-07 11:41:22 -070080 if ((s == "xyz.openbmc_project.Logging.Entry.Level.Debug") ||
81 (s == "xyz.openbmc_project.Logging.Entry.Level.Informational") ||
82 (s == "xyz.openbmc_project.Logging.Entry.Level.Notice"))
Andrew Geisslercb92c032018-08-17 07:56:14 -070083 {
84 return "OK";
85 }
Ed Tanous3174e4d2020-10-07 11:41:22 -070086 if (s == "xyz.openbmc_project.Logging.Entry.Level.Warning")
Andrew Geisslercb92c032018-08-17 07:56:14 -070087 {
88 return "Warning";
89 }
90 return "";
91}
92
Abhishek Patel9017faf2021-09-14 22:48:55 -050093inline std::optional<bool> getProviderNotifyAction(const std::string& notify)
94{
95 std::optional<bool> notifyAction;
96 if (notify == "xyz.openbmc_project.Logging.Entry.Notify.Notify")
97 {
98 notifyAction = true;
99 }
100 else if (notify == "xyz.openbmc_project.Logging.Entry.Notify.Inhibit")
101 {
102 notifyAction = false;
103 }
104
105 return notifyAction;
106}
107
Ed Tanous18f8f602023-07-18 10:07:23 -0700108inline std::string getDumpPath(std::string_view dumpType)
109{
110 std::string dbusDumpPath = "/xyz/openbmc_project/dump/";
111 std::ranges::transform(dumpType, std::back_inserter(dbusDumpPath),
112 bmcweb::asciiToLower);
113
114 return dbusDumpPath;
115}
116
Ed Tanous055713e2024-07-17 17:19:36 -0700117inline bool getUniqueEntryID(const std::string& logEntry, std::string& entryID,
Jason M. Billse85d6b12019-07-29 17:01:15 -0700118 const bool firstEntry = true)
Jason M. Bills95820182019-04-22 16:25:34 -0700119{
Ed Tanous271584a2019-07-09 16:24:22 -0700120 static time_t prevTs = 0;
Jason M. Bills95820182019-04-22 16:25:34 -0700121 static int index = 0;
Jason M. Billse85d6b12019-07-29 17:01:15 -0700122 if (firstEntry)
123 {
124 prevTs = 0;
125 }
126
Jason M. Bills95820182019-04-22 16:25:34 -0700127 // Get the entry timestamp
Ed Tanous271584a2019-07-09 16:24:22 -0700128 std::time_t curTs = 0;
Jason M. Bills95820182019-04-22 16:25:34 -0700129 std::tm timeStruct = {};
130 std::istringstream entryStream(logEntry);
131 if (entryStream >> std::get_time(&timeStruct, "%Y-%m-%dT%H:%M:%S"))
132 {
133 curTs = std::mktime(&timeStruct);
134 }
135 // If the timestamp isn't unique, increment the index
136 if (curTs == prevTs)
137 {
138 index++;
139 }
140 else
141 {
142 // Otherwise, reset it
143 index = 0;
144 }
145 // Save the timestamp
146 prevTs = curTs;
147
148 entryID = std::to_string(curTs);
149 if (index > 0)
150 {
151 entryID += "_" + std::to_string(index);
152 }
153 return true;
154}
155
Ed Tanous4ff0f1f2024-09-04 17:27:37 -0700156inline bool
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500157 getRedfishLogFiles(std::vector<std::filesystem::path>& redfishLogFiles)
Jason M. Bills95820182019-04-22 16:25:34 -0700158{
159 static const std::filesystem::path redfishLogDir = "/var/log";
160 static const std::string redfishLogFilename = "redfish";
161
162 // Loop through the directory looking for redfish log files
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500163 for (const std::filesystem::directory_entry& dirEnt :
Jason M. Bills95820182019-04-22 16:25:34 -0700164 std::filesystem::directory_iterator(redfishLogDir))
165 {
166 // If we find a redfish log file, save the path
167 std::string filename = dirEnt.path().filename();
Ed Tanous11ba3972022-07-11 09:50:41 -0700168 if (filename.starts_with(redfishLogFilename))
Jason M. Bills95820182019-04-22 16:25:34 -0700169 {
170 redfishLogFiles.emplace_back(redfishLogDir / filename);
171 }
172 }
173 // As the log files rotate, they are appended with a ".#" that is higher for
174 // the older logs. Since we don't expect more than 10 log files, we
175 // can just sort the list to get them in order from newest to oldest
Ed Tanous3544d2a2023-08-06 18:12:20 -0700176 std::ranges::sort(redfishLogFiles);
Jason M. Bills95820182019-04-22 16:25:34 -0700177
178 return !redfishLogFiles.empty();
179}
180
Asmitha Karunanithi68dd0752022-11-15 11:33:46 -0600181inline log_entry::OriginatorTypes
182 mapDbusOriginatorTypeToRedfish(const std::string& originatorType)
183{
184 if (originatorType ==
185 "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Client")
186 {
187 return log_entry::OriginatorTypes::Client;
188 }
189 if (originatorType ==
190 "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Internal")
191 {
192 return log_entry::OriginatorTypes::Internal;
193 }
194 if (originatorType ==
195 "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.SupportingService")
196 {
197 return log_entry::OriginatorTypes::SupportingService;
198 }
199 return log_entry::OriginatorTypes::Invalid;
200}
201
Claire Weinanaefe3782022-07-15 19:17:19 -0700202inline void parseDumpEntryFromDbusObject(
Jiaqing Zhao2d613eb2022-08-15 16:03:00 +0800203 const dbus::utility::ManagedObjectType::value_type& object,
Claire Weinanc6fecda2022-07-15 10:43:25 -0700204 std::string& dumpStatus, uint64_t& size, uint64_t& timestampUs,
Asmitha Karunanithi68dd0752022-11-15 11:33:46 -0600205 std::string& originatorId, log_entry::OriginatorTypes& originatorType,
Claire Weinanaefe3782022-07-15 19:17:19 -0700206 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
207{
208 for (const auto& interfaceMap : object.second)
209 {
210 if (interfaceMap.first == "xyz.openbmc_project.Common.Progress")
211 {
212 for (const auto& propertyMap : interfaceMap.second)
213 {
214 if (propertyMap.first == "Status")
215 {
216 const auto* status =
217 std::get_if<std::string>(&propertyMap.second);
218 if (status == nullptr)
219 {
220 messages::internalError(asyncResp->res);
221 break;
222 }
223 dumpStatus = *status;
224 }
225 }
226 }
227 else if (interfaceMap.first == "xyz.openbmc_project.Dump.Entry")
228 {
229 for (const auto& propertyMap : interfaceMap.second)
230 {
231 if (propertyMap.first == "Size")
232 {
233 const auto* sizePtr =
234 std::get_if<uint64_t>(&propertyMap.second);
235 if (sizePtr == nullptr)
236 {
237 messages::internalError(asyncResp->res);
238 break;
239 }
240 size = *sizePtr;
241 break;
242 }
243 }
244 }
245 else if (interfaceMap.first == "xyz.openbmc_project.Time.EpochTime")
246 {
247 for (const auto& propertyMap : interfaceMap.second)
248 {
249 if (propertyMap.first == "Elapsed")
250 {
251 const uint64_t* usecsTimeStamp =
252 std::get_if<uint64_t>(&propertyMap.second);
253 if (usecsTimeStamp == nullptr)
254 {
255 messages::internalError(asyncResp->res);
256 break;
257 }
Claire Weinanc6fecda2022-07-15 10:43:25 -0700258 timestampUs = *usecsTimeStamp;
Claire Weinanaefe3782022-07-15 19:17:19 -0700259 break;
260 }
261 }
262 }
Asmitha Karunanithi68dd0752022-11-15 11:33:46 -0600263 else if (interfaceMap.first ==
264 "xyz.openbmc_project.Common.OriginatedBy")
265 {
266 for (const auto& propertyMap : interfaceMap.second)
267 {
268 if (propertyMap.first == "OriginatorId")
269 {
270 const std::string* id =
271 std::get_if<std::string>(&propertyMap.second);
272 if (id == nullptr)
273 {
274 messages::internalError(asyncResp->res);
275 break;
276 }
277 originatorId = *id;
278 }
279
280 if (propertyMap.first == "OriginatorType")
281 {
282 const std::string* type =
283 std::get_if<std::string>(&propertyMap.second);
284 if (type == nullptr)
285 {
286 messages::internalError(asyncResp->res);
287 break;
288 }
289
290 originatorType = mapDbusOriginatorTypeToRedfish(*type);
291 if (originatorType == log_entry::OriginatorTypes::Invalid)
292 {
293 messages::internalError(asyncResp->res);
294 break;
295 }
296 }
297 }
298 }
Claire Weinanaefe3782022-07-15 19:17:19 -0700299 }
300}
301
Nan Zhou21ab4042022-06-26 23:07:40 +0000302static std::string getDumpEntriesPath(const std::string& dumpType)
Claire Weinanfdd26902022-03-01 14:18:25 -0800303{
304 std::string entriesPath;
305
306 if (dumpType == "BMC")
307 {
Ed Tanous253f11b2024-05-16 09:38:31 -0700308 entriesPath =
309 std::format("/redfish/v1/Managers/{}/LogServices/Dump/Entries/",
310 BMCWEB_REDFISH_MANAGER_URI_NAME);
Claire Weinanfdd26902022-03-01 14:18:25 -0800311 }
312 else if (dumpType == "FaultLog")
313 {
Ed Tanous253f11b2024-05-16 09:38:31 -0700314 entriesPath =
315 std::format("/redfish/v1/Managers/{}/LogServices/FaultLog/Entries/",
316 BMCWEB_REDFISH_MANAGER_URI_NAME);
Claire Weinanfdd26902022-03-01 14:18:25 -0800317 }
318 else if (dumpType == "System")
319 {
Ed Tanous253f11b2024-05-16 09:38:31 -0700320 entriesPath =
321 std::format("/redfish/v1/Systems/{}/LogServices/Dump/Entries/",
322 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Claire Weinanfdd26902022-03-01 14:18:25 -0800323 }
324 else
325 {
Ed Tanous62598e32023-07-17 17:06:25 -0700326 BMCWEB_LOG_ERROR("getDumpEntriesPath() invalid dump type: {}",
327 dumpType);
Claire Weinanfdd26902022-03-01 14:18:25 -0800328 }
329
330 // Returns empty string on error
331 return entriesPath;
332}
333
zhanghch058d1b46d2021-04-01 11:18:24 +0800334inline void
335 getDumpEntryCollection(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
336 const std::string& dumpType)
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500337{
Claire Weinanfdd26902022-03-01 14:18:25 -0800338 std::string entriesPath = getDumpEntriesPath(dumpType);
339 if (entriesPath.empty())
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500340 {
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500341 messages::internalError(asyncResp->res);
342 return;
343 }
344
George Liu5eb468d2023-06-20 17:03:24 +0800345 sdbusplus::message::object_path path("/xyz/openbmc_project/dump");
346 dbus::utility::getManagedObjects(
347 "xyz.openbmc_project.Dump.Manager", path,
Claire Weinanfdd26902022-03-01 14:18:25 -0800348 [asyncResp, entriesPath,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800349 dumpType](const boost::system::error_code& ec,
George Liu5eb468d2023-06-20 17:03:24 +0800350 const dbus::utility::ManagedObjectType& objects) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400351 if (ec)
352 {
353 BMCWEB_LOG_ERROR("DumpEntry resp_handler got error {}", ec);
354 messages::internalError(asyncResp->res);
355 return;
356 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700357
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400358 // Remove ending slash
359 std::string odataIdStr = entriesPath;
360 if (!odataIdStr.empty())
361 {
362 odataIdStr.pop_back();
363 }
Claire Weinanfdd26902022-03-01 14:18:25 -0800364
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400365 asyncResp->res.jsonValue["@odata.type"] =
366 "#LogEntryCollection.LogEntryCollection";
367 asyncResp->res.jsonValue["@odata.id"] = std::move(odataIdStr);
368 asyncResp->res.jsonValue["Name"] = dumpType + " Dump Entries";
369 asyncResp->res.jsonValue["Description"] =
370 "Collection of " + dumpType + " Dump Entries";
Claire Weinanfdd26902022-03-01 14:18:25 -0800371
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400372 nlohmann::json::array_t entriesArray;
373 std::string dumpEntryPath = getDumpPath(dumpType) + "/entry/";
Ed Tanous002d39b2022-05-31 08:59:27 -0700374
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400375 dbus::utility::ManagedObjectType resp(objects);
376 std::ranges::sort(resp, [](const auto& l, const auto& r) {
377 return AlphanumLess<std::string>()(l.first.filename(),
378 r.first.filename());
379 });
380
381 for (auto& object : resp)
382 {
383 if (object.first.str.find(dumpEntryPath) == std::string::npos)
384 {
385 continue;
386 }
387 uint64_t timestampUs = 0;
388 uint64_t size = 0;
389 std::string dumpStatus;
390 std::string originatorId;
391 log_entry::OriginatorTypes originatorType =
392 log_entry::OriginatorTypes::Internal;
393 nlohmann::json::object_t thisEntry;
394
395 std::string entryID = object.first.filename();
396 if (entryID.empty())
397 {
398 continue;
399 }
400
401 parseDumpEntryFromDbusObject(object, dumpStatus, size,
402 timestampUs, originatorId,
403 originatorType, asyncResp);
404
405 if (dumpStatus !=
406 "xyz.openbmc_project.Common.Progress.OperationStatus.Completed" &&
407 !dumpStatus.empty())
408 {
409 // Dump status is not Complete, no need to enumerate
410 continue;
411 }
412
413 thisEntry["@odata.type"] = "#LogEntry.v1_11_0.LogEntry";
414 thisEntry["@odata.id"] = entriesPath + entryID;
415 thisEntry["Id"] = entryID;
416 thisEntry["EntryType"] = "Event";
417 thisEntry["Name"] = dumpType + " Dump Entry";
418 thisEntry["Created"] =
419 redfish::time_utils::getDateTimeUintUs(timestampUs);
420
421 if (!originatorId.empty())
422 {
423 thisEntry["Originator"] = originatorId;
424 thisEntry["OriginatorType"] = originatorType;
425 }
426
427 if (dumpType == "BMC")
428 {
429 thisEntry["DiagnosticDataType"] = "Manager";
430 thisEntry["AdditionalDataURI"] =
431 entriesPath + entryID + "/attachment";
432 thisEntry["AdditionalDataSizeBytes"] = size;
433 }
434 else if (dumpType == "System")
435 {
436 thisEntry["DiagnosticDataType"] = "OEM";
437 thisEntry["OEMDiagnosticDataType"] = "System";
438 thisEntry["AdditionalDataURI"] =
439 entriesPath + entryID + "/attachment";
440 thisEntry["AdditionalDataSizeBytes"] = size;
441 }
442 entriesArray.emplace_back(std::move(thisEntry));
443 }
444 asyncResp->res.jsonValue["Members@odata.count"] =
445 entriesArray.size();
446 asyncResp->res.jsonValue["Members"] = std::move(entriesArray);
Ed Tanous002d39b2022-05-31 08:59:27 -0700447 });
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500448}
449
zhanghch058d1b46d2021-04-01 11:18:24 +0800450inline void
Claire Weinanc7a6d662022-06-13 16:36:39 -0700451 getDumpEntryById(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
zhanghch058d1b46d2021-04-01 11:18:24 +0800452 const std::string& entryID, const std::string& dumpType)
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500453{
Claire Weinanfdd26902022-03-01 14:18:25 -0800454 std::string entriesPath = getDumpEntriesPath(dumpType);
455 if (entriesPath.empty())
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500456 {
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500457 messages::internalError(asyncResp->res);
458 return;
459 }
460
George Liu5eb468d2023-06-20 17:03:24 +0800461 sdbusplus::message::object_path path("/xyz/openbmc_project/dump");
462 dbus::utility::getManagedObjects(
463 "xyz.openbmc_project.Dump.Manager", path,
Claire Weinanfdd26902022-03-01 14:18:25 -0800464 [asyncResp, entryID, dumpType,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800465 entriesPath](const boost::system::error_code& ec,
Ed Tanous02cad962022-06-30 16:50:15 -0700466 const dbus::utility::ManagedObjectType& resp) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400467 if (ec)
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500468 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400469 BMCWEB_LOG_ERROR("DumpEntry resp_handler got error {}", ec);
470 messages::internalError(asyncResp->res);
471 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700472 }
473
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400474 bool foundDumpEntry = false;
475 std::string dumpEntryPath = getDumpPath(dumpType) + "/entry/";
Ed Tanous002d39b2022-05-31 08:59:27 -0700476
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400477 for (const auto& objectPath : resp)
Ed Tanous002d39b2022-05-31 08:59:27 -0700478 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400479 if (objectPath.first.str != dumpEntryPath + entryID)
480 {
481 continue;
482 }
483
484 foundDumpEntry = true;
485 uint64_t timestampUs = 0;
486 uint64_t size = 0;
487 std::string dumpStatus;
488 std::string originatorId;
489 log_entry::OriginatorTypes originatorType =
490 log_entry::OriginatorTypes::Internal;
491
492 parseDumpEntryFromDbusObject(objectPath, dumpStatus, size,
493 timestampUs, originatorId,
494 originatorType, asyncResp);
495
496 if (dumpStatus !=
497 "xyz.openbmc_project.Common.Progress.OperationStatus.Completed" &&
498 !dumpStatus.empty())
499 {
500 // Dump status is not Complete
501 // return not found until status is changed to Completed
502 messages::resourceNotFound(asyncResp->res,
503 dumpType + " dump", entryID);
504 return;
505 }
506
507 asyncResp->res.jsonValue["@odata.type"] =
508 "#LogEntry.v1_11_0.LogEntry";
509 asyncResp->res.jsonValue["@odata.id"] = entriesPath + entryID;
510 asyncResp->res.jsonValue["Id"] = entryID;
511 asyncResp->res.jsonValue["EntryType"] = "Event";
512 asyncResp->res.jsonValue["Name"] = dumpType + " Dump Entry";
513 asyncResp->res.jsonValue["Created"] =
514 redfish::time_utils::getDateTimeUintUs(timestampUs);
515
516 if (!originatorId.empty())
517 {
518 asyncResp->res.jsonValue["Originator"] = originatorId;
519 asyncResp->res.jsonValue["OriginatorType"] = originatorType;
520 }
521
522 if (dumpType == "BMC")
523 {
524 asyncResp->res.jsonValue["DiagnosticDataType"] = "Manager";
525 asyncResp->res.jsonValue["AdditionalDataURI"] =
526 entriesPath + entryID + "/attachment";
527 asyncResp->res.jsonValue["AdditionalDataSizeBytes"] = size;
528 }
529 else if (dumpType == "System")
530 {
531 asyncResp->res.jsonValue["DiagnosticDataType"] = "OEM";
532 asyncResp->res.jsonValue["OEMDiagnosticDataType"] =
533 "System";
534 asyncResp->res.jsonValue["AdditionalDataURI"] =
535 entriesPath + entryID + "/attachment";
536 asyncResp->res.jsonValue["AdditionalDataSizeBytes"] = size;
537 }
538 }
539 if (!foundDumpEntry)
540 {
541 BMCWEB_LOG_WARNING("Can't find Dump Entry {}", entryID);
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +0200542 messages::resourceNotFound(asyncResp->res, dumpType + " dump",
543 entryID);
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500544 return;
545 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400546 });
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500547}
548
zhanghch058d1b46d2021-04-01 11:18:24 +0800549inline void deleteDumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Stanley Chu98782562020-11-04 16:10:24 +0800550 const std::string& entryID,
Asmitha Karunanithib47452b2020-09-25 02:02:19 -0500551 const std::string& dumpType)
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500552{
Patrick Williams5a39f772023-10-20 11:20:21 -0500553 auto respHandler = [asyncResp,
554 entryID](const boost::system::error_code& ec) {
Ed Tanous62598e32023-07-17 17:06:25 -0700555 BMCWEB_LOG_DEBUG("Dump Entry doDelete callback: Done");
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500556 if (ec)
557 {
George Liu3de8d8b2021-03-22 17:49:39 +0800558 if (ec.value() == EBADR)
559 {
560 messages::resourceNotFound(asyncResp->res, "LogEntry", entryID);
561 return;
562 }
Ed Tanous62598e32023-07-17 17:06:25 -0700563 BMCWEB_LOG_ERROR(
564 "Dump (DBus) doDelete respHandler got error {} entryID={}", ec,
565 entryID);
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500566 messages::internalError(asyncResp->res);
567 return;
568 }
569 };
Ed Tanous18f8f602023-07-18 10:07:23 -0700570
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500571 crow::connections::systemBus->async_method_call(
572 respHandler, "xyz.openbmc_project.Dump.Manager",
Ed Tanous18f8f602023-07-18 10:07:23 -0700573 std::format("{}/entry/{}", getDumpPath(dumpType), entryID),
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500574 "xyz.openbmc_project.Object.Delete", "Delete");
575}
Abhilash Rajub5f288d2023-11-08 22:32:44 -0600576inline bool checkSizeLimit(int fd, crow::Response& res)
577{
578 long long int size = lseek(fd, 0, SEEK_END);
579 if (size <= 0)
580 {
581 BMCWEB_LOG_ERROR("Failed to get size of file, lseek() returned {}",
582 size);
583 messages::internalError(res);
584 return false;
585 }
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500586
Abhilash Rajub5f288d2023-11-08 22:32:44 -0600587 // Arbitrary max size of 20MB to accommodate BMC dumps
588 constexpr long long int maxFileSize = 20LL * 1024LL * 1024LL;
589 if (size > maxFileSize)
590 {
591 BMCWEB_LOG_ERROR("File size {} exceeds maximum allowed size of {}",
592 size, maxFileSize);
593 messages::internalError(res);
594 return false;
595 }
596 off_t rc = lseek(fd, 0, SEEK_SET);
597 if (rc < 0)
598 {
599 BMCWEB_LOG_ERROR("Failed to reset file offset to 0");
600 messages::internalError(res);
601 return false;
602 }
603 return true;
604}
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400605inline void downloadEntryCallback(
606 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
607 const std::string& entryID, const std::string& downloadEntryType,
608 const boost::system::error_code& ec,
609 const sdbusplus::message::unix_fd& unixfd)
Carson Labrado168d1b12023-03-27 17:04:46 +0000610{
611 if (ec.value() == EBADR)
612 {
613 messages::resourceNotFound(asyncResp->res, "EntryAttachment", entryID);
614 return;
615 }
616 if (ec)
617 {
618 BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
619 messages::internalError(asyncResp->res);
620 return;
621 }
622
623 // Make sure we know how to process the retrieved entry attachment
624 if ((downloadEntryType != "BMC") && (downloadEntryType != "System"))
625 {
626 BMCWEB_LOG_ERROR("downloadEntryCallback() invalid entry type: {}",
627 downloadEntryType);
628 messages::internalError(asyncResp->res);
629 }
630
631 int fd = -1;
632 fd = dup(unixfd);
633 if (fd < 0)
634 {
635 BMCWEB_LOG_ERROR("Failed to open file");
636 messages::internalError(asyncResp->res);
637 return;
638 }
Abhilash Rajub5f288d2023-11-08 22:32:44 -0600639 if (!checkSizeLimit(fd, asyncResp->res))
Carson Labrado168d1b12023-03-27 17:04:46 +0000640 {
Carson Labrado168d1b12023-03-27 17:04:46 +0000641 close(fd);
642 return;
643 }
Carson Labrado168d1b12023-03-27 17:04:46 +0000644 if (downloadEntryType == "System")
645 {
Abhilash Rajub5f288d2023-11-08 22:32:44 -0600646 if (!asyncResp->res.openFd(fd, bmcweb::EncodingType::Base64))
647 {
648 messages::internalError(asyncResp->res);
649 close(fd);
650 return;
651 }
Carson Labrado168d1b12023-03-27 17:04:46 +0000652 asyncResp->res.addHeader(
653 boost::beast::http::field::content_transfer_encoding, "Base64");
Abhilash Rajub5f288d2023-11-08 22:32:44 -0600654 return;
Carson Labrado168d1b12023-03-27 17:04:46 +0000655 }
Abhilash Rajub5f288d2023-11-08 22:32:44 -0600656 if (!asyncResp->res.openFd(fd))
Ed Tanous27b0cf92023-08-07 12:02:40 -0700657 {
Abhilash Rajub5f288d2023-11-08 22:32:44 -0600658 messages::internalError(asyncResp->res);
659 close(fd);
660 return;
Ed Tanous27b0cf92023-08-07 12:02:40 -0700661 }
Carson Labrado168d1b12023-03-27 17:04:46 +0000662 asyncResp->res.addHeader(boost::beast::http::field::content_type,
663 "application/octet-stream");
664}
665
666inline void
667 downloadDumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
668 const std::string& entryID, const std::string& dumpType)
669{
670 if (dumpType != "BMC")
671 {
672 BMCWEB_LOG_WARNING("Can't find Dump Entry {}", entryID);
673 messages::resourceNotFound(asyncResp->res, dumpType + " dump", entryID);
674 return;
675 }
676
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400677 std::string dumpEntryPath =
678 std::format("{}/entry/{}", getDumpPath(dumpType), entryID);
Carson Labrado168d1b12023-03-27 17:04:46 +0000679
680 auto downloadDumpEntryHandler =
681 [asyncResp, entryID,
682 dumpType](const boost::system::error_code& ec,
683 const sdbusplus::message::unix_fd& unixfd) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400684 downloadEntryCallback(asyncResp, entryID, dumpType, ec, unixfd);
685 };
Carson Labrado168d1b12023-03-27 17:04:46 +0000686
687 crow::connections::systemBus->async_method_call(
688 std::move(downloadDumpEntryHandler), "xyz.openbmc_project.Dump.Manager",
689 dumpEntryPath, "xyz.openbmc_project.Dump.Entry", "GetFileHandle");
690}
691
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400692inline void downloadEventLogEntry(
693 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
694 const std::string& systemName, const std::string& entryID,
695 const std::string& dumpType)
Carson Labrado168d1b12023-03-27 17:04:46 +0000696{
Ed Tanous25b54db2024-04-17 15:40:31 -0700697 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Carson Labrado168d1b12023-03-27 17:04:46 +0000698 {
699 // Option currently returns no systems. TBD
700 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
701 systemName);
702 return;
703 }
Ed Tanous253f11b2024-05-16 09:38:31 -0700704 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Carson Labrado168d1b12023-03-27 17:04:46 +0000705 {
706 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
707 systemName);
708 return;
709 }
710
711 std::string entryPath =
712 sdbusplus::message::object_path("/xyz/openbmc_project/logging/entry") /
713 entryID;
714
715 auto downloadEventLogEntryHandler =
716 [asyncResp, entryID,
717 dumpType](const boost::system::error_code& ec,
718 const sdbusplus::message::unix_fd& unixfd) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400719 downloadEntryCallback(asyncResp, entryID, dumpType, ec, unixfd);
720 };
Carson Labrado168d1b12023-03-27 17:04:46 +0000721
722 crow::connections::systemBus->async_method_call(
723 std::move(downloadEventLogEntryHandler), "xyz.openbmc_project.Logging",
724 entryPath, "xyz.openbmc_project.Logging.Entry", "GetEntry");
725}
726
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600727inline DumpCreationProgress
728 mapDbusStatusToDumpProgress(const std::string& status)
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500729{
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600730 if (status ==
731 "xyz.openbmc_project.Common.Progress.OperationStatus.Failed" ||
732 status == "xyz.openbmc_project.Common.Progress.OperationStatus.Aborted")
733 {
734 return DumpCreationProgress::DUMP_CREATE_FAILED;
735 }
736 if (status ==
737 "xyz.openbmc_project.Common.Progress.OperationStatus.Completed")
738 {
739 return DumpCreationProgress::DUMP_CREATE_SUCCESS;
740 }
741 return DumpCreationProgress::DUMP_CREATE_INPROGRESS;
742}
743
744inline DumpCreationProgress
745 getDumpCompletionStatus(const dbus::utility::DBusPropertiesMap& values)
746{
747 for (const auto& [key, val] : values)
748 {
749 if (key == "Status")
Ed Tanous002d39b2022-05-31 08:59:27 -0700750 {
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600751 const std::string* value = std::get_if<std::string>(&val);
752 if (value == nullptr)
753 {
Ed Tanous62598e32023-07-17 17:06:25 -0700754 BMCWEB_LOG_ERROR("Status property value is null");
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600755 return DumpCreationProgress::DUMP_CREATE_FAILED;
756 }
757 return mapDbusStatusToDumpProgress(*value);
758 }
759 }
760 return DumpCreationProgress::DUMP_CREATE_INPROGRESS;
761}
762
763inline std::string getDumpEntryPath(const std::string& dumpPath)
764{
765 if (dumpPath == "/xyz/openbmc_project/dump/bmc/entry")
766 {
Ed Tanous253f11b2024-05-16 09:38:31 -0700767 return std::format("/redfish/v1/Managers/{}/LogServices/Dump/Entries/",
Ed Tanous9f565092024-07-12 22:06:53 -0700768 BMCWEB_REDFISH_MANAGER_URI_NAME);
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600769 }
770 if (dumpPath == "/xyz/openbmc_project/dump/system/entry")
771 {
Ed Tanous253f11b2024-05-16 09:38:31 -0700772 return std::format("/redfish/v1/Systems/{}/LogServices/Dump/Entries/",
773 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600774 }
775 return "";
776}
777
778inline void createDumpTaskCallback(
779 task::Payload&& payload,
780 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
781 const sdbusplus::message::object_path& createdObjPath)
782{
783 const std::string dumpPath = createdObjPath.parent_path().str;
784 const std::string dumpId = createdObjPath.filename();
785
786 std::string dumpEntryPath = getDumpEntryPath(dumpPath);
787
788 if (dumpEntryPath.empty())
789 {
Ed Tanous62598e32023-07-17 17:06:25 -0700790 BMCWEB_LOG_ERROR("Invalid dump type received");
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600791 messages::internalError(asyncResp->res);
792 return;
793 }
794
795 crow::connections::systemBus->async_method_call(
Ed Tanous8cb2c022024-03-27 16:31:46 -0700796 [asyncResp, payload = std::move(payload), createdObjPath,
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600797 dumpEntryPath{std::move(dumpEntryPath)},
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800798 dumpId](const boost::system::error_code& ec,
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600799 const std::string& introspectXml) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400800 if (ec)
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600801 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400802 BMCWEB_LOG_ERROR("Introspect call failed with error: {}",
803 ec.message());
804 messages::internalError(asyncResp->res);
805 return;
806 }
807
808 // Check if the created dump object has implemented Progress
809 // interface to track dump completion. If yes, fetch the "Status"
810 // property of the interface, modify the task state accordingly.
811 // Else, return task completed.
812 tinyxml2::XMLDocument doc;
813
814 doc.Parse(introspectXml.data(), introspectXml.size());
815 tinyxml2::XMLNode* pRoot = doc.FirstChildElement("node");
816 if (pRoot == nullptr)
817 {
818 BMCWEB_LOG_ERROR("XML document failed to parse");
819 messages::internalError(asyncResp->res);
820 return;
821 }
822 tinyxml2::XMLElement* interfaceNode =
823 pRoot->FirstChildElement("interface");
824
825 bool isProgressIntfPresent = false;
826 while (interfaceNode != nullptr)
827 {
828 const char* thisInterfaceName =
829 interfaceNode->Attribute("name");
830 if (thisInterfaceName != nullptr)
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600831 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400832 if (thisInterfaceName ==
833 std::string_view("xyz.openbmc_project.Common.Progress"))
834 {
835 interfaceNode =
836 interfaceNode->NextSiblingElement("interface");
837 continue;
838 }
839 isProgressIntfPresent = true;
840 break;
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600841 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400842 interfaceNode = interfaceNode->NextSiblingElement("interface");
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600843 }
844
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400845 std::shared_ptr<task::TaskData> task = task::TaskData::createTask(
846 [createdObjPath, dumpEntryPath, dumpId, isProgressIntfPresent](
847 const boost::system::error_code& ec2,
848 sdbusplus::message_t& msg,
849 const std::shared_ptr<task::TaskData>& taskData) {
850 if (ec2)
851 {
852 BMCWEB_LOG_ERROR("{}: Error in creating dump",
853 createdObjPath.str);
854 taskData->messages.emplace_back(
855 messages::internalError());
856 taskData->state = "Cancelled";
857 return task::completed;
858 }
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600859
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400860 if (isProgressIntfPresent)
861 {
862 dbus::utility::DBusPropertiesMap values;
863 std::string prop;
864 msg.read(prop, values);
865
866 DumpCreationProgress dumpStatus =
867 getDumpCompletionStatus(values);
868 if (dumpStatus ==
869 DumpCreationProgress::DUMP_CREATE_FAILED)
870 {
871 BMCWEB_LOG_ERROR("{}: Error in creating dump",
872 createdObjPath.str);
873 taskData->state = "Cancelled";
874 return task::completed;
875 }
876
877 if (dumpStatus ==
878 DumpCreationProgress::DUMP_CREATE_INPROGRESS)
879 {
880 BMCWEB_LOG_DEBUG(
881 "{}: Dump creation task is in progress",
882 createdObjPath.str);
883 return !task::completed;
884 }
885 }
886
887 nlohmann::json retMessage = messages::success();
888 taskData->messages.emplace_back(retMessage);
889
890 boost::urls::url url = boost::urls::format(
891 "/redfish/v1/Managers/{}/LogServices/Dump/Entries/{}",
892 BMCWEB_REDFISH_MANAGER_URI_NAME, dumpId);
893
894 std::string headerLoc = "Location: ";
895 headerLoc += url.buffer();
896
897 taskData->payload->httpHeaders.emplace_back(
898 std::move(headerLoc));
899
900 BMCWEB_LOG_DEBUG("{}: Dump creation task completed",
Ed Tanous62598e32023-07-17 17:06:25 -0700901 createdObjPath.str);
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400902 taskData->state = "Completed";
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600903 return task::completed;
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400904 },
905 "type='signal',interface='org.freedesktop.DBus.Properties',"
906 "member='PropertiesChanged',path='" +
907 createdObjPath.str + "'");
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600908
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400909 // The task timer is set to max time limit within which the
910 // requested dump will be collected.
911 task->startTimer(std::chrono::minutes(6));
912 task->populateResp(asyncResp->res);
913 task->payload.emplace(payload);
Patrick Williams5a39f772023-10-20 11:20:21 -0500914 },
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600915 "xyz.openbmc_project.Dump.Manager", createdObjPath,
916 "org.freedesktop.DBus.Introspectable", "Introspect");
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500917}
918
zhanghch058d1b46d2021-04-01 11:18:24 +0800919inline void createDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
920 const crow::Request& req, const std::string& dumpType)
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500921{
Claire Weinanfdd26902022-03-01 14:18:25 -0800922 std::string dumpPath = getDumpEntriesPath(dumpType);
923 if (dumpPath.empty())
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500924 {
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500925 messages::internalError(asyncResp->res);
926 return;
927 }
928
929 std::optional<std::string> diagnosticDataType;
930 std::optional<std::string> oemDiagnosticDataType;
931
Myung Baeafc474a2024-10-09 00:53:29 -0700932 if (!redfish::json_util::readJsonAction( //
933 req, asyncResp->res, //
934 "DiagnosticDataType", diagnosticDataType, //
935 "OEMDiagnosticDataType", oemDiagnosticDataType //
936 ))
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500937 {
938 return;
939 }
940
941 if (dumpType == "System")
942 {
943 if (!oemDiagnosticDataType || !diagnosticDataType)
944 {
Ed Tanous62598e32023-07-17 17:06:25 -0700945 BMCWEB_LOG_ERROR(
946 "CreateDump action parameter 'DiagnosticDataType'/'OEMDiagnosticDataType' value not found!");
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500947 messages::actionParameterMissing(
948 asyncResp->res, "CollectDiagnosticData",
949 "DiagnosticDataType & OEMDiagnosticDataType");
950 return;
951 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700952 if ((*oemDiagnosticDataType != "System") ||
953 (*diagnosticDataType != "OEM"))
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500954 {
Ed Tanous62598e32023-07-17 17:06:25 -0700955 BMCWEB_LOG_ERROR("Wrong parameter values passed");
Ed Tanousace85d62021-10-26 12:45:59 -0700956 messages::internalError(asyncResp->res);
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500957 return;
958 }
Ed Tanous253f11b2024-05-16 09:38:31 -0700959 dumpPath = std::format("/redfish/v1/Systems/{}/LogServices/Dump/",
960 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500961 }
962 else if (dumpType == "BMC")
963 {
964 if (!diagnosticDataType)
965 {
Ed Tanous62598e32023-07-17 17:06:25 -0700966 BMCWEB_LOG_ERROR(
967 "CreateDump action parameter 'DiagnosticDataType' not found!");
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500968 messages::actionParameterMissing(
969 asyncResp->res, "CollectDiagnosticData", "DiagnosticDataType");
970 return;
971 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700972 if (*diagnosticDataType != "Manager")
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500973 {
Ed Tanous62598e32023-07-17 17:06:25 -0700974 BMCWEB_LOG_ERROR(
975 "Wrong parameter value passed for 'DiagnosticDataType'");
Ed Tanousace85d62021-10-26 12:45:59 -0700976 messages::internalError(asyncResp->res);
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500977 return;
978 }
Ed Tanous253f11b2024-05-16 09:38:31 -0700979 dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/Dump/",
980 BMCWEB_REDFISH_MANAGER_URI_NAME);
Asmitha Karunanithi59075712021-10-22 01:17:41 -0500981 }
982 else
983 {
Ed Tanous62598e32023-07-17 17:06:25 -0700984 BMCWEB_LOG_ERROR("CreateDump failed. Unknown dump type");
Asmitha Karunanithi59075712021-10-22 01:17:41 -0500985 messages::internalError(asyncResp->res);
986 return;
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500987 }
988
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600989 std::vector<std::pair<std::string, std::variant<std::string, uint64_t>>>
990 createDumpParamVec;
991
Carson Labradof574a8e2023-03-22 02:26:00 +0000992 if (req.session != nullptr)
993 {
994 createDumpParamVec.emplace_back(
995 "xyz.openbmc_project.Dump.Create.CreateParameters.OriginatorId",
996 req.session->clientIp);
997 createDumpParamVec.emplace_back(
998 "xyz.openbmc_project.Dump.Create.CreateParameters.OriginatorType",
999 "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Client");
1000 }
Asmitha Karunanithi68dd0752022-11-15 11:33:46 -06001001
Asmitha Karunanithia43be802020-05-07 05:05:36 -05001002 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001003 [asyncResp, payload(task::Payload(req)),
1004 dumpPath](const boost::system::error_code& ec,
1005 const sdbusplus::message_t& msg,
1006 const sdbusplus::message::object_path& objPath) mutable {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001007 if (ec)
Asmitha Karunanithi59075712021-10-22 01:17:41 -05001008 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001009 BMCWEB_LOG_ERROR("CreateDump resp_handler got error {}", ec);
1010 const sd_bus_error* dbusError = msg.get_error();
1011 if (dbusError == nullptr)
1012 {
1013 messages::internalError(asyncResp->res);
1014 return;
1015 }
1016
1017 BMCWEB_LOG_ERROR("CreateDump DBus error: {} and error msg: {}",
1018 dbusError->name, dbusError->message);
1019 if (std::string_view(
1020 "xyz.openbmc_project.Common.Error.NotAllowed") ==
1021 dbusError->name)
1022 {
1023 messages::resourceInStandby(asyncResp->res);
1024 return;
1025 }
1026 if (std::string_view(
1027 "xyz.openbmc_project.Dump.Create.Error.Disabled") ==
1028 dbusError->name)
1029 {
1030 messages::serviceDisabled(asyncResp->res, dumpPath);
1031 return;
1032 }
1033 if (std::string_view(
1034 "xyz.openbmc_project.Common.Error.Unavailable") ==
1035 dbusError->name)
1036 {
1037 messages::resourceInUse(asyncResp->res);
1038 return;
1039 }
1040 // Other Dbus errors such as:
1041 // xyz.openbmc_project.Common.Error.InvalidArgument &
1042 // org.freedesktop.DBus.Error.InvalidArgs are all related to
1043 // the dbus call that is made here in the bmcweb
1044 // implementation and has nothing to do with the client's
1045 // input in the request. Hence, returning internal error
1046 // back to the client.
Asmitha Karunanithi59075712021-10-22 01:17:41 -05001047 messages::internalError(asyncResp->res);
1048 return;
1049 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001050 BMCWEB_LOG_DEBUG("Dump Created. Path: {}", objPath.str);
1051 createDumpTaskCallback(std::move(payload), asyncResp, objPath);
1052 },
Ed Tanous18f8f602023-07-18 10:07:23 -07001053 "xyz.openbmc_project.Dump.Manager", getDumpPath(dumpType),
Asmitha Karunanithi8e317782020-12-10 03:35:05 -06001054 "xyz.openbmc_project.Dump.Create", "CreateDump", createDumpParamVec);
Asmitha Karunanithia43be802020-05-07 05:05:36 -05001055}
1056
zhanghch058d1b46d2021-04-01 11:18:24 +08001057inline void clearDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1058 const std::string& dumpType)
Asmitha Karunanithi80319af2020-05-07 05:30:21 -05001059{
Claire Weinan0d946212022-07-13 19:40:19 -07001060 crow::connections::systemBus->async_method_call(
1061 [asyncResp](const boost::system::error_code& ec) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001062 if (ec)
1063 {
1064 BMCWEB_LOG_ERROR("clearDump resp_handler got error {}", ec);
1065 messages::internalError(asyncResp->res);
1066 return;
1067 }
1068 },
Ed Tanous18f8f602023-07-18 10:07:23 -07001069 "xyz.openbmc_project.Dump.Manager", getDumpPath(dumpType),
Claire Weinan0d946212022-07-13 19:40:19 -07001070 "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
Asmitha Karunanithi80319af2020-05-07 05:30:21 -05001071}
1072
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001073inline void parseCrashdumpParameters(
1074 const dbus::utility::DBusPropertiesMap& params, std::string& filename,
1075 std::string& timestamp, std::string& logfile)
Johnathan Mantey043a0532020-03-10 17:15:28 -07001076{
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +02001077 const std::string* filenamePtr = nullptr;
1078 const std::string* timestampPtr = nullptr;
1079 const std::string* logfilePtr = nullptr;
1080
1081 const bool success = sdbusplus::unpackPropertiesNoThrow(
1082 dbus_utils::UnpackErrorPrinter(), params, "Timestamp", timestampPtr,
1083 "Filename", filenamePtr, "Log", logfilePtr);
1084
1085 if (!success)
Johnathan Mantey043a0532020-03-10 17:15:28 -07001086 {
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +02001087 return;
1088 }
1089
1090 if (filenamePtr != nullptr)
1091 {
1092 filename = *filenamePtr;
1093 }
1094
1095 if (timestampPtr != nullptr)
1096 {
1097 timestamp = *timestampPtr;
1098 }
1099
1100 if (logfilePtr != nullptr)
1101 {
1102 logfile = *logfilePtr;
Johnathan Mantey043a0532020-03-10 17:15:28 -07001103 }
1104}
1105
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001106inline void requestRoutesSystemLogServiceCollection(App& app)
Ed Tanous1da66f72018-07-27 16:13:37 -07001107{
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001108 /**
1109 * Functions triggers appropriate requests on DBus
1110 */
Ed Tanous22d268c2022-05-19 09:39:07 -07001111 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/")
Ed Tanoused398212021-06-09 17:05:54 -07001112 .privileges(redfish::privileges::getLogServiceCollection)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001113 .methods(
1114 boost::beast::http::verb::
1115 get)([&app](const crow::Request& req,
1116 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1117 const std::string& systemName) {
1118 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07001119 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001120 return;
1121 }
1122 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1123 {
1124 // Option currently returns no systems. TBD
1125 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1126 systemName);
1127 return;
1128 }
1129 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1130 {
1131 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1132 systemName);
Ed Tanous002d39b2022-05-31 08:59:27 -07001133 return;
1134 }
Ed Tanous45ca1b82022-03-25 13:07:27 -07001135
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001136 // Collections don't include the static data added by SubRoute
1137 // because it has a duplicate entry for members
1138 asyncResp->res.jsonValue["@odata.type"] =
1139 "#LogServiceCollection.LogServiceCollection";
1140 asyncResp->res.jsonValue["@odata.id"] =
1141 std::format("/redfish/v1/Systems/{}/LogServices",
1142 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1143 asyncResp->res.jsonValue["Name"] = "System Log Services Collection";
1144 asyncResp->res.jsonValue["Description"] =
1145 "Collection of LogServices for this Computer System";
1146 nlohmann::json& logServiceArray =
1147 asyncResp->res.jsonValue["Members"];
1148 logServiceArray = nlohmann::json::array();
1149 nlohmann::json::object_t eventLog;
1150 eventLog["@odata.id"] =
1151 std::format("/redfish/v1/Systems/{}/LogServices/EventLog",
1152 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1153 logServiceArray.emplace_back(std::move(eventLog));
1154 if constexpr (BMCWEB_REDFISH_DUMP_LOG)
Ed Tanous002d39b2022-05-31 08:59:27 -07001155 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001156 nlohmann::json::object_t dumpLog;
1157 dumpLog["@odata.id"] =
1158 std::format("/redfish/v1/Systems/{}/LogServices/Dump",
1159 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1160 logServiceArray.emplace_back(std::move(dumpLog));
Ed Tanous002d39b2022-05-31 08:59:27 -07001161 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001162
1163 if constexpr (BMCWEB_REDFISH_CPU_LOG)
1164 {
1165 nlohmann::json::object_t crashdump;
1166 crashdump["@odata.id"] =
1167 std::format("/redfish/v1/Systems/{}/LogServices/Crashdump",
1168 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1169 logServiceArray.emplace_back(std::move(crashdump));
1170 }
1171
1172 if constexpr (BMCWEB_REDFISH_HOST_LOGGER)
1173 {
1174 nlohmann::json::object_t hostlogger;
1175 hostlogger["@odata.id"] =
1176 std::format("/redfish/v1/Systems/{}/LogServices/HostLogger",
1177 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1178 logServiceArray.emplace_back(std::move(hostlogger));
1179 }
1180 asyncResp->res.jsonValue["Members@odata.count"] =
1181 logServiceArray.size();
1182
1183 constexpr std::array<std::string_view, 1> interfaces = {
1184 "xyz.openbmc_project.State.Boot.PostCode"};
1185 dbus::utility::getSubTreePaths(
1186 "/", 0, interfaces,
1187 [asyncResp](const boost::system::error_code& ec,
1188 const dbus::utility::MapperGetSubTreePathsResponse&
1189 subtreePath) {
1190 if (ec)
1191 {
1192 BMCWEB_LOG_ERROR("{}", ec);
1193 return;
1194 }
1195
1196 for (const auto& pathStr : subtreePath)
1197 {
1198 if (pathStr.find("PostCode") != std::string::npos)
1199 {
1200 nlohmann::json& logServiceArrayLocal =
1201 asyncResp->res.jsonValue["Members"];
1202 nlohmann::json::object_t member;
1203 member["@odata.id"] = std::format(
1204 "/redfish/v1/Systems/{}/LogServices/PostCodes",
1205 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1206
1207 logServiceArrayLocal.emplace_back(
1208 std::move(member));
1209
1210 asyncResp->res.jsonValue["Members@odata.count"] =
1211 logServiceArrayLocal.size();
1212 return;
1213 }
1214 }
1215 });
Ed Tanous45ca1b82022-03-25 13:07:27 -07001216 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001217}
1218
1219inline void requestRoutesEventLogService(App& app)
1220{
Ed Tanous22d268c2022-05-19 09:39:07 -07001221 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/")
Ed Tanoused398212021-06-09 17:05:54 -07001222 .privileges(redfish::privileges::getLogService)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001223 .methods(
1224 boost::beast::http::verb::
1225 get)([&app](const crow::Request& req,
1226 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1227 const std::string& systemName) {
1228 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1229 {
1230 return;
1231 }
1232 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1233 {
1234 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1235 systemName);
1236 return;
1237 }
1238 asyncResp->res.jsonValue["@odata.id"] =
1239 std::format("/redfish/v1/Systems/{}/LogServices/EventLog",
1240 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1241 asyncResp->res.jsonValue["@odata.type"] =
1242 "#LogService.v1_2_0.LogService";
1243 asyncResp->res.jsonValue["Name"] = "Event Log Service";
1244 asyncResp->res.jsonValue["Description"] =
1245 "System Event Log Service";
1246 asyncResp->res.jsonValue["Id"] = "EventLog";
1247 asyncResp->res.jsonValue["OverWritePolicy"] =
1248 log_service::OverWritePolicy::WrapsWhenFull;
Tejas Patil7c8c4052021-06-04 17:43:14 +05301249
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001250 std::pair<std::string, std::string> redfishDateTimeOffset =
1251 redfish::time_utils::getDateTimeOffsetNow();
Tejas Patil7c8c4052021-06-04 17:43:14 +05301252
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001253 asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
1254 asyncResp->res.jsonValue["DateTimeLocalOffset"] =
1255 redfishDateTimeOffset.second;
Tejas Patil7c8c4052021-06-04 17:43:14 +05301256
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001257 asyncResp->res.jsonValue["Entries"]["@odata.id"] = std::format(
1258 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
Ed Tanous20fa6a22024-05-20 18:02:58 -07001259 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001260 asyncResp->res
1261 .jsonValue["Actions"]["#LogService.ClearLog"]["target"]
1262
1263 = std::format(
1264 "/redfish/v1/Systems/{}/LogServices/EventLog/Actions/LogService.ClearLog",
1265 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1266 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001267}
1268
Alexander Hansen599b9af2024-08-06 15:11:57 +02001269inline void handleSystemsLogServicesEventLogActionsClearPost(
1270 App& app, const crow::Request& req,
1271 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1272 const std::string& systemName)
1273{
1274 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1275 {
1276 return;
1277 }
1278 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1279 {
1280 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1281 systemName);
1282 return;
1283 }
1284
1285 // Clear the EventLog by deleting the log files
1286 std::vector<std::filesystem::path> redfishLogFiles;
1287 if (getRedfishLogFiles(redfishLogFiles))
1288 {
1289 for (const std::filesystem::path& file : redfishLogFiles)
1290 {
1291 std::error_code ec;
1292 std::filesystem::remove(file, ec);
1293 }
1294 }
1295
1296 // Reload rsyslog so it knows to start new log files
1297 crow::connections::systemBus->async_method_call(
1298 [asyncResp](const boost::system::error_code& ec) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001299 if (ec)
1300 {
1301 BMCWEB_LOG_ERROR("Failed to reload rsyslog: {}", ec);
1302 messages::internalError(asyncResp->res);
1303 return;
1304 }
Alexander Hansen599b9af2024-08-06 15:11:57 +02001305
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001306 messages::success(asyncResp->res);
1307 },
Alexander Hansen599b9af2024-08-06 15:11:57 +02001308 "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
1309 "org.freedesktop.systemd1.Manager", "ReloadUnit", "rsyslog.service",
1310 "replace");
1311}
1312
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001313inline void requestRoutesJournalEventLogClear(App& app)
1314{
Jason M. Bills4978b632022-02-22 14:17:43 -08001315 BMCWEB_ROUTE(
1316 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07001317 "/redfish/v1/Systems/<str>/LogServices/EventLog/Actions/LogService.ClearLog/")
Ed Tanous432a8902021-06-14 15:28:56 -07001318 .privileges({{"ConfigureComponents"}})
Alexander Hansen599b9af2024-08-06 15:11:57 +02001319 .methods(boost::beast::http::verb::post)(std::bind_front(
1320 handleSystemsLogServicesEventLogActionsClearPost, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001321}
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001322
Jason M. Billsac992cd2022-06-24 13:31:46 -07001323enum class LogParseError
1324{
1325 success,
1326 parseFailed,
1327 messageIdNotInRegistry,
1328};
1329
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001330static LogParseError fillEventLogEntryJson(
1331 const std::string& logEntryID, const std::string& logEntry,
1332 nlohmann::json::object_t& logEntryJson)
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001333{
Jason M. Bills95820182019-04-22 16:25:34 -07001334 // The redfish log format is "<Timestamp> <MessageId>,<MessageArgs>"
Jason M. Billscd225da2019-05-08 15:31:57 -07001335 // First get the Timestamp
Ed Tanousf23b7292020-10-15 09:41:17 -07001336 size_t space = logEntry.find_first_of(' ');
Jason M. Billscd225da2019-05-08 15:31:57 -07001337 if (space == std::string::npos)
Jason M. Bills95820182019-04-22 16:25:34 -07001338 {
Jason M. Billsac992cd2022-06-24 13:31:46 -07001339 return LogParseError::parseFailed;
Jason M. Bills95820182019-04-22 16:25:34 -07001340 }
Jason M. Billscd225da2019-05-08 15:31:57 -07001341 std::string timestamp = logEntry.substr(0, space);
1342 // Then get the log contents
Ed Tanousf23b7292020-10-15 09:41:17 -07001343 size_t entryStart = logEntry.find_first_not_of(' ', space);
Jason M. Billscd225da2019-05-08 15:31:57 -07001344 if (entryStart == std::string::npos)
1345 {
Jason M. Billsac992cd2022-06-24 13:31:46 -07001346 return LogParseError::parseFailed;
Jason M. Billscd225da2019-05-08 15:31:57 -07001347 }
1348 std::string_view entry(logEntry);
1349 entry.remove_prefix(entryStart);
1350 // Use split to separate the entry into its fields
1351 std::vector<std::string> logEntryFields;
Ed Tanous50ebd4a2023-01-19 19:03:17 -08001352 bmcweb::split(logEntryFields, entry, ',');
Jason M. Billscd225da2019-05-08 15:31:57 -07001353 // We need at least a MessageId to be valid
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001354 auto logEntryIter = logEntryFields.begin();
1355 if (logEntryIter == logEntryFields.end())
Jason M. Billscd225da2019-05-08 15:31:57 -07001356 {
Jason M. Billsac992cd2022-06-24 13:31:46 -07001357 return LogParseError::parseFailed;
Jason M. Billscd225da2019-05-08 15:31:57 -07001358 }
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001359 std::string& messageID = *logEntryIter;
Jason M. Bills4851d452019-03-28 11:27:48 -07001360 // Get the Message from the MessageRegistry
Ed Tanousfffb8c12022-02-07 23:53:03 -08001361 const registries::Message* message = registries::getMessage(messageID);
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001362
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001363 logEntryIter++;
Sui Chen54417b02022-03-24 14:59:52 -07001364 if (message == nullptr)
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001365 {
Ed Tanous62598e32023-07-17 17:06:25 -07001366 BMCWEB_LOG_WARNING("Log entry not found in registry: {}", logEntry);
Jason M. Billsac992cd2022-06-24 13:31:46 -07001367 return LogParseError::messageIdNotInRegistry;
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001368 }
1369
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001370 std::vector<std::string_view> messageArgs(logEntryIter,
1371 logEntryFields.end());
Ed Tanousc05bba42023-06-28 08:33:29 -07001372 messageArgs.resize(message->numberOfArgs);
1373
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001374 std::string msg =
1375 redfish::registries::fillMessageArgs(messageArgs, message->message);
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001376 if (msg.empty())
Jason M. Bills4851d452019-03-28 11:27:48 -07001377 {
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001378 return LogParseError::parseFailed;
Jason M. Bills4851d452019-03-28 11:27:48 -07001379 }
1380
Jason M. Bills95820182019-04-22 16:25:34 -07001381 // Get the Created time from the timestamp. The log timestamp is in RFC3339
1382 // format which matches the Redfish format except for the fractional seconds
1383 // between the '.' and the '+', so just remove them.
Ed Tanousf23b7292020-10-15 09:41:17 -07001384 std::size_t dot = timestamp.find_first_of('.');
1385 std::size_t plus = timestamp.find_first_of('+');
Jason M. Bills95820182019-04-22 16:25:34 -07001386 if (dot != std::string::npos && plus != std::string::npos)
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001387 {
Jason M. Bills95820182019-04-22 16:25:34 -07001388 timestamp.erase(dot, plus - dot);
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001389 }
1390
1391 // Fill in the log entry with the gathered data
Vijay Lobo9c11a172021-10-07 16:53:16 -05001392 logEntryJson["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
Ed Tanousef4c65b2023-04-24 15:28:50 -07001393 logEntryJson["@odata.id"] = boost::urls::format(
Ed Tanous253f11b2024-05-16 09:38:31 -07001394 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}",
1395 BMCWEB_REDFISH_SYSTEM_URI_NAME, logEntryID);
Jason M. Bills84afc482022-06-24 12:38:23 -07001396 logEntryJson["Name"] = "System Event Log Entry";
1397 logEntryJson["Id"] = logEntryID;
1398 logEntryJson["Message"] = std::move(msg);
1399 logEntryJson["MessageId"] = std::move(messageID);
1400 logEntryJson["MessageArgs"] = messageArgs;
1401 logEntryJson["EntryType"] = "Event";
1402 logEntryJson["Severity"] = message->messageSeverity;
1403 logEntryJson["Created"] = std::move(timestamp);
Jason M. Billsac992cd2022-06-24 13:31:46 -07001404 return LogParseError::success;
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001405}
1406
Ed Tanous898f2aa2024-08-07 12:18:22 -07001407inline void fillEventLogLogEntryFromPropertyMap(
1408 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1409 const dbus::utility::DBusPropertiesMap& resp,
1410 nlohmann::json& objectToFillOut)
1411{
Alexander Hansen262dcc12024-09-19 12:04:03 +02001412 std::optional<DbusEventLogEntry> optEntry =
1413 fillDbusEventLogEntryFromPropertyMap(resp);
Ed Tanous898f2aa2024-08-07 12:18:22 -07001414
Alexander Hansen262dcc12024-09-19 12:04:03 +02001415 if (!optEntry.has_value())
Ed Tanous898f2aa2024-08-07 12:18:22 -07001416 {
1417 messages::internalError(asyncResp->res);
1418 return;
1419 }
Alexander Hansen262dcc12024-09-19 12:04:03 +02001420 DbusEventLogEntry entry = optEntry.value();
Ed Tanous898f2aa2024-08-07 12:18:22 -07001421
1422 objectToFillOut["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
1423 objectToFillOut["@odata.id"] = boost::urls::format(
1424 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}",
Alexander Hansen262dcc12024-09-19 12:04:03 +02001425 BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(entry.Id));
Ed Tanous898f2aa2024-08-07 12:18:22 -07001426 objectToFillOut["Name"] = "System Event Log Entry";
Alexander Hansen262dcc12024-09-19 12:04:03 +02001427 objectToFillOut["Id"] = std::to_string(entry.Id);
1428 objectToFillOut["Message"] = entry.Message;
1429 objectToFillOut["Resolved"] = entry.Resolved;
1430 std::optional<bool> notifyAction =
1431 getProviderNotifyAction(entry.ServiceProviderNotify);
Ed Tanous898f2aa2024-08-07 12:18:22 -07001432 if (notifyAction)
1433 {
1434 objectToFillOut["ServiceProviderNotified"] = *notifyAction;
1435 }
Alexander Hansen262dcc12024-09-19 12:04:03 +02001436 if ((entry.Resolution != nullptr) && !entry.Resolution->empty())
Ed Tanous898f2aa2024-08-07 12:18:22 -07001437 {
Alexander Hansen262dcc12024-09-19 12:04:03 +02001438 objectToFillOut["Resolution"] = *entry.Resolution;
Ed Tanous898f2aa2024-08-07 12:18:22 -07001439 }
1440 objectToFillOut["EntryType"] = "Event";
Alexander Hansen262dcc12024-09-19 12:04:03 +02001441 objectToFillOut["Severity"] =
1442 translateSeverityDbusToRedfish(entry.Severity);
Ed Tanous898f2aa2024-08-07 12:18:22 -07001443 objectToFillOut["Created"] =
Alexander Hansen262dcc12024-09-19 12:04:03 +02001444 redfish::time_utils::getDateTimeUintMs(entry.Timestamp);
Ed Tanous898f2aa2024-08-07 12:18:22 -07001445 objectToFillOut["Modified"] =
Alexander Hansen262dcc12024-09-19 12:04:03 +02001446 redfish::time_utils::getDateTimeUintMs(entry.UpdateTimestamp);
1447 if (entry.Path != nullptr)
Ed Tanous898f2aa2024-08-07 12:18:22 -07001448 {
1449 objectToFillOut["AdditionalDataURI"] = boost::urls::format(
1450 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}/attachment",
Alexander Hansen262dcc12024-09-19 12:04:03 +02001451 BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(entry.Id));
Ed Tanous898f2aa2024-08-07 12:18:22 -07001452 }
1453}
1454
Ed Tanousb7290962024-08-07 11:09:51 -07001455inline void afterLogEntriesGetManagedObjects(
1456 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1457 const boost::system::error_code& ec,
1458 const dbus::utility::ManagedObjectType& resp)
1459{
1460 if (ec)
1461 {
1462 // TODO Handle for specific error code
1463 BMCWEB_LOG_ERROR("getLogEntriesIfaceData resp_handler got error {}",
1464 ec);
1465 messages::internalError(asyncResp->res);
1466 return;
1467 }
1468 nlohmann::json::array_t entriesArray;
1469 for (const auto& objectPath : resp)
1470 {
Ed Tanous898f2aa2024-08-07 12:18:22 -07001471 dbus::utility::DBusPropertiesMap propsFlattened;
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001472 auto isEntry =
1473 std::ranges::find_if(objectPath.second, [](const auto& object) {
1474 return object.first == "xyz.openbmc_project.Logging.Entry";
1475 });
Ed Tanous898f2aa2024-08-07 12:18:22 -07001476 if (isEntry == objectPath.second.end())
Ed Tanousb7290962024-08-07 11:09:51 -07001477 {
1478 continue;
1479 }
Ed Tanous898f2aa2024-08-07 12:18:22 -07001480 for (const auto& interfaceMap : objectPath.second)
Ed Tanousb7290962024-08-07 11:09:51 -07001481 {
Ed Tanous898f2aa2024-08-07 12:18:22 -07001482 for (const auto& propertyMap : interfaceMap.second)
Ed Tanousb7290962024-08-07 11:09:51 -07001483 {
Ed Tanous898f2aa2024-08-07 12:18:22 -07001484 propsFlattened.emplace_back(propertyMap.first,
1485 propertyMap.second);
Ed Tanousb7290962024-08-07 11:09:51 -07001486 }
1487 }
Ed Tanous898f2aa2024-08-07 12:18:22 -07001488 fillEventLogLogEntryFromPropertyMap(asyncResp, propsFlattened,
1489 entriesArray.emplace_back());
Ed Tanousb7290962024-08-07 11:09:51 -07001490 }
Ed Tanous898f2aa2024-08-07 12:18:22 -07001491
Ed Tanousb7290962024-08-07 11:09:51 -07001492 std::ranges::sort(entriesArray, [](const nlohmann::json& left,
1493 const nlohmann::json& right) {
1494 return (left["Id"] <= right["Id"]);
1495 });
1496 asyncResp->res.jsonValue["Members@odata.count"] = entriesArray.size();
1497 asyncResp->res.jsonValue["Members"] = std::move(entriesArray);
1498}
1499
Alexander Hansen599b9af2024-08-06 15:11:57 +02001500inline void handleSystemsLogServiceEventLogLogEntryCollection(
1501 App& app, const crow::Request& req,
1502 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1503 const std::string& systemName)
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001504{
Alexander Hansen599b9af2024-08-06 15:11:57 +02001505 query_param::QueryCapabilities capabilities = {
1506 .canDelegateTop = true,
1507 .canDelegateSkip = true,
1508 };
1509 query_param::Query delegatedQuery;
1510 if (!redfish::setUpRedfishRouteWithDelegation(app, req, asyncResp,
1511 delegatedQuery, capabilities))
1512 {
1513 return;
1514 }
1515 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1516 {
1517 // Option currently returns no systems. TBD
1518 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1519 systemName);
1520 return;
1521 }
1522 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1523 {
1524 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1525 systemName);
1526 return;
1527 }
1528
1529 size_t top = delegatedQuery.top.value_or(query_param::Query::maxTop);
1530 size_t skip = delegatedQuery.skip.value_or(0);
1531
1532 // Collections don't include the static data added by SubRoute
1533 // because it has a duplicate entry for members
1534 asyncResp->res.jsonValue["@odata.type"] =
1535 "#LogEntryCollection.LogEntryCollection";
1536 asyncResp->res.jsonValue["@odata.id"] =
1537 std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
1538 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1539 asyncResp->res.jsonValue["Name"] = "System Event Log Entries";
1540 asyncResp->res.jsonValue["Description"] =
1541 "Collection of System Event Log Entries";
1542
1543 nlohmann::json& logEntryArray = asyncResp->res.jsonValue["Members"];
1544 logEntryArray = nlohmann::json::array();
1545 // Go through the log files and create a unique ID for each
1546 // entry
1547 std::vector<std::filesystem::path> redfishLogFiles;
1548 getRedfishLogFiles(redfishLogFiles);
1549 uint64_t entryCount = 0;
1550 std::string logEntry;
1551
1552 // Oldest logs are in the last file, so start there and loop
1553 // backwards
1554 for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend(); it++)
1555 {
1556 std::ifstream logStream(*it);
1557 if (!logStream.is_open())
Ed Tanous002d39b2022-05-31 08:59:27 -07001558 {
Alexander Hansen599b9af2024-08-06 15:11:57 +02001559 continue;
Ed Tanous22d268c2022-05-19 09:39:07 -07001560 }
1561
Alexander Hansen599b9af2024-08-06 15:11:57 +02001562 // Reset the unique ID on the first entry
1563 bool firstEntry = true;
1564 while (std::getline(logStream, logEntry))
Ed Tanous002d39b2022-05-31 08:59:27 -07001565 {
Alexander Hansen599b9af2024-08-06 15:11:57 +02001566 std::string idStr;
1567 if (!getUniqueEntryID(logEntry, idStr, firstEntry))
1568 {
1569 continue;
1570 }
1571 firstEntry = false;
1572
1573 nlohmann::json::object_t bmcLogEntry;
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001574 LogParseError status =
1575 fillEventLogEntryJson(idStr, logEntry, bmcLogEntry);
Alexander Hansen599b9af2024-08-06 15:11:57 +02001576 if (status == LogParseError::messageIdNotInRegistry)
1577 {
1578 continue;
1579 }
1580 if (status != LogParseError::success)
1581 {
1582 messages::internalError(asyncResp->res);
1583 return;
1584 }
1585
1586 entryCount++;
1587 // Handle paging using skip (number of entries to skip from the
1588 // start) and top (number of entries to display)
1589 if (entryCount <= skip || entryCount > skip + top)
Jason M. Bills4978b632022-02-22 14:17:43 -08001590 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001591 continue;
Jason M. Bills4978b632022-02-22 14:17:43 -08001592 }
Jason M. Bills897967d2019-07-29 17:05:30 -07001593
Alexander Hansen599b9af2024-08-06 15:11:57 +02001594 logEntryArray.emplace_back(std::move(bmcLogEntry));
1595 }
1596 }
1597 asyncResp->res.jsonValue["Members@odata.count"] = entryCount;
1598 if (skip + top < entryCount)
1599 {
1600 asyncResp->res.jsonValue["Members@odata.nextLink"] =
1601 boost::urls::format(
1602 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries?$skip={}",
1603 BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(skip + top));
1604 }
1605}
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001606
Alexander Hansen599b9af2024-08-06 15:11:57 +02001607inline void requestRoutesJournalEventLogEntryCollection(App& app)
1608{
1609 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/")
1610 .privileges(redfish::privileges::getLogEntryCollection)
1611 .methods(boost::beast::http::verb::get)(std::bind_front(
1612 handleSystemsLogServiceEventLogLogEntryCollection, std::ref(app)));
1613}
1614
1615inline void handleSystemsLogServiceEventLogEntriesGet(
1616 App& app, const crow::Request& req,
1617 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1618 const std::string& systemName, const std::string& param)
1619{
1620 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1621 {
1622 return;
1623 }
1624 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1625 {
1626 // Option currently returns no systems. TBD
1627 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1628 systemName);
1629 return;
1630 }
1631
1632 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1633 {
1634 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1635 systemName);
1636 return;
1637 }
1638
1639 const std::string& targetID = param;
1640
1641 // Go through the log files and check the unique ID for each
1642 // entry to find the target entry
1643 std::vector<std::filesystem::path> redfishLogFiles;
1644 getRedfishLogFiles(redfishLogFiles);
1645 std::string logEntry;
1646
1647 // Oldest logs are in the last file, so start there and loop
1648 // backwards
1649 for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend(); it++)
1650 {
1651 std::ifstream logStream(*it);
1652 if (!logStream.is_open())
1653 {
1654 continue;
1655 }
1656
1657 // Reset the unique ID on the first entry
1658 bool firstEntry = true;
1659 while (std::getline(logStream, logEntry))
1660 {
1661 std::string idStr;
1662 if (!getUniqueEntryID(logEntry, idStr, firstEntry))
1663 {
1664 continue;
1665 }
1666 firstEntry = false;
1667
1668 if (idStr == targetID)
1669 {
Jason M. Billsde703c52022-06-23 14:19:04 -07001670 nlohmann::json::object_t bmcLogEntry;
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001671 LogParseError status =
1672 fillEventLogEntryJson(idStr, logEntry, bmcLogEntry);
Jason M. Billsac992cd2022-06-24 13:31:46 -07001673 if (status != LogParseError::success)
Ed Tanous002d39b2022-05-31 08:59:27 -07001674 {
1675 messages::internalError(asyncResp->res);
1676 return;
Andrew Geisslercb92c032018-08-17 07:56:14 -07001677 }
Alexander Hansen599b9af2024-08-06 15:11:57 +02001678 asyncResp->res.jsonValue.update(bmcLogEntry);
1679 return;
Jason M. Bills4978b632022-02-22 14:17:43 -08001680 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001681 }
Alexander Hansen599b9af2024-08-06 15:11:57 +02001682 }
1683 // Requested ID was not found
1684 messages::resourceNotFound(asyncResp->res, "LogEntry", targetID);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001685}
Chicago Duan336e96c2019-07-15 14:22:08 +08001686
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001687inline void requestRoutesJournalEventLogEntry(App& app)
1688{
1689 BMCWEB_ROUTE(
Ed Tanous22d268c2022-05-19 09:39:07 -07001690 app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001691 .privileges(redfish::privileges::getLogEntry)
Alexander Hansen599b9af2024-08-06 15:11:57 +02001692 .methods(boost::beast::http::verb::get)(std::bind_front(
1693 handleSystemsLogServiceEventLogEntriesGet, std::ref(app)));
1694}
1695
1696inline void dBusEventLogEntryCollection(
1697 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1698{
1699 // Collections don't include the static data added by SubRoute
1700 // because it has a duplicate entry for members
1701 asyncResp->res.jsonValue["@odata.type"] =
1702 "#LogEntryCollection.LogEntryCollection";
1703 asyncResp->res.jsonValue["@odata.id"] =
1704 std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
1705 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1706 asyncResp->res.jsonValue["Name"] = "System Event Log Entries";
1707 asyncResp->res.jsonValue["Description"] =
1708 "Collection of System Event Log Entries";
1709
1710 // DBus implementation of EventLog/Entries
1711 // Make call to Logging Service to find all log entry objects
1712 sdbusplus::message::object_path path("/xyz/openbmc_project/logging");
1713 dbus::utility::getManagedObjects(
1714 "xyz.openbmc_project.Logging", path,
1715 [asyncResp](const boost::system::error_code& ec,
1716 const dbus::utility::ManagedObjectType& resp) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001717 afterLogEntriesGetManagedObjects(asyncResp, ec, resp);
1718 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001719}
1720
1721inline void requestRoutesDBusEventLogEntryCollection(App& app)
1722{
Ed Tanous22d268c2022-05-19 09:39:07 -07001723 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/")
Ed Tanoused398212021-06-09 17:05:54 -07001724 .privileges(redfish::privileges::getLogEntryCollection)
Ed Tanous002d39b2022-05-31 08:59:27 -07001725 .methods(boost::beast::http::verb::get)(
1726 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07001727 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1728 const std::string& systemName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001729 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1730 {
1731 return;
1732 }
1733 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1734 {
1735 // Option currently returns no systems. TBD
1736 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1737 systemName);
1738 return;
1739 }
1740 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1741 {
1742 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1743 systemName);
1744 return;
1745 }
1746 dBusEventLogEntryCollection(asyncResp);
1747 });
Alexander Hansen599b9af2024-08-06 15:11:57 +02001748}
Ed Tanous22d268c2022-05-19 09:39:07 -07001749
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001750inline void dBusEventLogEntryGet(
1751 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID)
Alexander Hansen599b9af2024-08-06 15:11:57 +02001752{
1753 dbus::utility::escapePathForDbus(entryID);
Ed Tanous002d39b2022-05-31 08:59:27 -07001754
Alexander Hansen599b9af2024-08-06 15:11:57 +02001755 // DBus implementation of EventLog/Entries
1756 // Make call to Logging Service to find all log entry objects
Ed Tanousdeae6a72024-11-11 21:58:57 -08001757 dbus::utility::getAllProperties(
1758 "xyz.openbmc_project.Logging",
Alexander Hansen599b9af2024-08-06 15:11:57 +02001759 "/xyz/openbmc_project/logging/entry/" + entryID, "",
1760 [asyncResp, entryID](const boost::system::error_code& ec,
1761 const dbus::utility::DBusPropertiesMap& resp) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001762 if (ec.value() == EBADR)
1763 {
1764 messages::resourceNotFound(asyncResp->res, "EventLogEntry",
1765 entryID);
1766 return;
1767 }
1768 if (ec)
1769 {
1770 BMCWEB_LOG_ERROR(
1771 "EventLogEntry (DBus) resp_handler got error {}", ec);
1772 messages::internalError(asyncResp->res);
1773 return;
1774 }
Alexander Hansen599b9af2024-08-06 15:11:57 +02001775
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001776 fillEventLogLogEntryFromPropertyMap(asyncResp, resp,
1777 asyncResp->res.jsonValue);
1778 });
Alexander Hansen599b9af2024-08-06 15:11:57 +02001779}
1780
1781inline void
1782 dBusEventLogEntryPatch(const crow::Request& req,
1783 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1784 const std::string& entryId)
1785{
1786 std::optional<bool> resolved;
1787
1788 if (!json_util::readJsonPatch(req, asyncResp->res, "Resolved", resolved))
1789 {
1790 return;
1791 }
1792 BMCWEB_LOG_DEBUG("Set Resolved");
1793
1794 setDbusProperty(asyncResp, "Resolved", "xyz.openbmc_project.Logging",
1795 "/xyz/openbmc_project/logging/entry/" + entryId,
1796 "xyz.openbmc_project.Logging.Entry", "Resolved",
1797 resolved.value_or(false));
1798}
1799
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001800inline void dBusEventLogEntryDelete(
1801 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID)
Alexander Hansen599b9af2024-08-06 15:11:57 +02001802{
1803 BMCWEB_LOG_DEBUG("Do delete single event entries.");
1804
1805 dbus::utility::escapePathForDbus(entryID);
1806
1807 // Process response from Logging service.
1808 auto respHandler = [asyncResp,
1809 entryID](const boost::system::error_code& ec) {
1810 BMCWEB_LOG_DEBUG("EventLogEntry (DBus) doDelete callback: Done");
1811 if (ec)
1812 {
1813 if (ec.value() == EBADR)
Ed Tanous45ca1b82022-03-25 13:07:27 -07001814 {
Alexander Hansen599b9af2024-08-06 15:11:57 +02001815 messages::resourceNotFound(asyncResp->res, "LogEntry", entryID);
Ed Tanous45ca1b82022-03-25 13:07:27 -07001816 return;
1817 }
Alexander Hansen599b9af2024-08-06 15:11:57 +02001818 // TODO Handle for specific error code
1819 BMCWEB_LOG_ERROR(
1820 "EventLogEntry (DBus) doDelete respHandler got error {}", ec);
1821 asyncResp->res.result(
1822 boost::beast::http::status::internal_server_error);
1823 return;
1824 }
Abhishek Patel9017faf2021-09-14 22:48:55 -05001825
Alexander Hansen599b9af2024-08-06 15:11:57 +02001826 asyncResp->res.result(boost::beast::http::status::ok);
1827 };
1828
1829 // Make call to Logging service to request Delete Log
1830 crow::connections::systemBus->async_method_call(
1831 respHandler, "xyz.openbmc_project.Logging",
1832 "/xyz/openbmc_project/logging/entry/" + entryID,
1833 "xyz.openbmc_project.Object.Delete", "Delete");
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001834}
Xiaochao Ma75710de2021-01-21 17:56:02 +08001835
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001836inline void requestRoutesDBusEventLogEntry(App& app)
Adriana Kobylak400fd1f2021-01-29 09:01:30 -06001837{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001838 BMCWEB_ROUTE(
Ed Tanous22d268c2022-05-19 09:39:07 -07001839 app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001840 .privileges(redfish::privileges::getLogEntry)
Ed Tanous002d39b2022-05-31 08:59:27 -07001841 .methods(boost::beast::http::verb::get)(
1842 [&app](const crow::Request& req,
1843 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous898f2aa2024-08-07 12:18:22 -07001844 const std::string& systemName, const std::string& entryId) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001845 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1846 {
1847 return;
1848 }
1849 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1850 {
1851 // Option currently returns no systems. TBD
1852 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1853 systemName);
1854 return;
1855 }
1856 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1857 {
1858 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1859 systemName);
1860 return;
1861 }
Ed Tanous22d268c2022-05-19 09:39:07 -07001862
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001863 dBusEventLogEntryGet(asyncResp, entryId);
1864 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001865
1866 BMCWEB_ROUTE(
Ed Tanous22d268c2022-05-19 09:39:07 -07001867 app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001868 .privileges(redfish::privileges::patchLogEntry)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001869 .methods(boost::beast::http::verb::patch)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07001870 [&app](const crow::Request& req,
1871 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -07001872 const std::string& systemName, const std::string& entryId) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001873 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1874 {
1875 return;
1876 }
1877 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1878 {
1879 // Option currently returns no systems. TBD
1880 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1881 systemName);
1882 return;
1883 }
1884 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1885 {
1886 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1887 systemName);
1888 return;
1889 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001890
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001891 dBusEventLogEntryPatch(req, asyncResp, entryId);
1892 });
Adriana Kobylak400fd1f2021-01-29 09:01:30 -06001893
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001894 BMCWEB_ROUTE(
Ed Tanous22d268c2022-05-19 09:39:07 -07001895 app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001896 .privileges(redfish::privileges::deleteLogEntry)
1897
Ed Tanous002d39b2022-05-31 08:59:27 -07001898 .methods(boost::beast::http::verb::delete_)(
1899 [&app](const crow::Request& req,
1900 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -07001901 const std::string& systemName, const std::string& param) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001902 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1903 {
1904 return;
1905 }
1906 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1907 {
1908 // Option currently returns no systems. TBD
1909 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1910 systemName);
1911 return;
1912 }
1913 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1914 {
1915 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1916 systemName);
1917 return;
1918 }
1919 dBusEventLogEntryDelete(asyncResp, param);
1920 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001921}
1922
Spencer Kub7028eb2021-10-26 15:27:35 +08001923constexpr const char* hostLoggerFolderPath = "/var/log/console";
1924
1925inline bool
1926 getHostLoggerFiles(const std::string& hostLoggerFilePath,
1927 std::vector<std::filesystem::path>& hostLoggerFiles)
1928{
1929 std::error_code ec;
1930 std::filesystem::directory_iterator logPath(hostLoggerFilePath, ec);
1931 if (ec)
1932 {
Carson Labradobf2dded2023-08-10 00:37:06 +00001933 BMCWEB_LOG_WARNING("{}", ec.message());
Spencer Kub7028eb2021-10-26 15:27:35 +08001934 return false;
1935 }
1936 for (const std::filesystem::directory_entry& it : logPath)
1937 {
1938 std::string filename = it.path().filename();
1939 // Prefix of each log files is "log". Find the file and save the
1940 // path
Ed Tanous11ba3972022-07-11 09:50:41 -07001941 if (filename.starts_with("log"))
Spencer Kub7028eb2021-10-26 15:27:35 +08001942 {
1943 hostLoggerFiles.emplace_back(it.path());
1944 }
1945 }
1946 // As the log files rotate, they are appended with a ".#" that is higher for
1947 // the older logs. Since we start from oldest logs, sort the name in
1948 // descending order.
1949 std::sort(hostLoggerFiles.rbegin(), hostLoggerFiles.rend(),
1950 AlphanumLess<std::string>());
1951
1952 return true;
1953}
1954
Ed Tanous02cad962022-06-30 16:50:15 -07001955inline bool getHostLoggerEntries(
1956 const std::vector<std::filesystem::path>& hostLoggerFiles, uint64_t skip,
1957 uint64_t top, std::vector<std::string>& logEntries, size_t& logCount)
Spencer Kub7028eb2021-10-26 15:27:35 +08001958{
1959 GzFileReader logFile;
1960
1961 // Go though all log files and expose host logs.
1962 for (const std::filesystem::path& it : hostLoggerFiles)
1963 {
1964 if (!logFile.gzGetLines(it.string(), skip, top, logEntries, logCount))
1965 {
Ed Tanous62598e32023-07-17 17:06:25 -07001966 BMCWEB_LOG_ERROR("fail to expose host logs");
Spencer Kub7028eb2021-10-26 15:27:35 +08001967 return false;
1968 }
1969 }
1970 // Get lastMessage from constructor by getter
1971 std::string lastMessage = logFile.getLastMessage();
1972 if (!lastMessage.empty())
1973 {
1974 logCount++;
1975 if (logCount > skip && logCount <= (skip + top))
1976 {
1977 logEntries.push_back(lastMessage);
1978 }
1979 }
1980 return true;
1981}
1982
Claire Weinandd72e872022-08-15 14:20:06 -07001983inline void handleBMCLogServicesCollectionGet(
Claire Weinanfdd26902022-03-01 14:18:25 -08001984 crow::App& app, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07001985 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1986 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08001987{
1988 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1989 {
1990 return;
1991 }
Ed Tanous253f11b2024-05-16 09:38:31 -07001992
1993 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
1994 {
1995 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
1996 return;
1997 }
1998
Claire Weinanfdd26902022-03-01 14:18:25 -08001999 // Collections don't include the static data added by SubRoute
2000 // because it has a duplicate entry for members
2001 asyncResp->res.jsonValue["@odata.type"] =
2002 "#LogServiceCollection.LogServiceCollection";
Ed Tanous253f11b2024-05-16 09:38:31 -07002003 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
2004 "/redfish/v1/Managers/{}/LogServices", BMCWEB_REDFISH_MANAGER_URI_NAME);
Claire Weinanfdd26902022-03-01 14:18:25 -08002005 asyncResp->res.jsonValue["Name"] = "Open BMC Log Services Collection";
2006 asyncResp->res.jsonValue["Description"] =
2007 "Collection of LogServices for this Manager";
2008 nlohmann::json& logServiceArray = asyncResp->res.jsonValue["Members"];
2009 logServiceArray = nlohmann::json::array();
2010
Ed Tanous25b54db2024-04-17 15:40:31 -07002011 if constexpr (BMCWEB_REDFISH_BMC_JOURNAL)
2012 {
2013 nlohmann::json::object_t journal;
Ed Tanous253f11b2024-05-16 09:38:31 -07002014 journal["@odata.id"] =
2015 boost::urls::format("/redfish/v1/Managers/{}/LogServices/Journal",
2016 BMCWEB_REDFISH_MANAGER_URI_NAME);
Ed Tanous25b54db2024-04-17 15:40:31 -07002017 logServiceArray.emplace_back(std::move(journal));
2018 }
Claire Weinanfdd26902022-03-01 14:18:25 -08002019
2020 asyncResp->res.jsonValue["Members@odata.count"] = logServiceArray.size();
2021
Ed Tanous25b54db2024-04-17 15:40:31 -07002022 if constexpr (BMCWEB_REDFISH_DUMP_LOG)
2023 {
2024 constexpr std::array<std::string_view, 1> interfaces = {
2025 "xyz.openbmc_project.Collection.DeleteAll"};
2026 dbus::utility::getSubTreePaths(
2027 "/xyz/openbmc_project/dump", 0, interfaces,
2028 [asyncResp](const boost::system::error_code& ec,
2029 const dbus::utility::MapperGetSubTreePathsResponse&
2030 subTreePaths) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002031 if (ec)
Ed Tanous25b54db2024-04-17 15:40:31 -07002032 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002033 BMCWEB_LOG_ERROR(
2034 "handleBMCLogServicesCollectionGet respHandler got error {}",
2035 ec);
2036 // Assume that getting an error simply means there are no
2037 // dump LogServices. Return without adding any error
2038 // response.
2039 return;
Ed Tanous25b54db2024-04-17 15:40:31 -07002040 }
Ed Tanous25b54db2024-04-17 15:40:31 -07002041
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002042 nlohmann::json& logServiceArrayLocal =
2043 asyncResp->res.jsonValue["Members"];
2044
2045 for (const std::string& path : subTreePaths)
2046 {
2047 if (path == "/xyz/openbmc_project/dump/bmc")
2048 {
2049 nlohmann::json::object_t member;
2050 member["@odata.id"] = boost::urls::format(
2051 "/redfish/v1/Managers/{}/LogServices/Dump",
2052 BMCWEB_REDFISH_MANAGER_URI_NAME);
2053 logServiceArrayLocal.emplace_back(std::move(member));
2054 }
2055 else if (path == "/xyz/openbmc_project/dump/faultlog")
2056 {
2057 nlohmann::json::object_t member;
2058 member["@odata.id"] = boost::urls::format(
2059 "/redfish/v1/Managers/{}/LogServices/FaultLog",
2060 BMCWEB_REDFISH_MANAGER_URI_NAME);
2061 logServiceArrayLocal.emplace_back(std::move(member));
2062 }
2063 }
2064
2065 asyncResp->res.jsonValue["Members@odata.count"] =
2066 logServiceArrayLocal.size();
2067 });
Ed Tanous25b54db2024-04-17 15:40:31 -07002068 }
Claire Weinanfdd26902022-03-01 14:18:25 -08002069}
2070
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002071inline void requestRoutesBMCLogServiceCollection(App& app)
2072{
Ed Tanous253f11b2024-05-16 09:38:31 -07002073 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/")
Gunnar Millsad89dcf2021-07-30 14:40:11 -05002074 .privileges(redfish::privileges::getLogServiceCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002075 .methods(boost::beast::http::verb::get)(
Claire Weinandd72e872022-08-15 14:20:06 -07002076 std::bind_front(handleBMCLogServicesCollectionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002077}
Ed Tanous1da66f72018-07-27 16:13:37 -07002078
Claire Weinanfdd26902022-03-01 14:18:25 -08002079inline void
2080 getDumpServiceInfo(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2081 const std::string& dumpType)
2082{
2083 std::string dumpPath;
Ed Tanous539d8c62024-06-19 14:38:27 -07002084 log_service::OverWritePolicy overWritePolicy =
2085 log_service::OverWritePolicy::Invalid;
Claire Weinanfdd26902022-03-01 14:18:25 -08002086 bool collectDiagnosticDataSupported = false;
2087
2088 if (dumpType == "BMC")
2089 {
Ed Tanous253f11b2024-05-16 09:38:31 -07002090 dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/Dump",
2091 BMCWEB_REDFISH_MANAGER_URI_NAME);
Ed Tanous539d8c62024-06-19 14:38:27 -07002092 overWritePolicy = log_service::OverWritePolicy::WrapsWhenFull;
Claire Weinanfdd26902022-03-01 14:18:25 -08002093 collectDiagnosticDataSupported = true;
2094 }
2095 else if (dumpType == "FaultLog")
2096 {
Ed Tanous253f11b2024-05-16 09:38:31 -07002097 dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/FaultLog",
2098 BMCWEB_REDFISH_MANAGER_URI_NAME);
Ed Tanous539d8c62024-06-19 14:38:27 -07002099 overWritePolicy = log_service::OverWritePolicy::Unknown;
Claire Weinanfdd26902022-03-01 14:18:25 -08002100 collectDiagnosticDataSupported = false;
2101 }
2102 else if (dumpType == "System")
2103 {
Ed Tanous253f11b2024-05-16 09:38:31 -07002104 dumpPath = std::format("/redfish/v1/Systems/{}/LogServices/Dump",
2105 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanous539d8c62024-06-19 14:38:27 -07002106 overWritePolicy = log_service::OverWritePolicy::WrapsWhenFull;
Claire Weinanfdd26902022-03-01 14:18:25 -08002107 collectDiagnosticDataSupported = true;
2108 }
2109 else
2110 {
Ed Tanous62598e32023-07-17 17:06:25 -07002111 BMCWEB_LOG_ERROR("getDumpServiceInfo() invalid dump type: {}",
2112 dumpType);
Claire Weinanfdd26902022-03-01 14:18:25 -08002113 messages::internalError(asyncResp->res);
2114 return;
2115 }
2116
2117 asyncResp->res.jsonValue["@odata.id"] = dumpPath;
2118 asyncResp->res.jsonValue["@odata.type"] = "#LogService.v1_2_0.LogService";
2119 asyncResp->res.jsonValue["Name"] = "Dump LogService";
2120 asyncResp->res.jsonValue["Description"] = dumpType + " Dump LogService";
2121 asyncResp->res.jsonValue["Id"] = std::filesystem::path(dumpPath).filename();
Ed Tanous539d8c62024-06-19 14:38:27 -07002122 asyncResp->res.jsonValue["OverWritePolicy"] = overWritePolicy;
Claire Weinanfdd26902022-03-01 14:18:25 -08002123
2124 std::pair<std::string, std::string> redfishDateTimeOffset =
Ed Tanous2b829372022-08-03 14:22:34 -07002125 redfish::time_utils::getDateTimeOffsetNow();
Claire Weinanfdd26902022-03-01 14:18:25 -08002126 asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
2127 asyncResp->res.jsonValue["DateTimeLocalOffset"] =
2128 redfishDateTimeOffset.second;
2129
2130 asyncResp->res.jsonValue["Entries"]["@odata.id"] = dumpPath + "/Entries";
Claire Weinanfdd26902022-03-01 14:18:25 -08002131
2132 if (collectDiagnosticDataSupported)
2133 {
2134 asyncResp->res.jsonValue["Actions"]["#LogService.CollectDiagnosticData"]
2135 ["target"] =
2136 dumpPath + "/Actions/LogService.CollectDiagnosticData";
2137 }
Claire Weinan0d946212022-07-13 19:40:19 -07002138
2139 constexpr std::array<std::string_view, 1> interfaces = {deleteAllInterface};
2140 dbus::utility::getSubTreePaths(
2141 "/xyz/openbmc_project/dump", 0, interfaces,
2142 [asyncResp, dumpType, dumpPath](
2143 const boost::system::error_code& ec,
2144 const dbus::utility::MapperGetSubTreePathsResponse& subTreePaths) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002145 if (ec)
Claire Weinan0d946212022-07-13 19:40:19 -07002146 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002147 BMCWEB_LOG_ERROR("getDumpServiceInfo respHandler got error {}",
2148 ec);
2149 // Assume that getting an error simply means there are no dump
2150 // LogServices. Return without adding any error response.
2151 return;
Claire Weinan0d946212022-07-13 19:40:19 -07002152 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002153 std::string dbusDumpPath = getDumpPath(dumpType);
2154 for (const std::string& path : subTreePaths)
2155 {
2156 if (path == dbusDumpPath)
2157 {
2158 asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"]
2159 ["target"] =
2160 dumpPath + "/Actions/LogService.ClearLog";
2161 break;
2162 }
2163 }
2164 });
Claire Weinanfdd26902022-03-01 14:18:25 -08002165}
2166
2167inline void handleLogServicesDumpServiceGet(
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 }
2182
Claire Weinanfdd26902022-03-01 14:18:25 -08002183 getDumpServiceInfo(asyncResp, dumpType);
2184}
2185
Ed Tanous22d268c2022-05-19 09:39:07 -07002186inline void handleLogServicesDumpServiceComputerSystemGet(
2187 crow::App& app, const crow::Request& req,
2188 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2189 const std::string& chassisId)
2190{
2191 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2192 {
2193 return;
2194 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002195 if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous22d268c2022-05-19 09:39:07 -07002196 {
2197 messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
2198 return;
2199 }
2200 getDumpServiceInfo(asyncResp, "System");
2201}
2202
Claire Weinanfdd26902022-03-01 14:18:25 -08002203inline void handleLogServicesDumpEntriesCollectionGet(
2204 crow::App& app, const std::string& dumpType, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07002205 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2206 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002207{
2208 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2209 {
2210 return;
2211 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002212
2213 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2214 {
2215 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2216 return;
2217 }
Claire Weinanfdd26902022-03-01 14:18:25 -08002218 getDumpEntryCollection(asyncResp, dumpType);
2219}
2220
Ed Tanous22d268c2022-05-19 09:39:07 -07002221inline void handleLogServicesDumpEntriesCollectionComputerSystemGet(
2222 crow::App& app, const crow::Request& req,
2223 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2224 const std::string& chassisId)
2225{
2226 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2227 {
2228 return;
2229 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002230 if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous22d268c2022-05-19 09:39:07 -07002231 {
2232 messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
2233 return;
2234 }
2235 getDumpEntryCollection(asyncResp, "System");
2236}
2237
Claire Weinanfdd26902022-03-01 14:18:25 -08002238inline void handleLogServicesDumpEntryGet(
2239 crow::App& app, const std::string& dumpType, const crow::Request& req,
2240 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous253f11b2024-05-16 09:38:31 -07002241 const std::string& managerId, const std::string& dumpId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002242{
2243 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2244 {
2245 return;
2246 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002247 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2248 {
2249 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2250 return;
2251 }
Claire Weinanfdd26902022-03-01 14:18:25 -08002252 getDumpEntryById(asyncResp, dumpId, dumpType);
2253}
Carson Labrado168d1b12023-03-27 17:04:46 +00002254
Ed Tanous22d268c2022-05-19 09:39:07 -07002255inline void handleLogServicesDumpEntryComputerSystemGet(
2256 crow::App& app, const crow::Request& req,
2257 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2258 const std::string& chassisId, const std::string& dumpId)
2259{
2260 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2261 {
2262 return;
2263 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002264 if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous22d268c2022-05-19 09:39:07 -07002265 {
2266 messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
2267 return;
2268 }
2269 getDumpEntryById(asyncResp, dumpId, "System");
2270}
Claire Weinanfdd26902022-03-01 14:18:25 -08002271
2272inline void handleLogServicesDumpEntryDelete(
2273 crow::App& app, const std::string& dumpType, const crow::Request& req,
2274 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous253f11b2024-05-16 09:38:31 -07002275 const std::string& managerId, const std::string& dumpId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002276{
2277 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2278 {
2279 return;
2280 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002281
2282 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2283 {
2284 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2285 return;
2286 }
Claire Weinanfdd26902022-03-01 14:18:25 -08002287 deleteDumpEntry(asyncResp, dumpId, dumpType);
2288}
2289
Ed Tanous22d268c2022-05-19 09:39:07 -07002290inline void handleLogServicesDumpEntryComputerSystemDelete(
2291 crow::App& app, const crow::Request& req,
2292 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2293 const std::string& chassisId, const std::string& dumpId)
2294{
2295 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2296 {
2297 return;
2298 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002299 if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous22d268c2022-05-19 09:39:07 -07002300 {
2301 messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
2302 return;
2303 }
2304 deleteDumpEntry(asyncResp, dumpId, "System");
2305}
2306
Carson Labrado168d1b12023-03-27 17:04:46 +00002307inline void handleLogServicesDumpEntryDownloadGet(
2308 crow::App& app, const std::string& dumpType, const crow::Request& req,
2309 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous253f11b2024-05-16 09:38:31 -07002310 const std::string& managerId, const std::string& dumpId)
Carson Labrado168d1b12023-03-27 17:04:46 +00002311{
2312 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2313 {
2314 return;
2315 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002316
2317 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2318 {
2319 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2320 return;
2321 }
Carson Labrado168d1b12023-03-27 17:04:46 +00002322 downloadDumpEntry(asyncResp, dumpId, dumpType);
2323}
2324
2325inline void handleDBusEventLogEntryDownloadGet(
2326 crow::App& app, const std::string& dumpType, const crow::Request& req,
2327 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2328 const std::string& systemName, const std::string& entryID)
2329{
2330 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2331 {
2332 return;
2333 }
2334 if (!http_helpers::isContentTypeAllowed(
2335 req.getHeaderValue("Accept"),
2336 http_helpers::ContentType::OctetStream, true))
2337 {
2338 asyncResp->res.result(boost::beast::http::status::bad_request);
2339 return;
2340 }
2341 downloadEventLogEntry(asyncResp, systemName, entryID, dumpType);
2342}
2343
Claire Weinanfdd26902022-03-01 14:18:25 -08002344inline void handleLogServicesDumpCollectDiagnosticDataPost(
2345 crow::App& app, const std::string& dumpType, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07002346 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2347 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002348{
2349 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2350 {
2351 return;
2352 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002353 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2354 {
2355 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2356 return;
2357 }
2358
Claire Weinanfdd26902022-03-01 14:18:25 -08002359 createDump(asyncResp, req, dumpType);
2360}
2361
Ed Tanous22d268c2022-05-19 09:39:07 -07002362inline void handleLogServicesDumpCollectDiagnosticDataComputerSystemPost(
2363 crow::App& app, const crow::Request& req,
2364 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002365 const std::string& systemName)
Ed Tanous22d268c2022-05-19 09:39:07 -07002366{
2367 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2368 {
2369 return;
2370 }
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002371
Ed Tanous25b54db2024-04-17 15:40:31 -07002372 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous22d268c2022-05-19 09:39:07 -07002373 {
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002374 // Option currently returns no systems. TBD
2375 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2376 systemName);
2377 return;
2378 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002379 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002380 {
2381 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2382 systemName);
Ed Tanous22d268c2022-05-19 09:39:07 -07002383 return;
2384 }
2385 createDump(asyncResp, req, "System");
2386}
2387
Claire Weinanfdd26902022-03-01 14:18:25 -08002388inline void handleLogServicesDumpClearLogPost(
2389 crow::App& app, const std::string& dumpType, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07002390 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2391 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002392{
2393 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2394 {
2395 return;
2396 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002397
2398 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2399 {
2400 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2401 return;
2402 }
Claire Weinanfdd26902022-03-01 14:18:25 -08002403 clearDump(asyncResp, dumpType);
2404}
2405
Ed Tanous22d268c2022-05-19 09:39:07 -07002406inline void handleLogServicesDumpClearLogComputerSystemPost(
2407 crow::App& app, const crow::Request& req,
2408 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002409 const std::string& systemName)
Ed Tanous22d268c2022-05-19 09:39:07 -07002410{
2411 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2412 {
2413 return;
2414 }
Ed Tanous25b54db2024-04-17 15:40:31 -07002415 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous22d268c2022-05-19 09:39:07 -07002416 {
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002417 // Option currently returns no systems. TBD
2418 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2419 systemName);
2420 return;
2421 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002422 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002423 {
2424 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2425 systemName);
Ed Tanous22d268c2022-05-19 09:39:07 -07002426 return;
2427 }
2428 clearDump(asyncResp, "System");
2429}
2430
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002431inline void requestRoutesBMCDumpService(App& app)
2432{
Ed Tanous253f11b2024-05-16 09:38:31 -07002433 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/Dump/")
Ed Tanoused398212021-06-09 17:05:54 -07002434 .privileges(redfish::privileges::getLogService)
Claire Weinanfdd26902022-03-01 14:18:25 -08002435 .methods(boost::beast::http::verb::get)(std::bind_front(
2436 handleLogServicesDumpServiceGet, std::ref(app), "BMC"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002437}
2438
2439inline void requestRoutesBMCDumpEntryCollection(App& app)
2440{
Ed Tanous253f11b2024-05-16 09:38:31 -07002441 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/")
Ed Tanoused398212021-06-09 17:05:54 -07002442 .privileges(redfish::privileges::getLogEntryCollection)
Claire Weinanfdd26902022-03-01 14:18:25 -08002443 .methods(boost::beast::http::verb::get)(std::bind_front(
2444 handleLogServicesDumpEntriesCollectionGet, std::ref(app), "BMC"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002445}
2446
2447inline void requestRoutesBMCDumpEntry(App& app)
2448{
2449 BMCWEB_ROUTE(app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002450 "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002451 .privileges(redfish::privileges::getLogEntry)
Claire Weinanfdd26902022-03-01 14:18:25 -08002452 .methods(boost::beast::http::verb::get)(std::bind_front(
2453 handleLogServicesDumpEntryGet, std::ref(app), "BMC"));
2454
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002455 BMCWEB_ROUTE(app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002456 "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002457 .privileges(redfish::privileges::deleteLogEntry)
Claire Weinanfdd26902022-03-01 14:18:25 -08002458 .methods(boost::beast::http::verb::delete_)(std::bind_front(
2459 handleLogServicesDumpEntryDelete, std::ref(app), "BMC"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002460}
2461
Carson Labrado168d1b12023-03-27 17:04:46 +00002462inline void requestRoutesBMCDumpEntryDownload(App& app)
2463{
2464 BMCWEB_ROUTE(
2465 app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002466 "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/attachment/")
Carson Labrado168d1b12023-03-27 17:04:46 +00002467 .privileges(redfish::privileges::getLogEntry)
2468 .methods(boost::beast::http::verb::get)(std::bind_front(
2469 handleLogServicesDumpEntryDownloadGet, std::ref(app), "BMC"));
2470}
2471
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002472inline void requestRoutesBMCDumpCreate(App& app)
2473{
George Liu0fda0f12021-11-16 10:06:17 +08002474 BMCWEB_ROUTE(
2475 app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002476 "/redfish/v1/Managers/<str>/LogServices/Dump/Actions/LogService.CollectDiagnosticData/")
Ed Tanoused398212021-06-09 17:05:54 -07002477 .privileges(redfish::privileges::postLogService)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002478 .methods(boost::beast::http::verb::post)(
Claire Weinanfdd26902022-03-01 14:18:25 -08002479 std::bind_front(handleLogServicesDumpCollectDiagnosticDataPost,
2480 std::ref(app), "BMC"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002481}
2482
2483inline void requestRoutesBMCDumpClear(App& app)
2484{
George Liu0fda0f12021-11-16 10:06:17 +08002485 BMCWEB_ROUTE(
2486 app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002487 "/redfish/v1/Managers/<str>/LogServices/Dump/Actions/LogService.ClearLog/")
Ed Tanoused398212021-06-09 17:05:54 -07002488 .privileges(redfish::privileges::postLogService)
Claire Weinanfdd26902022-03-01 14:18:25 -08002489 .methods(boost::beast::http::verb::post)(std::bind_front(
2490 handleLogServicesDumpClearLogPost, std::ref(app), "BMC"));
2491}
2492
Carson Labrado168d1b12023-03-27 17:04:46 +00002493inline void requestRoutesDBusEventLogEntryDownload(App& app)
2494{
2495 BMCWEB_ROUTE(
2496 app,
Ravi Teja9e9d99d2023-11-08 05:33:59 -06002497 "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/attachment/")
Carson Labrado168d1b12023-03-27 17:04:46 +00002498 .privileges(redfish::privileges::getLogEntry)
2499 .methods(boost::beast::http::verb::get)(std::bind_front(
2500 handleDBusEventLogEntryDownloadGet, std::ref(app), "System"));
2501}
2502
Claire Weinanfdd26902022-03-01 14:18:25 -08002503inline void requestRoutesFaultLogDumpService(App& app)
2504{
Ed Tanous253f11b2024-05-16 09:38:31 -07002505 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/")
Claire Weinanfdd26902022-03-01 14:18:25 -08002506 .privileges(redfish::privileges::getLogService)
2507 .methods(boost::beast::http::verb::get)(std::bind_front(
2508 handleLogServicesDumpServiceGet, std::ref(app), "FaultLog"));
2509}
2510
2511inline void requestRoutesFaultLogDumpEntryCollection(App& app)
2512{
Ed Tanous253f11b2024-05-16 09:38:31 -07002513 BMCWEB_ROUTE(app,
2514 "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/")
Claire Weinanfdd26902022-03-01 14:18:25 -08002515 .privileges(redfish::privileges::getLogEntryCollection)
2516 .methods(boost::beast::http::verb::get)(
2517 std::bind_front(handleLogServicesDumpEntriesCollectionGet,
2518 std::ref(app), "FaultLog"));
2519}
2520
2521inline void requestRoutesFaultLogDumpEntry(App& app)
2522{
Ed Tanous253f11b2024-05-16 09:38:31 -07002523 BMCWEB_ROUTE(
2524 app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/<str>/")
Claire Weinanfdd26902022-03-01 14:18:25 -08002525 .privileges(redfish::privileges::getLogEntry)
2526 .methods(boost::beast::http::verb::get)(std::bind_front(
2527 handleLogServicesDumpEntryGet, std::ref(app), "FaultLog"));
2528
Ed Tanous253f11b2024-05-16 09:38:31 -07002529 BMCWEB_ROUTE(
2530 app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/<str>/")
Claire Weinanfdd26902022-03-01 14:18:25 -08002531 .privileges(redfish::privileges::deleteLogEntry)
2532 .methods(boost::beast::http::verb::delete_)(std::bind_front(
2533 handleLogServicesDumpEntryDelete, std::ref(app), "FaultLog"));
2534}
2535
2536inline void requestRoutesFaultLogDumpClear(App& app)
2537{
2538 BMCWEB_ROUTE(
2539 app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002540 "/redfish/v1/Managers/<str>/LogServices/FaultLog/Actions/LogService.ClearLog/")
Claire Weinanfdd26902022-03-01 14:18:25 -08002541 .privileges(redfish::privileges::postLogService)
2542 .methods(boost::beast::http::verb::post)(std::bind_front(
2543 handleLogServicesDumpClearLogPost, std::ref(app), "FaultLog"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002544}
2545
2546inline void requestRoutesSystemDumpService(App& app)
2547{
Ed Tanous22d268c2022-05-19 09:39:07 -07002548 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Dump/")
Ed Tanoused398212021-06-09 17:05:54 -07002549 .privileges(redfish::privileges::getLogService)
Claire Weinan6ab9ad52022-08-12 18:20:17 -07002550 .methods(boost::beast::http::verb::get)(std::bind_front(
Ed Tanous22d268c2022-05-19 09:39:07 -07002551 handleLogServicesDumpServiceComputerSystemGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002552}
2553
2554inline void requestRoutesSystemDumpEntryCollection(App& app)
2555{
Ed Tanous22d268c2022-05-19 09:39:07 -07002556 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/")
Ed Tanoused398212021-06-09 17:05:54 -07002557 .privileges(redfish::privileges::getLogEntryCollection)
Ed Tanous22d268c2022-05-19 09:39:07 -07002558 .methods(boost::beast::http::verb::get)(std::bind_front(
2559 handleLogServicesDumpEntriesCollectionComputerSystemGet,
2560 std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002561}
2562
2563inline void requestRoutesSystemDumpEntry(App& app)
2564{
2565 BMCWEB_ROUTE(app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002566 "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002567 .privileges(redfish::privileges::getLogEntry)
Claire Weinan6ab9ad52022-08-12 18:20:17 -07002568 .methods(boost::beast::http::verb::get)(std::bind_front(
Ed Tanous22d268c2022-05-19 09:39:07 -07002569 handleLogServicesDumpEntryComputerSystemGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002570
2571 BMCWEB_ROUTE(app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002572 "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002573 .privileges(redfish::privileges::deleteLogEntry)
Claire Weinan6ab9ad52022-08-12 18:20:17 -07002574 .methods(boost::beast::http::verb::delete_)(std::bind_front(
Ed Tanous22d268c2022-05-19 09:39:07 -07002575 handleLogServicesDumpEntryComputerSystemDelete, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002576}
2577
2578inline void requestRoutesSystemDumpCreate(App& app)
2579{
George Liu0fda0f12021-11-16 10:06:17 +08002580 BMCWEB_ROUTE(
2581 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002582 "/redfish/v1/Systems/<str>/LogServices/Dump/Actions/LogService.CollectDiagnosticData/")
Ed Tanoused398212021-06-09 17:05:54 -07002583 .privileges(redfish::privileges::postLogService)
Ed Tanous22d268c2022-05-19 09:39:07 -07002584 .methods(boost::beast::http::verb::post)(std::bind_front(
2585 handleLogServicesDumpCollectDiagnosticDataComputerSystemPost,
2586 std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002587}
2588
2589inline void requestRoutesSystemDumpClear(App& app)
2590{
George Liu0fda0f12021-11-16 10:06:17 +08002591 BMCWEB_ROUTE(
2592 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002593 "/redfish/v1/Systems/<str>/LogServices/Dump/Actions/LogService.ClearLog/")
Ed Tanoused398212021-06-09 17:05:54 -07002594 .privileges(redfish::privileges::postLogService)
Claire Weinan6ab9ad52022-08-12 18:20:17 -07002595 .methods(boost::beast::http::verb::post)(std::bind_front(
Ed Tanous22d268c2022-05-19 09:39:07 -07002596 handleLogServicesDumpClearLogComputerSystemPost, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002597}
2598
2599inline void requestRoutesCrashdumpService(App& app)
2600{
2601 // Note: Deviated from redfish privilege registry for GET & HEAD
2602 // method for security reasons.
2603 /**
2604 * Functions triggers appropriate requests on DBus
2605 */
Ed Tanous22d268c2022-05-19 09:39:07 -07002606 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Crashdump/")
Ed Tanoused398212021-06-09 17:05:54 -07002607 // This is incorrect, should be:
2608 //.privileges(redfish::privileges::getLogService)
Ed Tanous432a8902021-06-14 15:28:56 -07002609 .privileges({{"ConfigureManager"}})
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002610 .methods(
2611 boost::beast::http::verb::
2612 get)([&app](const crow::Request& req,
2613 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2614 const std::string& systemName) {
2615 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2616 {
2617 return;
2618 }
2619 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
2620 {
2621 // Option currently returns no systems. TBD
2622 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2623 systemName);
2624 return;
2625 }
2626 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2627 {
2628 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2629 systemName);
2630 return;
2631 }
Ed Tanous22d268c2022-05-19 09:39:07 -07002632
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002633 // Copy over the static data to include the entries added by
2634 // SubRoute
2635 asyncResp->res.jsonValue["@odata.id"] =
2636 std::format("/redfish/v1/Systems/{}/LogServices/Crashdump",
2637 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2638 asyncResp->res.jsonValue["@odata.type"] =
2639 "#LogService.v1_2_0.LogService";
2640 asyncResp->res.jsonValue["Name"] = "Open BMC Oem Crashdump Service";
2641 asyncResp->res.jsonValue["Description"] = "Oem Crashdump Service";
2642 asyncResp->res.jsonValue["Id"] = "Crashdump";
2643 asyncResp->res.jsonValue["OverWritePolicy"] =
2644 log_service::OverWritePolicy::WrapsWhenFull;
2645 asyncResp->res.jsonValue["MaxNumberOfRecords"] = 3;
Tejas Patil7c8c4052021-06-04 17:43:14 +05302646
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002647 std::pair<std::string, std::string> redfishDateTimeOffset =
2648 redfish::time_utils::getDateTimeOffsetNow();
2649 asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
2650 asyncResp->res.jsonValue["DateTimeLocalOffset"] =
2651 redfishDateTimeOffset.second;
Tejas Patil7c8c4052021-06-04 17:43:14 +05302652
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002653 asyncResp->res.jsonValue["Entries"]["@odata.id"] = std::format(
2654 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries",
2655 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2656 asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"]
2657 ["target"] = std::format(
2658 "/redfish/v1/Systems/{}/LogServices/Crashdump/Actions/LogService.ClearLog",
2659 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2660 asyncResp->res
2661 .jsonValue["Actions"]["#LogService.CollectDiagnosticData"]
2662 ["target"] = std::format(
2663 "/redfish/v1/Systems/{}/LogServices/Crashdump/Actions/LogService.CollectDiagnosticData",
2664 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2665 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002666}
2667
2668void inline requestRoutesCrashdumpClear(App& app)
2669{
George Liu0fda0f12021-11-16 10:06:17 +08002670 BMCWEB_ROUTE(
2671 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002672 "/redfish/v1/Systems/<str>/LogServices/Crashdump/Actions/LogService.ClearLog/")
Ed Tanoused398212021-06-09 17:05:54 -07002673 // This is incorrect, should be:
2674 //.privileges(redfish::privileges::postLogService)
Ed Tanous432a8902021-06-14 15:28:56 -07002675 .privileges({{"ConfigureComponents"}})
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002676 .methods(boost::beast::http::verb::post)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07002677 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07002678 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2679 const std::string& systemName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002680 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2681 {
2682 return;
2683 }
2684 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
2685 {
2686 // Option currently returns no systems. TBD
2687 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2688 systemName);
2689 return;
2690 }
2691 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2692 {
2693 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2694 systemName);
2695 return;
2696 }
2697 crow::connections::systemBus->async_method_call(
2698 [asyncResp](const boost::system::error_code& ec,
2699 const std::string&) {
2700 if (ec)
2701 {
2702 messages::internalError(asyncResp->res);
2703 return;
2704 }
2705 messages::success(asyncResp->res);
2706 },
2707 crashdumpObject, crashdumpPath, deleteAllInterface,
2708 "DeleteAll");
2709 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002710}
Jason M. Bills5b61b5e2019-10-16 10:59:02 -07002711
Ed Tanous4ff0f1f2024-09-04 17:27:37 -07002712inline void
zhanghch058d1b46d2021-04-01 11:18:24 +08002713 logCrashdumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2714 const std::string& logID, nlohmann::json& logEntryJson)
Jason M. Billse855dd22019-10-08 11:37:48 -07002715{
Johnathan Mantey043a0532020-03-10 17:15:28 -07002716 auto getStoredLogCallback =
Ed Tanousb9d36b42022-02-26 21:42:46 -08002717 [asyncResp, logID,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002718 &logEntryJson](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002719 const dbus::utility::DBusPropertiesMap& params) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002720 if (ec)
2721 {
2722 BMCWEB_LOG_DEBUG("failed to get log ec: {}", ec.message());
2723 if (ec.value() ==
2724 boost::system::linux_error::bad_request_descriptor)
2725 {
2726 messages::resourceNotFound(asyncResp->res, "LogEntry",
2727 logID);
2728 }
2729 else
2730 {
2731 messages::internalError(asyncResp->res);
2732 }
2733 return;
2734 }
2735
2736 std::string timestamp{};
2737 std::string filename{};
2738 std::string logfile{};
2739 parseCrashdumpParameters(params, filename, timestamp, logfile);
2740
2741 if (filename.empty() || timestamp.empty())
Jason M. Bills1ddcf012019-11-26 14:59:21 -08002742 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002743 messages::resourceNotFound(asyncResp->res, "LogEntry", logID);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002744 return;
2745 }
2746
2747 std::string crashdumpURI =
2748 std::format(
2749 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries/",
2750 BMCWEB_REDFISH_SYSTEM_URI_NAME) +
2751 logID + "/" + filename;
2752 nlohmann::json::object_t logEntry;
2753 logEntry["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
2754 logEntry["@odata.id"] = boost::urls::format(
2755 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries/{}",
2756 BMCWEB_REDFISH_SYSTEM_URI_NAME, logID);
2757 logEntry["Name"] = "CPU Crashdump";
2758 logEntry["Id"] = logID;
2759 logEntry["EntryType"] = log_entry::LogEntryType::Oem;
2760 logEntry["AdditionalDataURI"] = std::move(crashdumpURI);
2761 logEntry["DiagnosticDataType"] = "OEM";
2762 logEntry["OEMDiagnosticDataType"] = "PECICrashdump";
2763 logEntry["Created"] = std::move(timestamp);
2764
2765 // If logEntryJson references an array of LogEntry resources
2766 // ('Members' list), then push this as a new entry, otherwise set it
2767 // directly
2768 if (logEntryJson.is_array())
2769 {
2770 logEntryJson.push_back(logEntry);
2771 asyncResp->res.jsonValue["Members@odata.count"] =
2772 logEntryJson.size();
Jason M. Bills2b20ef62022-01-06 15:48:07 -08002773 }
2774 else
2775 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002776 logEntryJson.update(logEntry);
Jason M. Bills2b20ef62022-01-06 15:48:07 -08002777 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002778 };
Ed Tanousdeae6a72024-11-11 21:58:57 -08002779 dbus::utility::getAllProperties(
2780 crashdumpObject, crashdumpPath + std::string("/") + logID,
2781 crashdumpInterface, std::move(getStoredLogCallback));
Jason M. Billse855dd22019-10-08 11:37:48 -07002782}
2783
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002784inline void requestRoutesCrashdumpEntryCollection(App& app)
Ed Tanous1da66f72018-07-27 16:13:37 -07002785{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002786 // Note: Deviated from redfish privilege registry for GET & HEAD
2787 // method for security reasons.
Ed Tanous1da66f72018-07-27 16:13:37 -07002788 /**
2789 * Functions triggers appropriate requests on DBus
2790 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002791 BMCWEB_ROUTE(app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002792 "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/")
Ed Tanoused398212021-06-09 17:05:54 -07002793 // This is incorrect, should be.
2794 //.privileges(redfish::privileges::postLogEntryCollection)
Ed Tanous432a8902021-06-14 15:28:56 -07002795 .privileges({{"ConfigureComponents"}})
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002796 .methods(
2797 boost::beast::http::verb::
2798 get)([&app](const crow::Request& req,
2799 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2800 const std::string& systemName) {
2801 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous45ca1b82022-03-25 13:07:27 -07002802 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002803 return;
Ed Tanous45ca1b82022-03-25 13:07:27 -07002804 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002805 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous002d39b2022-05-31 08:59:27 -07002806 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002807 // Option currently returns no systems. TBD
2808 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2809 systemName);
2810 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07002811 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002812 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2813 {
2814 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2815 systemName);
2816 return;
2817 }
2818
2819 constexpr std::array<std::string_view, 1> interfaces = {
2820 crashdumpInterface};
2821 dbus::utility::getSubTreePaths(
2822 "/", 0, interfaces,
2823 [asyncResp](const boost::system::error_code& ec,
2824 const std::vector<std::string>& resp) {
2825 if (ec)
2826 {
2827 if (ec.value() !=
2828 boost::system::errc::no_such_file_or_directory)
2829 {
2830 BMCWEB_LOG_DEBUG("failed to get entries ec: {}",
2831 ec.message());
2832 messages::internalError(asyncResp->res);
2833 return;
2834 }
2835 }
2836 asyncResp->res.jsonValue["@odata.type"] =
2837 "#LogEntryCollection.LogEntryCollection";
2838 asyncResp->res.jsonValue["@odata.id"] = std::format(
2839 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries",
2840 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2841 asyncResp->res.jsonValue["Name"] =
2842 "Open BMC Crashdump Entries";
2843 asyncResp->res.jsonValue["Description"] =
2844 "Collection of Crashdump Entries";
2845 asyncResp->res.jsonValue["Members"] =
2846 nlohmann::json::array();
2847 asyncResp->res.jsonValue["Members@odata.count"] = 0;
2848
2849 for (const std::string& path : resp)
2850 {
2851 const sdbusplus::message::object_path objPath(path);
2852 // Get the log ID
2853 std::string logID = objPath.filename();
2854 if (logID.empty())
2855 {
2856 continue;
2857 }
2858 // Add the log entry to the array
2859 logCrashdumpEntry(asyncResp, logID,
2860 asyncResp->res.jsonValue["Members"]);
2861 }
2862 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002863 });
2864}
Ed Tanous1da66f72018-07-27 16:13:37 -07002865
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002866inline void requestRoutesCrashdumpEntry(App& app)
Ed Tanous1da66f72018-07-27 16:13:37 -07002867{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002868 // Note: Deviated from redfish privilege registry for GET & HEAD
2869 // method for security reasons.
Ed Tanous1da66f72018-07-27 16:13:37 -07002870
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002871 BMCWEB_ROUTE(
Ed Tanous22d268c2022-05-19 09:39:07 -07002872 app, "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002873 // this is incorrect, should be
2874 // .privileges(redfish::privileges::getLogEntry)
Ed Tanous432a8902021-06-14 15:28:56 -07002875 .privileges({{"ConfigureComponents"}})
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002876 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07002877 [&app](const crow::Request& req,
2878 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -07002879 const std::string& systemName, const std::string& param) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002880 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2881 {
2882 return;
2883 }
2884 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
2885 {
2886 // Option currently returns no systems. TBD
2887 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2888 systemName);
2889 return;
2890 }
2891 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2892 {
2893 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2894 systemName);
2895 return;
2896 }
2897 const std::string& logID = param;
2898 logCrashdumpEntry(asyncResp, logID, asyncResp->res.jsonValue);
2899 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002900}
Ed Tanous1da66f72018-07-27 16:13:37 -07002901
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002902inline void requestRoutesCrashdumpFile(App& app)
2903{
2904 // Note: Deviated from redfish privilege registry for GET & HEAD
2905 // method for security reasons.
2906 BMCWEB_ROUTE(
2907 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002908 "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/<str>/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002909 .privileges(redfish::privileges::getLogEntry)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002910 .methods(boost::beast::http::verb::get)(
Nan Zhoua4ce1142022-08-02 18:45:25 +00002911 [](const crow::Request& req,
2912 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -07002913 const std::string& systemName, const std::string& logID,
2914 const std::string& fileName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002915 // Do not call getRedfishRoute here since the crashdump file is
2916 // not a Redfish resource.
Ed Tanous22d268c2022-05-19 09:39:07 -07002917
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002918 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
2919 {
2920 // Option currently returns no systems. TBD
2921 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2922 systemName);
2923 return;
2924 }
2925 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2926 {
2927 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2928 systemName);
2929 return;
2930 }
Ed Tanous22d268c2022-05-19 09:39:07 -07002931
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002932 auto getStoredLogCallback =
2933 [asyncResp, logID, fileName,
2934 url(boost::urls::url(req.url()))](
2935 const boost::system::error_code& ec,
2936 const std::vector<std::pair<
2937 std::string, dbus::utility::DbusVariantType>>&
2938 resp) {
2939 if (ec)
2940 {
2941 BMCWEB_LOG_DEBUG("failed to get log ec: {}",
2942 ec.message());
2943 messages::internalError(asyncResp->res);
2944 return;
2945 }
Jason M. Bills8e6c0992021-03-11 16:26:53 -08002946
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002947 std::string dbusFilename{};
2948 std::string dbusTimestamp{};
2949 std::string dbusFilepath{};
Jason M. Bills8e6c0992021-03-11 16:26:53 -08002950
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002951 parseCrashdumpParameters(resp, dbusFilename,
2952 dbusTimestamp, dbusFilepath);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002953
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002954 if (dbusFilename.empty() || dbusTimestamp.empty() ||
2955 dbusFilepath.empty())
2956 {
2957 messages::resourceNotFound(asyncResp->res,
2958 "LogEntry", logID);
2959 return;
2960 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002961
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002962 // Verify the file name parameter is correct
2963 if (fileName != dbusFilename)
2964 {
2965 messages::resourceNotFound(asyncResp->res,
2966 "LogEntry", logID);
2967 return;
2968 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002969
Myung Baed51c61b2024-09-13 10:35:34 -05002970 if (asyncResp->res.openFile(dbusFilepath) !=
2971 crow::OpenCode::Success)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002972 {
2973 messages::resourceNotFound(asyncResp->res,
2974 "LogEntry", logID);
2975 return;
2976 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002977
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002978 // Configure this to be a file download when accessed
2979 // from a browser
2980 asyncResp->res.addHeader(
2981 boost::beast::http::field::content_disposition,
2982 "attachment");
2983 };
Ed Tanousdeae6a72024-11-11 21:58:57 -08002984 dbus::utility::getAllProperties(
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002985 *crow::connections::systemBus, crashdumpObject,
2986 crashdumpPath + std::string("/") + logID,
2987 crashdumpInterface, std::move(getStoredLogCallback));
2988 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002989}
2990
Jason M. Billsc5a4c822022-01-06 15:51:23 -08002991enum class OEMDiagnosticType
2992{
2993 onDemand,
2994 telemetry,
2995 invalid,
2996};
2997
Ed Tanous26ccae32023-02-16 10:28:44 -08002998inline OEMDiagnosticType getOEMDiagnosticType(std::string_view oemDiagStr)
Jason M. Billsc5a4c822022-01-06 15:51:23 -08002999{
3000 if (oemDiagStr == "OnDemand")
3001 {
3002 return OEMDiagnosticType::onDemand;
3003 }
3004 if (oemDiagStr == "Telemetry")
3005 {
3006 return OEMDiagnosticType::telemetry;
3007 }
3008
3009 return OEMDiagnosticType::invalid;
3010}
3011
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003012inline void requestRoutesCrashdumpCollect(App& app)
3013{
3014 // Note: Deviated from redfish privilege registry for GET & HEAD
3015 // method for security reasons.
George Liu0fda0f12021-11-16 10:06:17 +08003016 BMCWEB_ROUTE(
3017 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07003018 "/redfish/v1/Systems/<str>/LogServices/Crashdump/Actions/LogService.CollectDiagnosticData/")
Ed Tanoused398212021-06-09 17:05:54 -07003019 // The below is incorrect; Should be ConfigureManager
3020 //.privileges(redfish::privileges::postLogService)
Ed Tanous432a8902021-06-14 15:28:56 -07003021 .privileges({{"ConfigureComponents"}})
Ed Tanous002d39b2022-05-31 08:59:27 -07003022 .methods(boost::beast::http::verb::post)(
3023 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07003024 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3025 const std::string& systemName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003026 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07003027 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003028 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07003029 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003030
3031 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous002d39b2022-05-31 08:59:27 -07003032 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003033 // Option currently returns no systems. TBD
3034 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3035 systemName);
3036 return;
3037 }
3038 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
3039 {
3040 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3041 systemName);
3042 return;
3043 }
3044
3045 std::string diagnosticDataType;
3046 std::string oemDiagnosticDataType;
Myung Baeafc474a2024-10-09 00:53:29 -07003047 if (!redfish::json_util::readJsonAction( //
3048 req, asyncResp->res, //
3049 "DiagnosticDataType", diagnosticDataType, //
3050 "OEMDiagnosticDataType", oemDiagnosticDataType //
3051 ))
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003052 {
3053 return;
3054 }
3055
3056 if (diagnosticDataType != "OEM")
3057 {
3058 BMCWEB_LOG_ERROR(
3059 "Only OEM DiagnosticDataType supported for Crashdump");
3060 messages::actionParameterValueFormatError(
3061 asyncResp->res, diagnosticDataType,
3062 "DiagnosticDataType", "CollectDiagnosticData");
3063 return;
3064 }
3065
3066 OEMDiagnosticType oemDiagType =
3067 getOEMDiagnosticType(oemDiagnosticDataType);
3068
3069 std::string iface;
3070 std::string method;
3071 std::string taskMatchStr;
3072 if (oemDiagType == OEMDiagnosticType::onDemand)
3073 {
3074 iface = crashdumpOnDemandInterface;
3075 method = "GenerateOnDemandLog";
3076 taskMatchStr =
3077 "type='signal',"
3078 "interface='org.freedesktop.DBus.Properties',"
3079 "member='PropertiesChanged',"
3080 "arg0namespace='com.intel.crashdump'";
3081 }
3082 else if (oemDiagType == OEMDiagnosticType::telemetry)
3083 {
3084 iface = crashdumpTelemetryInterface;
3085 method = "GenerateTelemetryLog";
3086 taskMatchStr =
3087 "type='signal',"
3088 "interface='org.freedesktop.DBus.Properties',"
3089 "member='PropertiesChanged',"
3090 "arg0namespace='com.intel.crashdump'";
Ed Tanous002d39b2022-05-31 08:59:27 -07003091 }
3092 else
3093 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003094 BMCWEB_LOG_ERROR("Unsupported OEMDiagnosticDataType: {}",
3095 oemDiagnosticDataType);
3096 messages::actionParameterValueFormatError(
3097 asyncResp->res, oemDiagnosticDataType,
3098 "OEMDiagnosticDataType", "CollectDiagnosticData");
3099 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07003100 }
Ed Tanous1da66f72018-07-27 16:13:37 -07003101
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003102 auto collectCrashdumpCallback =
3103 [asyncResp, payload(task::Payload(req)),
3104 taskMatchStr](const boost::system::error_code& ec,
3105 const std::string&) mutable {
3106 if (ec)
3107 {
3108 if (ec.value() ==
3109 boost::system::errc::operation_not_supported)
3110 {
3111 messages::resourceInStandby(asyncResp->res);
3112 }
3113 else if (ec.value() == boost::system::errc::
3114 device_or_resource_busy)
3115 {
3116 messages::serviceTemporarilyUnavailable(
3117 asyncResp->res, "60");
3118 }
3119 else
3120 {
3121 messages::internalError(asyncResp->res);
3122 }
3123 return;
3124 }
3125 std::shared_ptr<task::TaskData> task =
3126 task::TaskData::createTask(
3127 [](const boost::system::error_code& ec2,
3128 sdbusplus::message_t&,
3129 const std::shared_ptr<task::TaskData>&
3130 taskData) {
3131 if (!ec2)
3132 {
3133 taskData->messages.emplace_back(
3134 messages::taskCompletedOK(
3135 std::to_string(
3136 taskData->index)));
3137 taskData->state = "Completed";
3138 }
3139 return task::completed;
3140 },
3141 taskMatchStr);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003142
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003143 task->startTimer(std::chrono::minutes(5));
3144 task->populateResp(asyncResp->res);
3145 task->payload.emplace(std::move(payload));
3146 };
3147
3148 crow::connections::systemBus->async_method_call(
3149 std::move(collectCrashdumpCallback), crashdumpObject,
3150 crashdumpPath, iface, method);
3151 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003152}
Kenny L. Ku6eda7682020-06-19 09:48:36 -07003153
Alexander Hansen599b9af2024-08-06 15:11:57 +02003154inline void dBusLogServiceActionsClear(
3155 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
3156{
3157 BMCWEB_LOG_DEBUG("Do delete all entries.");
3158
3159 // Process response from Logging service.
3160 auto respHandler = [asyncResp](const boost::system::error_code& ec) {
3161 BMCWEB_LOG_DEBUG("doClearLog resp_handler callback: Done");
3162 if (ec)
3163 {
3164 // TODO Handle for specific error code
3165 BMCWEB_LOG_ERROR("doClearLog resp_handler got error {}", ec);
3166 asyncResp->res.result(
3167 boost::beast::http::status::internal_server_error);
3168 return;
3169 }
3170
3171 asyncResp->res.result(boost::beast::http::status::no_content);
3172 };
3173
3174 // Make call to Logging service to request Clear Log
3175 crow::connections::systemBus->async_method_call(
3176 respHandler, "xyz.openbmc_project.Logging",
3177 "/xyz/openbmc_project/logging",
3178 "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
3179}
3180
Andrew Geisslercb92c032018-08-17 07:56:14 -07003181/**
3182 * DBusLogServiceActionsClear class supports POST method for ClearLog action.
3183 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003184inline void requestRoutesDBusLogServiceActionsClear(App& app)
Andrew Geisslercb92c032018-08-17 07:56:14 -07003185{
Andrew Geisslercb92c032018-08-17 07:56:14 -07003186 /**
3187 * Function handles POST method request.
3188 * The Clear Log actions does not require any parameter.The action deletes
3189 * all entries found in the Entries collection for this Log Service.
3190 */
Andrew Geisslercb92c032018-08-17 07:56:14 -07003191
George Liu0fda0f12021-11-16 10:06:17 +08003192 BMCWEB_ROUTE(
3193 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07003194 "/redfish/v1/Systems/<str>/LogServices/EventLog/Actions/LogService.ClearLog/")
Ed Tanoused398212021-06-09 17:05:54 -07003195 .privileges(redfish::privileges::postLogService)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003196 .methods(boost::beast::http::verb::post)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07003197 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07003198 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3199 const std::string& systemName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003200 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3201 {
3202 return;
3203 }
3204 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
3205 {
3206 // Option currently returns no systems. TBD
3207 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3208 systemName);
3209 return;
3210 }
3211 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
3212 {
3213 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3214 systemName);
3215 return;
3216 }
3217 dBusLogServiceActionsClear(asyncResp);
3218 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003219}
ZhikuiRena3316fc2020-01-29 14:58:08 -08003220
Ed Tanous1da66f72018-07-27 16:13:37 -07003221} // namespace redfish