blob: 5af8852b03070f99b9e42853a0057b65ce4c88b8 [file] [log] [blame]
Ed Tanous1da66f72018-07-27 16:13:37 -07001/*
Ed Tanous6be832e2024-09-10 11:44:48 -07002Copyright (c) 2018 Intel Corporation
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
Ed Tanous1da66f72018-07-27 16:13:37 -070015*/
16#pragma once
17
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080018#include "app.hpp"
George Liu7a1dbc42022-12-07 16:03:22 +080019#include "dbus_utility.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080020#include "error_messages.hpp"
Asmitha Karunanithi68dd0752022-11-15 11:33:46 -060021#include "generated/enums/log_entry.hpp"
Ed Tanous539d8c62024-06-19 14:38:27 -070022#include "generated/enums/log_service.hpp"
Spencer Kub7028eb2021-10-26 15:27:35 +080023#include "gzfile.hpp"
George Liu647b3cd2021-07-05 12:43:56 +080024#include "http_utility.hpp"
Spencer Kub7028eb2021-10-26 15:27:35 +080025#include "human_sort.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080026#include "query.hpp"
Jason M. Bills4851d452019-03-28 11:27:48 -070027#include "registries.hpp"
28#include "registries/base_message_registry.hpp"
29#include "registries/openbmc_message_registry.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080030#include "registries/privilege_registry.hpp"
James Feist46229572020-02-19 15:11:58 -080031#include "task.hpp"
Ed Tanous5b904292024-04-16 11:10:17 -070032#include "task_messages.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080033#include "utils/dbus_utils.hpp"
Ed Tanous5b904292024-04-16 11:10:17 -070034#include "utils/json_utils.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080035#include "utils/time_utils.hpp"
Ed Tanous1da66f72018-07-27 16:13:37 -070036
Myung Bae75e8e212023-11-30 12:53:46 -080037#include <systemd/sd-id128.h>
Asmitha Karunanithi8e317782020-12-10 03:35:05 -060038#include <tinyxml2.h>
Adriana Kobylak400fd1f2021-01-29 09:01:30 -060039#include <unistd.h>
Jason M. Billse1f26342018-07-18 12:12:00 -070040
Ed Tanous07c8c202022-07-11 10:08:08 -070041#include <boost/beast/http/verb.hpp>
Ed Tanous1da66f72018-07-27 16:13:37 -070042#include <boost/container/flat_map.hpp>
Jason M. Bills1ddcf012019-11-26 14:59:21 -080043#include <boost/system/linux_error.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070044#include <boost/url/format.hpp>
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +020045#include <sdbusplus/asio/property.hpp>
46#include <sdbusplus/unpack_properties.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050047
George Liu7a1dbc42022-12-07 16:03:22 +080048#include <array>
George Liu647b3cd2021-07-05 12:43:56 +080049#include <charconv>
Abhilash Rajub5f288d2023-11-08 22:32:44 -060050#include <cstddef>
James Feist4418c7f2019-04-15 11:09:15 -070051#include <filesystem>
Ed Tanous18f8f602023-07-18 10:07:23 -070052#include <iterator>
Xiaochao Ma75710de2021-01-21 17:56:02 +080053#include <optional>
Ed Tanous3544d2a2023-08-06 18:12:20 -070054#include <ranges>
Ed Tanous26702d02021-11-03 15:02:33 -070055#include <span>
Ed Tanous18f8f602023-07-18 10:07:23 -070056#include <string>
Jason M. Billscd225da2019-05-08 15:31:57 -070057#include <string_view>
Ed Tanousabf2add2019-01-22 16:40:12 -080058#include <variant>
Ed Tanous1da66f72018-07-27 16:13:37 -070059
60namespace redfish
61{
62
Patrick Williams89492a12023-05-10 07:51:34 -050063constexpr const char* crashdumpObject = "com.intel.crashdump";
64constexpr const char* crashdumpPath = "/com/intel/crashdump";
65constexpr const char* crashdumpInterface = "com.intel.crashdump";
66constexpr const char* deleteAllInterface =
Jason M. Bills5b61b5e2019-10-16 10:59:02 -070067 "xyz.openbmc_project.Collection.DeleteAll";
Patrick Williams89492a12023-05-10 07:51:34 -050068constexpr const char* crashdumpOnDemandInterface =
Jason M. Bills424c4172019-03-21 13:50:33 -070069 "com.intel.crashdump.OnDemand";
Patrick Williams89492a12023-05-10 07:51:34 -050070constexpr const char* crashdumpTelemetryInterface =
Kenny L. Ku6eda7682020-06-19 09:48:36 -070071 "com.intel.crashdump.Telemetry";
Ed Tanous1da66f72018-07-27 16:13:37 -070072
Asmitha Karunanithi8e317782020-12-10 03:35:05 -060073enum class DumpCreationProgress
74{
75 DUMP_CREATE_SUCCESS,
76 DUMP_CREATE_FAILED,
77 DUMP_CREATE_INPROGRESS
78};
79
James Feistf6150402019-01-08 10:36:20 -080080namespace fs = std::filesystem;
Ed Tanous1da66f72018-07-27 16:13:37 -070081
Gunnar Mills1214b7e2020-06-04 10:11:30 -050082inline std::string translateSeverityDbusToRedfish(const std::string& s)
Andrew Geisslercb92c032018-08-17 07:56:14 -070083{
Ed Tanousd4d25792020-09-29 15:15:03 -070084 if ((s == "xyz.openbmc_project.Logging.Entry.Level.Alert") ||
85 (s == "xyz.openbmc_project.Logging.Entry.Level.Critical") ||
86 (s == "xyz.openbmc_project.Logging.Entry.Level.Emergency") ||
87 (s == "xyz.openbmc_project.Logging.Entry.Level.Error"))
Andrew Geisslercb92c032018-08-17 07:56:14 -070088 {
89 return "Critical";
90 }
Ed Tanous3174e4d2020-10-07 11:41:22 -070091 if ((s == "xyz.openbmc_project.Logging.Entry.Level.Debug") ||
92 (s == "xyz.openbmc_project.Logging.Entry.Level.Informational") ||
93 (s == "xyz.openbmc_project.Logging.Entry.Level.Notice"))
Andrew Geisslercb92c032018-08-17 07:56:14 -070094 {
95 return "OK";
96 }
Ed Tanous3174e4d2020-10-07 11:41:22 -070097 if (s == "xyz.openbmc_project.Logging.Entry.Level.Warning")
Andrew Geisslercb92c032018-08-17 07:56:14 -070098 {
99 return "Warning";
100 }
101 return "";
102}
103
Abhishek Patel9017faf2021-09-14 22:48:55 -0500104inline std::optional<bool> getProviderNotifyAction(const std::string& notify)
105{
106 std::optional<bool> notifyAction;
107 if (notify == "xyz.openbmc_project.Logging.Entry.Notify.Notify")
108 {
109 notifyAction = true;
110 }
111 else if (notify == "xyz.openbmc_project.Logging.Entry.Notify.Inhibit")
112 {
113 notifyAction = false;
114 }
115
116 return notifyAction;
117}
118
Ed Tanous18f8f602023-07-18 10:07:23 -0700119inline std::string getDumpPath(std::string_view dumpType)
120{
121 std::string dbusDumpPath = "/xyz/openbmc_project/dump/";
122 std::ranges::transform(dumpType, std::back_inserter(dbusDumpPath),
123 bmcweb::asciiToLower);
124
125 return dbusDumpPath;
126}
127
Ed Tanous055713e2024-07-17 17:19:36 -0700128inline bool getUniqueEntryID(const std::string& logEntry, std::string& entryID,
Jason M. Billse85d6b12019-07-29 17:01:15 -0700129 const bool firstEntry = true)
Jason M. Bills95820182019-04-22 16:25:34 -0700130{
Ed Tanous271584a2019-07-09 16:24:22 -0700131 static time_t prevTs = 0;
Jason M. Bills95820182019-04-22 16:25:34 -0700132 static int index = 0;
Jason M. Billse85d6b12019-07-29 17:01:15 -0700133 if (firstEntry)
134 {
135 prevTs = 0;
136 }
137
Jason M. Bills95820182019-04-22 16:25:34 -0700138 // Get the entry timestamp
Ed Tanous271584a2019-07-09 16:24:22 -0700139 std::time_t curTs = 0;
Jason M. Bills95820182019-04-22 16:25:34 -0700140 std::tm timeStruct = {};
141 std::istringstream entryStream(logEntry);
142 if (entryStream >> std::get_time(&timeStruct, "%Y-%m-%dT%H:%M:%S"))
143 {
144 curTs = std::mktime(&timeStruct);
145 }
146 // If the timestamp isn't unique, increment the index
147 if (curTs == prevTs)
148 {
149 index++;
150 }
151 else
152 {
153 // Otherwise, reset it
154 index = 0;
155 }
156 // Save the timestamp
157 prevTs = curTs;
158
159 entryID = std::to_string(curTs);
160 if (index > 0)
161 {
162 entryID += "_" + std::to_string(index);
163 }
164 return true;
165}
166
Ed Tanous4ff0f1f2024-09-04 17:27:37 -0700167inline bool
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500168 getRedfishLogFiles(std::vector<std::filesystem::path>& redfishLogFiles)
Jason M. Bills95820182019-04-22 16:25:34 -0700169{
170 static const std::filesystem::path redfishLogDir = "/var/log";
171 static const std::string redfishLogFilename = "redfish";
172
173 // Loop through the directory looking for redfish log files
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500174 for (const std::filesystem::directory_entry& dirEnt :
Jason M. Bills95820182019-04-22 16:25:34 -0700175 std::filesystem::directory_iterator(redfishLogDir))
176 {
177 // If we find a redfish log file, save the path
178 std::string filename = dirEnt.path().filename();
Ed Tanous11ba3972022-07-11 09:50:41 -0700179 if (filename.starts_with(redfishLogFilename))
Jason M. Bills95820182019-04-22 16:25:34 -0700180 {
181 redfishLogFiles.emplace_back(redfishLogDir / filename);
182 }
183 }
184 // As the log files rotate, they are appended with a ".#" that is higher for
185 // the older logs. Since we don't expect more than 10 log files, we
186 // can just sort the list to get them in order from newest to oldest
Ed Tanous3544d2a2023-08-06 18:12:20 -0700187 std::ranges::sort(redfishLogFiles);
Jason M. Bills95820182019-04-22 16:25:34 -0700188
189 return !redfishLogFiles.empty();
190}
191
Asmitha Karunanithi68dd0752022-11-15 11:33:46 -0600192inline log_entry::OriginatorTypes
193 mapDbusOriginatorTypeToRedfish(const std::string& originatorType)
194{
195 if (originatorType ==
196 "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Client")
197 {
198 return log_entry::OriginatorTypes::Client;
199 }
200 if (originatorType ==
201 "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Internal")
202 {
203 return log_entry::OriginatorTypes::Internal;
204 }
205 if (originatorType ==
206 "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.SupportingService")
207 {
208 return log_entry::OriginatorTypes::SupportingService;
209 }
210 return log_entry::OriginatorTypes::Invalid;
211}
212
Claire Weinanaefe3782022-07-15 19:17:19 -0700213inline void parseDumpEntryFromDbusObject(
Jiaqing Zhao2d613eb2022-08-15 16:03:00 +0800214 const dbus::utility::ManagedObjectType::value_type& object,
Claire Weinanc6fecda2022-07-15 10:43:25 -0700215 std::string& dumpStatus, uint64_t& size, uint64_t& timestampUs,
Asmitha Karunanithi68dd0752022-11-15 11:33:46 -0600216 std::string& originatorId, log_entry::OriginatorTypes& originatorType,
Claire Weinanaefe3782022-07-15 19:17:19 -0700217 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
218{
219 for (const auto& interfaceMap : object.second)
220 {
221 if (interfaceMap.first == "xyz.openbmc_project.Common.Progress")
222 {
223 for (const auto& propertyMap : interfaceMap.second)
224 {
225 if (propertyMap.first == "Status")
226 {
227 const auto* status =
228 std::get_if<std::string>(&propertyMap.second);
229 if (status == nullptr)
230 {
231 messages::internalError(asyncResp->res);
232 break;
233 }
234 dumpStatus = *status;
235 }
236 }
237 }
238 else if (interfaceMap.first == "xyz.openbmc_project.Dump.Entry")
239 {
240 for (const auto& propertyMap : interfaceMap.second)
241 {
242 if (propertyMap.first == "Size")
243 {
244 const auto* sizePtr =
245 std::get_if<uint64_t>(&propertyMap.second);
246 if (sizePtr == nullptr)
247 {
248 messages::internalError(asyncResp->res);
249 break;
250 }
251 size = *sizePtr;
252 break;
253 }
254 }
255 }
256 else if (interfaceMap.first == "xyz.openbmc_project.Time.EpochTime")
257 {
258 for (const auto& propertyMap : interfaceMap.second)
259 {
260 if (propertyMap.first == "Elapsed")
261 {
262 const uint64_t* usecsTimeStamp =
263 std::get_if<uint64_t>(&propertyMap.second);
264 if (usecsTimeStamp == nullptr)
265 {
266 messages::internalError(asyncResp->res);
267 break;
268 }
Claire Weinanc6fecda2022-07-15 10:43:25 -0700269 timestampUs = *usecsTimeStamp;
Claire Weinanaefe3782022-07-15 19:17:19 -0700270 break;
271 }
272 }
273 }
Asmitha Karunanithi68dd0752022-11-15 11:33:46 -0600274 else if (interfaceMap.first ==
275 "xyz.openbmc_project.Common.OriginatedBy")
276 {
277 for (const auto& propertyMap : interfaceMap.second)
278 {
279 if (propertyMap.first == "OriginatorId")
280 {
281 const std::string* id =
282 std::get_if<std::string>(&propertyMap.second);
283 if (id == nullptr)
284 {
285 messages::internalError(asyncResp->res);
286 break;
287 }
288 originatorId = *id;
289 }
290
291 if (propertyMap.first == "OriginatorType")
292 {
293 const std::string* type =
294 std::get_if<std::string>(&propertyMap.second);
295 if (type == nullptr)
296 {
297 messages::internalError(asyncResp->res);
298 break;
299 }
300
301 originatorType = mapDbusOriginatorTypeToRedfish(*type);
302 if (originatorType == log_entry::OriginatorTypes::Invalid)
303 {
304 messages::internalError(asyncResp->res);
305 break;
306 }
307 }
308 }
309 }
Claire Weinanaefe3782022-07-15 19:17:19 -0700310 }
311}
312
Nan Zhou21ab4042022-06-26 23:07:40 +0000313static std::string getDumpEntriesPath(const std::string& dumpType)
Claire Weinanfdd26902022-03-01 14:18:25 -0800314{
315 std::string entriesPath;
316
317 if (dumpType == "BMC")
318 {
Ed Tanous253f11b2024-05-16 09:38:31 -0700319 entriesPath =
320 std::format("/redfish/v1/Managers/{}/LogServices/Dump/Entries/",
321 BMCWEB_REDFISH_MANAGER_URI_NAME);
Claire Weinanfdd26902022-03-01 14:18:25 -0800322 }
323 else if (dumpType == "FaultLog")
324 {
Ed Tanous253f11b2024-05-16 09:38:31 -0700325 entriesPath =
326 std::format("/redfish/v1/Managers/{}/LogServices/FaultLog/Entries/",
327 BMCWEB_REDFISH_MANAGER_URI_NAME);
Claire Weinanfdd26902022-03-01 14:18:25 -0800328 }
329 else if (dumpType == "System")
330 {
Ed Tanous253f11b2024-05-16 09:38:31 -0700331 entriesPath =
332 std::format("/redfish/v1/Systems/{}/LogServices/Dump/Entries/",
333 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Claire Weinanfdd26902022-03-01 14:18:25 -0800334 }
335 else
336 {
Ed Tanous62598e32023-07-17 17:06:25 -0700337 BMCWEB_LOG_ERROR("getDumpEntriesPath() invalid dump type: {}",
338 dumpType);
Claire Weinanfdd26902022-03-01 14:18:25 -0800339 }
340
341 // Returns empty string on error
342 return entriesPath;
343}
344
zhanghch058d1b46d2021-04-01 11:18:24 +0800345inline void
346 getDumpEntryCollection(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
347 const std::string& dumpType)
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500348{
Claire Weinanfdd26902022-03-01 14:18:25 -0800349 std::string entriesPath = getDumpEntriesPath(dumpType);
350 if (entriesPath.empty())
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500351 {
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500352 messages::internalError(asyncResp->res);
353 return;
354 }
355
George Liu5eb468d2023-06-20 17:03:24 +0800356 sdbusplus::message::object_path path("/xyz/openbmc_project/dump");
357 dbus::utility::getManagedObjects(
358 "xyz.openbmc_project.Dump.Manager", path,
Claire Weinanfdd26902022-03-01 14:18:25 -0800359 [asyncResp, entriesPath,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800360 dumpType](const boost::system::error_code& ec,
George Liu5eb468d2023-06-20 17:03:24 +0800361 const dbus::utility::ManagedObjectType& objects) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400362 if (ec)
363 {
364 BMCWEB_LOG_ERROR("DumpEntry resp_handler got error {}", ec);
365 messages::internalError(asyncResp->res);
366 return;
367 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700368
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400369 // Remove ending slash
370 std::string odataIdStr = entriesPath;
371 if (!odataIdStr.empty())
372 {
373 odataIdStr.pop_back();
374 }
Claire Weinanfdd26902022-03-01 14:18:25 -0800375
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400376 asyncResp->res.jsonValue["@odata.type"] =
377 "#LogEntryCollection.LogEntryCollection";
378 asyncResp->res.jsonValue["@odata.id"] = std::move(odataIdStr);
379 asyncResp->res.jsonValue["Name"] = dumpType + " Dump Entries";
380 asyncResp->res.jsonValue["Description"] =
381 "Collection of " + dumpType + " Dump Entries";
Claire Weinanfdd26902022-03-01 14:18:25 -0800382
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400383 nlohmann::json::array_t entriesArray;
384 std::string dumpEntryPath = getDumpPath(dumpType) + "/entry/";
Ed Tanous002d39b2022-05-31 08:59:27 -0700385
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400386 dbus::utility::ManagedObjectType resp(objects);
387 std::ranges::sort(resp, [](const auto& l, const auto& r) {
388 return AlphanumLess<std::string>()(l.first.filename(),
389 r.first.filename());
390 });
391
392 for (auto& object : resp)
393 {
394 if (object.first.str.find(dumpEntryPath) == std::string::npos)
395 {
396 continue;
397 }
398 uint64_t timestampUs = 0;
399 uint64_t size = 0;
400 std::string dumpStatus;
401 std::string originatorId;
402 log_entry::OriginatorTypes originatorType =
403 log_entry::OriginatorTypes::Internal;
404 nlohmann::json::object_t thisEntry;
405
406 std::string entryID = object.first.filename();
407 if (entryID.empty())
408 {
409 continue;
410 }
411
412 parseDumpEntryFromDbusObject(object, dumpStatus, size,
413 timestampUs, originatorId,
414 originatorType, asyncResp);
415
416 if (dumpStatus !=
417 "xyz.openbmc_project.Common.Progress.OperationStatus.Completed" &&
418 !dumpStatus.empty())
419 {
420 // Dump status is not Complete, no need to enumerate
421 continue;
422 }
423
424 thisEntry["@odata.type"] = "#LogEntry.v1_11_0.LogEntry";
425 thisEntry["@odata.id"] = entriesPath + entryID;
426 thisEntry["Id"] = entryID;
427 thisEntry["EntryType"] = "Event";
428 thisEntry["Name"] = dumpType + " Dump Entry";
429 thisEntry["Created"] =
430 redfish::time_utils::getDateTimeUintUs(timestampUs);
431
432 if (!originatorId.empty())
433 {
434 thisEntry["Originator"] = originatorId;
435 thisEntry["OriginatorType"] = originatorType;
436 }
437
438 if (dumpType == "BMC")
439 {
440 thisEntry["DiagnosticDataType"] = "Manager";
441 thisEntry["AdditionalDataURI"] =
442 entriesPath + entryID + "/attachment";
443 thisEntry["AdditionalDataSizeBytes"] = size;
444 }
445 else if (dumpType == "System")
446 {
447 thisEntry["DiagnosticDataType"] = "OEM";
448 thisEntry["OEMDiagnosticDataType"] = "System";
449 thisEntry["AdditionalDataURI"] =
450 entriesPath + entryID + "/attachment";
451 thisEntry["AdditionalDataSizeBytes"] = size;
452 }
453 entriesArray.emplace_back(std::move(thisEntry));
454 }
455 asyncResp->res.jsonValue["Members@odata.count"] =
456 entriesArray.size();
457 asyncResp->res.jsonValue["Members"] = std::move(entriesArray);
Ed Tanous002d39b2022-05-31 08:59:27 -0700458 });
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500459}
460
zhanghch058d1b46d2021-04-01 11:18:24 +0800461inline void
Claire Weinanc7a6d662022-06-13 16:36:39 -0700462 getDumpEntryById(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
zhanghch058d1b46d2021-04-01 11:18:24 +0800463 const std::string& entryID, const std::string& dumpType)
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500464{
Claire Weinanfdd26902022-03-01 14:18:25 -0800465 std::string entriesPath = getDumpEntriesPath(dumpType);
466 if (entriesPath.empty())
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500467 {
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500468 messages::internalError(asyncResp->res);
469 return;
470 }
471
George Liu5eb468d2023-06-20 17:03:24 +0800472 sdbusplus::message::object_path path("/xyz/openbmc_project/dump");
473 dbus::utility::getManagedObjects(
474 "xyz.openbmc_project.Dump.Manager", path,
Claire Weinanfdd26902022-03-01 14:18:25 -0800475 [asyncResp, entryID, dumpType,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800476 entriesPath](const boost::system::error_code& ec,
Ed Tanous02cad962022-06-30 16:50:15 -0700477 const dbus::utility::ManagedObjectType& resp) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400478 if (ec)
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500479 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400480 BMCWEB_LOG_ERROR("DumpEntry resp_handler got error {}", ec);
481 messages::internalError(asyncResp->res);
482 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700483 }
484
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400485 bool foundDumpEntry = false;
486 std::string dumpEntryPath = getDumpPath(dumpType) + "/entry/";
Ed Tanous002d39b2022-05-31 08:59:27 -0700487
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400488 for (const auto& objectPath : resp)
Ed Tanous002d39b2022-05-31 08:59:27 -0700489 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400490 if (objectPath.first.str != dumpEntryPath + entryID)
491 {
492 continue;
493 }
494
495 foundDumpEntry = true;
496 uint64_t timestampUs = 0;
497 uint64_t size = 0;
498 std::string dumpStatus;
499 std::string originatorId;
500 log_entry::OriginatorTypes originatorType =
501 log_entry::OriginatorTypes::Internal;
502
503 parseDumpEntryFromDbusObject(objectPath, dumpStatus, size,
504 timestampUs, originatorId,
505 originatorType, asyncResp);
506
507 if (dumpStatus !=
508 "xyz.openbmc_project.Common.Progress.OperationStatus.Completed" &&
509 !dumpStatus.empty())
510 {
511 // Dump status is not Complete
512 // return not found until status is changed to Completed
513 messages::resourceNotFound(asyncResp->res,
514 dumpType + " dump", entryID);
515 return;
516 }
517
518 asyncResp->res.jsonValue["@odata.type"] =
519 "#LogEntry.v1_11_0.LogEntry";
520 asyncResp->res.jsonValue["@odata.id"] = entriesPath + entryID;
521 asyncResp->res.jsonValue["Id"] = entryID;
522 asyncResp->res.jsonValue["EntryType"] = "Event";
523 asyncResp->res.jsonValue["Name"] = dumpType + " Dump Entry";
524 asyncResp->res.jsonValue["Created"] =
525 redfish::time_utils::getDateTimeUintUs(timestampUs);
526
527 if (!originatorId.empty())
528 {
529 asyncResp->res.jsonValue["Originator"] = originatorId;
530 asyncResp->res.jsonValue["OriginatorType"] = originatorType;
531 }
532
533 if (dumpType == "BMC")
534 {
535 asyncResp->res.jsonValue["DiagnosticDataType"] = "Manager";
536 asyncResp->res.jsonValue["AdditionalDataURI"] =
537 entriesPath + entryID + "/attachment";
538 asyncResp->res.jsonValue["AdditionalDataSizeBytes"] = size;
539 }
540 else if (dumpType == "System")
541 {
542 asyncResp->res.jsonValue["DiagnosticDataType"] = "OEM";
543 asyncResp->res.jsonValue["OEMDiagnosticDataType"] =
544 "System";
545 asyncResp->res.jsonValue["AdditionalDataURI"] =
546 entriesPath + entryID + "/attachment";
547 asyncResp->res.jsonValue["AdditionalDataSizeBytes"] = size;
548 }
549 }
550 if (!foundDumpEntry)
551 {
552 BMCWEB_LOG_WARNING("Can't find Dump Entry {}", entryID);
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +0200553 messages::resourceNotFound(asyncResp->res, dumpType + " dump",
554 entryID);
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500555 return;
556 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400557 });
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500558}
559
zhanghch058d1b46d2021-04-01 11:18:24 +0800560inline void deleteDumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Stanley Chu98782562020-11-04 16:10:24 +0800561 const std::string& entryID,
Asmitha Karunanithib47452b2020-09-25 02:02:19 -0500562 const std::string& dumpType)
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500563{
Patrick Williams5a39f772023-10-20 11:20:21 -0500564 auto respHandler = [asyncResp,
565 entryID](const boost::system::error_code& ec) {
Ed Tanous62598e32023-07-17 17:06:25 -0700566 BMCWEB_LOG_DEBUG("Dump Entry doDelete callback: Done");
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500567 if (ec)
568 {
George Liu3de8d8b2021-03-22 17:49:39 +0800569 if (ec.value() == EBADR)
570 {
571 messages::resourceNotFound(asyncResp->res, "LogEntry", entryID);
572 return;
573 }
Ed Tanous62598e32023-07-17 17:06:25 -0700574 BMCWEB_LOG_ERROR(
575 "Dump (DBus) doDelete respHandler got error {} entryID={}", ec,
576 entryID);
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500577 messages::internalError(asyncResp->res);
578 return;
579 }
580 };
Ed Tanous18f8f602023-07-18 10:07:23 -0700581
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500582 crow::connections::systemBus->async_method_call(
583 respHandler, "xyz.openbmc_project.Dump.Manager",
Ed Tanous18f8f602023-07-18 10:07:23 -0700584 std::format("{}/entry/{}", getDumpPath(dumpType), entryID),
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500585 "xyz.openbmc_project.Object.Delete", "Delete");
586}
Abhilash Rajub5f288d2023-11-08 22:32:44 -0600587inline bool checkSizeLimit(int fd, crow::Response& res)
588{
589 long long int size = lseek(fd, 0, SEEK_END);
590 if (size <= 0)
591 {
592 BMCWEB_LOG_ERROR("Failed to get size of file, lseek() returned {}",
593 size);
594 messages::internalError(res);
595 return false;
596 }
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500597
Abhilash Rajub5f288d2023-11-08 22:32:44 -0600598 // Arbitrary max size of 20MB to accommodate BMC dumps
599 constexpr long long int maxFileSize = 20LL * 1024LL * 1024LL;
600 if (size > maxFileSize)
601 {
602 BMCWEB_LOG_ERROR("File size {} exceeds maximum allowed size of {}",
603 size, maxFileSize);
604 messages::internalError(res);
605 return false;
606 }
607 off_t rc = lseek(fd, 0, SEEK_SET);
608 if (rc < 0)
609 {
610 BMCWEB_LOG_ERROR("Failed to reset file offset to 0");
611 messages::internalError(res);
612 return false;
613 }
614 return true;
615}
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400616inline void downloadEntryCallback(
617 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
618 const std::string& entryID, const std::string& downloadEntryType,
619 const boost::system::error_code& ec,
620 const sdbusplus::message::unix_fd& unixfd)
Carson Labrado168d1b12023-03-27 17:04:46 +0000621{
622 if (ec.value() == EBADR)
623 {
624 messages::resourceNotFound(asyncResp->res, "EntryAttachment", entryID);
625 return;
626 }
627 if (ec)
628 {
629 BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
630 messages::internalError(asyncResp->res);
631 return;
632 }
633
634 // Make sure we know how to process the retrieved entry attachment
635 if ((downloadEntryType != "BMC") && (downloadEntryType != "System"))
636 {
637 BMCWEB_LOG_ERROR("downloadEntryCallback() invalid entry type: {}",
638 downloadEntryType);
639 messages::internalError(asyncResp->res);
640 }
641
642 int fd = -1;
643 fd = dup(unixfd);
644 if (fd < 0)
645 {
646 BMCWEB_LOG_ERROR("Failed to open file");
647 messages::internalError(asyncResp->res);
648 return;
649 }
Abhilash Rajub5f288d2023-11-08 22:32:44 -0600650 if (!checkSizeLimit(fd, asyncResp->res))
Carson Labrado168d1b12023-03-27 17:04:46 +0000651 {
Carson Labrado168d1b12023-03-27 17:04:46 +0000652 close(fd);
653 return;
654 }
Carson Labrado168d1b12023-03-27 17:04:46 +0000655 if (downloadEntryType == "System")
656 {
Abhilash Rajub5f288d2023-11-08 22:32:44 -0600657 if (!asyncResp->res.openFd(fd, bmcweb::EncodingType::Base64))
658 {
659 messages::internalError(asyncResp->res);
660 close(fd);
661 return;
662 }
Carson Labrado168d1b12023-03-27 17:04:46 +0000663 asyncResp->res.addHeader(
664 boost::beast::http::field::content_transfer_encoding, "Base64");
Abhilash Rajub5f288d2023-11-08 22:32:44 -0600665 return;
Carson Labrado168d1b12023-03-27 17:04:46 +0000666 }
Abhilash Rajub5f288d2023-11-08 22:32:44 -0600667 if (!asyncResp->res.openFd(fd))
Ed Tanous27b0cf92023-08-07 12:02:40 -0700668 {
Abhilash Rajub5f288d2023-11-08 22:32:44 -0600669 messages::internalError(asyncResp->res);
670 close(fd);
671 return;
Ed Tanous27b0cf92023-08-07 12:02:40 -0700672 }
Carson Labrado168d1b12023-03-27 17:04:46 +0000673 asyncResp->res.addHeader(boost::beast::http::field::content_type,
674 "application/octet-stream");
675}
676
677inline void
678 downloadDumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
679 const std::string& entryID, const std::string& dumpType)
680{
681 if (dumpType != "BMC")
682 {
683 BMCWEB_LOG_WARNING("Can't find Dump Entry {}", entryID);
684 messages::resourceNotFound(asyncResp->res, dumpType + " dump", entryID);
685 return;
686 }
687
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400688 std::string dumpEntryPath =
689 std::format("{}/entry/{}", getDumpPath(dumpType), entryID);
Carson Labrado168d1b12023-03-27 17:04:46 +0000690
691 auto downloadDumpEntryHandler =
692 [asyncResp, entryID,
693 dumpType](const boost::system::error_code& ec,
694 const sdbusplus::message::unix_fd& unixfd) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400695 downloadEntryCallback(asyncResp, entryID, dumpType, ec, unixfd);
696 };
Carson Labrado168d1b12023-03-27 17:04:46 +0000697
698 crow::connections::systemBus->async_method_call(
699 std::move(downloadDumpEntryHandler), "xyz.openbmc_project.Dump.Manager",
700 dumpEntryPath, "xyz.openbmc_project.Dump.Entry", "GetFileHandle");
701}
702
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400703inline void downloadEventLogEntry(
704 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
705 const std::string& systemName, const std::string& entryID,
706 const std::string& dumpType)
Carson Labrado168d1b12023-03-27 17:04:46 +0000707{
Ed Tanous25b54db2024-04-17 15:40:31 -0700708 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Carson Labrado168d1b12023-03-27 17:04:46 +0000709 {
710 // Option currently returns no systems. TBD
711 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
712 systemName);
713 return;
714 }
Ed Tanous253f11b2024-05-16 09:38:31 -0700715 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Carson Labrado168d1b12023-03-27 17:04:46 +0000716 {
717 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
718 systemName);
719 return;
720 }
721
722 std::string entryPath =
723 sdbusplus::message::object_path("/xyz/openbmc_project/logging/entry") /
724 entryID;
725
726 auto downloadEventLogEntryHandler =
727 [asyncResp, entryID,
728 dumpType](const boost::system::error_code& ec,
729 const sdbusplus::message::unix_fd& unixfd) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400730 downloadEntryCallback(asyncResp, entryID, dumpType, ec, unixfd);
731 };
Carson Labrado168d1b12023-03-27 17:04:46 +0000732
733 crow::connections::systemBus->async_method_call(
734 std::move(downloadEventLogEntryHandler), "xyz.openbmc_project.Logging",
735 entryPath, "xyz.openbmc_project.Logging.Entry", "GetEntry");
736}
737
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600738inline DumpCreationProgress
739 mapDbusStatusToDumpProgress(const std::string& status)
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500740{
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600741 if (status ==
742 "xyz.openbmc_project.Common.Progress.OperationStatus.Failed" ||
743 status == "xyz.openbmc_project.Common.Progress.OperationStatus.Aborted")
744 {
745 return DumpCreationProgress::DUMP_CREATE_FAILED;
746 }
747 if (status ==
748 "xyz.openbmc_project.Common.Progress.OperationStatus.Completed")
749 {
750 return DumpCreationProgress::DUMP_CREATE_SUCCESS;
751 }
752 return DumpCreationProgress::DUMP_CREATE_INPROGRESS;
753}
754
755inline DumpCreationProgress
756 getDumpCompletionStatus(const dbus::utility::DBusPropertiesMap& values)
757{
758 for (const auto& [key, val] : values)
759 {
760 if (key == "Status")
Ed Tanous002d39b2022-05-31 08:59:27 -0700761 {
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600762 const std::string* value = std::get_if<std::string>(&val);
763 if (value == nullptr)
764 {
Ed Tanous62598e32023-07-17 17:06:25 -0700765 BMCWEB_LOG_ERROR("Status property value is null");
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600766 return DumpCreationProgress::DUMP_CREATE_FAILED;
767 }
768 return mapDbusStatusToDumpProgress(*value);
769 }
770 }
771 return DumpCreationProgress::DUMP_CREATE_INPROGRESS;
772}
773
774inline std::string getDumpEntryPath(const std::string& dumpPath)
775{
776 if (dumpPath == "/xyz/openbmc_project/dump/bmc/entry")
777 {
Ed Tanous253f11b2024-05-16 09:38:31 -0700778 return std::format("/redfish/v1/Managers/{}/LogServices/Dump/Entries/",
Ed Tanous9f565092024-07-12 22:06:53 -0700779 BMCWEB_REDFISH_MANAGER_URI_NAME);
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600780 }
781 if (dumpPath == "/xyz/openbmc_project/dump/system/entry")
782 {
Ed Tanous253f11b2024-05-16 09:38:31 -0700783 return std::format("/redfish/v1/Systems/{}/LogServices/Dump/Entries/",
784 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600785 }
786 return "";
787}
788
789inline void createDumpTaskCallback(
790 task::Payload&& payload,
791 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
792 const sdbusplus::message::object_path& createdObjPath)
793{
794 const std::string dumpPath = createdObjPath.parent_path().str;
795 const std::string dumpId = createdObjPath.filename();
796
797 std::string dumpEntryPath = getDumpEntryPath(dumpPath);
798
799 if (dumpEntryPath.empty())
800 {
Ed Tanous62598e32023-07-17 17:06:25 -0700801 BMCWEB_LOG_ERROR("Invalid dump type received");
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600802 messages::internalError(asyncResp->res);
803 return;
804 }
805
806 crow::connections::systemBus->async_method_call(
Ed Tanous8cb2c022024-03-27 16:31:46 -0700807 [asyncResp, payload = std::move(payload), createdObjPath,
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600808 dumpEntryPath{std::move(dumpEntryPath)},
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800809 dumpId](const boost::system::error_code& ec,
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600810 const std::string& introspectXml) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400811 if (ec)
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600812 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400813 BMCWEB_LOG_ERROR("Introspect call failed with error: {}",
814 ec.message());
815 messages::internalError(asyncResp->res);
816 return;
817 }
818
819 // Check if the created dump object has implemented Progress
820 // interface to track dump completion. If yes, fetch the "Status"
821 // property of the interface, modify the task state accordingly.
822 // Else, return task completed.
823 tinyxml2::XMLDocument doc;
824
825 doc.Parse(introspectXml.data(), introspectXml.size());
826 tinyxml2::XMLNode* pRoot = doc.FirstChildElement("node");
827 if (pRoot == nullptr)
828 {
829 BMCWEB_LOG_ERROR("XML document failed to parse");
830 messages::internalError(asyncResp->res);
831 return;
832 }
833 tinyxml2::XMLElement* interfaceNode =
834 pRoot->FirstChildElement("interface");
835
836 bool isProgressIntfPresent = false;
837 while (interfaceNode != nullptr)
838 {
839 const char* thisInterfaceName =
840 interfaceNode->Attribute("name");
841 if (thisInterfaceName != nullptr)
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600842 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400843 if (thisInterfaceName ==
844 std::string_view("xyz.openbmc_project.Common.Progress"))
845 {
846 interfaceNode =
847 interfaceNode->NextSiblingElement("interface");
848 continue;
849 }
850 isProgressIntfPresent = true;
851 break;
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600852 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400853 interfaceNode = interfaceNode->NextSiblingElement("interface");
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600854 }
855
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400856 std::shared_ptr<task::TaskData> task = task::TaskData::createTask(
857 [createdObjPath, dumpEntryPath, dumpId, isProgressIntfPresent](
858 const boost::system::error_code& ec2,
859 sdbusplus::message_t& msg,
860 const std::shared_ptr<task::TaskData>& taskData) {
861 if (ec2)
862 {
863 BMCWEB_LOG_ERROR("{}: Error in creating dump",
864 createdObjPath.str);
865 taskData->messages.emplace_back(
866 messages::internalError());
867 taskData->state = "Cancelled";
868 return task::completed;
869 }
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600870
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400871 if (isProgressIntfPresent)
872 {
873 dbus::utility::DBusPropertiesMap values;
874 std::string prop;
875 msg.read(prop, values);
876
877 DumpCreationProgress dumpStatus =
878 getDumpCompletionStatus(values);
879 if (dumpStatus ==
880 DumpCreationProgress::DUMP_CREATE_FAILED)
881 {
882 BMCWEB_LOG_ERROR("{}: Error in creating dump",
883 createdObjPath.str);
884 taskData->state = "Cancelled";
885 return task::completed;
886 }
887
888 if (dumpStatus ==
889 DumpCreationProgress::DUMP_CREATE_INPROGRESS)
890 {
891 BMCWEB_LOG_DEBUG(
892 "{}: Dump creation task is in progress",
893 createdObjPath.str);
894 return !task::completed;
895 }
896 }
897
898 nlohmann::json retMessage = messages::success();
899 taskData->messages.emplace_back(retMessage);
900
901 boost::urls::url url = boost::urls::format(
902 "/redfish/v1/Managers/{}/LogServices/Dump/Entries/{}",
903 BMCWEB_REDFISH_MANAGER_URI_NAME, dumpId);
904
905 std::string headerLoc = "Location: ";
906 headerLoc += url.buffer();
907
908 taskData->payload->httpHeaders.emplace_back(
909 std::move(headerLoc));
910
911 BMCWEB_LOG_DEBUG("{}: Dump creation task completed",
Ed Tanous62598e32023-07-17 17:06:25 -0700912 createdObjPath.str);
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400913 taskData->state = "Completed";
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600914 return task::completed;
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400915 },
916 "type='signal',interface='org.freedesktop.DBus.Properties',"
917 "member='PropertiesChanged',path='" +
918 createdObjPath.str + "'");
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600919
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400920 // The task timer is set to max time limit within which the
921 // requested dump will be collected.
922 task->startTimer(std::chrono::minutes(6));
923 task->populateResp(asyncResp->res);
924 task->payload.emplace(payload);
Patrick Williams5a39f772023-10-20 11:20:21 -0500925 },
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600926 "xyz.openbmc_project.Dump.Manager", createdObjPath,
927 "org.freedesktop.DBus.Introspectable", "Introspect");
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500928}
929
zhanghch058d1b46d2021-04-01 11:18:24 +0800930inline void createDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
931 const crow::Request& req, const std::string& dumpType)
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500932{
Claire Weinanfdd26902022-03-01 14:18:25 -0800933 std::string dumpPath = getDumpEntriesPath(dumpType);
934 if (dumpPath.empty())
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500935 {
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500936 messages::internalError(asyncResp->res);
937 return;
938 }
939
940 std::optional<std::string> diagnosticDataType;
941 std::optional<std::string> oemDiagnosticDataType;
942
Willy Tu15ed6782021-12-14 11:03:16 -0800943 if (!redfish::json_util::readJsonAction(
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500944 req, asyncResp->res, "DiagnosticDataType", diagnosticDataType,
945 "OEMDiagnosticDataType", oemDiagnosticDataType))
946 {
947 return;
948 }
949
950 if (dumpType == "System")
951 {
952 if (!oemDiagnosticDataType || !diagnosticDataType)
953 {
Ed Tanous62598e32023-07-17 17:06:25 -0700954 BMCWEB_LOG_ERROR(
955 "CreateDump action parameter 'DiagnosticDataType'/'OEMDiagnosticDataType' value not found!");
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500956 messages::actionParameterMissing(
957 asyncResp->res, "CollectDiagnosticData",
958 "DiagnosticDataType & OEMDiagnosticDataType");
959 return;
960 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700961 if ((*oemDiagnosticDataType != "System") ||
962 (*diagnosticDataType != "OEM"))
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500963 {
Ed Tanous62598e32023-07-17 17:06:25 -0700964 BMCWEB_LOG_ERROR("Wrong parameter values passed");
Ed Tanousace85d62021-10-26 12:45:59 -0700965 messages::internalError(asyncResp->res);
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500966 return;
967 }
Ed Tanous253f11b2024-05-16 09:38:31 -0700968 dumpPath = std::format("/redfish/v1/Systems/{}/LogServices/Dump/",
969 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500970 }
971 else if (dumpType == "BMC")
972 {
973 if (!diagnosticDataType)
974 {
Ed Tanous62598e32023-07-17 17:06:25 -0700975 BMCWEB_LOG_ERROR(
976 "CreateDump action parameter 'DiagnosticDataType' not found!");
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500977 messages::actionParameterMissing(
978 asyncResp->res, "CollectDiagnosticData", "DiagnosticDataType");
979 return;
980 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700981 if (*diagnosticDataType != "Manager")
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500982 {
Ed Tanous62598e32023-07-17 17:06:25 -0700983 BMCWEB_LOG_ERROR(
984 "Wrong parameter value passed for 'DiagnosticDataType'");
Ed Tanousace85d62021-10-26 12:45:59 -0700985 messages::internalError(asyncResp->res);
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500986 return;
987 }
Ed Tanous253f11b2024-05-16 09:38:31 -0700988 dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/Dump/",
989 BMCWEB_REDFISH_MANAGER_URI_NAME);
Asmitha Karunanithi59075712021-10-22 01:17:41 -0500990 }
991 else
992 {
Ed Tanous62598e32023-07-17 17:06:25 -0700993 BMCWEB_LOG_ERROR("CreateDump failed. Unknown dump type");
Asmitha Karunanithi59075712021-10-22 01:17:41 -0500994 messages::internalError(asyncResp->res);
995 return;
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500996 }
997
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600998 std::vector<std::pair<std::string, std::variant<std::string, uint64_t>>>
999 createDumpParamVec;
1000
Carson Labradof574a8e2023-03-22 02:26:00 +00001001 if (req.session != nullptr)
1002 {
1003 createDumpParamVec.emplace_back(
1004 "xyz.openbmc_project.Dump.Create.CreateParameters.OriginatorId",
1005 req.session->clientIp);
1006 createDumpParamVec.emplace_back(
1007 "xyz.openbmc_project.Dump.Create.CreateParameters.OriginatorType",
1008 "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Client");
1009 }
Asmitha Karunanithi68dd0752022-11-15 11:33:46 -06001010
Asmitha Karunanithia43be802020-05-07 05:05:36 -05001011 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001012 [asyncResp, payload(task::Payload(req)),
1013 dumpPath](const boost::system::error_code& ec,
1014 const sdbusplus::message_t& msg,
1015 const sdbusplus::message::object_path& objPath) mutable {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001016 if (ec)
Asmitha Karunanithi59075712021-10-22 01:17:41 -05001017 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001018 BMCWEB_LOG_ERROR("CreateDump resp_handler got error {}", ec);
1019 const sd_bus_error* dbusError = msg.get_error();
1020 if (dbusError == nullptr)
1021 {
1022 messages::internalError(asyncResp->res);
1023 return;
1024 }
1025
1026 BMCWEB_LOG_ERROR("CreateDump DBus error: {} and error msg: {}",
1027 dbusError->name, dbusError->message);
1028 if (std::string_view(
1029 "xyz.openbmc_project.Common.Error.NotAllowed") ==
1030 dbusError->name)
1031 {
1032 messages::resourceInStandby(asyncResp->res);
1033 return;
1034 }
1035 if (std::string_view(
1036 "xyz.openbmc_project.Dump.Create.Error.Disabled") ==
1037 dbusError->name)
1038 {
1039 messages::serviceDisabled(asyncResp->res, dumpPath);
1040 return;
1041 }
1042 if (std::string_view(
1043 "xyz.openbmc_project.Common.Error.Unavailable") ==
1044 dbusError->name)
1045 {
1046 messages::resourceInUse(asyncResp->res);
1047 return;
1048 }
1049 // Other Dbus errors such as:
1050 // xyz.openbmc_project.Common.Error.InvalidArgument &
1051 // org.freedesktop.DBus.Error.InvalidArgs are all related to
1052 // the dbus call that is made here in the bmcweb
1053 // implementation and has nothing to do with the client's
1054 // input in the request. Hence, returning internal error
1055 // back to the client.
Asmitha Karunanithi59075712021-10-22 01:17:41 -05001056 messages::internalError(asyncResp->res);
1057 return;
1058 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001059 BMCWEB_LOG_DEBUG("Dump Created. Path: {}", objPath.str);
1060 createDumpTaskCallback(std::move(payload), asyncResp, objPath);
1061 },
Ed Tanous18f8f602023-07-18 10:07:23 -07001062 "xyz.openbmc_project.Dump.Manager", getDumpPath(dumpType),
Asmitha Karunanithi8e317782020-12-10 03:35:05 -06001063 "xyz.openbmc_project.Dump.Create", "CreateDump", createDumpParamVec);
Asmitha Karunanithia43be802020-05-07 05:05:36 -05001064}
1065
zhanghch058d1b46d2021-04-01 11:18:24 +08001066inline void clearDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1067 const std::string& dumpType)
Asmitha Karunanithi80319af2020-05-07 05:30:21 -05001068{
Claire Weinan0d946212022-07-13 19:40:19 -07001069 crow::connections::systemBus->async_method_call(
1070 [asyncResp](const boost::system::error_code& ec) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001071 if (ec)
1072 {
1073 BMCWEB_LOG_ERROR("clearDump resp_handler got error {}", ec);
1074 messages::internalError(asyncResp->res);
1075 return;
1076 }
1077 },
Ed Tanous18f8f602023-07-18 10:07:23 -07001078 "xyz.openbmc_project.Dump.Manager", getDumpPath(dumpType),
Claire Weinan0d946212022-07-13 19:40:19 -07001079 "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
Asmitha Karunanithi80319af2020-05-07 05:30:21 -05001080}
1081
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001082inline void parseCrashdumpParameters(
1083 const dbus::utility::DBusPropertiesMap& params, std::string& filename,
1084 std::string& timestamp, std::string& logfile)
Johnathan Mantey043a0532020-03-10 17:15:28 -07001085{
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +02001086 const std::string* filenamePtr = nullptr;
1087 const std::string* timestampPtr = nullptr;
1088 const std::string* logfilePtr = nullptr;
1089
1090 const bool success = sdbusplus::unpackPropertiesNoThrow(
1091 dbus_utils::UnpackErrorPrinter(), params, "Timestamp", timestampPtr,
1092 "Filename", filenamePtr, "Log", logfilePtr);
1093
1094 if (!success)
Johnathan Mantey043a0532020-03-10 17:15:28 -07001095 {
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +02001096 return;
1097 }
1098
1099 if (filenamePtr != nullptr)
1100 {
1101 filename = *filenamePtr;
1102 }
1103
1104 if (timestampPtr != nullptr)
1105 {
1106 timestamp = *timestampPtr;
1107 }
1108
1109 if (logfilePtr != nullptr)
1110 {
1111 logfile = *logfilePtr;
Johnathan Mantey043a0532020-03-10 17:15:28 -07001112 }
1113}
1114
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001115inline void requestRoutesSystemLogServiceCollection(App& app)
Ed Tanous1da66f72018-07-27 16:13:37 -07001116{
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001117 /**
1118 * Functions triggers appropriate requests on DBus
1119 */
Ed Tanous22d268c2022-05-19 09:39:07 -07001120 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/")
Ed Tanoused398212021-06-09 17:05:54 -07001121 .privileges(redfish::privileges::getLogServiceCollection)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001122 .methods(
1123 boost::beast::http::verb::
1124 get)([&app](const crow::Request& req,
1125 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1126 const std::string& systemName) {
1127 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07001128 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001129 return;
1130 }
1131 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1132 {
1133 // Option currently returns no systems. TBD
1134 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1135 systemName);
1136 return;
1137 }
1138 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1139 {
1140 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1141 systemName);
Ed Tanous002d39b2022-05-31 08:59:27 -07001142 return;
1143 }
Ed Tanous45ca1b82022-03-25 13:07:27 -07001144
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001145 // Collections don't include the static data added by SubRoute
1146 // because it has a duplicate entry for members
1147 asyncResp->res.jsonValue["@odata.type"] =
1148 "#LogServiceCollection.LogServiceCollection";
1149 asyncResp->res.jsonValue["@odata.id"] =
1150 std::format("/redfish/v1/Systems/{}/LogServices",
1151 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1152 asyncResp->res.jsonValue["Name"] = "System Log Services Collection";
1153 asyncResp->res.jsonValue["Description"] =
1154 "Collection of LogServices for this Computer System";
1155 nlohmann::json& logServiceArray =
1156 asyncResp->res.jsonValue["Members"];
1157 logServiceArray = nlohmann::json::array();
1158 nlohmann::json::object_t eventLog;
1159 eventLog["@odata.id"] =
1160 std::format("/redfish/v1/Systems/{}/LogServices/EventLog",
1161 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1162 logServiceArray.emplace_back(std::move(eventLog));
1163 if constexpr (BMCWEB_REDFISH_DUMP_LOG)
Ed Tanous002d39b2022-05-31 08:59:27 -07001164 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001165 nlohmann::json::object_t dumpLog;
1166 dumpLog["@odata.id"] =
1167 std::format("/redfish/v1/Systems/{}/LogServices/Dump",
1168 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1169 logServiceArray.emplace_back(std::move(dumpLog));
Ed Tanous002d39b2022-05-31 08:59:27 -07001170 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001171
1172 if constexpr (BMCWEB_REDFISH_CPU_LOG)
1173 {
1174 nlohmann::json::object_t crashdump;
1175 crashdump["@odata.id"] =
1176 std::format("/redfish/v1/Systems/{}/LogServices/Crashdump",
1177 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1178 logServiceArray.emplace_back(std::move(crashdump));
1179 }
1180
1181 if constexpr (BMCWEB_REDFISH_HOST_LOGGER)
1182 {
1183 nlohmann::json::object_t hostlogger;
1184 hostlogger["@odata.id"] =
1185 std::format("/redfish/v1/Systems/{}/LogServices/HostLogger",
1186 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1187 logServiceArray.emplace_back(std::move(hostlogger));
1188 }
1189 asyncResp->res.jsonValue["Members@odata.count"] =
1190 logServiceArray.size();
1191
1192 constexpr std::array<std::string_view, 1> interfaces = {
1193 "xyz.openbmc_project.State.Boot.PostCode"};
1194 dbus::utility::getSubTreePaths(
1195 "/", 0, interfaces,
1196 [asyncResp](const boost::system::error_code& ec,
1197 const dbus::utility::MapperGetSubTreePathsResponse&
1198 subtreePath) {
1199 if (ec)
1200 {
1201 BMCWEB_LOG_ERROR("{}", ec);
1202 return;
1203 }
1204
1205 for (const auto& pathStr : subtreePath)
1206 {
1207 if (pathStr.find("PostCode") != std::string::npos)
1208 {
1209 nlohmann::json& logServiceArrayLocal =
1210 asyncResp->res.jsonValue["Members"];
1211 nlohmann::json::object_t member;
1212 member["@odata.id"] = std::format(
1213 "/redfish/v1/Systems/{}/LogServices/PostCodes",
1214 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1215
1216 logServiceArrayLocal.emplace_back(
1217 std::move(member));
1218
1219 asyncResp->res.jsonValue["Members@odata.count"] =
1220 logServiceArrayLocal.size();
1221 return;
1222 }
1223 }
1224 });
Ed Tanous45ca1b82022-03-25 13:07:27 -07001225 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001226}
1227
1228inline void requestRoutesEventLogService(App& app)
1229{
Ed Tanous22d268c2022-05-19 09:39:07 -07001230 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/")
Ed Tanoused398212021-06-09 17:05:54 -07001231 .privileges(redfish::privileges::getLogService)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001232 .methods(
1233 boost::beast::http::verb::
1234 get)([&app](const crow::Request& req,
1235 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1236 const std::string& systemName) {
1237 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1238 {
1239 return;
1240 }
1241 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1242 {
1243 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1244 systemName);
1245 return;
1246 }
1247 asyncResp->res.jsonValue["@odata.id"] =
1248 std::format("/redfish/v1/Systems/{}/LogServices/EventLog",
1249 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1250 asyncResp->res.jsonValue["@odata.type"] =
1251 "#LogService.v1_2_0.LogService";
1252 asyncResp->res.jsonValue["Name"] = "Event Log Service";
1253 asyncResp->res.jsonValue["Description"] =
1254 "System Event Log Service";
1255 asyncResp->res.jsonValue["Id"] = "EventLog";
1256 asyncResp->res.jsonValue["OverWritePolicy"] =
1257 log_service::OverWritePolicy::WrapsWhenFull;
Tejas Patil7c8c4052021-06-04 17:43:14 +05301258
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001259 std::pair<std::string, std::string> redfishDateTimeOffset =
1260 redfish::time_utils::getDateTimeOffsetNow();
Tejas Patil7c8c4052021-06-04 17:43:14 +05301261
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001262 asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
1263 asyncResp->res.jsonValue["DateTimeLocalOffset"] =
1264 redfishDateTimeOffset.second;
Tejas Patil7c8c4052021-06-04 17:43:14 +05301265
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001266 asyncResp->res.jsonValue["Entries"]["@odata.id"] = std::format(
1267 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
Ed Tanous20fa6a22024-05-20 18:02:58 -07001268 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001269 asyncResp->res
1270 .jsonValue["Actions"]["#LogService.ClearLog"]["target"]
1271
1272 = std::format(
1273 "/redfish/v1/Systems/{}/LogServices/EventLog/Actions/LogService.ClearLog",
1274 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1275 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001276}
1277
Alexander Hansen599b9af2024-08-06 15:11:57 +02001278inline void handleSystemsLogServicesEventLogActionsClearPost(
1279 App& app, const crow::Request& req,
1280 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1281 const std::string& systemName)
1282{
1283 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1284 {
1285 return;
1286 }
1287 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1288 {
1289 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1290 systemName);
1291 return;
1292 }
1293
1294 // Clear the EventLog by deleting the log files
1295 std::vector<std::filesystem::path> redfishLogFiles;
1296 if (getRedfishLogFiles(redfishLogFiles))
1297 {
1298 for (const std::filesystem::path& file : redfishLogFiles)
1299 {
1300 std::error_code ec;
1301 std::filesystem::remove(file, ec);
1302 }
1303 }
1304
1305 // Reload rsyslog so it knows to start new log files
1306 crow::connections::systemBus->async_method_call(
1307 [asyncResp](const boost::system::error_code& ec) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001308 if (ec)
1309 {
1310 BMCWEB_LOG_ERROR("Failed to reload rsyslog: {}", ec);
1311 messages::internalError(asyncResp->res);
1312 return;
1313 }
Alexander Hansen599b9af2024-08-06 15:11:57 +02001314
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001315 messages::success(asyncResp->res);
1316 },
Alexander Hansen599b9af2024-08-06 15:11:57 +02001317 "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
1318 "org.freedesktop.systemd1.Manager", "ReloadUnit", "rsyslog.service",
1319 "replace");
1320}
1321
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001322inline void requestRoutesJournalEventLogClear(App& app)
1323{
Jason M. Bills4978b632022-02-22 14:17:43 -08001324 BMCWEB_ROUTE(
1325 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07001326 "/redfish/v1/Systems/<str>/LogServices/EventLog/Actions/LogService.ClearLog/")
Ed Tanous432a8902021-06-14 15:28:56 -07001327 .privileges({{"ConfigureComponents"}})
Alexander Hansen599b9af2024-08-06 15:11:57 +02001328 .methods(boost::beast::http::verb::post)(std::bind_front(
1329 handleSystemsLogServicesEventLogActionsClearPost, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001330}
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001331
Jason M. Billsac992cd2022-06-24 13:31:46 -07001332enum class LogParseError
1333{
1334 success,
1335 parseFailed,
1336 messageIdNotInRegistry,
1337};
1338
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001339static LogParseError fillEventLogEntryJson(
1340 const std::string& logEntryID, const std::string& logEntry,
1341 nlohmann::json::object_t& logEntryJson)
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001342{
Jason M. Bills95820182019-04-22 16:25:34 -07001343 // The redfish log format is "<Timestamp> <MessageId>,<MessageArgs>"
Jason M. Billscd225da2019-05-08 15:31:57 -07001344 // First get the Timestamp
Ed Tanousf23b7292020-10-15 09:41:17 -07001345 size_t space = logEntry.find_first_of(' ');
Jason M. Billscd225da2019-05-08 15:31:57 -07001346 if (space == std::string::npos)
Jason M. Bills95820182019-04-22 16:25:34 -07001347 {
Jason M. Billsac992cd2022-06-24 13:31:46 -07001348 return LogParseError::parseFailed;
Jason M. Bills95820182019-04-22 16:25:34 -07001349 }
Jason M. Billscd225da2019-05-08 15:31:57 -07001350 std::string timestamp = logEntry.substr(0, space);
1351 // Then get the log contents
Ed Tanousf23b7292020-10-15 09:41:17 -07001352 size_t entryStart = logEntry.find_first_not_of(' ', space);
Jason M. Billscd225da2019-05-08 15:31:57 -07001353 if (entryStart == std::string::npos)
1354 {
Jason M. Billsac992cd2022-06-24 13:31:46 -07001355 return LogParseError::parseFailed;
Jason M. Billscd225da2019-05-08 15:31:57 -07001356 }
1357 std::string_view entry(logEntry);
1358 entry.remove_prefix(entryStart);
1359 // Use split to separate the entry into its fields
1360 std::vector<std::string> logEntryFields;
Ed Tanous50ebd4a2023-01-19 19:03:17 -08001361 bmcweb::split(logEntryFields, entry, ',');
Jason M. Billscd225da2019-05-08 15:31:57 -07001362 // We need at least a MessageId to be valid
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001363 auto logEntryIter = logEntryFields.begin();
1364 if (logEntryIter == logEntryFields.end())
Jason M. Billscd225da2019-05-08 15:31:57 -07001365 {
Jason M. Billsac992cd2022-06-24 13:31:46 -07001366 return LogParseError::parseFailed;
Jason M. Billscd225da2019-05-08 15:31:57 -07001367 }
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001368 std::string& messageID = *logEntryIter;
Jason M. Bills4851d452019-03-28 11:27:48 -07001369 // Get the Message from the MessageRegistry
Ed Tanousfffb8c12022-02-07 23:53:03 -08001370 const registries::Message* message = registries::getMessage(messageID);
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001371
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001372 logEntryIter++;
Sui Chen54417b02022-03-24 14:59:52 -07001373 if (message == nullptr)
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001374 {
Ed Tanous62598e32023-07-17 17:06:25 -07001375 BMCWEB_LOG_WARNING("Log entry not found in registry: {}", logEntry);
Jason M. Billsac992cd2022-06-24 13:31:46 -07001376 return LogParseError::messageIdNotInRegistry;
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001377 }
1378
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001379 std::vector<std::string_view> messageArgs(logEntryIter,
1380 logEntryFields.end());
Ed Tanousc05bba42023-06-28 08:33:29 -07001381 messageArgs.resize(message->numberOfArgs);
1382
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001383 std::string msg =
1384 redfish::registries::fillMessageArgs(messageArgs, message->message);
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001385 if (msg.empty())
Jason M. Bills4851d452019-03-28 11:27:48 -07001386 {
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001387 return LogParseError::parseFailed;
Jason M. Bills4851d452019-03-28 11:27:48 -07001388 }
1389
Jason M. Bills95820182019-04-22 16:25:34 -07001390 // Get the Created time from the timestamp. The log timestamp is in RFC3339
1391 // format which matches the Redfish format except for the fractional seconds
1392 // between the '.' and the '+', so just remove them.
Ed Tanousf23b7292020-10-15 09:41:17 -07001393 std::size_t dot = timestamp.find_first_of('.');
1394 std::size_t plus = timestamp.find_first_of('+');
Jason M. Bills95820182019-04-22 16:25:34 -07001395 if (dot != std::string::npos && plus != std::string::npos)
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001396 {
Jason M. Bills95820182019-04-22 16:25:34 -07001397 timestamp.erase(dot, plus - dot);
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001398 }
1399
1400 // Fill in the log entry with the gathered data
Vijay Lobo9c11a172021-10-07 16:53:16 -05001401 logEntryJson["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
Ed Tanousef4c65b2023-04-24 15:28:50 -07001402 logEntryJson["@odata.id"] = boost::urls::format(
Ed Tanous253f11b2024-05-16 09:38:31 -07001403 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}",
1404 BMCWEB_REDFISH_SYSTEM_URI_NAME, logEntryID);
Jason M. Bills84afc482022-06-24 12:38:23 -07001405 logEntryJson["Name"] = "System Event Log Entry";
1406 logEntryJson["Id"] = logEntryID;
1407 logEntryJson["Message"] = std::move(msg);
1408 logEntryJson["MessageId"] = std::move(messageID);
1409 logEntryJson["MessageArgs"] = messageArgs;
1410 logEntryJson["EntryType"] = "Event";
1411 logEntryJson["Severity"] = message->messageSeverity;
1412 logEntryJson["Created"] = std::move(timestamp);
Jason M. Billsac992cd2022-06-24 13:31:46 -07001413 return LogParseError::success;
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001414}
1415
Ed Tanous898f2aa2024-08-07 12:18:22 -07001416inline void fillEventLogLogEntryFromPropertyMap(
1417 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1418 const dbus::utility::DBusPropertiesMap& resp,
1419 nlohmann::json& objectToFillOut)
1420{
1421 uint32_t id = 0;
1422 uint64_t timestamp = 0;
1423 uint64_t updateTimestamp = 0;
1424 std::string severity;
1425 std::string message;
1426 const std::string* filePath = nullptr;
1427 const std::string* resolution = nullptr;
1428 bool resolved = false;
1429 std::string notify;
1430 // clang-format off
1431 bool success = sdbusplus::unpackPropertiesNoThrow(
1432 dbus_utils::UnpackErrorPrinter(), resp,
1433 "Id", id,
1434 "Message", message,
1435 "Path", filePath,
1436 "Resolution", resolution,
1437 "Resolved", resolved,
1438 "ServiceProviderNotify", notify,
1439 "Severity", severity,
1440 "Timestamp", timestamp,
1441 "UpdateTimestamp", updateTimestamp
1442 );
1443 // clang-format on
1444
1445 if (!success)
1446 {
1447 messages::internalError(asyncResp->res);
1448 return;
1449 }
1450
1451 objectToFillOut["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
1452 objectToFillOut["@odata.id"] = boost::urls::format(
1453 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}",
1454 BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(id));
1455 objectToFillOut["Name"] = "System Event Log Entry";
1456 objectToFillOut["Id"] = std::to_string(id);
1457 objectToFillOut["Message"] = message;
1458 objectToFillOut["Resolved"] = resolved;
1459 std::optional<bool> notifyAction = getProviderNotifyAction(notify);
1460 if (notifyAction)
1461 {
1462 objectToFillOut["ServiceProviderNotified"] = *notifyAction;
1463 }
1464 if ((resolution != nullptr) && !resolution->empty())
1465 {
1466 objectToFillOut["Resolution"] = *resolution;
1467 }
1468 objectToFillOut["EntryType"] = "Event";
1469 objectToFillOut["Severity"] = translateSeverityDbusToRedfish(severity);
1470 objectToFillOut["Created"] =
1471 redfish::time_utils::getDateTimeUintMs(timestamp);
1472 objectToFillOut["Modified"] =
1473 redfish::time_utils::getDateTimeUintMs(updateTimestamp);
1474 if (filePath != nullptr)
1475 {
1476 objectToFillOut["AdditionalDataURI"] = boost::urls::format(
1477 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}/attachment",
1478 BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(id));
1479 }
1480}
1481
Ed Tanousb7290962024-08-07 11:09:51 -07001482inline void afterLogEntriesGetManagedObjects(
1483 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1484 const boost::system::error_code& ec,
1485 const dbus::utility::ManagedObjectType& resp)
1486{
1487 if (ec)
1488 {
1489 // TODO Handle for specific error code
1490 BMCWEB_LOG_ERROR("getLogEntriesIfaceData resp_handler got error {}",
1491 ec);
1492 messages::internalError(asyncResp->res);
1493 return;
1494 }
1495 nlohmann::json::array_t entriesArray;
1496 for (const auto& objectPath : resp)
1497 {
Ed Tanous898f2aa2024-08-07 12:18:22 -07001498 dbus::utility::DBusPropertiesMap propsFlattened;
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001499 auto isEntry =
1500 std::ranges::find_if(objectPath.second, [](const auto& object) {
1501 return object.first == "xyz.openbmc_project.Logging.Entry";
1502 });
Ed Tanous898f2aa2024-08-07 12:18:22 -07001503 if (isEntry == objectPath.second.end())
Ed Tanousb7290962024-08-07 11:09:51 -07001504 {
1505 continue;
1506 }
Ed Tanous898f2aa2024-08-07 12:18:22 -07001507 for (const auto& interfaceMap : objectPath.second)
Ed Tanousb7290962024-08-07 11:09:51 -07001508 {
Ed Tanous898f2aa2024-08-07 12:18:22 -07001509 for (const auto& propertyMap : interfaceMap.second)
Ed Tanousb7290962024-08-07 11:09:51 -07001510 {
Ed Tanous898f2aa2024-08-07 12:18:22 -07001511 propsFlattened.emplace_back(propertyMap.first,
1512 propertyMap.second);
Ed Tanousb7290962024-08-07 11:09:51 -07001513 }
1514 }
Ed Tanous898f2aa2024-08-07 12:18:22 -07001515 fillEventLogLogEntryFromPropertyMap(asyncResp, propsFlattened,
1516 entriesArray.emplace_back());
Ed Tanousb7290962024-08-07 11:09:51 -07001517 }
Ed Tanous898f2aa2024-08-07 12:18:22 -07001518
Ed Tanousb7290962024-08-07 11:09:51 -07001519 std::ranges::sort(entriesArray, [](const nlohmann::json& left,
1520 const nlohmann::json& right) {
1521 return (left["Id"] <= right["Id"]);
1522 });
1523 asyncResp->res.jsonValue["Members@odata.count"] = entriesArray.size();
1524 asyncResp->res.jsonValue["Members"] = std::move(entriesArray);
1525}
1526
Alexander Hansen599b9af2024-08-06 15:11:57 +02001527inline void handleSystemsLogServiceEventLogLogEntryCollection(
1528 App& app, const crow::Request& req,
1529 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1530 const std::string& systemName)
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001531{
Alexander Hansen599b9af2024-08-06 15:11:57 +02001532 query_param::QueryCapabilities capabilities = {
1533 .canDelegateTop = true,
1534 .canDelegateSkip = true,
1535 };
1536 query_param::Query delegatedQuery;
1537 if (!redfish::setUpRedfishRouteWithDelegation(app, req, asyncResp,
1538 delegatedQuery, capabilities))
1539 {
1540 return;
1541 }
1542 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1543 {
1544 // Option currently returns no systems. TBD
1545 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1546 systemName);
1547 return;
1548 }
1549 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1550 {
1551 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1552 systemName);
1553 return;
1554 }
1555
1556 size_t top = delegatedQuery.top.value_or(query_param::Query::maxTop);
1557 size_t skip = delegatedQuery.skip.value_or(0);
1558
1559 // Collections don't include the static data added by SubRoute
1560 // because it has a duplicate entry for members
1561 asyncResp->res.jsonValue["@odata.type"] =
1562 "#LogEntryCollection.LogEntryCollection";
1563 asyncResp->res.jsonValue["@odata.id"] =
1564 std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
1565 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1566 asyncResp->res.jsonValue["Name"] = "System Event Log Entries";
1567 asyncResp->res.jsonValue["Description"] =
1568 "Collection of System Event Log Entries";
1569
1570 nlohmann::json& logEntryArray = asyncResp->res.jsonValue["Members"];
1571 logEntryArray = nlohmann::json::array();
1572 // Go through the log files and create a unique ID for each
1573 // entry
1574 std::vector<std::filesystem::path> redfishLogFiles;
1575 getRedfishLogFiles(redfishLogFiles);
1576 uint64_t entryCount = 0;
1577 std::string logEntry;
1578
1579 // Oldest logs are in the last file, so start there and loop
1580 // backwards
1581 for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend(); it++)
1582 {
1583 std::ifstream logStream(*it);
1584 if (!logStream.is_open())
Ed Tanous002d39b2022-05-31 08:59:27 -07001585 {
Alexander Hansen599b9af2024-08-06 15:11:57 +02001586 continue;
Ed Tanous22d268c2022-05-19 09:39:07 -07001587 }
1588
Alexander Hansen599b9af2024-08-06 15:11:57 +02001589 // Reset the unique ID on the first entry
1590 bool firstEntry = true;
1591 while (std::getline(logStream, logEntry))
Ed Tanous002d39b2022-05-31 08:59:27 -07001592 {
Alexander Hansen599b9af2024-08-06 15:11:57 +02001593 std::string idStr;
1594 if (!getUniqueEntryID(logEntry, idStr, firstEntry))
1595 {
1596 continue;
1597 }
1598 firstEntry = false;
1599
1600 nlohmann::json::object_t bmcLogEntry;
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001601 LogParseError status =
1602 fillEventLogEntryJson(idStr, logEntry, bmcLogEntry);
Alexander Hansen599b9af2024-08-06 15:11:57 +02001603 if (status == LogParseError::messageIdNotInRegistry)
1604 {
1605 continue;
1606 }
1607 if (status != LogParseError::success)
1608 {
1609 messages::internalError(asyncResp->res);
1610 return;
1611 }
1612
1613 entryCount++;
1614 // Handle paging using skip (number of entries to skip from the
1615 // start) and top (number of entries to display)
1616 if (entryCount <= skip || entryCount > skip + top)
Jason M. Bills4978b632022-02-22 14:17:43 -08001617 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001618 continue;
Jason M. Bills4978b632022-02-22 14:17:43 -08001619 }
Jason M. Bills897967d2019-07-29 17:05:30 -07001620
Alexander Hansen599b9af2024-08-06 15:11:57 +02001621 logEntryArray.emplace_back(std::move(bmcLogEntry));
1622 }
1623 }
1624 asyncResp->res.jsonValue["Members@odata.count"] = entryCount;
1625 if (skip + top < entryCount)
1626 {
1627 asyncResp->res.jsonValue["Members@odata.nextLink"] =
1628 boost::urls::format(
1629 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries?$skip={}",
1630 BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(skip + top));
1631 }
1632}
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001633
Alexander Hansen599b9af2024-08-06 15:11:57 +02001634inline void requestRoutesJournalEventLogEntryCollection(App& app)
1635{
1636 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/")
1637 .privileges(redfish::privileges::getLogEntryCollection)
1638 .methods(boost::beast::http::verb::get)(std::bind_front(
1639 handleSystemsLogServiceEventLogLogEntryCollection, std::ref(app)));
1640}
1641
1642inline void handleSystemsLogServiceEventLogEntriesGet(
1643 App& app, const crow::Request& req,
1644 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1645 const std::string& systemName, const std::string& param)
1646{
1647 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1648 {
1649 return;
1650 }
1651 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1652 {
1653 // Option currently returns no systems. TBD
1654 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1655 systemName);
1656 return;
1657 }
1658
1659 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1660 {
1661 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1662 systemName);
1663 return;
1664 }
1665
1666 const std::string& targetID = param;
1667
1668 // Go through the log files and check the unique ID for each
1669 // entry to find the target entry
1670 std::vector<std::filesystem::path> redfishLogFiles;
1671 getRedfishLogFiles(redfishLogFiles);
1672 std::string logEntry;
1673
1674 // Oldest logs are in the last file, so start there and loop
1675 // backwards
1676 for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend(); it++)
1677 {
1678 std::ifstream logStream(*it);
1679 if (!logStream.is_open())
1680 {
1681 continue;
1682 }
1683
1684 // Reset the unique ID on the first entry
1685 bool firstEntry = true;
1686 while (std::getline(logStream, logEntry))
1687 {
1688 std::string idStr;
1689 if (!getUniqueEntryID(logEntry, idStr, firstEntry))
1690 {
1691 continue;
1692 }
1693 firstEntry = false;
1694
1695 if (idStr == targetID)
1696 {
Jason M. Billsde703c52022-06-23 14:19:04 -07001697 nlohmann::json::object_t bmcLogEntry;
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001698 LogParseError status =
1699 fillEventLogEntryJson(idStr, logEntry, bmcLogEntry);
Jason M. Billsac992cd2022-06-24 13:31:46 -07001700 if (status != LogParseError::success)
Ed Tanous002d39b2022-05-31 08:59:27 -07001701 {
1702 messages::internalError(asyncResp->res);
1703 return;
Andrew Geisslercb92c032018-08-17 07:56:14 -07001704 }
Alexander Hansen599b9af2024-08-06 15:11:57 +02001705 asyncResp->res.jsonValue.update(bmcLogEntry);
1706 return;
Jason M. Bills4978b632022-02-22 14:17:43 -08001707 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001708 }
Alexander Hansen599b9af2024-08-06 15:11:57 +02001709 }
1710 // Requested ID was not found
1711 messages::resourceNotFound(asyncResp->res, "LogEntry", targetID);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001712}
Chicago Duan336e96c2019-07-15 14:22:08 +08001713
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001714inline void requestRoutesJournalEventLogEntry(App& app)
1715{
1716 BMCWEB_ROUTE(
Ed Tanous22d268c2022-05-19 09:39:07 -07001717 app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001718 .privileges(redfish::privileges::getLogEntry)
Alexander Hansen599b9af2024-08-06 15:11:57 +02001719 .methods(boost::beast::http::verb::get)(std::bind_front(
1720 handleSystemsLogServiceEventLogEntriesGet, std::ref(app)));
1721}
1722
1723inline void dBusEventLogEntryCollection(
1724 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1725{
1726 // Collections don't include the static data added by SubRoute
1727 // because it has a duplicate entry for members
1728 asyncResp->res.jsonValue["@odata.type"] =
1729 "#LogEntryCollection.LogEntryCollection";
1730 asyncResp->res.jsonValue["@odata.id"] =
1731 std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
1732 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1733 asyncResp->res.jsonValue["Name"] = "System Event Log Entries";
1734 asyncResp->res.jsonValue["Description"] =
1735 "Collection of System Event Log Entries";
1736
1737 // DBus implementation of EventLog/Entries
1738 // Make call to Logging Service to find all log entry objects
1739 sdbusplus::message::object_path path("/xyz/openbmc_project/logging");
1740 dbus::utility::getManagedObjects(
1741 "xyz.openbmc_project.Logging", path,
1742 [asyncResp](const boost::system::error_code& ec,
1743 const dbus::utility::ManagedObjectType& resp) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001744 afterLogEntriesGetManagedObjects(asyncResp, ec, resp);
1745 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001746}
1747
1748inline void requestRoutesDBusEventLogEntryCollection(App& app)
1749{
Ed Tanous22d268c2022-05-19 09:39:07 -07001750 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/")
Ed Tanoused398212021-06-09 17:05:54 -07001751 .privileges(redfish::privileges::getLogEntryCollection)
Ed Tanous002d39b2022-05-31 08:59:27 -07001752 .methods(boost::beast::http::verb::get)(
1753 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07001754 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1755 const std::string& systemName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001756 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1757 {
1758 return;
1759 }
1760 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1761 {
1762 // Option currently returns no systems. TBD
1763 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1764 systemName);
1765 return;
1766 }
1767 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1768 {
1769 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1770 systemName);
1771 return;
1772 }
1773 dBusEventLogEntryCollection(asyncResp);
1774 });
Alexander Hansen599b9af2024-08-06 15:11:57 +02001775}
Ed Tanous22d268c2022-05-19 09:39:07 -07001776
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001777inline void dBusEventLogEntryGet(
1778 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID)
Alexander Hansen599b9af2024-08-06 15:11:57 +02001779{
1780 dbus::utility::escapePathForDbus(entryID);
Ed Tanous002d39b2022-05-31 08:59:27 -07001781
Alexander Hansen599b9af2024-08-06 15:11:57 +02001782 // DBus implementation of EventLog/Entries
1783 // Make call to Logging Service to find all log entry objects
1784 sdbusplus::asio::getAllProperties(
1785 *crow::connections::systemBus, "xyz.openbmc_project.Logging",
1786 "/xyz/openbmc_project/logging/entry/" + entryID, "",
1787 [asyncResp, entryID](const boost::system::error_code& ec,
1788 const dbus::utility::DBusPropertiesMap& resp) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001789 if (ec.value() == EBADR)
1790 {
1791 messages::resourceNotFound(asyncResp->res, "EventLogEntry",
1792 entryID);
1793 return;
1794 }
1795 if (ec)
1796 {
1797 BMCWEB_LOG_ERROR(
1798 "EventLogEntry (DBus) resp_handler got error {}", ec);
1799 messages::internalError(asyncResp->res);
1800 return;
1801 }
Alexander Hansen599b9af2024-08-06 15:11:57 +02001802
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001803 fillEventLogLogEntryFromPropertyMap(asyncResp, resp,
1804 asyncResp->res.jsonValue);
1805 });
Alexander Hansen599b9af2024-08-06 15:11:57 +02001806}
1807
1808inline void
1809 dBusEventLogEntryPatch(const crow::Request& req,
1810 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1811 const std::string& entryId)
1812{
1813 std::optional<bool> resolved;
1814
1815 if (!json_util::readJsonPatch(req, asyncResp->res, "Resolved", resolved))
1816 {
1817 return;
1818 }
1819 BMCWEB_LOG_DEBUG("Set Resolved");
1820
1821 setDbusProperty(asyncResp, "Resolved", "xyz.openbmc_project.Logging",
1822 "/xyz/openbmc_project/logging/entry/" + entryId,
1823 "xyz.openbmc_project.Logging.Entry", "Resolved",
1824 resolved.value_or(false));
1825}
1826
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001827inline void dBusEventLogEntryDelete(
1828 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID)
Alexander Hansen599b9af2024-08-06 15:11:57 +02001829{
1830 BMCWEB_LOG_DEBUG("Do delete single event entries.");
1831
1832 dbus::utility::escapePathForDbus(entryID);
1833
1834 // Process response from Logging service.
1835 auto respHandler = [asyncResp,
1836 entryID](const boost::system::error_code& ec) {
1837 BMCWEB_LOG_DEBUG("EventLogEntry (DBus) doDelete callback: Done");
1838 if (ec)
1839 {
1840 if (ec.value() == EBADR)
Ed Tanous45ca1b82022-03-25 13:07:27 -07001841 {
Alexander Hansen599b9af2024-08-06 15:11:57 +02001842 messages::resourceNotFound(asyncResp->res, "LogEntry", entryID);
Ed Tanous45ca1b82022-03-25 13:07:27 -07001843 return;
1844 }
Alexander Hansen599b9af2024-08-06 15:11:57 +02001845 // TODO Handle for specific error code
1846 BMCWEB_LOG_ERROR(
1847 "EventLogEntry (DBus) doDelete respHandler got error {}", ec);
1848 asyncResp->res.result(
1849 boost::beast::http::status::internal_server_error);
1850 return;
1851 }
Abhishek Patel9017faf2021-09-14 22:48:55 -05001852
Alexander Hansen599b9af2024-08-06 15:11:57 +02001853 asyncResp->res.result(boost::beast::http::status::ok);
1854 };
1855
1856 // Make call to Logging service to request Delete Log
1857 crow::connections::systemBus->async_method_call(
1858 respHandler, "xyz.openbmc_project.Logging",
1859 "/xyz/openbmc_project/logging/entry/" + entryID,
1860 "xyz.openbmc_project.Object.Delete", "Delete");
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001861}
Xiaochao Ma75710de2021-01-21 17:56:02 +08001862
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001863inline void requestRoutesDBusEventLogEntry(App& app)
Adriana Kobylak400fd1f2021-01-29 09:01:30 -06001864{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001865 BMCWEB_ROUTE(
Ed Tanous22d268c2022-05-19 09:39:07 -07001866 app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001867 .privileges(redfish::privileges::getLogEntry)
Ed Tanous002d39b2022-05-31 08:59:27 -07001868 .methods(boost::beast::http::verb::get)(
1869 [&app](const crow::Request& req,
1870 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous898f2aa2024-08-07 12:18:22 -07001871 const std::string& systemName, const std::string& entryId) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001872 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1873 {
1874 return;
1875 }
1876 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1877 {
1878 // Option currently returns no systems. TBD
1879 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1880 systemName);
1881 return;
1882 }
1883 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1884 {
1885 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1886 systemName);
1887 return;
1888 }
Ed Tanous22d268c2022-05-19 09:39:07 -07001889
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001890 dBusEventLogEntryGet(asyncResp, entryId);
1891 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001892
1893 BMCWEB_ROUTE(
Ed Tanous22d268c2022-05-19 09:39:07 -07001894 app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001895 .privileges(redfish::privileges::patchLogEntry)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001896 .methods(boost::beast::http::verb::patch)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07001897 [&app](const crow::Request& req,
1898 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -07001899 const std::string& systemName, const std::string& entryId) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001900 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1901 {
1902 return;
1903 }
1904 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1905 {
1906 // Option currently returns no systems. TBD
1907 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1908 systemName);
1909 return;
1910 }
1911 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1912 {
1913 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1914 systemName);
1915 return;
1916 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001917
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001918 dBusEventLogEntryPatch(req, asyncResp, entryId);
1919 });
Adriana Kobylak400fd1f2021-01-29 09:01:30 -06001920
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001921 BMCWEB_ROUTE(
Ed Tanous22d268c2022-05-19 09:39:07 -07001922 app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001923 .privileges(redfish::privileges::deleteLogEntry)
1924
Ed Tanous002d39b2022-05-31 08:59:27 -07001925 .methods(boost::beast::http::verb::delete_)(
1926 [&app](const crow::Request& req,
1927 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -07001928 const std::string& systemName, const std::string& param) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001929 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1930 {
1931 return;
1932 }
1933 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1934 {
1935 // Option currently returns no systems. TBD
1936 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1937 systemName);
1938 return;
1939 }
1940 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1941 {
1942 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1943 systemName);
1944 return;
1945 }
1946 dBusEventLogEntryDelete(asyncResp, param);
1947 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001948}
1949
Spencer Kub7028eb2021-10-26 15:27:35 +08001950constexpr const char* hostLoggerFolderPath = "/var/log/console";
1951
1952inline bool
1953 getHostLoggerFiles(const std::string& hostLoggerFilePath,
1954 std::vector<std::filesystem::path>& hostLoggerFiles)
1955{
1956 std::error_code ec;
1957 std::filesystem::directory_iterator logPath(hostLoggerFilePath, ec);
1958 if (ec)
1959 {
Carson Labradobf2dded2023-08-10 00:37:06 +00001960 BMCWEB_LOG_WARNING("{}", ec.message());
Spencer Kub7028eb2021-10-26 15:27:35 +08001961 return false;
1962 }
1963 for (const std::filesystem::directory_entry& it : logPath)
1964 {
1965 std::string filename = it.path().filename();
1966 // Prefix of each log files is "log". Find the file and save the
1967 // path
Ed Tanous11ba3972022-07-11 09:50:41 -07001968 if (filename.starts_with("log"))
Spencer Kub7028eb2021-10-26 15:27:35 +08001969 {
1970 hostLoggerFiles.emplace_back(it.path());
1971 }
1972 }
1973 // As the log files rotate, they are appended with a ".#" that is higher for
1974 // the older logs. Since we start from oldest logs, sort the name in
1975 // descending order.
1976 std::sort(hostLoggerFiles.rbegin(), hostLoggerFiles.rend(),
1977 AlphanumLess<std::string>());
1978
1979 return true;
1980}
1981
Ed Tanous02cad962022-06-30 16:50:15 -07001982inline bool getHostLoggerEntries(
1983 const std::vector<std::filesystem::path>& hostLoggerFiles, uint64_t skip,
1984 uint64_t top, std::vector<std::string>& logEntries, size_t& logCount)
Spencer Kub7028eb2021-10-26 15:27:35 +08001985{
1986 GzFileReader logFile;
1987
1988 // Go though all log files and expose host logs.
1989 for (const std::filesystem::path& it : hostLoggerFiles)
1990 {
1991 if (!logFile.gzGetLines(it.string(), skip, top, logEntries, logCount))
1992 {
Ed Tanous62598e32023-07-17 17:06:25 -07001993 BMCWEB_LOG_ERROR("fail to expose host logs");
Spencer Kub7028eb2021-10-26 15:27:35 +08001994 return false;
1995 }
1996 }
1997 // Get lastMessage from constructor by getter
1998 std::string lastMessage = logFile.getLastMessage();
1999 if (!lastMessage.empty())
2000 {
2001 logCount++;
2002 if (logCount > skip && logCount <= (skip + top))
2003 {
2004 logEntries.push_back(lastMessage);
2005 }
2006 }
2007 return true;
2008}
2009
Claire Weinandd72e872022-08-15 14:20:06 -07002010inline void handleBMCLogServicesCollectionGet(
Claire Weinanfdd26902022-03-01 14:18:25 -08002011 crow::App& app, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07002012 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2013 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002014{
2015 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2016 {
2017 return;
2018 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002019
2020 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2021 {
2022 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2023 return;
2024 }
2025
Claire Weinanfdd26902022-03-01 14:18:25 -08002026 // Collections don't include the static data added by SubRoute
2027 // because it has a duplicate entry for members
2028 asyncResp->res.jsonValue["@odata.type"] =
2029 "#LogServiceCollection.LogServiceCollection";
Ed Tanous253f11b2024-05-16 09:38:31 -07002030 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
2031 "/redfish/v1/Managers/{}/LogServices", BMCWEB_REDFISH_MANAGER_URI_NAME);
Claire Weinanfdd26902022-03-01 14:18:25 -08002032 asyncResp->res.jsonValue["Name"] = "Open BMC Log Services Collection";
2033 asyncResp->res.jsonValue["Description"] =
2034 "Collection of LogServices for this Manager";
2035 nlohmann::json& logServiceArray = asyncResp->res.jsonValue["Members"];
2036 logServiceArray = nlohmann::json::array();
2037
Ed Tanous25b54db2024-04-17 15:40:31 -07002038 if constexpr (BMCWEB_REDFISH_BMC_JOURNAL)
2039 {
2040 nlohmann::json::object_t journal;
Ed Tanous253f11b2024-05-16 09:38:31 -07002041 journal["@odata.id"] =
2042 boost::urls::format("/redfish/v1/Managers/{}/LogServices/Journal",
2043 BMCWEB_REDFISH_MANAGER_URI_NAME);
Ed Tanous25b54db2024-04-17 15:40:31 -07002044 logServiceArray.emplace_back(std::move(journal));
2045 }
Claire Weinanfdd26902022-03-01 14:18:25 -08002046
2047 asyncResp->res.jsonValue["Members@odata.count"] = logServiceArray.size();
2048
Ed Tanous25b54db2024-04-17 15:40:31 -07002049 if constexpr (BMCWEB_REDFISH_DUMP_LOG)
2050 {
2051 constexpr std::array<std::string_view, 1> interfaces = {
2052 "xyz.openbmc_project.Collection.DeleteAll"};
2053 dbus::utility::getSubTreePaths(
2054 "/xyz/openbmc_project/dump", 0, interfaces,
2055 [asyncResp](const boost::system::error_code& ec,
2056 const dbus::utility::MapperGetSubTreePathsResponse&
2057 subTreePaths) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002058 if (ec)
Ed Tanous25b54db2024-04-17 15:40:31 -07002059 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002060 BMCWEB_LOG_ERROR(
2061 "handleBMCLogServicesCollectionGet respHandler got error {}",
2062 ec);
2063 // Assume that getting an error simply means there are no
2064 // dump LogServices. Return without adding any error
2065 // response.
2066 return;
Ed Tanous25b54db2024-04-17 15:40:31 -07002067 }
Ed Tanous25b54db2024-04-17 15:40:31 -07002068
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002069 nlohmann::json& logServiceArrayLocal =
2070 asyncResp->res.jsonValue["Members"];
2071
2072 for (const std::string& path : subTreePaths)
2073 {
2074 if (path == "/xyz/openbmc_project/dump/bmc")
2075 {
2076 nlohmann::json::object_t member;
2077 member["@odata.id"] = boost::urls::format(
2078 "/redfish/v1/Managers/{}/LogServices/Dump",
2079 BMCWEB_REDFISH_MANAGER_URI_NAME);
2080 logServiceArrayLocal.emplace_back(std::move(member));
2081 }
2082 else if (path == "/xyz/openbmc_project/dump/faultlog")
2083 {
2084 nlohmann::json::object_t member;
2085 member["@odata.id"] = boost::urls::format(
2086 "/redfish/v1/Managers/{}/LogServices/FaultLog",
2087 BMCWEB_REDFISH_MANAGER_URI_NAME);
2088 logServiceArrayLocal.emplace_back(std::move(member));
2089 }
2090 }
2091
2092 asyncResp->res.jsonValue["Members@odata.count"] =
2093 logServiceArrayLocal.size();
2094 });
Ed Tanous25b54db2024-04-17 15:40:31 -07002095 }
Claire Weinanfdd26902022-03-01 14:18:25 -08002096}
2097
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002098inline void requestRoutesBMCLogServiceCollection(App& app)
2099{
Ed Tanous253f11b2024-05-16 09:38:31 -07002100 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/")
Gunnar Millsad89dcf2021-07-30 14:40:11 -05002101 .privileges(redfish::privileges::getLogServiceCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002102 .methods(boost::beast::http::verb::get)(
Claire Weinandd72e872022-08-15 14:20:06 -07002103 std::bind_front(handleBMCLogServicesCollectionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002104}
Ed Tanous1da66f72018-07-27 16:13:37 -07002105
Claire Weinanfdd26902022-03-01 14:18:25 -08002106inline void
2107 getDumpServiceInfo(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2108 const std::string& dumpType)
2109{
2110 std::string dumpPath;
Ed Tanous539d8c62024-06-19 14:38:27 -07002111 log_service::OverWritePolicy overWritePolicy =
2112 log_service::OverWritePolicy::Invalid;
Claire Weinanfdd26902022-03-01 14:18:25 -08002113 bool collectDiagnosticDataSupported = false;
2114
2115 if (dumpType == "BMC")
2116 {
Ed Tanous253f11b2024-05-16 09:38:31 -07002117 dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/Dump",
2118 BMCWEB_REDFISH_MANAGER_URI_NAME);
Ed Tanous539d8c62024-06-19 14:38:27 -07002119 overWritePolicy = log_service::OverWritePolicy::WrapsWhenFull;
Claire Weinanfdd26902022-03-01 14:18:25 -08002120 collectDiagnosticDataSupported = true;
2121 }
2122 else if (dumpType == "FaultLog")
2123 {
Ed Tanous253f11b2024-05-16 09:38:31 -07002124 dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/FaultLog",
2125 BMCWEB_REDFISH_MANAGER_URI_NAME);
Ed Tanous539d8c62024-06-19 14:38:27 -07002126 overWritePolicy = log_service::OverWritePolicy::Unknown;
Claire Weinanfdd26902022-03-01 14:18:25 -08002127 collectDiagnosticDataSupported = false;
2128 }
2129 else if (dumpType == "System")
2130 {
Ed Tanous253f11b2024-05-16 09:38:31 -07002131 dumpPath = std::format("/redfish/v1/Systems/{}/LogServices/Dump",
2132 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanous539d8c62024-06-19 14:38:27 -07002133 overWritePolicy = log_service::OverWritePolicy::WrapsWhenFull;
Claire Weinanfdd26902022-03-01 14:18:25 -08002134 collectDiagnosticDataSupported = true;
2135 }
2136 else
2137 {
Ed Tanous62598e32023-07-17 17:06:25 -07002138 BMCWEB_LOG_ERROR("getDumpServiceInfo() invalid dump type: {}",
2139 dumpType);
Claire Weinanfdd26902022-03-01 14:18:25 -08002140 messages::internalError(asyncResp->res);
2141 return;
2142 }
2143
2144 asyncResp->res.jsonValue["@odata.id"] = dumpPath;
2145 asyncResp->res.jsonValue["@odata.type"] = "#LogService.v1_2_0.LogService";
2146 asyncResp->res.jsonValue["Name"] = "Dump LogService";
2147 asyncResp->res.jsonValue["Description"] = dumpType + " Dump LogService";
2148 asyncResp->res.jsonValue["Id"] = std::filesystem::path(dumpPath).filename();
Ed Tanous539d8c62024-06-19 14:38:27 -07002149 asyncResp->res.jsonValue["OverWritePolicy"] = overWritePolicy;
Claire Weinanfdd26902022-03-01 14:18:25 -08002150
2151 std::pair<std::string, std::string> redfishDateTimeOffset =
Ed Tanous2b829372022-08-03 14:22:34 -07002152 redfish::time_utils::getDateTimeOffsetNow();
Claire Weinanfdd26902022-03-01 14:18:25 -08002153 asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
2154 asyncResp->res.jsonValue["DateTimeLocalOffset"] =
2155 redfishDateTimeOffset.second;
2156
2157 asyncResp->res.jsonValue["Entries"]["@odata.id"] = dumpPath + "/Entries";
Claire Weinanfdd26902022-03-01 14:18:25 -08002158
2159 if (collectDiagnosticDataSupported)
2160 {
2161 asyncResp->res.jsonValue["Actions"]["#LogService.CollectDiagnosticData"]
2162 ["target"] =
2163 dumpPath + "/Actions/LogService.CollectDiagnosticData";
2164 }
Claire Weinan0d946212022-07-13 19:40:19 -07002165
2166 constexpr std::array<std::string_view, 1> interfaces = {deleteAllInterface};
2167 dbus::utility::getSubTreePaths(
2168 "/xyz/openbmc_project/dump", 0, interfaces,
2169 [asyncResp, dumpType, dumpPath](
2170 const boost::system::error_code& ec,
2171 const dbus::utility::MapperGetSubTreePathsResponse& subTreePaths) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002172 if (ec)
Claire Weinan0d946212022-07-13 19:40:19 -07002173 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002174 BMCWEB_LOG_ERROR("getDumpServiceInfo respHandler got error {}",
2175 ec);
2176 // Assume that getting an error simply means there are no dump
2177 // LogServices. Return without adding any error response.
2178 return;
Claire Weinan0d946212022-07-13 19:40:19 -07002179 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002180 std::string dbusDumpPath = getDumpPath(dumpType);
2181 for (const std::string& path : subTreePaths)
2182 {
2183 if (path == dbusDumpPath)
2184 {
2185 asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"]
2186 ["target"] =
2187 dumpPath + "/Actions/LogService.ClearLog";
2188 break;
2189 }
2190 }
2191 });
Claire Weinanfdd26902022-03-01 14:18:25 -08002192}
2193
2194inline void handleLogServicesDumpServiceGet(
2195 crow::App& app, const std::string& dumpType, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07002196 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2197 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002198{
2199 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2200 {
2201 return;
2202 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002203
2204 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2205 {
2206 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2207 return;
2208 }
2209
Claire Weinanfdd26902022-03-01 14:18:25 -08002210 getDumpServiceInfo(asyncResp, dumpType);
2211}
2212
Ed Tanous22d268c2022-05-19 09:39:07 -07002213inline void handleLogServicesDumpServiceComputerSystemGet(
2214 crow::App& app, const crow::Request& req,
2215 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2216 const std::string& chassisId)
2217{
2218 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2219 {
2220 return;
2221 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002222 if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous22d268c2022-05-19 09:39:07 -07002223 {
2224 messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
2225 return;
2226 }
2227 getDumpServiceInfo(asyncResp, "System");
2228}
2229
Claire Weinanfdd26902022-03-01 14:18:25 -08002230inline void handleLogServicesDumpEntriesCollectionGet(
2231 crow::App& app, const std::string& dumpType, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07002232 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2233 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002234{
2235 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2236 {
2237 return;
2238 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002239
2240 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2241 {
2242 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2243 return;
2244 }
Claire Weinanfdd26902022-03-01 14:18:25 -08002245 getDumpEntryCollection(asyncResp, dumpType);
2246}
2247
Ed Tanous22d268c2022-05-19 09:39:07 -07002248inline void handleLogServicesDumpEntriesCollectionComputerSystemGet(
2249 crow::App& app, const crow::Request& req,
2250 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2251 const std::string& chassisId)
2252{
2253 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2254 {
2255 return;
2256 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002257 if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous22d268c2022-05-19 09:39:07 -07002258 {
2259 messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
2260 return;
2261 }
2262 getDumpEntryCollection(asyncResp, "System");
2263}
2264
Claire Weinanfdd26902022-03-01 14:18:25 -08002265inline void handleLogServicesDumpEntryGet(
2266 crow::App& app, const std::string& dumpType, const crow::Request& req,
2267 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous253f11b2024-05-16 09:38:31 -07002268 const std::string& managerId, const std::string& dumpId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002269{
2270 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2271 {
2272 return;
2273 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002274 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2275 {
2276 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2277 return;
2278 }
Claire Weinanfdd26902022-03-01 14:18:25 -08002279 getDumpEntryById(asyncResp, dumpId, dumpType);
2280}
Carson Labrado168d1b12023-03-27 17:04:46 +00002281
Ed Tanous22d268c2022-05-19 09:39:07 -07002282inline void handleLogServicesDumpEntryComputerSystemGet(
2283 crow::App& app, const crow::Request& req,
2284 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2285 const std::string& chassisId, const std::string& dumpId)
2286{
2287 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2288 {
2289 return;
2290 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002291 if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous22d268c2022-05-19 09:39:07 -07002292 {
2293 messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
2294 return;
2295 }
2296 getDumpEntryById(asyncResp, dumpId, "System");
2297}
Claire Weinanfdd26902022-03-01 14:18:25 -08002298
2299inline void handleLogServicesDumpEntryDelete(
2300 crow::App& app, const std::string& dumpType, const crow::Request& req,
2301 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous253f11b2024-05-16 09:38:31 -07002302 const std::string& managerId, const std::string& dumpId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002303{
2304 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2305 {
2306 return;
2307 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002308
2309 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2310 {
2311 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2312 return;
2313 }
Claire Weinanfdd26902022-03-01 14:18:25 -08002314 deleteDumpEntry(asyncResp, dumpId, dumpType);
2315}
2316
Ed Tanous22d268c2022-05-19 09:39:07 -07002317inline void handleLogServicesDumpEntryComputerSystemDelete(
2318 crow::App& app, const crow::Request& req,
2319 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2320 const std::string& chassisId, const std::string& dumpId)
2321{
2322 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2323 {
2324 return;
2325 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002326 if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous22d268c2022-05-19 09:39:07 -07002327 {
2328 messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
2329 return;
2330 }
2331 deleteDumpEntry(asyncResp, dumpId, "System");
2332}
2333
Carson Labrado168d1b12023-03-27 17:04:46 +00002334inline void handleLogServicesDumpEntryDownloadGet(
2335 crow::App& app, const std::string& dumpType, const crow::Request& req,
2336 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous253f11b2024-05-16 09:38:31 -07002337 const std::string& managerId, const std::string& dumpId)
Carson Labrado168d1b12023-03-27 17:04:46 +00002338{
2339 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2340 {
2341 return;
2342 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002343
2344 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2345 {
2346 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2347 return;
2348 }
Carson Labrado168d1b12023-03-27 17:04:46 +00002349 downloadDumpEntry(asyncResp, dumpId, dumpType);
2350}
2351
2352inline void handleDBusEventLogEntryDownloadGet(
2353 crow::App& app, const std::string& dumpType, const crow::Request& req,
2354 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2355 const std::string& systemName, const std::string& entryID)
2356{
2357 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2358 {
2359 return;
2360 }
2361 if (!http_helpers::isContentTypeAllowed(
2362 req.getHeaderValue("Accept"),
2363 http_helpers::ContentType::OctetStream, true))
2364 {
2365 asyncResp->res.result(boost::beast::http::status::bad_request);
2366 return;
2367 }
2368 downloadEventLogEntry(asyncResp, systemName, entryID, dumpType);
2369}
2370
Claire Weinanfdd26902022-03-01 14:18:25 -08002371inline void handleLogServicesDumpCollectDiagnosticDataPost(
2372 crow::App& app, const std::string& dumpType, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07002373 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2374 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002375{
2376 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2377 {
2378 return;
2379 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002380 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2381 {
2382 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2383 return;
2384 }
2385
Claire Weinanfdd26902022-03-01 14:18:25 -08002386 createDump(asyncResp, req, dumpType);
2387}
2388
Ed Tanous22d268c2022-05-19 09:39:07 -07002389inline void handleLogServicesDumpCollectDiagnosticDataComputerSystemPost(
2390 crow::App& app, const crow::Request& req,
2391 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002392 const std::string& systemName)
Ed Tanous22d268c2022-05-19 09:39:07 -07002393{
2394 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2395 {
2396 return;
2397 }
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002398
Ed Tanous25b54db2024-04-17 15:40:31 -07002399 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous22d268c2022-05-19 09:39:07 -07002400 {
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002401 // Option currently returns no systems. TBD
2402 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2403 systemName);
2404 return;
2405 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002406 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002407 {
2408 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2409 systemName);
Ed Tanous22d268c2022-05-19 09:39:07 -07002410 return;
2411 }
2412 createDump(asyncResp, req, "System");
2413}
2414
Claire Weinanfdd26902022-03-01 14:18:25 -08002415inline void handleLogServicesDumpClearLogPost(
2416 crow::App& app, const std::string& dumpType, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07002417 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2418 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002419{
2420 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2421 {
2422 return;
2423 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002424
2425 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2426 {
2427 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2428 return;
2429 }
Claire Weinanfdd26902022-03-01 14:18:25 -08002430 clearDump(asyncResp, dumpType);
2431}
2432
Ed Tanous22d268c2022-05-19 09:39:07 -07002433inline void handleLogServicesDumpClearLogComputerSystemPost(
2434 crow::App& app, const crow::Request& req,
2435 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002436 const std::string& systemName)
Ed Tanous22d268c2022-05-19 09:39:07 -07002437{
2438 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2439 {
2440 return;
2441 }
Ed Tanous25b54db2024-04-17 15:40:31 -07002442 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous22d268c2022-05-19 09:39:07 -07002443 {
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002444 // Option currently returns no systems. TBD
2445 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2446 systemName);
2447 return;
2448 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002449 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002450 {
2451 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2452 systemName);
Ed Tanous22d268c2022-05-19 09:39:07 -07002453 return;
2454 }
2455 clearDump(asyncResp, "System");
2456}
2457
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002458inline void requestRoutesBMCDumpService(App& app)
2459{
Ed Tanous253f11b2024-05-16 09:38:31 -07002460 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/Dump/")
Ed Tanoused398212021-06-09 17:05:54 -07002461 .privileges(redfish::privileges::getLogService)
Claire Weinanfdd26902022-03-01 14:18:25 -08002462 .methods(boost::beast::http::verb::get)(std::bind_front(
2463 handleLogServicesDumpServiceGet, std::ref(app), "BMC"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002464}
2465
2466inline void requestRoutesBMCDumpEntryCollection(App& app)
2467{
Ed Tanous253f11b2024-05-16 09:38:31 -07002468 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/")
Ed Tanoused398212021-06-09 17:05:54 -07002469 .privileges(redfish::privileges::getLogEntryCollection)
Claire Weinanfdd26902022-03-01 14:18:25 -08002470 .methods(boost::beast::http::verb::get)(std::bind_front(
2471 handleLogServicesDumpEntriesCollectionGet, std::ref(app), "BMC"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002472}
2473
2474inline void requestRoutesBMCDumpEntry(App& app)
2475{
2476 BMCWEB_ROUTE(app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002477 "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002478 .privileges(redfish::privileges::getLogEntry)
Claire Weinanfdd26902022-03-01 14:18:25 -08002479 .methods(boost::beast::http::verb::get)(std::bind_front(
2480 handleLogServicesDumpEntryGet, std::ref(app), "BMC"));
2481
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002482 BMCWEB_ROUTE(app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002483 "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002484 .privileges(redfish::privileges::deleteLogEntry)
Claire Weinanfdd26902022-03-01 14:18:25 -08002485 .methods(boost::beast::http::verb::delete_)(std::bind_front(
2486 handleLogServicesDumpEntryDelete, std::ref(app), "BMC"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002487}
2488
Carson Labrado168d1b12023-03-27 17:04:46 +00002489inline void requestRoutesBMCDumpEntryDownload(App& app)
2490{
2491 BMCWEB_ROUTE(
2492 app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002493 "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/attachment/")
Carson Labrado168d1b12023-03-27 17:04:46 +00002494 .privileges(redfish::privileges::getLogEntry)
2495 .methods(boost::beast::http::verb::get)(std::bind_front(
2496 handleLogServicesDumpEntryDownloadGet, std::ref(app), "BMC"));
2497}
2498
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002499inline void requestRoutesBMCDumpCreate(App& app)
2500{
George Liu0fda0f12021-11-16 10:06:17 +08002501 BMCWEB_ROUTE(
2502 app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002503 "/redfish/v1/Managers/<str>/LogServices/Dump/Actions/LogService.CollectDiagnosticData/")
Ed Tanoused398212021-06-09 17:05:54 -07002504 .privileges(redfish::privileges::postLogService)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002505 .methods(boost::beast::http::verb::post)(
Claire Weinanfdd26902022-03-01 14:18:25 -08002506 std::bind_front(handleLogServicesDumpCollectDiagnosticDataPost,
2507 std::ref(app), "BMC"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002508}
2509
2510inline void requestRoutesBMCDumpClear(App& app)
2511{
George Liu0fda0f12021-11-16 10:06:17 +08002512 BMCWEB_ROUTE(
2513 app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002514 "/redfish/v1/Managers/<str>/LogServices/Dump/Actions/LogService.ClearLog/")
Ed Tanoused398212021-06-09 17:05:54 -07002515 .privileges(redfish::privileges::postLogService)
Claire Weinanfdd26902022-03-01 14:18:25 -08002516 .methods(boost::beast::http::verb::post)(std::bind_front(
2517 handleLogServicesDumpClearLogPost, std::ref(app), "BMC"));
2518}
2519
Carson Labrado168d1b12023-03-27 17:04:46 +00002520inline void requestRoutesDBusEventLogEntryDownload(App& app)
2521{
2522 BMCWEB_ROUTE(
2523 app,
Ravi Teja9e9d99d2023-11-08 05:33:59 -06002524 "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/attachment/")
Carson Labrado168d1b12023-03-27 17:04:46 +00002525 .privileges(redfish::privileges::getLogEntry)
2526 .methods(boost::beast::http::verb::get)(std::bind_front(
2527 handleDBusEventLogEntryDownloadGet, std::ref(app), "System"));
2528}
2529
Claire Weinanfdd26902022-03-01 14:18:25 -08002530inline void requestRoutesFaultLogDumpService(App& app)
2531{
Ed Tanous253f11b2024-05-16 09:38:31 -07002532 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/")
Claire Weinanfdd26902022-03-01 14:18:25 -08002533 .privileges(redfish::privileges::getLogService)
2534 .methods(boost::beast::http::verb::get)(std::bind_front(
2535 handleLogServicesDumpServiceGet, std::ref(app), "FaultLog"));
2536}
2537
2538inline void requestRoutesFaultLogDumpEntryCollection(App& app)
2539{
Ed Tanous253f11b2024-05-16 09:38:31 -07002540 BMCWEB_ROUTE(app,
2541 "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/")
Claire Weinanfdd26902022-03-01 14:18:25 -08002542 .privileges(redfish::privileges::getLogEntryCollection)
2543 .methods(boost::beast::http::verb::get)(
2544 std::bind_front(handleLogServicesDumpEntriesCollectionGet,
2545 std::ref(app), "FaultLog"));
2546}
2547
2548inline void requestRoutesFaultLogDumpEntry(App& app)
2549{
Ed Tanous253f11b2024-05-16 09:38:31 -07002550 BMCWEB_ROUTE(
2551 app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/<str>/")
Claire Weinanfdd26902022-03-01 14:18:25 -08002552 .privileges(redfish::privileges::getLogEntry)
2553 .methods(boost::beast::http::verb::get)(std::bind_front(
2554 handleLogServicesDumpEntryGet, std::ref(app), "FaultLog"));
2555
Ed Tanous253f11b2024-05-16 09:38:31 -07002556 BMCWEB_ROUTE(
2557 app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/<str>/")
Claire Weinanfdd26902022-03-01 14:18:25 -08002558 .privileges(redfish::privileges::deleteLogEntry)
2559 .methods(boost::beast::http::verb::delete_)(std::bind_front(
2560 handleLogServicesDumpEntryDelete, std::ref(app), "FaultLog"));
2561}
2562
2563inline void requestRoutesFaultLogDumpClear(App& app)
2564{
2565 BMCWEB_ROUTE(
2566 app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002567 "/redfish/v1/Managers/<str>/LogServices/FaultLog/Actions/LogService.ClearLog/")
Claire Weinanfdd26902022-03-01 14:18:25 -08002568 .privileges(redfish::privileges::postLogService)
2569 .methods(boost::beast::http::verb::post)(std::bind_front(
2570 handleLogServicesDumpClearLogPost, std::ref(app), "FaultLog"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002571}
2572
2573inline void requestRoutesSystemDumpService(App& app)
2574{
Ed Tanous22d268c2022-05-19 09:39:07 -07002575 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Dump/")
Ed Tanoused398212021-06-09 17:05:54 -07002576 .privileges(redfish::privileges::getLogService)
Claire Weinan6ab9ad52022-08-12 18:20:17 -07002577 .methods(boost::beast::http::verb::get)(std::bind_front(
Ed Tanous22d268c2022-05-19 09:39:07 -07002578 handleLogServicesDumpServiceComputerSystemGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002579}
2580
2581inline void requestRoutesSystemDumpEntryCollection(App& app)
2582{
Ed Tanous22d268c2022-05-19 09:39:07 -07002583 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/")
Ed Tanoused398212021-06-09 17:05:54 -07002584 .privileges(redfish::privileges::getLogEntryCollection)
Ed Tanous22d268c2022-05-19 09:39:07 -07002585 .methods(boost::beast::http::verb::get)(std::bind_front(
2586 handleLogServicesDumpEntriesCollectionComputerSystemGet,
2587 std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002588}
2589
2590inline void requestRoutesSystemDumpEntry(App& app)
2591{
2592 BMCWEB_ROUTE(app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002593 "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002594 .privileges(redfish::privileges::getLogEntry)
Claire Weinan6ab9ad52022-08-12 18:20:17 -07002595 .methods(boost::beast::http::verb::get)(std::bind_front(
Ed Tanous22d268c2022-05-19 09:39:07 -07002596 handleLogServicesDumpEntryComputerSystemGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002597
2598 BMCWEB_ROUTE(app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002599 "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002600 .privileges(redfish::privileges::deleteLogEntry)
Claire Weinan6ab9ad52022-08-12 18:20:17 -07002601 .methods(boost::beast::http::verb::delete_)(std::bind_front(
Ed Tanous22d268c2022-05-19 09:39:07 -07002602 handleLogServicesDumpEntryComputerSystemDelete, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002603}
2604
2605inline void requestRoutesSystemDumpCreate(App& app)
2606{
George Liu0fda0f12021-11-16 10:06:17 +08002607 BMCWEB_ROUTE(
2608 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002609 "/redfish/v1/Systems/<str>/LogServices/Dump/Actions/LogService.CollectDiagnosticData/")
Ed Tanoused398212021-06-09 17:05:54 -07002610 .privileges(redfish::privileges::postLogService)
Ed Tanous22d268c2022-05-19 09:39:07 -07002611 .methods(boost::beast::http::verb::post)(std::bind_front(
2612 handleLogServicesDumpCollectDiagnosticDataComputerSystemPost,
2613 std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002614}
2615
2616inline void requestRoutesSystemDumpClear(App& app)
2617{
George Liu0fda0f12021-11-16 10:06:17 +08002618 BMCWEB_ROUTE(
2619 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002620 "/redfish/v1/Systems/<str>/LogServices/Dump/Actions/LogService.ClearLog/")
Ed Tanoused398212021-06-09 17:05:54 -07002621 .privileges(redfish::privileges::postLogService)
Claire Weinan6ab9ad52022-08-12 18:20:17 -07002622 .methods(boost::beast::http::verb::post)(std::bind_front(
Ed Tanous22d268c2022-05-19 09:39:07 -07002623 handleLogServicesDumpClearLogComputerSystemPost, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002624}
2625
2626inline void requestRoutesCrashdumpService(App& app)
2627{
2628 // Note: Deviated from redfish privilege registry for GET & HEAD
2629 // method for security reasons.
2630 /**
2631 * Functions triggers appropriate requests on DBus
2632 */
Ed Tanous22d268c2022-05-19 09:39:07 -07002633 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Crashdump/")
Ed Tanoused398212021-06-09 17:05:54 -07002634 // This is incorrect, should be:
2635 //.privileges(redfish::privileges::getLogService)
Ed Tanous432a8902021-06-14 15:28:56 -07002636 .privileges({{"ConfigureManager"}})
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002637 .methods(
2638 boost::beast::http::verb::
2639 get)([&app](const crow::Request& req,
2640 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2641 const std::string& systemName) {
2642 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2643 {
2644 return;
2645 }
2646 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
2647 {
2648 // Option currently returns no systems. TBD
2649 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2650 systemName);
2651 return;
2652 }
2653 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2654 {
2655 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2656 systemName);
2657 return;
2658 }
Ed Tanous22d268c2022-05-19 09:39:07 -07002659
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002660 // Copy over the static data to include the entries added by
2661 // SubRoute
2662 asyncResp->res.jsonValue["@odata.id"] =
2663 std::format("/redfish/v1/Systems/{}/LogServices/Crashdump",
2664 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2665 asyncResp->res.jsonValue["@odata.type"] =
2666 "#LogService.v1_2_0.LogService";
2667 asyncResp->res.jsonValue["Name"] = "Open BMC Oem Crashdump Service";
2668 asyncResp->res.jsonValue["Description"] = "Oem Crashdump Service";
2669 asyncResp->res.jsonValue["Id"] = "Crashdump";
2670 asyncResp->res.jsonValue["OverWritePolicy"] =
2671 log_service::OverWritePolicy::WrapsWhenFull;
2672 asyncResp->res.jsonValue["MaxNumberOfRecords"] = 3;
Tejas Patil7c8c4052021-06-04 17:43:14 +05302673
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002674 std::pair<std::string, std::string> redfishDateTimeOffset =
2675 redfish::time_utils::getDateTimeOffsetNow();
2676 asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
2677 asyncResp->res.jsonValue["DateTimeLocalOffset"] =
2678 redfishDateTimeOffset.second;
Tejas Patil7c8c4052021-06-04 17:43:14 +05302679
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002680 asyncResp->res.jsonValue["Entries"]["@odata.id"] = std::format(
2681 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries",
2682 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2683 asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"]
2684 ["target"] = std::format(
2685 "/redfish/v1/Systems/{}/LogServices/Crashdump/Actions/LogService.ClearLog",
2686 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2687 asyncResp->res
2688 .jsonValue["Actions"]["#LogService.CollectDiagnosticData"]
2689 ["target"] = std::format(
2690 "/redfish/v1/Systems/{}/LogServices/Crashdump/Actions/LogService.CollectDiagnosticData",
2691 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2692 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002693}
2694
2695void inline requestRoutesCrashdumpClear(App& app)
2696{
George Liu0fda0f12021-11-16 10:06:17 +08002697 BMCWEB_ROUTE(
2698 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002699 "/redfish/v1/Systems/<str>/LogServices/Crashdump/Actions/LogService.ClearLog/")
Ed Tanoused398212021-06-09 17:05:54 -07002700 // This is incorrect, should be:
2701 //.privileges(redfish::privileges::postLogService)
Ed Tanous432a8902021-06-14 15:28:56 -07002702 .privileges({{"ConfigureComponents"}})
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002703 .methods(boost::beast::http::verb::post)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07002704 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07002705 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2706 const std::string& systemName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002707 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2708 {
2709 return;
2710 }
2711 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
2712 {
2713 // Option currently returns no systems. TBD
2714 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2715 systemName);
2716 return;
2717 }
2718 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2719 {
2720 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2721 systemName);
2722 return;
2723 }
2724 crow::connections::systemBus->async_method_call(
2725 [asyncResp](const boost::system::error_code& ec,
2726 const std::string&) {
2727 if (ec)
2728 {
2729 messages::internalError(asyncResp->res);
2730 return;
2731 }
2732 messages::success(asyncResp->res);
2733 },
2734 crashdumpObject, crashdumpPath, deleteAllInterface,
2735 "DeleteAll");
2736 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002737}
Jason M. Bills5b61b5e2019-10-16 10:59:02 -07002738
Ed Tanous4ff0f1f2024-09-04 17:27:37 -07002739inline void
zhanghch058d1b46d2021-04-01 11:18:24 +08002740 logCrashdumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2741 const std::string& logID, nlohmann::json& logEntryJson)
Jason M. Billse855dd22019-10-08 11:37:48 -07002742{
Johnathan Mantey043a0532020-03-10 17:15:28 -07002743 auto getStoredLogCallback =
Ed Tanousb9d36b42022-02-26 21:42:46 -08002744 [asyncResp, logID,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002745 &logEntryJson](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002746 const dbus::utility::DBusPropertiesMap& params) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002747 if (ec)
2748 {
2749 BMCWEB_LOG_DEBUG("failed to get log ec: {}", ec.message());
2750 if (ec.value() ==
2751 boost::system::linux_error::bad_request_descriptor)
2752 {
2753 messages::resourceNotFound(asyncResp->res, "LogEntry",
2754 logID);
2755 }
2756 else
2757 {
2758 messages::internalError(asyncResp->res);
2759 }
2760 return;
2761 }
2762
2763 std::string timestamp{};
2764 std::string filename{};
2765 std::string logfile{};
2766 parseCrashdumpParameters(params, filename, timestamp, logfile);
2767
2768 if (filename.empty() || timestamp.empty())
Jason M. Bills1ddcf012019-11-26 14:59:21 -08002769 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002770 messages::resourceNotFound(asyncResp->res, "LogEntry", logID);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002771 return;
2772 }
2773
2774 std::string crashdumpURI =
2775 std::format(
2776 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries/",
2777 BMCWEB_REDFISH_SYSTEM_URI_NAME) +
2778 logID + "/" + filename;
2779 nlohmann::json::object_t logEntry;
2780 logEntry["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
2781 logEntry["@odata.id"] = boost::urls::format(
2782 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries/{}",
2783 BMCWEB_REDFISH_SYSTEM_URI_NAME, logID);
2784 logEntry["Name"] = "CPU Crashdump";
2785 logEntry["Id"] = logID;
2786 logEntry["EntryType"] = log_entry::LogEntryType::Oem;
2787 logEntry["AdditionalDataURI"] = std::move(crashdumpURI);
2788 logEntry["DiagnosticDataType"] = "OEM";
2789 logEntry["OEMDiagnosticDataType"] = "PECICrashdump";
2790 logEntry["Created"] = std::move(timestamp);
2791
2792 // If logEntryJson references an array of LogEntry resources
2793 // ('Members' list), then push this as a new entry, otherwise set it
2794 // directly
2795 if (logEntryJson.is_array())
2796 {
2797 logEntryJson.push_back(logEntry);
2798 asyncResp->res.jsonValue["Members@odata.count"] =
2799 logEntryJson.size();
Jason M. Bills2b20ef62022-01-06 15:48:07 -08002800 }
2801 else
2802 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002803 logEntryJson.update(logEntry);
Jason M. Bills2b20ef62022-01-06 15:48:07 -08002804 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002805 };
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +02002806 sdbusplus::asio::getAllProperties(
2807 *crow::connections::systemBus, crashdumpObject,
2808 crashdumpPath + std::string("/") + logID, crashdumpInterface,
2809 std::move(getStoredLogCallback));
Jason M. Billse855dd22019-10-08 11:37:48 -07002810}
2811
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002812inline void requestRoutesCrashdumpEntryCollection(App& app)
Ed Tanous1da66f72018-07-27 16:13:37 -07002813{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002814 // Note: Deviated from redfish privilege registry for GET & HEAD
2815 // method for security reasons.
Ed Tanous1da66f72018-07-27 16:13:37 -07002816 /**
2817 * Functions triggers appropriate requests on DBus
2818 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002819 BMCWEB_ROUTE(app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002820 "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/")
Ed Tanoused398212021-06-09 17:05:54 -07002821 // This is incorrect, should be.
2822 //.privileges(redfish::privileges::postLogEntryCollection)
Ed Tanous432a8902021-06-14 15:28:56 -07002823 .privileges({{"ConfigureComponents"}})
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002824 .methods(
2825 boost::beast::http::verb::
2826 get)([&app](const crow::Request& req,
2827 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2828 const std::string& systemName) {
2829 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous45ca1b82022-03-25 13:07:27 -07002830 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002831 return;
Ed Tanous45ca1b82022-03-25 13:07:27 -07002832 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002833 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous002d39b2022-05-31 08:59:27 -07002834 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002835 // Option currently returns no systems. TBD
2836 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2837 systemName);
2838 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07002839 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002840 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2841 {
2842 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2843 systemName);
2844 return;
2845 }
2846
2847 constexpr std::array<std::string_view, 1> interfaces = {
2848 crashdumpInterface};
2849 dbus::utility::getSubTreePaths(
2850 "/", 0, interfaces,
2851 [asyncResp](const boost::system::error_code& ec,
2852 const std::vector<std::string>& resp) {
2853 if (ec)
2854 {
2855 if (ec.value() !=
2856 boost::system::errc::no_such_file_or_directory)
2857 {
2858 BMCWEB_LOG_DEBUG("failed to get entries ec: {}",
2859 ec.message());
2860 messages::internalError(asyncResp->res);
2861 return;
2862 }
2863 }
2864 asyncResp->res.jsonValue["@odata.type"] =
2865 "#LogEntryCollection.LogEntryCollection";
2866 asyncResp->res.jsonValue["@odata.id"] = std::format(
2867 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries",
2868 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2869 asyncResp->res.jsonValue["Name"] =
2870 "Open BMC Crashdump Entries";
2871 asyncResp->res.jsonValue["Description"] =
2872 "Collection of Crashdump Entries";
2873 asyncResp->res.jsonValue["Members"] =
2874 nlohmann::json::array();
2875 asyncResp->res.jsonValue["Members@odata.count"] = 0;
2876
2877 for (const std::string& path : resp)
2878 {
2879 const sdbusplus::message::object_path objPath(path);
2880 // Get the log ID
2881 std::string logID = objPath.filename();
2882 if (logID.empty())
2883 {
2884 continue;
2885 }
2886 // Add the log entry to the array
2887 logCrashdumpEntry(asyncResp, logID,
2888 asyncResp->res.jsonValue["Members"]);
2889 }
2890 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002891 });
2892}
Ed Tanous1da66f72018-07-27 16:13:37 -07002893
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002894inline void requestRoutesCrashdumpEntry(App& app)
Ed Tanous1da66f72018-07-27 16:13:37 -07002895{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002896 // Note: Deviated from redfish privilege registry for GET & HEAD
2897 // method for security reasons.
Ed Tanous1da66f72018-07-27 16:13:37 -07002898
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002899 BMCWEB_ROUTE(
Ed Tanous22d268c2022-05-19 09:39:07 -07002900 app, "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002901 // this is incorrect, should be
2902 // .privileges(redfish::privileges::getLogEntry)
Ed Tanous432a8902021-06-14 15:28:56 -07002903 .privileges({{"ConfigureComponents"}})
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002904 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07002905 [&app](const crow::Request& req,
2906 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -07002907 const std::string& systemName, const std::string& param) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002908 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2909 {
2910 return;
2911 }
2912 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
2913 {
2914 // Option currently returns no systems. TBD
2915 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2916 systemName);
2917 return;
2918 }
2919 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2920 {
2921 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2922 systemName);
2923 return;
2924 }
2925 const std::string& logID = param;
2926 logCrashdumpEntry(asyncResp, logID, asyncResp->res.jsonValue);
2927 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002928}
Ed Tanous1da66f72018-07-27 16:13:37 -07002929
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002930inline void requestRoutesCrashdumpFile(App& app)
2931{
2932 // Note: Deviated from redfish privilege registry for GET & HEAD
2933 // method for security reasons.
2934 BMCWEB_ROUTE(
2935 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002936 "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/<str>/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002937 .privileges(redfish::privileges::getLogEntry)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002938 .methods(boost::beast::http::verb::get)(
Nan Zhoua4ce1142022-08-02 18:45:25 +00002939 [](const crow::Request& req,
2940 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -07002941 const std::string& systemName, const std::string& logID,
2942 const std::string& fileName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002943 // Do not call getRedfishRoute here since the crashdump file is
2944 // not a Redfish resource.
Ed Tanous22d268c2022-05-19 09:39:07 -07002945
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002946 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
2947 {
2948 // Option currently returns no systems. TBD
2949 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2950 systemName);
2951 return;
2952 }
2953 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2954 {
2955 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2956 systemName);
2957 return;
2958 }
Ed Tanous22d268c2022-05-19 09:39:07 -07002959
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002960 auto getStoredLogCallback =
2961 [asyncResp, logID, fileName,
2962 url(boost::urls::url(req.url()))](
2963 const boost::system::error_code& ec,
2964 const std::vector<std::pair<
2965 std::string, dbus::utility::DbusVariantType>>&
2966 resp) {
2967 if (ec)
2968 {
2969 BMCWEB_LOG_DEBUG("failed to get log ec: {}",
2970 ec.message());
2971 messages::internalError(asyncResp->res);
2972 return;
2973 }
Jason M. Bills8e6c0992021-03-11 16:26:53 -08002974
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002975 std::string dbusFilename{};
2976 std::string dbusTimestamp{};
2977 std::string dbusFilepath{};
Jason M. Bills8e6c0992021-03-11 16:26:53 -08002978
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002979 parseCrashdumpParameters(resp, dbusFilename,
2980 dbusTimestamp, dbusFilepath);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002981
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002982 if (dbusFilename.empty() || dbusTimestamp.empty() ||
2983 dbusFilepath.empty())
2984 {
2985 messages::resourceNotFound(asyncResp->res,
2986 "LogEntry", logID);
2987 return;
2988 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002989
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002990 // Verify the file name parameter is correct
2991 if (fileName != dbusFilename)
2992 {
2993 messages::resourceNotFound(asyncResp->res,
2994 "LogEntry", logID);
2995 return;
2996 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002997
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002998 if (!asyncResp->res.openFile(dbusFilepath))
2999 {
3000 messages::resourceNotFound(asyncResp->res,
3001 "LogEntry", logID);
3002 return;
3003 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003004
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003005 // Configure this to be a file download when accessed
3006 // from a browser
3007 asyncResp->res.addHeader(
3008 boost::beast::http::field::content_disposition,
3009 "attachment");
3010 };
3011 sdbusplus::asio::getAllProperties(
3012 *crow::connections::systemBus, crashdumpObject,
3013 crashdumpPath + std::string("/") + logID,
3014 crashdumpInterface, std::move(getStoredLogCallback));
3015 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003016}
3017
Jason M. Billsc5a4c822022-01-06 15:51:23 -08003018enum class OEMDiagnosticType
3019{
3020 onDemand,
3021 telemetry,
3022 invalid,
3023};
3024
Ed Tanous26ccae32023-02-16 10:28:44 -08003025inline OEMDiagnosticType getOEMDiagnosticType(std::string_view oemDiagStr)
Jason M. Billsc5a4c822022-01-06 15:51:23 -08003026{
3027 if (oemDiagStr == "OnDemand")
3028 {
3029 return OEMDiagnosticType::onDemand;
3030 }
3031 if (oemDiagStr == "Telemetry")
3032 {
3033 return OEMDiagnosticType::telemetry;
3034 }
3035
3036 return OEMDiagnosticType::invalid;
3037}
3038
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003039inline void requestRoutesCrashdumpCollect(App& app)
3040{
3041 // Note: Deviated from redfish privilege registry for GET & HEAD
3042 // method for security reasons.
George Liu0fda0f12021-11-16 10:06:17 +08003043 BMCWEB_ROUTE(
3044 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07003045 "/redfish/v1/Systems/<str>/LogServices/Crashdump/Actions/LogService.CollectDiagnosticData/")
Ed Tanoused398212021-06-09 17:05:54 -07003046 // The below is incorrect; Should be ConfigureManager
3047 //.privileges(redfish::privileges::postLogService)
Ed Tanous432a8902021-06-14 15:28:56 -07003048 .privileges({{"ConfigureComponents"}})
Ed Tanous002d39b2022-05-31 08:59:27 -07003049 .methods(boost::beast::http::verb::post)(
3050 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07003051 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3052 const std::string& systemName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003053 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07003054 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003055 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07003056 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003057
3058 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous002d39b2022-05-31 08:59:27 -07003059 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003060 // Option currently returns no systems. TBD
3061 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3062 systemName);
3063 return;
3064 }
3065 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
3066 {
3067 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3068 systemName);
3069 return;
3070 }
3071
3072 std::string diagnosticDataType;
3073 std::string oemDiagnosticDataType;
3074 if (!redfish::json_util::readJsonAction(
3075 req, asyncResp->res, "DiagnosticDataType",
3076 diagnosticDataType, "OEMDiagnosticDataType",
3077 oemDiagnosticDataType))
3078 {
3079 return;
3080 }
3081
3082 if (diagnosticDataType != "OEM")
3083 {
3084 BMCWEB_LOG_ERROR(
3085 "Only OEM DiagnosticDataType supported for Crashdump");
3086 messages::actionParameterValueFormatError(
3087 asyncResp->res, diagnosticDataType,
3088 "DiagnosticDataType", "CollectDiagnosticData");
3089 return;
3090 }
3091
3092 OEMDiagnosticType oemDiagType =
3093 getOEMDiagnosticType(oemDiagnosticDataType);
3094
3095 std::string iface;
3096 std::string method;
3097 std::string taskMatchStr;
3098 if (oemDiagType == OEMDiagnosticType::onDemand)
3099 {
3100 iface = crashdumpOnDemandInterface;
3101 method = "GenerateOnDemandLog";
3102 taskMatchStr =
3103 "type='signal',"
3104 "interface='org.freedesktop.DBus.Properties',"
3105 "member='PropertiesChanged',"
3106 "arg0namespace='com.intel.crashdump'";
3107 }
3108 else if (oemDiagType == OEMDiagnosticType::telemetry)
3109 {
3110 iface = crashdumpTelemetryInterface;
3111 method = "GenerateTelemetryLog";
3112 taskMatchStr =
3113 "type='signal',"
3114 "interface='org.freedesktop.DBus.Properties',"
3115 "member='PropertiesChanged',"
3116 "arg0namespace='com.intel.crashdump'";
Ed Tanous002d39b2022-05-31 08:59:27 -07003117 }
3118 else
3119 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003120 BMCWEB_LOG_ERROR("Unsupported OEMDiagnosticDataType: {}",
3121 oemDiagnosticDataType);
3122 messages::actionParameterValueFormatError(
3123 asyncResp->res, oemDiagnosticDataType,
3124 "OEMDiagnosticDataType", "CollectDiagnosticData");
3125 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07003126 }
Ed Tanous1da66f72018-07-27 16:13:37 -07003127
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003128 auto collectCrashdumpCallback =
3129 [asyncResp, payload(task::Payload(req)),
3130 taskMatchStr](const boost::system::error_code& ec,
3131 const std::string&) mutable {
3132 if (ec)
3133 {
3134 if (ec.value() ==
3135 boost::system::errc::operation_not_supported)
3136 {
3137 messages::resourceInStandby(asyncResp->res);
3138 }
3139 else if (ec.value() == boost::system::errc::
3140 device_or_resource_busy)
3141 {
3142 messages::serviceTemporarilyUnavailable(
3143 asyncResp->res, "60");
3144 }
3145 else
3146 {
3147 messages::internalError(asyncResp->res);
3148 }
3149 return;
3150 }
3151 std::shared_ptr<task::TaskData> task =
3152 task::TaskData::createTask(
3153 [](const boost::system::error_code& ec2,
3154 sdbusplus::message_t&,
3155 const std::shared_ptr<task::TaskData>&
3156 taskData) {
3157 if (!ec2)
3158 {
3159 taskData->messages.emplace_back(
3160 messages::taskCompletedOK(
3161 std::to_string(
3162 taskData->index)));
3163 taskData->state = "Completed";
3164 }
3165 return task::completed;
3166 },
3167 taskMatchStr);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003168
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003169 task->startTimer(std::chrono::minutes(5));
3170 task->populateResp(asyncResp->res);
3171 task->payload.emplace(std::move(payload));
3172 };
3173
3174 crow::connections::systemBus->async_method_call(
3175 std::move(collectCrashdumpCallback), crashdumpObject,
3176 crashdumpPath, iface, method);
3177 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003178}
Kenny L. Ku6eda7682020-06-19 09:48:36 -07003179
Alexander Hansen599b9af2024-08-06 15:11:57 +02003180inline void dBusLogServiceActionsClear(
3181 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
3182{
3183 BMCWEB_LOG_DEBUG("Do delete all entries.");
3184
3185 // Process response from Logging service.
3186 auto respHandler = [asyncResp](const boost::system::error_code& ec) {
3187 BMCWEB_LOG_DEBUG("doClearLog resp_handler callback: Done");
3188 if (ec)
3189 {
3190 // TODO Handle for specific error code
3191 BMCWEB_LOG_ERROR("doClearLog resp_handler got error {}", ec);
3192 asyncResp->res.result(
3193 boost::beast::http::status::internal_server_error);
3194 return;
3195 }
3196
3197 asyncResp->res.result(boost::beast::http::status::no_content);
3198 };
3199
3200 // Make call to Logging service to request Clear Log
3201 crow::connections::systemBus->async_method_call(
3202 respHandler, "xyz.openbmc_project.Logging",
3203 "/xyz/openbmc_project/logging",
3204 "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
3205}
3206
Andrew Geisslercb92c032018-08-17 07:56:14 -07003207/**
3208 * DBusLogServiceActionsClear class supports POST method for ClearLog action.
3209 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003210inline void requestRoutesDBusLogServiceActionsClear(App& app)
Andrew Geisslercb92c032018-08-17 07:56:14 -07003211{
Andrew Geisslercb92c032018-08-17 07:56:14 -07003212 /**
3213 * Function handles POST method request.
3214 * The Clear Log actions does not require any parameter.The action deletes
3215 * all entries found in the Entries collection for this Log Service.
3216 */
Andrew Geisslercb92c032018-08-17 07:56:14 -07003217
George Liu0fda0f12021-11-16 10:06:17 +08003218 BMCWEB_ROUTE(
3219 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07003220 "/redfish/v1/Systems/<str>/LogServices/EventLog/Actions/LogService.ClearLog/")
Ed Tanoused398212021-06-09 17:05:54 -07003221 .privileges(redfish::privileges::postLogService)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003222 .methods(boost::beast::http::verb::post)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07003223 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07003224 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3225 const std::string& systemName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003226 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3227 {
3228 return;
3229 }
3230 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
3231 {
3232 // Option currently returns no systems. TBD
3233 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3234 systemName);
3235 return;
3236 }
3237 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
3238 {
3239 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3240 systemName);
3241 return;
3242 }
3243 dBusLogServiceActionsClear(asyncResp);
3244 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003245}
ZhikuiRena3316fc2020-01-29 14:58:08 -08003246
Ed Tanous1da66f72018-07-27 16:13:37 -07003247} // namespace redfish