blob: 639a31488c7e00108ef5abf6907a29132c64a734 [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"
Alexander Hansen262dcc12024-09-19 12:04:03 +020033#include "utils/dbus_event_log_entry.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080034#include "utils/dbus_utils.hpp"
Ed Tanous5b904292024-04-16 11:10:17 -070035#include "utils/json_utils.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080036#include "utils/time_utils.hpp"
Ed Tanous1da66f72018-07-27 16:13:37 -070037
Myung Bae75e8e212023-11-30 12:53:46 -080038#include <systemd/sd-id128.h>
Asmitha Karunanithi8e317782020-12-10 03:35:05 -060039#include <tinyxml2.h>
Adriana Kobylak400fd1f2021-01-29 09:01:30 -060040#include <unistd.h>
Jason M. Billse1f26342018-07-18 12:12:00 -070041
Ed Tanous07c8c202022-07-11 10:08:08 -070042#include <boost/beast/http/verb.hpp>
Ed Tanous1da66f72018-07-27 16:13:37 -070043#include <boost/container/flat_map.hpp>
Jason M. Bills1ddcf012019-11-26 14:59:21 -080044#include <boost/system/linux_error.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070045#include <boost/url/format.hpp>
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +020046#include <sdbusplus/asio/property.hpp>
47#include <sdbusplus/unpack_properties.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050048
George Liu7a1dbc42022-12-07 16:03:22 +080049#include <array>
George Liu647b3cd2021-07-05 12:43:56 +080050#include <charconv>
Abhilash Rajub5f288d2023-11-08 22:32:44 -060051#include <cstddef>
James Feist4418c7f2019-04-15 11:09:15 -070052#include <filesystem>
Ed Tanous18f8f602023-07-18 10:07:23 -070053#include <iterator>
Xiaochao Ma75710de2021-01-21 17:56:02 +080054#include <optional>
Ed Tanous3544d2a2023-08-06 18:12:20 -070055#include <ranges>
Ed Tanous26702d02021-11-03 15:02:33 -070056#include <span>
Ed Tanous18f8f602023-07-18 10:07:23 -070057#include <string>
Jason M. Billscd225da2019-05-08 15:31:57 -070058#include <string_view>
Ed Tanousabf2add2019-01-22 16:40:12 -080059#include <variant>
Ed Tanous1da66f72018-07-27 16:13:37 -070060
61namespace redfish
62{
63
Patrick Williams89492a12023-05-10 07:51:34 -050064constexpr const char* crashdumpObject = "com.intel.crashdump";
65constexpr const char* crashdumpPath = "/com/intel/crashdump";
66constexpr const char* crashdumpInterface = "com.intel.crashdump";
67constexpr const char* deleteAllInterface =
Jason M. Bills5b61b5e2019-10-16 10:59:02 -070068 "xyz.openbmc_project.Collection.DeleteAll";
Patrick Williams89492a12023-05-10 07:51:34 -050069constexpr const char* crashdumpOnDemandInterface =
Jason M. Bills424c4172019-03-21 13:50:33 -070070 "com.intel.crashdump.OnDemand";
Patrick Williams89492a12023-05-10 07:51:34 -050071constexpr const char* crashdumpTelemetryInterface =
Kenny L. Ku6eda7682020-06-19 09:48:36 -070072 "com.intel.crashdump.Telemetry";
Ed Tanous1da66f72018-07-27 16:13:37 -070073
Asmitha Karunanithi8e317782020-12-10 03:35:05 -060074enum class DumpCreationProgress
75{
76 DUMP_CREATE_SUCCESS,
77 DUMP_CREATE_FAILED,
78 DUMP_CREATE_INPROGRESS
79};
80
James Feistf6150402019-01-08 10:36:20 -080081namespace fs = std::filesystem;
Ed Tanous1da66f72018-07-27 16:13:37 -070082
Gunnar Mills1214b7e2020-06-04 10:11:30 -050083inline std::string translateSeverityDbusToRedfish(const std::string& s)
Andrew Geisslercb92c032018-08-17 07:56:14 -070084{
Ed Tanousd4d25792020-09-29 15:15:03 -070085 if ((s == "xyz.openbmc_project.Logging.Entry.Level.Alert") ||
86 (s == "xyz.openbmc_project.Logging.Entry.Level.Critical") ||
87 (s == "xyz.openbmc_project.Logging.Entry.Level.Emergency") ||
88 (s == "xyz.openbmc_project.Logging.Entry.Level.Error"))
Andrew Geisslercb92c032018-08-17 07:56:14 -070089 {
90 return "Critical";
91 }
Ed Tanous3174e4d2020-10-07 11:41:22 -070092 if ((s == "xyz.openbmc_project.Logging.Entry.Level.Debug") ||
93 (s == "xyz.openbmc_project.Logging.Entry.Level.Informational") ||
94 (s == "xyz.openbmc_project.Logging.Entry.Level.Notice"))
Andrew Geisslercb92c032018-08-17 07:56:14 -070095 {
96 return "OK";
97 }
Ed Tanous3174e4d2020-10-07 11:41:22 -070098 if (s == "xyz.openbmc_project.Logging.Entry.Level.Warning")
Andrew Geisslercb92c032018-08-17 07:56:14 -070099 {
100 return "Warning";
101 }
102 return "";
103}
104
Abhishek Patel9017faf2021-09-14 22:48:55 -0500105inline std::optional<bool> getProviderNotifyAction(const std::string& notify)
106{
107 std::optional<bool> notifyAction;
108 if (notify == "xyz.openbmc_project.Logging.Entry.Notify.Notify")
109 {
110 notifyAction = true;
111 }
112 else if (notify == "xyz.openbmc_project.Logging.Entry.Notify.Inhibit")
113 {
114 notifyAction = false;
115 }
116
117 return notifyAction;
118}
119
Ed Tanous18f8f602023-07-18 10:07:23 -0700120inline std::string getDumpPath(std::string_view dumpType)
121{
122 std::string dbusDumpPath = "/xyz/openbmc_project/dump/";
123 std::ranges::transform(dumpType, std::back_inserter(dbusDumpPath),
124 bmcweb::asciiToLower);
125
126 return dbusDumpPath;
127}
128
Ed Tanous055713e2024-07-17 17:19:36 -0700129inline bool getUniqueEntryID(const std::string& logEntry, std::string& entryID,
Jason M. Billse85d6b12019-07-29 17:01:15 -0700130 const bool firstEntry = true)
Jason M. Bills95820182019-04-22 16:25:34 -0700131{
Ed Tanous271584a2019-07-09 16:24:22 -0700132 static time_t prevTs = 0;
Jason M. Bills95820182019-04-22 16:25:34 -0700133 static int index = 0;
Jason M. Billse85d6b12019-07-29 17:01:15 -0700134 if (firstEntry)
135 {
136 prevTs = 0;
137 }
138
Jason M. Bills95820182019-04-22 16:25:34 -0700139 // Get the entry timestamp
Ed Tanous271584a2019-07-09 16:24:22 -0700140 std::time_t curTs = 0;
Jason M. Bills95820182019-04-22 16:25:34 -0700141 std::tm timeStruct = {};
142 std::istringstream entryStream(logEntry);
143 if (entryStream >> std::get_time(&timeStruct, "%Y-%m-%dT%H:%M:%S"))
144 {
145 curTs = std::mktime(&timeStruct);
146 }
147 // If the timestamp isn't unique, increment the index
148 if (curTs == prevTs)
149 {
150 index++;
151 }
152 else
153 {
154 // Otherwise, reset it
155 index = 0;
156 }
157 // Save the timestamp
158 prevTs = curTs;
159
160 entryID = std::to_string(curTs);
161 if (index > 0)
162 {
163 entryID += "_" + std::to_string(index);
164 }
165 return true;
166}
167
Ed Tanous4ff0f1f2024-09-04 17:27:37 -0700168inline bool
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500169 getRedfishLogFiles(std::vector<std::filesystem::path>& redfishLogFiles)
Jason M. Bills95820182019-04-22 16:25:34 -0700170{
171 static const std::filesystem::path redfishLogDir = "/var/log";
172 static const std::string redfishLogFilename = "redfish";
173
174 // Loop through the directory looking for redfish log files
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500175 for (const std::filesystem::directory_entry& dirEnt :
Jason M. Bills95820182019-04-22 16:25:34 -0700176 std::filesystem::directory_iterator(redfishLogDir))
177 {
178 // If we find a redfish log file, save the path
179 std::string filename = dirEnt.path().filename();
Ed Tanous11ba3972022-07-11 09:50:41 -0700180 if (filename.starts_with(redfishLogFilename))
Jason M. Bills95820182019-04-22 16:25:34 -0700181 {
182 redfishLogFiles.emplace_back(redfishLogDir / filename);
183 }
184 }
185 // As the log files rotate, they are appended with a ".#" that is higher for
186 // the older logs. Since we don't expect more than 10 log files, we
187 // can just sort the list to get them in order from newest to oldest
Ed Tanous3544d2a2023-08-06 18:12:20 -0700188 std::ranges::sort(redfishLogFiles);
Jason M. Bills95820182019-04-22 16:25:34 -0700189
190 return !redfishLogFiles.empty();
191}
192
Asmitha Karunanithi68dd0752022-11-15 11:33:46 -0600193inline log_entry::OriginatorTypes
194 mapDbusOriginatorTypeToRedfish(const std::string& originatorType)
195{
196 if (originatorType ==
197 "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Client")
198 {
199 return log_entry::OriginatorTypes::Client;
200 }
201 if (originatorType ==
202 "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Internal")
203 {
204 return log_entry::OriginatorTypes::Internal;
205 }
206 if (originatorType ==
207 "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.SupportingService")
208 {
209 return log_entry::OriginatorTypes::SupportingService;
210 }
211 return log_entry::OriginatorTypes::Invalid;
212}
213
Claire Weinanaefe3782022-07-15 19:17:19 -0700214inline void parseDumpEntryFromDbusObject(
Jiaqing Zhao2d613eb2022-08-15 16:03:00 +0800215 const dbus::utility::ManagedObjectType::value_type& object,
Claire Weinanc6fecda2022-07-15 10:43:25 -0700216 std::string& dumpStatus, uint64_t& size, uint64_t& timestampUs,
Asmitha Karunanithi68dd0752022-11-15 11:33:46 -0600217 std::string& originatorId, log_entry::OriginatorTypes& originatorType,
Claire Weinanaefe3782022-07-15 19:17:19 -0700218 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
219{
220 for (const auto& interfaceMap : object.second)
221 {
222 if (interfaceMap.first == "xyz.openbmc_project.Common.Progress")
223 {
224 for (const auto& propertyMap : interfaceMap.second)
225 {
226 if (propertyMap.first == "Status")
227 {
228 const auto* status =
229 std::get_if<std::string>(&propertyMap.second);
230 if (status == nullptr)
231 {
232 messages::internalError(asyncResp->res);
233 break;
234 }
235 dumpStatus = *status;
236 }
237 }
238 }
239 else if (interfaceMap.first == "xyz.openbmc_project.Dump.Entry")
240 {
241 for (const auto& propertyMap : interfaceMap.second)
242 {
243 if (propertyMap.first == "Size")
244 {
245 const auto* sizePtr =
246 std::get_if<uint64_t>(&propertyMap.second);
247 if (sizePtr == nullptr)
248 {
249 messages::internalError(asyncResp->res);
250 break;
251 }
252 size = *sizePtr;
253 break;
254 }
255 }
256 }
257 else if (interfaceMap.first == "xyz.openbmc_project.Time.EpochTime")
258 {
259 for (const auto& propertyMap : interfaceMap.second)
260 {
261 if (propertyMap.first == "Elapsed")
262 {
263 const uint64_t* usecsTimeStamp =
264 std::get_if<uint64_t>(&propertyMap.second);
265 if (usecsTimeStamp == nullptr)
266 {
267 messages::internalError(asyncResp->res);
268 break;
269 }
Claire Weinanc6fecda2022-07-15 10:43:25 -0700270 timestampUs = *usecsTimeStamp;
Claire Weinanaefe3782022-07-15 19:17:19 -0700271 break;
272 }
273 }
274 }
Asmitha Karunanithi68dd0752022-11-15 11:33:46 -0600275 else if (interfaceMap.first ==
276 "xyz.openbmc_project.Common.OriginatedBy")
277 {
278 for (const auto& propertyMap : interfaceMap.second)
279 {
280 if (propertyMap.first == "OriginatorId")
281 {
282 const std::string* id =
283 std::get_if<std::string>(&propertyMap.second);
284 if (id == nullptr)
285 {
286 messages::internalError(asyncResp->res);
287 break;
288 }
289 originatorId = *id;
290 }
291
292 if (propertyMap.first == "OriginatorType")
293 {
294 const std::string* type =
295 std::get_if<std::string>(&propertyMap.second);
296 if (type == nullptr)
297 {
298 messages::internalError(asyncResp->res);
299 break;
300 }
301
302 originatorType = mapDbusOriginatorTypeToRedfish(*type);
303 if (originatorType == log_entry::OriginatorTypes::Invalid)
304 {
305 messages::internalError(asyncResp->res);
306 break;
307 }
308 }
309 }
310 }
Claire Weinanaefe3782022-07-15 19:17:19 -0700311 }
312}
313
Nan Zhou21ab4042022-06-26 23:07:40 +0000314static std::string getDumpEntriesPath(const std::string& dumpType)
Claire Weinanfdd26902022-03-01 14:18:25 -0800315{
316 std::string entriesPath;
317
318 if (dumpType == "BMC")
319 {
Ed Tanous253f11b2024-05-16 09:38:31 -0700320 entriesPath =
321 std::format("/redfish/v1/Managers/{}/LogServices/Dump/Entries/",
322 BMCWEB_REDFISH_MANAGER_URI_NAME);
Claire Weinanfdd26902022-03-01 14:18:25 -0800323 }
324 else if (dumpType == "FaultLog")
325 {
Ed Tanous253f11b2024-05-16 09:38:31 -0700326 entriesPath =
327 std::format("/redfish/v1/Managers/{}/LogServices/FaultLog/Entries/",
328 BMCWEB_REDFISH_MANAGER_URI_NAME);
Claire Weinanfdd26902022-03-01 14:18:25 -0800329 }
330 else if (dumpType == "System")
331 {
Ed Tanous253f11b2024-05-16 09:38:31 -0700332 entriesPath =
333 std::format("/redfish/v1/Systems/{}/LogServices/Dump/Entries/",
334 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Claire Weinanfdd26902022-03-01 14:18:25 -0800335 }
336 else
337 {
Ed Tanous62598e32023-07-17 17:06:25 -0700338 BMCWEB_LOG_ERROR("getDumpEntriesPath() invalid dump type: {}",
339 dumpType);
Claire Weinanfdd26902022-03-01 14:18:25 -0800340 }
341
342 // Returns empty string on error
343 return entriesPath;
344}
345
zhanghch058d1b46d2021-04-01 11:18:24 +0800346inline void
347 getDumpEntryCollection(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
348 const std::string& dumpType)
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500349{
Claire Weinanfdd26902022-03-01 14:18:25 -0800350 std::string entriesPath = getDumpEntriesPath(dumpType);
351 if (entriesPath.empty())
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500352 {
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500353 messages::internalError(asyncResp->res);
354 return;
355 }
356
George Liu5eb468d2023-06-20 17:03:24 +0800357 sdbusplus::message::object_path path("/xyz/openbmc_project/dump");
358 dbus::utility::getManagedObjects(
359 "xyz.openbmc_project.Dump.Manager", path,
Claire Weinanfdd26902022-03-01 14:18:25 -0800360 [asyncResp, entriesPath,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800361 dumpType](const boost::system::error_code& ec,
George Liu5eb468d2023-06-20 17:03:24 +0800362 const dbus::utility::ManagedObjectType& objects) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400363 if (ec)
364 {
365 BMCWEB_LOG_ERROR("DumpEntry resp_handler got error {}", ec);
366 messages::internalError(asyncResp->res);
367 return;
368 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700369
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400370 // Remove ending slash
371 std::string odataIdStr = entriesPath;
372 if (!odataIdStr.empty())
373 {
374 odataIdStr.pop_back();
375 }
Claire Weinanfdd26902022-03-01 14:18:25 -0800376
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400377 asyncResp->res.jsonValue["@odata.type"] =
378 "#LogEntryCollection.LogEntryCollection";
379 asyncResp->res.jsonValue["@odata.id"] = std::move(odataIdStr);
380 asyncResp->res.jsonValue["Name"] = dumpType + " Dump Entries";
381 asyncResp->res.jsonValue["Description"] =
382 "Collection of " + dumpType + " Dump Entries";
Claire Weinanfdd26902022-03-01 14:18:25 -0800383
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400384 nlohmann::json::array_t entriesArray;
385 std::string dumpEntryPath = getDumpPath(dumpType) + "/entry/";
Ed Tanous002d39b2022-05-31 08:59:27 -0700386
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400387 dbus::utility::ManagedObjectType resp(objects);
388 std::ranges::sort(resp, [](const auto& l, const auto& r) {
389 return AlphanumLess<std::string>()(l.first.filename(),
390 r.first.filename());
391 });
392
393 for (auto& object : resp)
394 {
395 if (object.first.str.find(dumpEntryPath) == std::string::npos)
396 {
397 continue;
398 }
399 uint64_t timestampUs = 0;
400 uint64_t size = 0;
401 std::string dumpStatus;
402 std::string originatorId;
403 log_entry::OriginatorTypes originatorType =
404 log_entry::OriginatorTypes::Internal;
405 nlohmann::json::object_t thisEntry;
406
407 std::string entryID = object.first.filename();
408 if (entryID.empty())
409 {
410 continue;
411 }
412
413 parseDumpEntryFromDbusObject(object, dumpStatus, size,
414 timestampUs, originatorId,
415 originatorType, asyncResp);
416
417 if (dumpStatus !=
418 "xyz.openbmc_project.Common.Progress.OperationStatus.Completed" &&
419 !dumpStatus.empty())
420 {
421 // Dump status is not Complete, no need to enumerate
422 continue;
423 }
424
425 thisEntry["@odata.type"] = "#LogEntry.v1_11_0.LogEntry";
426 thisEntry["@odata.id"] = entriesPath + entryID;
427 thisEntry["Id"] = entryID;
428 thisEntry["EntryType"] = "Event";
429 thisEntry["Name"] = dumpType + " Dump Entry";
430 thisEntry["Created"] =
431 redfish::time_utils::getDateTimeUintUs(timestampUs);
432
433 if (!originatorId.empty())
434 {
435 thisEntry["Originator"] = originatorId;
436 thisEntry["OriginatorType"] = originatorType;
437 }
438
439 if (dumpType == "BMC")
440 {
441 thisEntry["DiagnosticDataType"] = "Manager";
442 thisEntry["AdditionalDataURI"] =
443 entriesPath + entryID + "/attachment";
444 thisEntry["AdditionalDataSizeBytes"] = size;
445 }
446 else if (dumpType == "System")
447 {
448 thisEntry["DiagnosticDataType"] = "OEM";
449 thisEntry["OEMDiagnosticDataType"] = "System";
450 thisEntry["AdditionalDataURI"] =
451 entriesPath + entryID + "/attachment";
452 thisEntry["AdditionalDataSizeBytes"] = size;
453 }
454 entriesArray.emplace_back(std::move(thisEntry));
455 }
456 asyncResp->res.jsonValue["Members@odata.count"] =
457 entriesArray.size();
458 asyncResp->res.jsonValue["Members"] = std::move(entriesArray);
Ed Tanous002d39b2022-05-31 08:59:27 -0700459 });
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500460}
461
zhanghch058d1b46d2021-04-01 11:18:24 +0800462inline void
Claire Weinanc7a6d662022-06-13 16:36:39 -0700463 getDumpEntryById(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
zhanghch058d1b46d2021-04-01 11:18:24 +0800464 const std::string& entryID, const std::string& dumpType)
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500465{
Claire Weinanfdd26902022-03-01 14:18:25 -0800466 std::string entriesPath = getDumpEntriesPath(dumpType);
467 if (entriesPath.empty())
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500468 {
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500469 messages::internalError(asyncResp->res);
470 return;
471 }
472
George Liu5eb468d2023-06-20 17:03:24 +0800473 sdbusplus::message::object_path path("/xyz/openbmc_project/dump");
474 dbus::utility::getManagedObjects(
475 "xyz.openbmc_project.Dump.Manager", path,
Claire Weinanfdd26902022-03-01 14:18:25 -0800476 [asyncResp, entryID, dumpType,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800477 entriesPath](const boost::system::error_code& ec,
Ed Tanous02cad962022-06-30 16:50:15 -0700478 const dbus::utility::ManagedObjectType& resp) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400479 if (ec)
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500480 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400481 BMCWEB_LOG_ERROR("DumpEntry resp_handler got error {}", ec);
482 messages::internalError(asyncResp->res);
483 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700484 }
485
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400486 bool foundDumpEntry = false;
487 std::string dumpEntryPath = getDumpPath(dumpType) + "/entry/";
Ed Tanous002d39b2022-05-31 08:59:27 -0700488
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400489 for (const auto& objectPath : resp)
Ed Tanous002d39b2022-05-31 08:59:27 -0700490 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400491 if (objectPath.first.str != dumpEntryPath + entryID)
492 {
493 continue;
494 }
495
496 foundDumpEntry = true;
497 uint64_t timestampUs = 0;
498 uint64_t size = 0;
499 std::string dumpStatus;
500 std::string originatorId;
501 log_entry::OriginatorTypes originatorType =
502 log_entry::OriginatorTypes::Internal;
503
504 parseDumpEntryFromDbusObject(objectPath, dumpStatus, size,
505 timestampUs, originatorId,
506 originatorType, asyncResp);
507
508 if (dumpStatus !=
509 "xyz.openbmc_project.Common.Progress.OperationStatus.Completed" &&
510 !dumpStatus.empty())
511 {
512 // Dump status is not Complete
513 // return not found until status is changed to Completed
514 messages::resourceNotFound(asyncResp->res,
515 dumpType + " dump", entryID);
516 return;
517 }
518
519 asyncResp->res.jsonValue["@odata.type"] =
520 "#LogEntry.v1_11_0.LogEntry";
521 asyncResp->res.jsonValue["@odata.id"] = entriesPath + entryID;
522 asyncResp->res.jsonValue["Id"] = entryID;
523 asyncResp->res.jsonValue["EntryType"] = "Event";
524 asyncResp->res.jsonValue["Name"] = dumpType + " Dump Entry";
525 asyncResp->res.jsonValue["Created"] =
526 redfish::time_utils::getDateTimeUintUs(timestampUs);
527
528 if (!originatorId.empty())
529 {
530 asyncResp->res.jsonValue["Originator"] = originatorId;
531 asyncResp->res.jsonValue["OriginatorType"] = originatorType;
532 }
533
534 if (dumpType == "BMC")
535 {
536 asyncResp->res.jsonValue["DiagnosticDataType"] = "Manager";
537 asyncResp->res.jsonValue["AdditionalDataURI"] =
538 entriesPath + entryID + "/attachment";
539 asyncResp->res.jsonValue["AdditionalDataSizeBytes"] = size;
540 }
541 else if (dumpType == "System")
542 {
543 asyncResp->res.jsonValue["DiagnosticDataType"] = "OEM";
544 asyncResp->res.jsonValue["OEMDiagnosticDataType"] =
545 "System";
546 asyncResp->res.jsonValue["AdditionalDataURI"] =
547 entriesPath + entryID + "/attachment";
548 asyncResp->res.jsonValue["AdditionalDataSizeBytes"] = size;
549 }
550 }
551 if (!foundDumpEntry)
552 {
553 BMCWEB_LOG_WARNING("Can't find Dump Entry {}", entryID);
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +0200554 messages::resourceNotFound(asyncResp->res, dumpType + " dump",
555 entryID);
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500556 return;
557 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400558 });
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500559}
560
zhanghch058d1b46d2021-04-01 11:18:24 +0800561inline void deleteDumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Stanley Chu98782562020-11-04 16:10:24 +0800562 const std::string& entryID,
Asmitha Karunanithib47452b2020-09-25 02:02:19 -0500563 const std::string& dumpType)
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500564{
Patrick Williams5a39f772023-10-20 11:20:21 -0500565 auto respHandler = [asyncResp,
566 entryID](const boost::system::error_code& ec) {
Ed Tanous62598e32023-07-17 17:06:25 -0700567 BMCWEB_LOG_DEBUG("Dump Entry doDelete callback: Done");
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500568 if (ec)
569 {
George Liu3de8d8b2021-03-22 17:49:39 +0800570 if (ec.value() == EBADR)
571 {
572 messages::resourceNotFound(asyncResp->res, "LogEntry", entryID);
573 return;
574 }
Ed Tanous62598e32023-07-17 17:06:25 -0700575 BMCWEB_LOG_ERROR(
576 "Dump (DBus) doDelete respHandler got error {} entryID={}", ec,
577 entryID);
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500578 messages::internalError(asyncResp->res);
579 return;
580 }
581 };
Ed Tanous18f8f602023-07-18 10:07:23 -0700582
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500583 crow::connections::systemBus->async_method_call(
584 respHandler, "xyz.openbmc_project.Dump.Manager",
Ed Tanous18f8f602023-07-18 10:07:23 -0700585 std::format("{}/entry/{}", getDumpPath(dumpType), entryID),
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500586 "xyz.openbmc_project.Object.Delete", "Delete");
587}
Abhilash Rajub5f288d2023-11-08 22:32:44 -0600588inline bool checkSizeLimit(int fd, crow::Response& res)
589{
590 long long int size = lseek(fd, 0, SEEK_END);
591 if (size <= 0)
592 {
593 BMCWEB_LOG_ERROR("Failed to get size of file, lseek() returned {}",
594 size);
595 messages::internalError(res);
596 return false;
597 }
Asmitha Karunanithi5cb1dd22020-05-07 04:35:02 -0500598
Abhilash Rajub5f288d2023-11-08 22:32:44 -0600599 // Arbitrary max size of 20MB to accommodate BMC dumps
600 constexpr long long int maxFileSize = 20LL * 1024LL * 1024LL;
601 if (size > maxFileSize)
602 {
603 BMCWEB_LOG_ERROR("File size {} exceeds maximum allowed size of {}",
604 size, maxFileSize);
605 messages::internalError(res);
606 return false;
607 }
608 off_t rc = lseek(fd, 0, SEEK_SET);
609 if (rc < 0)
610 {
611 BMCWEB_LOG_ERROR("Failed to reset file offset to 0");
612 messages::internalError(res);
613 return false;
614 }
615 return true;
616}
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400617inline void downloadEntryCallback(
618 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
619 const std::string& entryID, const std::string& downloadEntryType,
620 const boost::system::error_code& ec,
621 const sdbusplus::message::unix_fd& unixfd)
Carson Labrado168d1b12023-03-27 17:04:46 +0000622{
623 if (ec.value() == EBADR)
624 {
625 messages::resourceNotFound(asyncResp->res, "EntryAttachment", entryID);
626 return;
627 }
628 if (ec)
629 {
630 BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
631 messages::internalError(asyncResp->res);
632 return;
633 }
634
635 // Make sure we know how to process the retrieved entry attachment
636 if ((downloadEntryType != "BMC") && (downloadEntryType != "System"))
637 {
638 BMCWEB_LOG_ERROR("downloadEntryCallback() invalid entry type: {}",
639 downloadEntryType);
640 messages::internalError(asyncResp->res);
641 }
642
643 int fd = -1;
644 fd = dup(unixfd);
645 if (fd < 0)
646 {
647 BMCWEB_LOG_ERROR("Failed to open file");
648 messages::internalError(asyncResp->res);
649 return;
650 }
Abhilash Rajub5f288d2023-11-08 22:32:44 -0600651 if (!checkSizeLimit(fd, asyncResp->res))
Carson Labrado168d1b12023-03-27 17:04:46 +0000652 {
Carson Labrado168d1b12023-03-27 17:04:46 +0000653 close(fd);
654 return;
655 }
Carson Labrado168d1b12023-03-27 17:04:46 +0000656 if (downloadEntryType == "System")
657 {
Abhilash Rajub5f288d2023-11-08 22:32:44 -0600658 if (!asyncResp->res.openFd(fd, bmcweb::EncodingType::Base64))
659 {
660 messages::internalError(asyncResp->res);
661 close(fd);
662 return;
663 }
Carson Labrado168d1b12023-03-27 17:04:46 +0000664 asyncResp->res.addHeader(
665 boost::beast::http::field::content_transfer_encoding, "Base64");
Abhilash Rajub5f288d2023-11-08 22:32:44 -0600666 return;
Carson Labrado168d1b12023-03-27 17:04:46 +0000667 }
Abhilash Rajub5f288d2023-11-08 22:32:44 -0600668 if (!asyncResp->res.openFd(fd))
Ed Tanous27b0cf92023-08-07 12:02:40 -0700669 {
Abhilash Rajub5f288d2023-11-08 22:32:44 -0600670 messages::internalError(asyncResp->res);
671 close(fd);
672 return;
Ed Tanous27b0cf92023-08-07 12:02:40 -0700673 }
Carson Labrado168d1b12023-03-27 17:04:46 +0000674 asyncResp->res.addHeader(boost::beast::http::field::content_type,
675 "application/octet-stream");
676}
677
678inline void
679 downloadDumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
680 const std::string& entryID, const std::string& dumpType)
681{
682 if (dumpType != "BMC")
683 {
684 BMCWEB_LOG_WARNING("Can't find Dump Entry {}", entryID);
685 messages::resourceNotFound(asyncResp->res, dumpType + " dump", entryID);
686 return;
687 }
688
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400689 std::string dumpEntryPath =
690 std::format("{}/entry/{}", getDumpPath(dumpType), entryID);
Carson Labrado168d1b12023-03-27 17:04:46 +0000691
692 auto downloadDumpEntryHandler =
693 [asyncResp, entryID,
694 dumpType](const boost::system::error_code& ec,
695 const sdbusplus::message::unix_fd& unixfd) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400696 downloadEntryCallback(asyncResp, entryID, dumpType, ec, unixfd);
697 };
Carson Labrado168d1b12023-03-27 17:04:46 +0000698
699 crow::connections::systemBus->async_method_call(
700 std::move(downloadDumpEntryHandler), "xyz.openbmc_project.Dump.Manager",
701 dumpEntryPath, "xyz.openbmc_project.Dump.Entry", "GetFileHandle");
702}
703
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400704inline void downloadEventLogEntry(
705 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
706 const std::string& systemName, const std::string& entryID,
707 const std::string& dumpType)
Carson Labrado168d1b12023-03-27 17:04:46 +0000708{
Ed Tanous25b54db2024-04-17 15:40:31 -0700709 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Carson Labrado168d1b12023-03-27 17:04:46 +0000710 {
711 // Option currently returns no systems. TBD
712 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
713 systemName);
714 return;
715 }
Ed Tanous253f11b2024-05-16 09:38:31 -0700716 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Carson Labrado168d1b12023-03-27 17:04:46 +0000717 {
718 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
719 systemName);
720 return;
721 }
722
723 std::string entryPath =
724 sdbusplus::message::object_path("/xyz/openbmc_project/logging/entry") /
725 entryID;
726
727 auto downloadEventLogEntryHandler =
728 [asyncResp, entryID,
729 dumpType](const boost::system::error_code& ec,
730 const sdbusplus::message::unix_fd& unixfd) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400731 downloadEntryCallback(asyncResp, entryID, dumpType, ec, unixfd);
732 };
Carson Labrado168d1b12023-03-27 17:04:46 +0000733
734 crow::connections::systemBus->async_method_call(
735 std::move(downloadEventLogEntryHandler), "xyz.openbmc_project.Logging",
736 entryPath, "xyz.openbmc_project.Logging.Entry", "GetEntry");
737}
738
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600739inline DumpCreationProgress
740 mapDbusStatusToDumpProgress(const std::string& status)
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500741{
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600742 if (status ==
743 "xyz.openbmc_project.Common.Progress.OperationStatus.Failed" ||
744 status == "xyz.openbmc_project.Common.Progress.OperationStatus.Aborted")
745 {
746 return DumpCreationProgress::DUMP_CREATE_FAILED;
747 }
748 if (status ==
749 "xyz.openbmc_project.Common.Progress.OperationStatus.Completed")
750 {
751 return DumpCreationProgress::DUMP_CREATE_SUCCESS;
752 }
753 return DumpCreationProgress::DUMP_CREATE_INPROGRESS;
754}
755
756inline DumpCreationProgress
757 getDumpCompletionStatus(const dbus::utility::DBusPropertiesMap& values)
758{
759 for (const auto& [key, val] : values)
760 {
761 if (key == "Status")
Ed Tanous002d39b2022-05-31 08:59:27 -0700762 {
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600763 const std::string* value = std::get_if<std::string>(&val);
764 if (value == nullptr)
765 {
Ed Tanous62598e32023-07-17 17:06:25 -0700766 BMCWEB_LOG_ERROR("Status property value is null");
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600767 return DumpCreationProgress::DUMP_CREATE_FAILED;
768 }
769 return mapDbusStatusToDumpProgress(*value);
770 }
771 }
772 return DumpCreationProgress::DUMP_CREATE_INPROGRESS;
773}
774
775inline std::string getDumpEntryPath(const std::string& dumpPath)
776{
777 if (dumpPath == "/xyz/openbmc_project/dump/bmc/entry")
778 {
Ed Tanous253f11b2024-05-16 09:38:31 -0700779 return std::format("/redfish/v1/Managers/{}/LogServices/Dump/Entries/",
Ed Tanous9f565092024-07-12 22:06:53 -0700780 BMCWEB_REDFISH_MANAGER_URI_NAME);
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600781 }
782 if (dumpPath == "/xyz/openbmc_project/dump/system/entry")
783 {
Ed Tanous253f11b2024-05-16 09:38:31 -0700784 return std::format("/redfish/v1/Systems/{}/LogServices/Dump/Entries/",
785 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600786 }
787 return "";
788}
789
790inline void createDumpTaskCallback(
791 task::Payload&& payload,
792 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
793 const sdbusplus::message::object_path& createdObjPath)
794{
795 const std::string dumpPath = createdObjPath.parent_path().str;
796 const std::string dumpId = createdObjPath.filename();
797
798 std::string dumpEntryPath = getDumpEntryPath(dumpPath);
799
800 if (dumpEntryPath.empty())
801 {
Ed Tanous62598e32023-07-17 17:06:25 -0700802 BMCWEB_LOG_ERROR("Invalid dump type received");
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600803 messages::internalError(asyncResp->res);
804 return;
805 }
806
807 crow::connections::systemBus->async_method_call(
Ed Tanous8cb2c022024-03-27 16:31:46 -0700808 [asyncResp, payload = std::move(payload), createdObjPath,
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600809 dumpEntryPath{std::move(dumpEntryPath)},
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800810 dumpId](const boost::system::error_code& ec,
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600811 const std::string& introspectXml) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400812 if (ec)
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600813 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400814 BMCWEB_LOG_ERROR("Introspect call failed with error: {}",
815 ec.message());
816 messages::internalError(asyncResp->res);
817 return;
818 }
819
820 // Check if the created dump object has implemented Progress
821 // interface to track dump completion. If yes, fetch the "Status"
822 // property of the interface, modify the task state accordingly.
823 // Else, return task completed.
824 tinyxml2::XMLDocument doc;
825
826 doc.Parse(introspectXml.data(), introspectXml.size());
827 tinyxml2::XMLNode* pRoot = doc.FirstChildElement("node");
828 if (pRoot == nullptr)
829 {
830 BMCWEB_LOG_ERROR("XML document failed to parse");
831 messages::internalError(asyncResp->res);
832 return;
833 }
834 tinyxml2::XMLElement* interfaceNode =
835 pRoot->FirstChildElement("interface");
836
837 bool isProgressIntfPresent = false;
838 while (interfaceNode != nullptr)
839 {
840 const char* thisInterfaceName =
841 interfaceNode->Attribute("name");
842 if (thisInterfaceName != nullptr)
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600843 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400844 if (thisInterfaceName ==
845 std::string_view("xyz.openbmc_project.Common.Progress"))
846 {
847 interfaceNode =
848 interfaceNode->NextSiblingElement("interface");
849 continue;
850 }
851 isProgressIntfPresent = true;
852 break;
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600853 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400854 interfaceNode = interfaceNode->NextSiblingElement("interface");
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600855 }
856
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400857 std::shared_ptr<task::TaskData> task = task::TaskData::createTask(
858 [createdObjPath, dumpEntryPath, dumpId, isProgressIntfPresent](
859 const boost::system::error_code& ec2,
860 sdbusplus::message_t& msg,
861 const std::shared_ptr<task::TaskData>& taskData) {
862 if (ec2)
863 {
864 BMCWEB_LOG_ERROR("{}: Error in creating dump",
865 createdObjPath.str);
866 taskData->messages.emplace_back(
867 messages::internalError());
868 taskData->state = "Cancelled";
869 return task::completed;
870 }
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600871
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400872 if (isProgressIntfPresent)
873 {
874 dbus::utility::DBusPropertiesMap values;
875 std::string prop;
876 msg.read(prop, values);
877
878 DumpCreationProgress dumpStatus =
879 getDumpCompletionStatus(values);
880 if (dumpStatus ==
881 DumpCreationProgress::DUMP_CREATE_FAILED)
882 {
883 BMCWEB_LOG_ERROR("{}: Error in creating dump",
884 createdObjPath.str);
885 taskData->state = "Cancelled";
886 return task::completed;
887 }
888
889 if (dumpStatus ==
890 DumpCreationProgress::DUMP_CREATE_INPROGRESS)
891 {
892 BMCWEB_LOG_DEBUG(
893 "{}: Dump creation task is in progress",
894 createdObjPath.str);
895 return !task::completed;
896 }
897 }
898
899 nlohmann::json retMessage = messages::success();
900 taskData->messages.emplace_back(retMessage);
901
902 boost::urls::url url = boost::urls::format(
903 "/redfish/v1/Managers/{}/LogServices/Dump/Entries/{}",
904 BMCWEB_REDFISH_MANAGER_URI_NAME, dumpId);
905
906 std::string headerLoc = "Location: ";
907 headerLoc += url.buffer();
908
909 taskData->payload->httpHeaders.emplace_back(
910 std::move(headerLoc));
911
912 BMCWEB_LOG_DEBUG("{}: Dump creation task completed",
Ed Tanous62598e32023-07-17 17:06:25 -0700913 createdObjPath.str);
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400914 taskData->state = "Completed";
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600915 return task::completed;
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400916 },
917 "type='signal',interface='org.freedesktop.DBus.Properties',"
918 "member='PropertiesChanged',path='" +
919 createdObjPath.str + "'");
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600920
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400921 // The task timer is set to max time limit within which the
922 // requested dump will be collected.
923 task->startTimer(std::chrono::minutes(6));
924 task->populateResp(asyncResp->res);
925 task->payload.emplace(payload);
Patrick Williams5a39f772023-10-20 11:20:21 -0500926 },
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600927 "xyz.openbmc_project.Dump.Manager", createdObjPath,
928 "org.freedesktop.DBus.Introspectable", "Introspect");
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500929}
930
zhanghch058d1b46d2021-04-01 11:18:24 +0800931inline void createDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
932 const crow::Request& req, const std::string& dumpType)
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500933{
Claire Weinanfdd26902022-03-01 14:18:25 -0800934 std::string dumpPath = getDumpEntriesPath(dumpType);
935 if (dumpPath.empty())
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500936 {
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500937 messages::internalError(asyncResp->res);
938 return;
939 }
940
941 std::optional<std::string> diagnosticDataType;
942 std::optional<std::string> oemDiagnosticDataType;
943
Willy Tu15ed6782021-12-14 11:03:16 -0800944 if (!redfish::json_util::readJsonAction(
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500945 req, asyncResp->res, "DiagnosticDataType", diagnosticDataType,
946 "OEMDiagnosticDataType", oemDiagnosticDataType))
947 {
948 return;
949 }
950
951 if (dumpType == "System")
952 {
953 if (!oemDiagnosticDataType || !diagnosticDataType)
954 {
Ed Tanous62598e32023-07-17 17:06:25 -0700955 BMCWEB_LOG_ERROR(
956 "CreateDump action parameter 'DiagnosticDataType'/'OEMDiagnosticDataType' value not found!");
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500957 messages::actionParameterMissing(
958 asyncResp->res, "CollectDiagnosticData",
959 "DiagnosticDataType & OEMDiagnosticDataType");
960 return;
961 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700962 if ((*oemDiagnosticDataType != "System") ||
963 (*diagnosticDataType != "OEM"))
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500964 {
Ed Tanous62598e32023-07-17 17:06:25 -0700965 BMCWEB_LOG_ERROR("Wrong parameter values passed");
Ed Tanousace85d62021-10-26 12:45:59 -0700966 messages::internalError(asyncResp->res);
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500967 return;
968 }
Ed Tanous253f11b2024-05-16 09:38:31 -0700969 dumpPath = std::format("/redfish/v1/Systems/{}/LogServices/Dump/",
970 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500971 }
972 else if (dumpType == "BMC")
973 {
974 if (!diagnosticDataType)
975 {
Ed Tanous62598e32023-07-17 17:06:25 -0700976 BMCWEB_LOG_ERROR(
977 "CreateDump action parameter 'DiagnosticDataType' not found!");
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500978 messages::actionParameterMissing(
979 asyncResp->res, "CollectDiagnosticData", "DiagnosticDataType");
980 return;
981 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700982 if (*diagnosticDataType != "Manager")
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500983 {
Ed Tanous62598e32023-07-17 17:06:25 -0700984 BMCWEB_LOG_ERROR(
985 "Wrong parameter value passed for 'DiagnosticDataType'");
Ed Tanousace85d62021-10-26 12:45:59 -0700986 messages::internalError(asyncResp->res);
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500987 return;
988 }
Ed Tanous253f11b2024-05-16 09:38:31 -0700989 dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/Dump/",
990 BMCWEB_REDFISH_MANAGER_URI_NAME);
Asmitha Karunanithi59075712021-10-22 01:17:41 -0500991 }
992 else
993 {
Ed Tanous62598e32023-07-17 17:06:25 -0700994 BMCWEB_LOG_ERROR("CreateDump failed. Unknown dump type");
Asmitha Karunanithi59075712021-10-22 01:17:41 -0500995 messages::internalError(asyncResp->res);
996 return;
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500997 }
998
Asmitha Karunanithi8e317782020-12-10 03:35:05 -0600999 std::vector<std::pair<std::string, std::variant<std::string, uint64_t>>>
1000 createDumpParamVec;
1001
Carson Labradof574a8e2023-03-22 02:26:00 +00001002 if (req.session != nullptr)
1003 {
1004 createDumpParamVec.emplace_back(
1005 "xyz.openbmc_project.Dump.Create.CreateParameters.OriginatorId",
1006 req.session->clientIp);
1007 createDumpParamVec.emplace_back(
1008 "xyz.openbmc_project.Dump.Create.CreateParameters.OriginatorType",
1009 "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Client");
1010 }
Asmitha Karunanithi68dd0752022-11-15 11:33:46 -06001011
Asmitha Karunanithia43be802020-05-07 05:05:36 -05001012 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001013 [asyncResp, payload(task::Payload(req)),
1014 dumpPath](const boost::system::error_code& ec,
1015 const sdbusplus::message_t& msg,
1016 const sdbusplus::message::object_path& objPath) mutable {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001017 if (ec)
Asmitha Karunanithi59075712021-10-22 01:17:41 -05001018 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001019 BMCWEB_LOG_ERROR("CreateDump resp_handler got error {}", ec);
1020 const sd_bus_error* dbusError = msg.get_error();
1021 if (dbusError == nullptr)
1022 {
1023 messages::internalError(asyncResp->res);
1024 return;
1025 }
1026
1027 BMCWEB_LOG_ERROR("CreateDump DBus error: {} and error msg: {}",
1028 dbusError->name, dbusError->message);
1029 if (std::string_view(
1030 "xyz.openbmc_project.Common.Error.NotAllowed") ==
1031 dbusError->name)
1032 {
1033 messages::resourceInStandby(asyncResp->res);
1034 return;
1035 }
1036 if (std::string_view(
1037 "xyz.openbmc_project.Dump.Create.Error.Disabled") ==
1038 dbusError->name)
1039 {
1040 messages::serviceDisabled(asyncResp->res, dumpPath);
1041 return;
1042 }
1043 if (std::string_view(
1044 "xyz.openbmc_project.Common.Error.Unavailable") ==
1045 dbusError->name)
1046 {
1047 messages::resourceInUse(asyncResp->res);
1048 return;
1049 }
1050 // Other Dbus errors such as:
1051 // xyz.openbmc_project.Common.Error.InvalidArgument &
1052 // org.freedesktop.DBus.Error.InvalidArgs are all related to
1053 // the dbus call that is made here in the bmcweb
1054 // implementation and has nothing to do with the client's
1055 // input in the request. Hence, returning internal error
1056 // back to the client.
Asmitha Karunanithi59075712021-10-22 01:17:41 -05001057 messages::internalError(asyncResp->res);
1058 return;
1059 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001060 BMCWEB_LOG_DEBUG("Dump Created. Path: {}", objPath.str);
1061 createDumpTaskCallback(std::move(payload), asyncResp, objPath);
1062 },
Ed Tanous18f8f602023-07-18 10:07:23 -07001063 "xyz.openbmc_project.Dump.Manager", getDumpPath(dumpType),
Asmitha Karunanithi8e317782020-12-10 03:35:05 -06001064 "xyz.openbmc_project.Dump.Create", "CreateDump", createDumpParamVec);
Asmitha Karunanithia43be802020-05-07 05:05:36 -05001065}
1066
zhanghch058d1b46d2021-04-01 11:18:24 +08001067inline void clearDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1068 const std::string& dumpType)
Asmitha Karunanithi80319af2020-05-07 05:30:21 -05001069{
Claire Weinan0d946212022-07-13 19:40:19 -07001070 crow::connections::systemBus->async_method_call(
1071 [asyncResp](const boost::system::error_code& ec) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001072 if (ec)
1073 {
1074 BMCWEB_LOG_ERROR("clearDump resp_handler got error {}", ec);
1075 messages::internalError(asyncResp->res);
1076 return;
1077 }
1078 },
Ed Tanous18f8f602023-07-18 10:07:23 -07001079 "xyz.openbmc_project.Dump.Manager", getDumpPath(dumpType),
Claire Weinan0d946212022-07-13 19:40:19 -07001080 "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
Asmitha Karunanithi80319af2020-05-07 05:30:21 -05001081}
1082
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001083inline void parseCrashdumpParameters(
1084 const dbus::utility::DBusPropertiesMap& params, std::string& filename,
1085 std::string& timestamp, std::string& logfile)
Johnathan Mantey043a0532020-03-10 17:15:28 -07001086{
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +02001087 const std::string* filenamePtr = nullptr;
1088 const std::string* timestampPtr = nullptr;
1089 const std::string* logfilePtr = nullptr;
1090
1091 const bool success = sdbusplus::unpackPropertiesNoThrow(
1092 dbus_utils::UnpackErrorPrinter(), params, "Timestamp", timestampPtr,
1093 "Filename", filenamePtr, "Log", logfilePtr);
1094
1095 if (!success)
Johnathan Mantey043a0532020-03-10 17:15:28 -07001096 {
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +02001097 return;
1098 }
1099
1100 if (filenamePtr != nullptr)
1101 {
1102 filename = *filenamePtr;
1103 }
1104
1105 if (timestampPtr != nullptr)
1106 {
1107 timestamp = *timestampPtr;
1108 }
1109
1110 if (logfilePtr != nullptr)
1111 {
1112 logfile = *logfilePtr;
Johnathan Mantey043a0532020-03-10 17:15:28 -07001113 }
1114}
1115
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001116inline void requestRoutesSystemLogServiceCollection(App& app)
Ed Tanous1da66f72018-07-27 16:13:37 -07001117{
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001118 /**
1119 * Functions triggers appropriate requests on DBus
1120 */
Ed Tanous22d268c2022-05-19 09:39:07 -07001121 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/")
Ed Tanoused398212021-06-09 17:05:54 -07001122 .privileges(redfish::privileges::getLogServiceCollection)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001123 .methods(
1124 boost::beast::http::verb::
1125 get)([&app](const crow::Request& req,
1126 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1127 const std::string& systemName) {
1128 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07001129 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001130 return;
1131 }
1132 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1133 {
1134 // Option currently returns no systems. TBD
1135 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1136 systemName);
1137 return;
1138 }
1139 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1140 {
1141 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1142 systemName);
Ed Tanous002d39b2022-05-31 08:59:27 -07001143 return;
1144 }
Ed Tanous45ca1b82022-03-25 13:07:27 -07001145
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001146 // Collections don't include the static data added by SubRoute
1147 // because it has a duplicate entry for members
1148 asyncResp->res.jsonValue["@odata.type"] =
1149 "#LogServiceCollection.LogServiceCollection";
1150 asyncResp->res.jsonValue["@odata.id"] =
1151 std::format("/redfish/v1/Systems/{}/LogServices",
1152 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1153 asyncResp->res.jsonValue["Name"] = "System Log Services Collection";
1154 asyncResp->res.jsonValue["Description"] =
1155 "Collection of LogServices for this Computer System";
1156 nlohmann::json& logServiceArray =
1157 asyncResp->res.jsonValue["Members"];
1158 logServiceArray = nlohmann::json::array();
1159 nlohmann::json::object_t eventLog;
1160 eventLog["@odata.id"] =
1161 std::format("/redfish/v1/Systems/{}/LogServices/EventLog",
1162 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1163 logServiceArray.emplace_back(std::move(eventLog));
1164 if constexpr (BMCWEB_REDFISH_DUMP_LOG)
Ed Tanous002d39b2022-05-31 08:59:27 -07001165 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001166 nlohmann::json::object_t dumpLog;
1167 dumpLog["@odata.id"] =
1168 std::format("/redfish/v1/Systems/{}/LogServices/Dump",
1169 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1170 logServiceArray.emplace_back(std::move(dumpLog));
Ed Tanous002d39b2022-05-31 08:59:27 -07001171 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001172
1173 if constexpr (BMCWEB_REDFISH_CPU_LOG)
1174 {
1175 nlohmann::json::object_t crashdump;
1176 crashdump["@odata.id"] =
1177 std::format("/redfish/v1/Systems/{}/LogServices/Crashdump",
1178 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1179 logServiceArray.emplace_back(std::move(crashdump));
1180 }
1181
1182 if constexpr (BMCWEB_REDFISH_HOST_LOGGER)
1183 {
1184 nlohmann::json::object_t hostlogger;
1185 hostlogger["@odata.id"] =
1186 std::format("/redfish/v1/Systems/{}/LogServices/HostLogger",
1187 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1188 logServiceArray.emplace_back(std::move(hostlogger));
1189 }
1190 asyncResp->res.jsonValue["Members@odata.count"] =
1191 logServiceArray.size();
1192
1193 constexpr std::array<std::string_view, 1> interfaces = {
1194 "xyz.openbmc_project.State.Boot.PostCode"};
1195 dbus::utility::getSubTreePaths(
1196 "/", 0, interfaces,
1197 [asyncResp](const boost::system::error_code& ec,
1198 const dbus::utility::MapperGetSubTreePathsResponse&
1199 subtreePath) {
1200 if (ec)
1201 {
1202 BMCWEB_LOG_ERROR("{}", ec);
1203 return;
1204 }
1205
1206 for (const auto& pathStr : subtreePath)
1207 {
1208 if (pathStr.find("PostCode") != std::string::npos)
1209 {
1210 nlohmann::json& logServiceArrayLocal =
1211 asyncResp->res.jsonValue["Members"];
1212 nlohmann::json::object_t member;
1213 member["@odata.id"] = std::format(
1214 "/redfish/v1/Systems/{}/LogServices/PostCodes",
1215 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1216
1217 logServiceArrayLocal.emplace_back(
1218 std::move(member));
1219
1220 asyncResp->res.jsonValue["Members@odata.count"] =
1221 logServiceArrayLocal.size();
1222 return;
1223 }
1224 }
1225 });
Ed Tanous45ca1b82022-03-25 13:07:27 -07001226 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001227}
1228
1229inline void requestRoutesEventLogService(App& app)
1230{
Ed Tanous22d268c2022-05-19 09:39:07 -07001231 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/")
Ed Tanoused398212021-06-09 17:05:54 -07001232 .privileges(redfish::privileges::getLogService)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001233 .methods(
1234 boost::beast::http::verb::
1235 get)([&app](const crow::Request& req,
1236 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1237 const std::string& systemName) {
1238 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1239 {
1240 return;
1241 }
1242 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1243 {
1244 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1245 systemName);
1246 return;
1247 }
1248 asyncResp->res.jsonValue["@odata.id"] =
1249 std::format("/redfish/v1/Systems/{}/LogServices/EventLog",
1250 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1251 asyncResp->res.jsonValue["@odata.type"] =
1252 "#LogService.v1_2_0.LogService";
1253 asyncResp->res.jsonValue["Name"] = "Event Log Service";
1254 asyncResp->res.jsonValue["Description"] =
1255 "System Event Log Service";
1256 asyncResp->res.jsonValue["Id"] = "EventLog";
1257 asyncResp->res.jsonValue["OverWritePolicy"] =
1258 log_service::OverWritePolicy::WrapsWhenFull;
Tejas Patil7c8c4052021-06-04 17:43:14 +05301259
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001260 std::pair<std::string, std::string> redfishDateTimeOffset =
1261 redfish::time_utils::getDateTimeOffsetNow();
Tejas Patil7c8c4052021-06-04 17:43:14 +05301262
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001263 asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
1264 asyncResp->res.jsonValue["DateTimeLocalOffset"] =
1265 redfishDateTimeOffset.second;
Tejas Patil7c8c4052021-06-04 17:43:14 +05301266
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001267 asyncResp->res.jsonValue["Entries"]["@odata.id"] = std::format(
1268 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
Ed Tanous20fa6a22024-05-20 18:02:58 -07001269 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001270 asyncResp->res
1271 .jsonValue["Actions"]["#LogService.ClearLog"]["target"]
1272
1273 = std::format(
1274 "/redfish/v1/Systems/{}/LogServices/EventLog/Actions/LogService.ClearLog",
1275 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1276 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001277}
1278
Alexander Hansen599b9af2024-08-06 15:11:57 +02001279inline void handleSystemsLogServicesEventLogActionsClearPost(
1280 App& app, const crow::Request& req,
1281 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1282 const std::string& systemName)
1283{
1284 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1285 {
1286 return;
1287 }
1288 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1289 {
1290 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1291 systemName);
1292 return;
1293 }
1294
1295 // Clear the EventLog by deleting the log files
1296 std::vector<std::filesystem::path> redfishLogFiles;
1297 if (getRedfishLogFiles(redfishLogFiles))
1298 {
1299 for (const std::filesystem::path& file : redfishLogFiles)
1300 {
1301 std::error_code ec;
1302 std::filesystem::remove(file, ec);
1303 }
1304 }
1305
1306 // Reload rsyslog so it knows to start new log files
1307 crow::connections::systemBus->async_method_call(
1308 [asyncResp](const boost::system::error_code& ec) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001309 if (ec)
1310 {
1311 BMCWEB_LOG_ERROR("Failed to reload rsyslog: {}", ec);
1312 messages::internalError(asyncResp->res);
1313 return;
1314 }
Alexander Hansen599b9af2024-08-06 15:11:57 +02001315
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001316 messages::success(asyncResp->res);
1317 },
Alexander Hansen599b9af2024-08-06 15:11:57 +02001318 "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
1319 "org.freedesktop.systemd1.Manager", "ReloadUnit", "rsyslog.service",
1320 "replace");
1321}
1322
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001323inline void requestRoutesJournalEventLogClear(App& app)
1324{
Jason M. Bills4978b632022-02-22 14:17:43 -08001325 BMCWEB_ROUTE(
1326 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07001327 "/redfish/v1/Systems/<str>/LogServices/EventLog/Actions/LogService.ClearLog/")
Ed Tanous432a8902021-06-14 15:28:56 -07001328 .privileges({{"ConfigureComponents"}})
Alexander Hansen599b9af2024-08-06 15:11:57 +02001329 .methods(boost::beast::http::verb::post)(std::bind_front(
1330 handleSystemsLogServicesEventLogActionsClearPost, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001331}
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001332
Jason M. Billsac992cd2022-06-24 13:31:46 -07001333enum class LogParseError
1334{
1335 success,
1336 parseFailed,
1337 messageIdNotInRegistry,
1338};
1339
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001340static LogParseError fillEventLogEntryJson(
1341 const std::string& logEntryID, const std::string& logEntry,
1342 nlohmann::json::object_t& logEntryJson)
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001343{
Jason M. Bills95820182019-04-22 16:25:34 -07001344 // The redfish log format is "<Timestamp> <MessageId>,<MessageArgs>"
Jason M. Billscd225da2019-05-08 15:31:57 -07001345 // First get the Timestamp
Ed Tanousf23b7292020-10-15 09:41:17 -07001346 size_t space = logEntry.find_first_of(' ');
Jason M. Billscd225da2019-05-08 15:31:57 -07001347 if (space == std::string::npos)
Jason M. Bills95820182019-04-22 16:25:34 -07001348 {
Jason M. Billsac992cd2022-06-24 13:31:46 -07001349 return LogParseError::parseFailed;
Jason M. Bills95820182019-04-22 16:25:34 -07001350 }
Jason M. Billscd225da2019-05-08 15:31:57 -07001351 std::string timestamp = logEntry.substr(0, space);
1352 // Then get the log contents
Ed Tanousf23b7292020-10-15 09:41:17 -07001353 size_t entryStart = logEntry.find_first_not_of(' ', space);
Jason M. Billscd225da2019-05-08 15:31:57 -07001354 if (entryStart == std::string::npos)
1355 {
Jason M. Billsac992cd2022-06-24 13:31:46 -07001356 return LogParseError::parseFailed;
Jason M. Billscd225da2019-05-08 15:31:57 -07001357 }
1358 std::string_view entry(logEntry);
1359 entry.remove_prefix(entryStart);
1360 // Use split to separate the entry into its fields
1361 std::vector<std::string> logEntryFields;
Ed Tanous50ebd4a2023-01-19 19:03:17 -08001362 bmcweb::split(logEntryFields, entry, ',');
Jason M. Billscd225da2019-05-08 15:31:57 -07001363 // We need at least a MessageId to be valid
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001364 auto logEntryIter = logEntryFields.begin();
1365 if (logEntryIter == logEntryFields.end())
Jason M. Billscd225da2019-05-08 15:31:57 -07001366 {
Jason M. Billsac992cd2022-06-24 13:31:46 -07001367 return LogParseError::parseFailed;
Jason M. Billscd225da2019-05-08 15:31:57 -07001368 }
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001369 std::string& messageID = *logEntryIter;
Jason M. Bills4851d452019-03-28 11:27:48 -07001370 // Get the Message from the MessageRegistry
Ed Tanousfffb8c12022-02-07 23:53:03 -08001371 const registries::Message* message = registries::getMessage(messageID);
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001372
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001373 logEntryIter++;
Sui Chen54417b02022-03-24 14:59:52 -07001374 if (message == nullptr)
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001375 {
Ed Tanous62598e32023-07-17 17:06:25 -07001376 BMCWEB_LOG_WARNING("Log entry not found in registry: {}", logEntry);
Jason M. Billsac992cd2022-06-24 13:31:46 -07001377 return LogParseError::messageIdNotInRegistry;
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001378 }
1379
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001380 std::vector<std::string_view> messageArgs(logEntryIter,
1381 logEntryFields.end());
Ed Tanousc05bba42023-06-28 08:33:29 -07001382 messageArgs.resize(message->numberOfArgs);
1383
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001384 std::string msg =
1385 redfish::registries::fillMessageArgs(messageArgs, message->message);
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001386 if (msg.empty())
Jason M. Bills4851d452019-03-28 11:27:48 -07001387 {
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001388 return LogParseError::parseFailed;
Jason M. Bills4851d452019-03-28 11:27:48 -07001389 }
1390
Jason M. Bills95820182019-04-22 16:25:34 -07001391 // Get the Created time from the timestamp. The log timestamp is in RFC3339
1392 // format which matches the Redfish format except for the fractional seconds
1393 // between the '.' and the '+', so just remove them.
Ed Tanousf23b7292020-10-15 09:41:17 -07001394 std::size_t dot = timestamp.find_first_of('.');
1395 std::size_t plus = timestamp.find_first_of('+');
Jason M. Bills95820182019-04-22 16:25:34 -07001396 if (dot != std::string::npos && plus != std::string::npos)
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001397 {
Jason M. Bills95820182019-04-22 16:25:34 -07001398 timestamp.erase(dot, plus - dot);
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001399 }
1400
1401 // Fill in the log entry with the gathered data
Vijay Lobo9c11a172021-10-07 16:53:16 -05001402 logEntryJson["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
Ed Tanousef4c65b2023-04-24 15:28:50 -07001403 logEntryJson["@odata.id"] = boost::urls::format(
Ed Tanous253f11b2024-05-16 09:38:31 -07001404 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}",
1405 BMCWEB_REDFISH_SYSTEM_URI_NAME, logEntryID);
Jason M. Bills84afc482022-06-24 12:38:23 -07001406 logEntryJson["Name"] = "System Event Log Entry";
1407 logEntryJson["Id"] = logEntryID;
1408 logEntryJson["Message"] = std::move(msg);
1409 logEntryJson["MessageId"] = std::move(messageID);
1410 logEntryJson["MessageArgs"] = messageArgs;
1411 logEntryJson["EntryType"] = "Event";
1412 logEntryJson["Severity"] = message->messageSeverity;
1413 logEntryJson["Created"] = std::move(timestamp);
Jason M. Billsac992cd2022-06-24 13:31:46 -07001414 return LogParseError::success;
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001415}
1416
Ed Tanous898f2aa2024-08-07 12:18:22 -07001417inline void fillEventLogLogEntryFromPropertyMap(
1418 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1419 const dbus::utility::DBusPropertiesMap& resp,
1420 nlohmann::json& objectToFillOut)
1421{
Alexander Hansen262dcc12024-09-19 12:04:03 +02001422 std::optional<DbusEventLogEntry> optEntry =
1423 fillDbusEventLogEntryFromPropertyMap(resp);
Ed Tanous898f2aa2024-08-07 12:18:22 -07001424
Alexander Hansen262dcc12024-09-19 12:04:03 +02001425 if (!optEntry.has_value())
Ed Tanous898f2aa2024-08-07 12:18:22 -07001426 {
1427 messages::internalError(asyncResp->res);
1428 return;
1429 }
Alexander Hansen262dcc12024-09-19 12:04:03 +02001430 DbusEventLogEntry entry = optEntry.value();
Ed Tanous898f2aa2024-08-07 12:18:22 -07001431
1432 objectToFillOut["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
1433 objectToFillOut["@odata.id"] = boost::urls::format(
1434 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}",
Alexander Hansen262dcc12024-09-19 12:04:03 +02001435 BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(entry.Id));
Ed Tanous898f2aa2024-08-07 12:18:22 -07001436 objectToFillOut["Name"] = "System Event Log Entry";
Alexander Hansen262dcc12024-09-19 12:04:03 +02001437 objectToFillOut["Id"] = std::to_string(entry.Id);
1438 objectToFillOut["Message"] = entry.Message;
1439 objectToFillOut["Resolved"] = entry.Resolved;
1440 std::optional<bool> notifyAction =
1441 getProviderNotifyAction(entry.ServiceProviderNotify);
Ed Tanous898f2aa2024-08-07 12:18:22 -07001442 if (notifyAction)
1443 {
1444 objectToFillOut["ServiceProviderNotified"] = *notifyAction;
1445 }
Alexander Hansen262dcc12024-09-19 12:04:03 +02001446 if ((entry.Resolution != nullptr) && !entry.Resolution->empty())
Ed Tanous898f2aa2024-08-07 12:18:22 -07001447 {
Alexander Hansen262dcc12024-09-19 12:04:03 +02001448 objectToFillOut["Resolution"] = *entry.Resolution;
Ed Tanous898f2aa2024-08-07 12:18:22 -07001449 }
1450 objectToFillOut["EntryType"] = "Event";
Alexander Hansen262dcc12024-09-19 12:04:03 +02001451 objectToFillOut["Severity"] =
1452 translateSeverityDbusToRedfish(entry.Severity);
Ed Tanous898f2aa2024-08-07 12:18:22 -07001453 objectToFillOut["Created"] =
Alexander Hansen262dcc12024-09-19 12:04:03 +02001454 redfish::time_utils::getDateTimeUintMs(entry.Timestamp);
Ed Tanous898f2aa2024-08-07 12:18:22 -07001455 objectToFillOut["Modified"] =
Alexander Hansen262dcc12024-09-19 12:04:03 +02001456 redfish::time_utils::getDateTimeUintMs(entry.UpdateTimestamp);
1457 if (entry.Path != nullptr)
Ed Tanous898f2aa2024-08-07 12:18:22 -07001458 {
1459 objectToFillOut["AdditionalDataURI"] = boost::urls::format(
1460 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}/attachment",
Alexander Hansen262dcc12024-09-19 12:04:03 +02001461 BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(entry.Id));
Ed Tanous898f2aa2024-08-07 12:18:22 -07001462 }
1463}
1464
Ed Tanousb7290962024-08-07 11:09:51 -07001465inline void afterLogEntriesGetManagedObjects(
1466 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1467 const boost::system::error_code& ec,
1468 const dbus::utility::ManagedObjectType& resp)
1469{
1470 if (ec)
1471 {
1472 // TODO Handle for specific error code
1473 BMCWEB_LOG_ERROR("getLogEntriesIfaceData resp_handler got error {}",
1474 ec);
1475 messages::internalError(asyncResp->res);
1476 return;
1477 }
1478 nlohmann::json::array_t entriesArray;
1479 for (const auto& objectPath : resp)
1480 {
Ed Tanous898f2aa2024-08-07 12:18:22 -07001481 dbus::utility::DBusPropertiesMap propsFlattened;
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001482 auto isEntry =
1483 std::ranges::find_if(objectPath.second, [](const auto& object) {
1484 return object.first == "xyz.openbmc_project.Logging.Entry";
1485 });
Ed Tanous898f2aa2024-08-07 12:18:22 -07001486 if (isEntry == objectPath.second.end())
Ed Tanousb7290962024-08-07 11:09:51 -07001487 {
1488 continue;
1489 }
Ed Tanous898f2aa2024-08-07 12:18:22 -07001490 for (const auto& interfaceMap : objectPath.second)
Ed Tanousb7290962024-08-07 11:09:51 -07001491 {
Ed Tanous898f2aa2024-08-07 12:18:22 -07001492 for (const auto& propertyMap : interfaceMap.second)
Ed Tanousb7290962024-08-07 11:09:51 -07001493 {
Ed Tanous898f2aa2024-08-07 12:18:22 -07001494 propsFlattened.emplace_back(propertyMap.first,
1495 propertyMap.second);
Ed Tanousb7290962024-08-07 11:09:51 -07001496 }
1497 }
Ed Tanous898f2aa2024-08-07 12:18:22 -07001498 fillEventLogLogEntryFromPropertyMap(asyncResp, propsFlattened,
1499 entriesArray.emplace_back());
Ed Tanousb7290962024-08-07 11:09:51 -07001500 }
Ed Tanous898f2aa2024-08-07 12:18:22 -07001501
Ed Tanousb7290962024-08-07 11:09:51 -07001502 std::ranges::sort(entriesArray, [](const nlohmann::json& left,
1503 const nlohmann::json& right) {
1504 return (left["Id"] <= right["Id"]);
1505 });
1506 asyncResp->res.jsonValue["Members@odata.count"] = entriesArray.size();
1507 asyncResp->res.jsonValue["Members"] = std::move(entriesArray);
1508}
1509
Alexander Hansen599b9af2024-08-06 15:11:57 +02001510inline void handleSystemsLogServiceEventLogLogEntryCollection(
1511 App& app, const crow::Request& req,
1512 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1513 const std::string& systemName)
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001514{
Alexander Hansen599b9af2024-08-06 15:11:57 +02001515 query_param::QueryCapabilities capabilities = {
1516 .canDelegateTop = true,
1517 .canDelegateSkip = true,
1518 };
1519 query_param::Query delegatedQuery;
1520 if (!redfish::setUpRedfishRouteWithDelegation(app, req, asyncResp,
1521 delegatedQuery, capabilities))
1522 {
1523 return;
1524 }
1525 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1526 {
1527 // Option currently returns no systems. TBD
1528 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1529 systemName);
1530 return;
1531 }
1532 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1533 {
1534 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1535 systemName);
1536 return;
1537 }
1538
1539 size_t top = delegatedQuery.top.value_or(query_param::Query::maxTop);
1540 size_t skip = delegatedQuery.skip.value_or(0);
1541
1542 // Collections don't include the static data added by SubRoute
1543 // because it has a duplicate entry for members
1544 asyncResp->res.jsonValue["@odata.type"] =
1545 "#LogEntryCollection.LogEntryCollection";
1546 asyncResp->res.jsonValue["@odata.id"] =
1547 std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
1548 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1549 asyncResp->res.jsonValue["Name"] = "System Event Log Entries";
1550 asyncResp->res.jsonValue["Description"] =
1551 "Collection of System Event Log Entries";
1552
1553 nlohmann::json& logEntryArray = asyncResp->res.jsonValue["Members"];
1554 logEntryArray = nlohmann::json::array();
1555 // Go through the log files and create a unique ID for each
1556 // entry
1557 std::vector<std::filesystem::path> redfishLogFiles;
1558 getRedfishLogFiles(redfishLogFiles);
1559 uint64_t entryCount = 0;
1560 std::string logEntry;
1561
1562 // Oldest logs are in the last file, so start there and loop
1563 // backwards
1564 for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend(); it++)
1565 {
1566 std::ifstream logStream(*it);
1567 if (!logStream.is_open())
Ed Tanous002d39b2022-05-31 08:59:27 -07001568 {
Alexander Hansen599b9af2024-08-06 15:11:57 +02001569 continue;
Ed Tanous22d268c2022-05-19 09:39:07 -07001570 }
1571
Alexander Hansen599b9af2024-08-06 15:11:57 +02001572 // Reset the unique ID on the first entry
1573 bool firstEntry = true;
1574 while (std::getline(logStream, logEntry))
Ed Tanous002d39b2022-05-31 08:59:27 -07001575 {
Alexander Hansen599b9af2024-08-06 15:11:57 +02001576 std::string idStr;
1577 if (!getUniqueEntryID(logEntry, idStr, firstEntry))
1578 {
1579 continue;
1580 }
1581 firstEntry = false;
1582
1583 nlohmann::json::object_t bmcLogEntry;
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001584 LogParseError status =
1585 fillEventLogEntryJson(idStr, logEntry, bmcLogEntry);
Alexander Hansen599b9af2024-08-06 15:11:57 +02001586 if (status == LogParseError::messageIdNotInRegistry)
1587 {
1588 continue;
1589 }
1590 if (status != LogParseError::success)
1591 {
1592 messages::internalError(asyncResp->res);
1593 return;
1594 }
1595
1596 entryCount++;
1597 // Handle paging using skip (number of entries to skip from the
1598 // start) and top (number of entries to display)
1599 if (entryCount <= skip || entryCount > skip + top)
Jason M. Bills4978b632022-02-22 14:17:43 -08001600 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001601 continue;
Jason M. Bills4978b632022-02-22 14:17:43 -08001602 }
Jason M. Bills897967d2019-07-29 17:05:30 -07001603
Alexander Hansen599b9af2024-08-06 15:11:57 +02001604 logEntryArray.emplace_back(std::move(bmcLogEntry));
1605 }
1606 }
1607 asyncResp->res.jsonValue["Members@odata.count"] = entryCount;
1608 if (skip + top < entryCount)
1609 {
1610 asyncResp->res.jsonValue["Members@odata.nextLink"] =
1611 boost::urls::format(
1612 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries?$skip={}",
1613 BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(skip + top));
1614 }
1615}
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001616
Alexander Hansen599b9af2024-08-06 15:11:57 +02001617inline void requestRoutesJournalEventLogEntryCollection(App& app)
1618{
1619 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/")
1620 .privileges(redfish::privileges::getLogEntryCollection)
1621 .methods(boost::beast::http::verb::get)(std::bind_front(
1622 handleSystemsLogServiceEventLogLogEntryCollection, std::ref(app)));
1623}
1624
1625inline void handleSystemsLogServiceEventLogEntriesGet(
1626 App& app, const crow::Request& req,
1627 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1628 const std::string& systemName, const std::string& param)
1629{
1630 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1631 {
1632 return;
1633 }
1634 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1635 {
1636 // Option currently returns no systems. TBD
1637 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1638 systemName);
1639 return;
1640 }
1641
1642 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1643 {
1644 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1645 systemName);
1646 return;
1647 }
1648
1649 const std::string& targetID = param;
1650
1651 // Go through the log files and check the unique ID for each
1652 // entry to find the target entry
1653 std::vector<std::filesystem::path> redfishLogFiles;
1654 getRedfishLogFiles(redfishLogFiles);
1655 std::string logEntry;
1656
1657 // Oldest logs are in the last file, so start there and loop
1658 // backwards
1659 for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend(); it++)
1660 {
1661 std::ifstream logStream(*it);
1662 if (!logStream.is_open())
1663 {
1664 continue;
1665 }
1666
1667 // Reset the unique ID on the first entry
1668 bool firstEntry = true;
1669 while (std::getline(logStream, logEntry))
1670 {
1671 std::string idStr;
1672 if (!getUniqueEntryID(logEntry, idStr, firstEntry))
1673 {
1674 continue;
1675 }
1676 firstEntry = false;
1677
1678 if (idStr == targetID)
1679 {
Jason M. Billsde703c52022-06-23 14:19:04 -07001680 nlohmann::json::object_t bmcLogEntry;
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001681 LogParseError status =
1682 fillEventLogEntryJson(idStr, logEntry, bmcLogEntry);
Jason M. Billsac992cd2022-06-24 13:31:46 -07001683 if (status != LogParseError::success)
Ed Tanous002d39b2022-05-31 08:59:27 -07001684 {
1685 messages::internalError(asyncResp->res);
1686 return;
Andrew Geisslercb92c032018-08-17 07:56:14 -07001687 }
Alexander Hansen599b9af2024-08-06 15:11:57 +02001688 asyncResp->res.jsonValue.update(bmcLogEntry);
1689 return;
Jason M. Bills4978b632022-02-22 14:17:43 -08001690 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001691 }
Alexander Hansen599b9af2024-08-06 15:11:57 +02001692 }
1693 // Requested ID was not found
1694 messages::resourceNotFound(asyncResp->res, "LogEntry", targetID);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001695}
Chicago Duan336e96c2019-07-15 14:22:08 +08001696
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001697inline void requestRoutesJournalEventLogEntry(App& app)
1698{
1699 BMCWEB_ROUTE(
Ed Tanous22d268c2022-05-19 09:39:07 -07001700 app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001701 .privileges(redfish::privileges::getLogEntry)
Alexander Hansen599b9af2024-08-06 15:11:57 +02001702 .methods(boost::beast::http::verb::get)(std::bind_front(
1703 handleSystemsLogServiceEventLogEntriesGet, std::ref(app)));
1704}
1705
1706inline void dBusEventLogEntryCollection(
1707 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1708{
1709 // Collections don't include the static data added by SubRoute
1710 // because it has a duplicate entry for members
1711 asyncResp->res.jsonValue["@odata.type"] =
1712 "#LogEntryCollection.LogEntryCollection";
1713 asyncResp->res.jsonValue["@odata.id"] =
1714 std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
1715 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1716 asyncResp->res.jsonValue["Name"] = "System Event Log Entries";
1717 asyncResp->res.jsonValue["Description"] =
1718 "Collection of System Event Log Entries";
1719
1720 // DBus implementation of EventLog/Entries
1721 // Make call to Logging Service to find all log entry objects
1722 sdbusplus::message::object_path path("/xyz/openbmc_project/logging");
1723 dbus::utility::getManagedObjects(
1724 "xyz.openbmc_project.Logging", path,
1725 [asyncResp](const boost::system::error_code& ec,
1726 const dbus::utility::ManagedObjectType& resp) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001727 afterLogEntriesGetManagedObjects(asyncResp, ec, resp);
1728 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001729}
1730
1731inline void requestRoutesDBusEventLogEntryCollection(App& app)
1732{
Ed Tanous22d268c2022-05-19 09:39:07 -07001733 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/")
Ed Tanoused398212021-06-09 17:05:54 -07001734 .privileges(redfish::privileges::getLogEntryCollection)
Ed Tanous002d39b2022-05-31 08:59:27 -07001735 .methods(boost::beast::http::verb::get)(
1736 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07001737 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1738 const std::string& systemName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001739 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1740 {
1741 return;
1742 }
1743 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1744 {
1745 // Option currently returns no systems. TBD
1746 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1747 systemName);
1748 return;
1749 }
1750 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1751 {
1752 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1753 systemName);
1754 return;
1755 }
1756 dBusEventLogEntryCollection(asyncResp);
1757 });
Alexander Hansen599b9af2024-08-06 15:11:57 +02001758}
Ed Tanous22d268c2022-05-19 09:39:07 -07001759
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001760inline void dBusEventLogEntryGet(
1761 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID)
Alexander Hansen599b9af2024-08-06 15:11:57 +02001762{
1763 dbus::utility::escapePathForDbus(entryID);
Ed Tanous002d39b2022-05-31 08:59:27 -07001764
Alexander Hansen599b9af2024-08-06 15:11:57 +02001765 // DBus implementation of EventLog/Entries
1766 // Make call to Logging Service to find all log entry objects
1767 sdbusplus::asio::getAllProperties(
1768 *crow::connections::systemBus, "xyz.openbmc_project.Logging",
1769 "/xyz/openbmc_project/logging/entry/" + entryID, "",
1770 [asyncResp, entryID](const boost::system::error_code& ec,
1771 const dbus::utility::DBusPropertiesMap& resp) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001772 if (ec.value() == EBADR)
1773 {
1774 messages::resourceNotFound(asyncResp->res, "EventLogEntry",
1775 entryID);
1776 return;
1777 }
1778 if (ec)
1779 {
1780 BMCWEB_LOG_ERROR(
1781 "EventLogEntry (DBus) resp_handler got error {}", ec);
1782 messages::internalError(asyncResp->res);
1783 return;
1784 }
Alexander Hansen599b9af2024-08-06 15:11:57 +02001785
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001786 fillEventLogLogEntryFromPropertyMap(asyncResp, resp,
1787 asyncResp->res.jsonValue);
1788 });
Alexander Hansen599b9af2024-08-06 15:11:57 +02001789}
1790
1791inline void
1792 dBusEventLogEntryPatch(const crow::Request& req,
1793 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1794 const std::string& entryId)
1795{
1796 std::optional<bool> resolved;
1797
1798 if (!json_util::readJsonPatch(req, asyncResp->res, "Resolved", resolved))
1799 {
1800 return;
1801 }
1802 BMCWEB_LOG_DEBUG("Set Resolved");
1803
1804 setDbusProperty(asyncResp, "Resolved", "xyz.openbmc_project.Logging",
1805 "/xyz/openbmc_project/logging/entry/" + entryId,
1806 "xyz.openbmc_project.Logging.Entry", "Resolved",
1807 resolved.value_or(false));
1808}
1809
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001810inline void dBusEventLogEntryDelete(
1811 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID)
Alexander Hansen599b9af2024-08-06 15:11:57 +02001812{
1813 BMCWEB_LOG_DEBUG("Do delete single event entries.");
1814
1815 dbus::utility::escapePathForDbus(entryID);
1816
1817 // Process response from Logging service.
1818 auto respHandler = [asyncResp,
1819 entryID](const boost::system::error_code& ec) {
1820 BMCWEB_LOG_DEBUG("EventLogEntry (DBus) doDelete callback: Done");
1821 if (ec)
1822 {
1823 if (ec.value() == EBADR)
Ed Tanous45ca1b82022-03-25 13:07:27 -07001824 {
Alexander Hansen599b9af2024-08-06 15:11:57 +02001825 messages::resourceNotFound(asyncResp->res, "LogEntry", entryID);
Ed Tanous45ca1b82022-03-25 13:07:27 -07001826 return;
1827 }
Alexander Hansen599b9af2024-08-06 15:11:57 +02001828 // TODO Handle for specific error code
1829 BMCWEB_LOG_ERROR(
1830 "EventLogEntry (DBus) doDelete respHandler got error {}", ec);
1831 asyncResp->res.result(
1832 boost::beast::http::status::internal_server_error);
1833 return;
1834 }
Abhishek Patel9017faf2021-09-14 22:48:55 -05001835
Alexander Hansen599b9af2024-08-06 15:11:57 +02001836 asyncResp->res.result(boost::beast::http::status::ok);
1837 };
1838
1839 // Make call to Logging service to request Delete Log
1840 crow::connections::systemBus->async_method_call(
1841 respHandler, "xyz.openbmc_project.Logging",
1842 "/xyz/openbmc_project/logging/entry/" + entryID,
1843 "xyz.openbmc_project.Object.Delete", "Delete");
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001844}
Xiaochao Ma75710de2021-01-21 17:56:02 +08001845
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001846inline void requestRoutesDBusEventLogEntry(App& app)
Adriana Kobylak400fd1f2021-01-29 09:01:30 -06001847{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001848 BMCWEB_ROUTE(
Ed Tanous22d268c2022-05-19 09:39:07 -07001849 app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001850 .privileges(redfish::privileges::getLogEntry)
Ed Tanous002d39b2022-05-31 08:59:27 -07001851 .methods(boost::beast::http::verb::get)(
1852 [&app](const crow::Request& req,
1853 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous898f2aa2024-08-07 12:18:22 -07001854 const std::string& systemName, const std::string& entryId) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001855 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1856 {
1857 return;
1858 }
1859 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1860 {
1861 // Option currently returns no systems. TBD
1862 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1863 systemName);
1864 return;
1865 }
1866 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1867 {
1868 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1869 systemName);
1870 return;
1871 }
Ed Tanous22d268c2022-05-19 09:39:07 -07001872
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001873 dBusEventLogEntryGet(asyncResp, entryId);
1874 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001875
1876 BMCWEB_ROUTE(
Ed Tanous22d268c2022-05-19 09:39:07 -07001877 app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001878 .privileges(redfish::privileges::patchLogEntry)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001879 .methods(boost::beast::http::verb::patch)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07001880 [&app](const crow::Request& req,
1881 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -07001882 const std::string& systemName, const std::string& entryId) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001883 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1884 {
1885 return;
1886 }
1887 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1888 {
1889 // Option currently returns no systems. TBD
1890 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1891 systemName);
1892 return;
1893 }
1894 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1895 {
1896 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1897 systemName);
1898 return;
1899 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001900
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001901 dBusEventLogEntryPatch(req, asyncResp, entryId);
1902 });
Adriana Kobylak400fd1f2021-01-29 09:01:30 -06001903
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001904 BMCWEB_ROUTE(
Ed Tanous22d268c2022-05-19 09:39:07 -07001905 app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001906 .privileges(redfish::privileges::deleteLogEntry)
1907
Ed Tanous002d39b2022-05-31 08:59:27 -07001908 .methods(boost::beast::http::verb::delete_)(
1909 [&app](const crow::Request& req,
1910 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -07001911 const std::string& systemName, const std::string& param) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001912 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1913 {
1914 return;
1915 }
1916 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1917 {
1918 // Option currently returns no systems. TBD
1919 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1920 systemName);
1921 return;
1922 }
1923 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1924 {
1925 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1926 systemName);
1927 return;
1928 }
1929 dBusEventLogEntryDelete(asyncResp, param);
1930 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001931}
1932
Spencer Kub7028eb2021-10-26 15:27:35 +08001933constexpr const char* hostLoggerFolderPath = "/var/log/console";
1934
1935inline bool
1936 getHostLoggerFiles(const std::string& hostLoggerFilePath,
1937 std::vector<std::filesystem::path>& hostLoggerFiles)
1938{
1939 std::error_code ec;
1940 std::filesystem::directory_iterator logPath(hostLoggerFilePath, ec);
1941 if (ec)
1942 {
Carson Labradobf2dded2023-08-10 00:37:06 +00001943 BMCWEB_LOG_WARNING("{}", ec.message());
Spencer Kub7028eb2021-10-26 15:27:35 +08001944 return false;
1945 }
1946 for (const std::filesystem::directory_entry& it : logPath)
1947 {
1948 std::string filename = it.path().filename();
1949 // Prefix of each log files is "log". Find the file and save the
1950 // path
Ed Tanous11ba3972022-07-11 09:50:41 -07001951 if (filename.starts_with("log"))
Spencer Kub7028eb2021-10-26 15:27:35 +08001952 {
1953 hostLoggerFiles.emplace_back(it.path());
1954 }
1955 }
1956 // As the log files rotate, they are appended with a ".#" that is higher for
1957 // the older logs. Since we start from oldest logs, sort the name in
1958 // descending order.
1959 std::sort(hostLoggerFiles.rbegin(), hostLoggerFiles.rend(),
1960 AlphanumLess<std::string>());
1961
1962 return true;
1963}
1964
Ed Tanous02cad962022-06-30 16:50:15 -07001965inline bool getHostLoggerEntries(
1966 const std::vector<std::filesystem::path>& hostLoggerFiles, uint64_t skip,
1967 uint64_t top, std::vector<std::string>& logEntries, size_t& logCount)
Spencer Kub7028eb2021-10-26 15:27:35 +08001968{
1969 GzFileReader logFile;
1970
1971 // Go though all log files and expose host logs.
1972 for (const std::filesystem::path& it : hostLoggerFiles)
1973 {
1974 if (!logFile.gzGetLines(it.string(), skip, top, logEntries, logCount))
1975 {
Ed Tanous62598e32023-07-17 17:06:25 -07001976 BMCWEB_LOG_ERROR("fail to expose host logs");
Spencer Kub7028eb2021-10-26 15:27:35 +08001977 return false;
1978 }
1979 }
1980 // Get lastMessage from constructor by getter
1981 std::string lastMessage = logFile.getLastMessage();
1982 if (!lastMessage.empty())
1983 {
1984 logCount++;
1985 if (logCount > skip && logCount <= (skip + top))
1986 {
1987 logEntries.push_back(lastMessage);
1988 }
1989 }
1990 return true;
1991}
1992
Claire Weinandd72e872022-08-15 14:20:06 -07001993inline void handleBMCLogServicesCollectionGet(
Claire Weinanfdd26902022-03-01 14:18:25 -08001994 crow::App& app, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07001995 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1996 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08001997{
1998 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1999 {
2000 return;
2001 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002002
2003 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2004 {
2005 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2006 return;
2007 }
2008
Claire Weinanfdd26902022-03-01 14:18:25 -08002009 // Collections don't include the static data added by SubRoute
2010 // because it has a duplicate entry for members
2011 asyncResp->res.jsonValue["@odata.type"] =
2012 "#LogServiceCollection.LogServiceCollection";
Ed Tanous253f11b2024-05-16 09:38:31 -07002013 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
2014 "/redfish/v1/Managers/{}/LogServices", BMCWEB_REDFISH_MANAGER_URI_NAME);
Claire Weinanfdd26902022-03-01 14:18:25 -08002015 asyncResp->res.jsonValue["Name"] = "Open BMC Log Services Collection";
2016 asyncResp->res.jsonValue["Description"] =
2017 "Collection of LogServices for this Manager";
2018 nlohmann::json& logServiceArray = asyncResp->res.jsonValue["Members"];
2019 logServiceArray = nlohmann::json::array();
2020
Ed Tanous25b54db2024-04-17 15:40:31 -07002021 if constexpr (BMCWEB_REDFISH_BMC_JOURNAL)
2022 {
2023 nlohmann::json::object_t journal;
Ed Tanous253f11b2024-05-16 09:38:31 -07002024 journal["@odata.id"] =
2025 boost::urls::format("/redfish/v1/Managers/{}/LogServices/Journal",
2026 BMCWEB_REDFISH_MANAGER_URI_NAME);
Ed Tanous25b54db2024-04-17 15:40:31 -07002027 logServiceArray.emplace_back(std::move(journal));
2028 }
Claire Weinanfdd26902022-03-01 14:18:25 -08002029
2030 asyncResp->res.jsonValue["Members@odata.count"] = logServiceArray.size();
2031
Ed Tanous25b54db2024-04-17 15:40:31 -07002032 if constexpr (BMCWEB_REDFISH_DUMP_LOG)
2033 {
2034 constexpr std::array<std::string_view, 1> interfaces = {
2035 "xyz.openbmc_project.Collection.DeleteAll"};
2036 dbus::utility::getSubTreePaths(
2037 "/xyz/openbmc_project/dump", 0, interfaces,
2038 [asyncResp](const boost::system::error_code& ec,
2039 const dbus::utility::MapperGetSubTreePathsResponse&
2040 subTreePaths) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002041 if (ec)
Ed Tanous25b54db2024-04-17 15:40:31 -07002042 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002043 BMCWEB_LOG_ERROR(
2044 "handleBMCLogServicesCollectionGet respHandler got error {}",
2045 ec);
2046 // Assume that getting an error simply means there are no
2047 // dump LogServices. Return without adding any error
2048 // response.
2049 return;
Ed Tanous25b54db2024-04-17 15:40:31 -07002050 }
Ed Tanous25b54db2024-04-17 15:40:31 -07002051
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002052 nlohmann::json& logServiceArrayLocal =
2053 asyncResp->res.jsonValue["Members"];
2054
2055 for (const std::string& path : subTreePaths)
2056 {
2057 if (path == "/xyz/openbmc_project/dump/bmc")
2058 {
2059 nlohmann::json::object_t member;
2060 member["@odata.id"] = boost::urls::format(
2061 "/redfish/v1/Managers/{}/LogServices/Dump",
2062 BMCWEB_REDFISH_MANAGER_URI_NAME);
2063 logServiceArrayLocal.emplace_back(std::move(member));
2064 }
2065 else if (path == "/xyz/openbmc_project/dump/faultlog")
2066 {
2067 nlohmann::json::object_t member;
2068 member["@odata.id"] = boost::urls::format(
2069 "/redfish/v1/Managers/{}/LogServices/FaultLog",
2070 BMCWEB_REDFISH_MANAGER_URI_NAME);
2071 logServiceArrayLocal.emplace_back(std::move(member));
2072 }
2073 }
2074
2075 asyncResp->res.jsonValue["Members@odata.count"] =
2076 logServiceArrayLocal.size();
2077 });
Ed Tanous25b54db2024-04-17 15:40:31 -07002078 }
Claire Weinanfdd26902022-03-01 14:18:25 -08002079}
2080
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002081inline void requestRoutesBMCLogServiceCollection(App& app)
2082{
Ed Tanous253f11b2024-05-16 09:38:31 -07002083 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/")
Gunnar Millsad89dcf2021-07-30 14:40:11 -05002084 .privileges(redfish::privileges::getLogServiceCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002085 .methods(boost::beast::http::verb::get)(
Claire Weinandd72e872022-08-15 14:20:06 -07002086 std::bind_front(handleBMCLogServicesCollectionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002087}
Ed Tanous1da66f72018-07-27 16:13:37 -07002088
Claire Weinanfdd26902022-03-01 14:18:25 -08002089inline void
2090 getDumpServiceInfo(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2091 const std::string& dumpType)
2092{
2093 std::string dumpPath;
Ed Tanous539d8c62024-06-19 14:38:27 -07002094 log_service::OverWritePolicy overWritePolicy =
2095 log_service::OverWritePolicy::Invalid;
Claire Weinanfdd26902022-03-01 14:18:25 -08002096 bool collectDiagnosticDataSupported = false;
2097
2098 if (dumpType == "BMC")
2099 {
Ed Tanous253f11b2024-05-16 09:38:31 -07002100 dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/Dump",
2101 BMCWEB_REDFISH_MANAGER_URI_NAME);
Ed Tanous539d8c62024-06-19 14:38:27 -07002102 overWritePolicy = log_service::OverWritePolicy::WrapsWhenFull;
Claire Weinanfdd26902022-03-01 14:18:25 -08002103 collectDiagnosticDataSupported = true;
2104 }
2105 else if (dumpType == "FaultLog")
2106 {
Ed Tanous253f11b2024-05-16 09:38:31 -07002107 dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/FaultLog",
2108 BMCWEB_REDFISH_MANAGER_URI_NAME);
Ed Tanous539d8c62024-06-19 14:38:27 -07002109 overWritePolicy = log_service::OverWritePolicy::Unknown;
Claire Weinanfdd26902022-03-01 14:18:25 -08002110 collectDiagnosticDataSupported = false;
2111 }
2112 else if (dumpType == "System")
2113 {
Ed Tanous253f11b2024-05-16 09:38:31 -07002114 dumpPath = std::format("/redfish/v1/Systems/{}/LogServices/Dump",
2115 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanous539d8c62024-06-19 14:38:27 -07002116 overWritePolicy = log_service::OverWritePolicy::WrapsWhenFull;
Claire Weinanfdd26902022-03-01 14:18:25 -08002117 collectDiagnosticDataSupported = true;
2118 }
2119 else
2120 {
Ed Tanous62598e32023-07-17 17:06:25 -07002121 BMCWEB_LOG_ERROR("getDumpServiceInfo() invalid dump type: {}",
2122 dumpType);
Claire Weinanfdd26902022-03-01 14:18:25 -08002123 messages::internalError(asyncResp->res);
2124 return;
2125 }
2126
2127 asyncResp->res.jsonValue["@odata.id"] = dumpPath;
2128 asyncResp->res.jsonValue["@odata.type"] = "#LogService.v1_2_0.LogService";
2129 asyncResp->res.jsonValue["Name"] = "Dump LogService";
2130 asyncResp->res.jsonValue["Description"] = dumpType + " Dump LogService";
2131 asyncResp->res.jsonValue["Id"] = std::filesystem::path(dumpPath).filename();
Ed Tanous539d8c62024-06-19 14:38:27 -07002132 asyncResp->res.jsonValue["OverWritePolicy"] = overWritePolicy;
Claire Weinanfdd26902022-03-01 14:18:25 -08002133
2134 std::pair<std::string, std::string> redfishDateTimeOffset =
Ed Tanous2b829372022-08-03 14:22:34 -07002135 redfish::time_utils::getDateTimeOffsetNow();
Claire Weinanfdd26902022-03-01 14:18:25 -08002136 asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
2137 asyncResp->res.jsonValue["DateTimeLocalOffset"] =
2138 redfishDateTimeOffset.second;
2139
2140 asyncResp->res.jsonValue["Entries"]["@odata.id"] = dumpPath + "/Entries";
Claire Weinanfdd26902022-03-01 14:18:25 -08002141
2142 if (collectDiagnosticDataSupported)
2143 {
2144 asyncResp->res.jsonValue["Actions"]["#LogService.CollectDiagnosticData"]
2145 ["target"] =
2146 dumpPath + "/Actions/LogService.CollectDiagnosticData";
2147 }
Claire Weinan0d946212022-07-13 19:40:19 -07002148
2149 constexpr std::array<std::string_view, 1> interfaces = {deleteAllInterface};
2150 dbus::utility::getSubTreePaths(
2151 "/xyz/openbmc_project/dump", 0, interfaces,
2152 [asyncResp, dumpType, dumpPath](
2153 const boost::system::error_code& ec,
2154 const dbus::utility::MapperGetSubTreePathsResponse& subTreePaths) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002155 if (ec)
Claire Weinan0d946212022-07-13 19:40:19 -07002156 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002157 BMCWEB_LOG_ERROR("getDumpServiceInfo respHandler got error {}",
2158 ec);
2159 // Assume that getting an error simply means there are no dump
2160 // LogServices. Return without adding any error response.
2161 return;
Claire Weinan0d946212022-07-13 19:40:19 -07002162 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002163 std::string dbusDumpPath = getDumpPath(dumpType);
2164 for (const std::string& path : subTreePaths)
2165 {
2166 if (path == dbusDumpPath)
2167 {
2168 asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"]
2169 ["target"] =
2170 dumpPath + "/Actions/LogService.ClearLog";
2171 break;
2172 }
2173 }
2174 });
Claire Weinanfdd26902022-03-01 14:18:25 -08002175}
2176
2177inline void handleLogServicesDumpServiceGet(
2178 crow::App& app, const std::string& dumpType, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07002179 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2180 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002181{
2182 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2183 {
2184 return;
2185 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002186
2187 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2188 {
2189 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2190 return;
2191 }
2192
Claire Weinanfdd26902022-03-01 14:18:25 -08002193 getDumpServiceInfo(asyncResp, dumpType);
2194}
2195
Ed Tanous22d268c2022-05-19 09:39:07 -07002196inline void handleLogServicesDumpServiceComputerSystemGet(
2197 crow::App& app, const crow::Request& req,
2198 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2199 const std::string& chassisId)
2200{
2201 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2202 {
2203 return;
2204 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002205 if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous22d268c2022-05-19 09:39:07 -07002206 {
2207 messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
2208 return;
2209 }
2210 getDumpServiceInfo(asyncResp, "System");
2211}
2212
Claire Weinanfdd26902022-03-01 14:18:25 -08002213inline void handleLogServicesDumpEntriesCollectionGet(
2214 crow::App& app, const std::string& dumpType, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07002215 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2216 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002217{
2218 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2219 {
2220 return;
2221 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002222
2223 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2224 {
2225 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2226 return;
2227 }
Claire Weinanfdd26902022-03-01 14:18:25 -08002228 getDumpEntryCollection(asyncResp, dumpType);
2229}
2230
Ed Tanous22d268c2022-05-19 09:39:07 -07002231inline void handleLogServicesDumpEntriesCollectionComputerSystemGet(
2232 crow::App& app, const crow::Request& req,
2233 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2234 const std::string& chassisId)
2235{
2236 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2237 {
2238 return;
2239 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002240 if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous22d268c2022-05-19 09:39:07 -07002241 {
2242 messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
2243 return;
2244 }
2245 getDumpEntryCollection(asyncResp, "System");
2246}
2247
Claire Weinanfdd26902022-03-01 14:18:25 -08002248inline void handleLogServicesDumpEntryGet(
2249 crow::App& app, const std::string& dumpType, const crow::Request& req,
2250 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous253f11b2024-05-16 09:38:31 -07002251 const std::string& managerId, const std::string& dumpId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002252{
2253 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2254 {
2255 return;
2256 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002257 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2258 {
2259 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2260 return;
2261 }
Claire Weinanfdd26902022-03-01 14:18:25 -08002262 getDumpEntryById(asyncResp, dumpId, dumpType);
2263}
Carson Labrado168d1b12023-03-27 17:04:46 +00002264
Ed Tanous22d268c2022-05-19 09:39:07 -07002265inline void handleLogServicesDumpEntryComputerSystemGet(
2266 crow::App& app, const crow::Request& req,
2267 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2268 const std::string& chassisId, const std::string& dumpId)
2269{
2270 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2271 {
2272 return;
2273 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002274 if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous22d268c2022-05-19 09:39:07 -07002275 {
2276 messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
2277 return;
2278 }
2279 getDumpEntryById(asyncResp, dumpId, "System");
2280}
Claire Weinanfdd26902022-03-01 14:18:25 -08002281
2282inline void handleLogServicesDumpEntryDelete(
2283 crow::App& app, const std::string& dumpType, const crow::Request& req,
2284 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous253f11b2024-05-16 09:38:31 -07002285 const std::string& managerId, const std::string& dumpId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002286{
2287 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2288 {
2289 return;
2290 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002291
2292 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2293 {
2294 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2295 return;
2296 }
Claire Weinanfdd26902022-03-01 14:18:25 -08002297 deleteDumpEntry(asyncResp, dumpId, dumpType);
2298}
2299
Ed Tanous22d268c2022-05-19 09:39:07 -07002300inline void handleLogServicesDumpEntryComputerSystemDelete(
2301 crow::App& app, const crow::Request& req,
2302 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2303 const std::string& chassisId, const std::string& dumpId)
2304{
2305 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2306 {
2307 return;
2308 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002309 if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous22d268c2022-05-19 09:39:07 -07002310 {
2311 messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
2312 return;
2313 }
2314 deleteDumpEntry(asyncResp, dumpId, "System");
2315}
2316
Carson Labrado168d1b12023-03-27 17:04:46 +00002317inline void handleLogServicesDumpEntryDownloadGet(
2318 crow::App& app, const std::string& dumpType, const crow::Request& req,
2319 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous253f11b2024-05-16 09:38:31 -07002320 const std::string& managerId, const std::string& dumpId)
Carson Labrado168d1b12023-03-27 17:04:46 +00002321{
2322 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2323 {
2324 return;
2325 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002326
2327 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2328 {
2329 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2330 return;
2331 }
Carson Labrado168d1b12023-03-27 17:04:46 +00002332 downloadDumpEntry(asyncResp, dumpId, dumpType);
2333}
2334
2335inline void handleDBusEventLogEntryDownloadGet(
2336 crow::App& app, const std::string& dumpType, const crow::Request& req,
2337 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2338 const std::string& systemName, const std::string& entryID)
2339{
2340 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2341 {
2342 return;
2343 }
2344 if (!http_helpers::isContentTypeAllowed(
2345 req.getHeaderValue("Accept"),
2346 http_helpers::ContentType::OctetStream, true))
2347 {
2348 asyncResp->res.result(boost::beast::http::status::bad_request);
2349 return;
2350 }
2351 downloadEventLogEntry(asyncResp, systemName, entryID, dumpType);
2352}
2353
Claire Weinanfdd26902022-03-01 14:18:25 -08002354inline void handleLogServicesDumpCollectDiagnosticDataPost(
2355 crow::App& app, const std::string& dumpType, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07002356 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2357 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002358{
2359 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2360 {
2361 return;
2362 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002363 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2364 {
2365 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2366 return;
2367 }
2368
Claire Weinanfdd26902022-03-01 14:18:25 -08002369 createDump(asyncResp, req, dumpType);
2370}
2371
Ed Tanous22d268c2022-05-19 09:39:07 -07002372inline void handleLogServicesDumpCollectDiagnosticDataComputerSystemPost(
2373 crow::App& app, const crow::Request& req,
2374 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002375 const std::string& systemName)
Ed Tanous22d268c2022-05-19 09:39:07 -07002376{
2377 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2378 {
2379 return;
2380 }
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002381
Ed Tanous25b54db2024-04-17 15:40:31 -07002382 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous22d268c2022-05-19 09:39:07 -07002383 {
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002384 // Option currently returns no systems. TBD
2385 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2386 systemName);
2387 return;
2388 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002389 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002390 {
2391 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2392 systemName);
Ed Tanous22d268c2022-05-19 09:39:07 -07002393 return;
2394 }
2395 createDump(asyncResp, req, "System");
2396}
2397
Claire Weinanfdd26902022-03-01 14:18:25 -08002398inline void handleLogServicesDumpClearLogPost(
2399 crow::App& app, const std::string& dumpType, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07002400 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2401 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002402{
2403 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2404 {
2405 return;
2406 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002407
2408 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2409 {
2410 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2411 return;
2412 }
Claire Weinanfdd26902022-03-01 14:18:25 -08002413 clearDump(asyncResp, dumpType);
2414}
2415
Ed Tanous22d268c2022-05-19 09:39:07 -07002416inline void handleLogServicesDumpClearLogComputerSystemPost(
2417 crow::App& app, const crow::Request& req,
2418 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002419 const std::string& systemName)
Ed Tanous22d268c2022-05-19 09:39:07 -07002420{
2421 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2422 {
2423 return;
2424 }
Ed Tanous25b54db2024-04-17 15:40:31 -07002425 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous22d268c2022-05-19 09:39:07 -07002426 {
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002427 // Option currently returns no systems. TBD
2428 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2429 systemName);
2430 return;
2431 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002432 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002433 {
2434 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2435 systemName);
Ed Tanous22d268c2022-05-19 09:39:07 -07002436 return;
2437 }
2438 clearDump(asyncResp, "System");
2439}
2440
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002441inline void requestRoutesBMCDumpService(App& app)
2442{
Ed Tanous253f11b2024-05-16 09:38:31 -07002443 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/Dump/")
Ed Tanoused398212021-06-09 17:05:54 -07002444 .privileges(redfish::privileges::getLogService)
Claire Weinanfdd26902022-03-01 14:18:25 -08002445 .methods(boost::beast::http::verb::get)(std::bind_front(
2446 handleLogServicesDumpServiceGet, std::ref(app), "BMC"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002447}
2448
2449inline void requestRoutesBMCDumpEntryCollection(App& app)
2450{
Ed Tanous253f11b2024-05-16 09:38:31 -07002451 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/")
Ed Tanoused398212021-06-09 17:05:54 -07002452 .privileges(redfish::privileges::getLogEntryCollection)
Claire Weinanfdd26902022-03-01 14:18:25 -08002453 .methods(boost::beast::http::verb::get)(std::bind_front(
2454 handleLogServicesDumpEntriesCollectionGet, std::ref(app), "BMC"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002455}
2456
2457inline void requestRoutesBMCDumpEntry(App& app)
2458{
2459 BMCWEB_ROUTE(app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002460 "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002461 .privileges(redfish::privileges::getLogEntry)
Claire Weinanfdd26902022-03-01 14:18:25 -08002462 .methods(boost::beast::http::verb::get)(std::bind_front(
2463 handleLogServicesDumpEntryGet, std::ref(app), "BMC"));
2464
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002465 BMCWEB_ROUTE(app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002466 "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002467 .privileges(redfish::privileges::deleteLogEntry)
Claire Weinanfdd26902022-03-01 14:18:25 -08002468 .methods(boost::beast::http::verb::delete_)(std::bind_front(
2469 handleLogServicesDumpEntryDelete, std::ref(app), "BMC"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002470}
2471
Carson Labrado168d1b12023-03-27 17:04:46 +00002472inline void requestRoutesBMCDumpEntryDownload(App& app)
2473{
2474 BMCWEB_ROUTE(
2475 app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002476 "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/attachment/")
Carson Labrado168d1b12023-03-27 17:04:46 +00002477 .privileges(redfish::privileges::getLogEntry)
2478 .methods(boost::beast::http::verb::get)(std::bind_front(
2479 handleLogServicesDumpEntryDownloadGet, std::ref(app), "BMC"));
2480}
2481
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002482inline void requestRoutesBMCDumpCreate(App& app)
2483{
George Liu0fda0f12021-11-16 10:06:17 +08002484 BMCWEB_ROUTE(
2485 app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002486 "/redfish/v1/Managers/<str>/LogServices/Dump/Actions/LogService.CollectDiagnosticData/")
Ed Tanoused398212021-06-09 17:05:54 -07002487 .privileges(redfish::privileges::postLogService)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002488 .methods(boost::beast::http::verb::post)(
Claire Weinanfdd26902022-03-01 14:18:25 -08002489 std::bind_front(handleLogServicesDumpCollectDiagnosticDataPost,
2490 std::ref(app), "BMC"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002491}
2492
2493inline void requestRoutesBMCDumpClear(App& app)
2494{
George Liu0fda0f12021-11-16 10:06:17 +08002495 BMCWEB_ROUTE(
2496 app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002497 "/redfish/v1/Managers/<str>/LogServices/Dump/Actions/LogService.ClearLog/")
Ed Tanoused398212021-06-09 17:05:54 -07002498 .privileges(redfish::privileges::postLogService)
Claire Weinanfdd26902022-03-01 14:18:25 -08002499 .methods(boost::beast::http::verb::post)(std::bind_front(
2500 handleLogServicesDumpClearLogPost, std::ref(app), "BMC"));
2501}
2502
Carson Labrado168d1b12023-03-27 17:04:46 +00002503inline void requestRoutesDBusEventLogEntryDownload(App& app)
2504{
2505 BMCWEB_ROUTE(
2506 app,
Ravi Teja9e9d99d2023-11-08 05:33:59 -06002507 "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/attachment/")
Carson Labrado168d1b12023-03-27 17:04:46 +00002508 .privileges(redfish::privileges::getLogEntry)
2509 .methods(boost::beast::http::verb::get)(std::bind_front(
2510 handleDBusEventLogEntryDownloadGet, std::ref(app), "System"));
2511}
2512
Claire Weinanfdd26902022-03-01 14:18:25 -08002513inline void requestRoutesFaultLogDumpService(App& app)
2514{
Ed Tanous253f11b2024-05-16 09:38:31 -07002515 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/")
Claire Weinanfdd26902022-03-01 14:18:25 -08002516 .privileges(redfish::privileges::getLogService)
2517 .methods(boost::beast::http::verb::get)(std::bind_front(
2518 handleLogServicesDumpServiceGet, std::ref(app), "FaultLog"));
2519}
2520
2521inline void requestRoutesFaultLogDumpEntryCollection(App& app)
2522{
Ed Tanous253f11b2024-05-16 09:38:31 -07002523 BMCWEB_ROUTE(app,
2524 "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/")
Claire Weinanfdd26902022-03-01 14:18:25 -08002525 .privileges(redfish::privileges::getLogEntryCollection)
2526 .methods(boost::beast::http::verb::get)(
2527 std::bind_front(handleLogServicesDumpEntriesCollectionGet,
2528 std::ref(app), "FaultLog"));
2529}
2530
2531inline void requestRoutesFaultLogDumpEntry(App& app)
2532{
Ed Tanous253f11b2024-05-16 09:38:31 -07002533 BMCWEB_ROUTE(
2534 app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/<str>/")
Claire Weinanfdd26902022-03-01 14:18:25 -08002535 .privileges(redfish::privileges::getLogEntry)
2536 .methods(boost::beast::http::verb::get)(std::bind_front(
2537 handleLogServicesDumpEntryGet, std::ref(app), "FaultLog"));
2538
Ed Tanous253f11b2024-05-16 09:38:31 -07002539 BMCWEB_ROUTE(
2540 app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/<str>/")
Claire Weinanfdd26902022-03-01 14:18:25 -08002541 .privileges(redfish::privileges::deleteLogEntry)
2542 .methods(boost::beast::http::verb::delete_)(std::bind_front(
2543 handleLogServicesDumpEntryDelete, std::ref(app), "FaultLog"));
2544}
2545
2546inline void requestRoutesFaultLogDumpClear(App& app)
2547{
2548 BMCWEB_ROUTE(
2549 app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002550 "/redfish/v1/Managers/<str>/LogServices/FaultLog/Actions/LogService.ClearLog/")
Claire Weinanfdd26902022-03-01 14:18:25 -08002551 .privileges(redfish::privileges::postLogService)
2552 .methods(boost::beast::http::verb::post)(std::bind_front(
2553 handleLogServicesDumpClearLogPost, std::ref(app), "FaultLog"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002554}
2555
2556inline void requestRoutesSystemDumpService(App& app)
2557{
Ed Tanous22d268c2022-05-19 09:39:07 -07002558 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Dump/")
Ed Tanoused398212021-06-09 17:05:54 -07002559 .privileges(redfish::privileges::getLogService)
Claire Weinan6ab9ad52022-08-12 18:20:17 -07002560 .methods(boost::beast::http::verb::get)(std::bind_front(
Ed Tanous22d268c2022-05-19 09:39:07 -07002561 handleLogServicesDumpServiceComputerSystemGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002562}
2563
2564inline void requestRoutesSystemDumpEntryCollection(App& app)
2565{
Ed Tanous22d268c2022-05-19 09:39:07 -07002566 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/")
Ed Tanoused398212021-06-09 17:05:54 -07002567 .privileges(redfish::privileges::getLogEntryCollection)
Ed Tanous22d268c2022-05-19 09:39:07 -07002568 .methods(boost::beast::http::verb::get)(std::bind_front(
2569 handleLogServicesDumpEntriesCollectionComputerSystemGet,
2570 std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002571}
2572
2573inline void requestRoutesSystemDumpEntry(App& app)
2574{
2575 BMCWEB_ROUTE(app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002576 "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002577 .privileges(redfish::privileges::getLogEntry)
Claire Weinan6ab9ad52022-08-12 18:20:17 -07002578 .methods(boost::beast::http::verb::get)(std::bind_front(
Ed Tanous22d268c2022-05-19 09:39:07 -07002579 handleLogServicesDumpEntryComputerSystemGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002580
2581 BMCWEB_ROUTE(app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002582 "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002583 .privileges(redfish::privileges::deleteLogEntry)
Claire Weinan6ab9ad52022-08-12 18:20:17 -07002584 .methods(boost::beast::http::verb::delete_)(std::bind_front(
Ed Tanous22d268c2022-05-19 09:39:07 -07002585 handleLogServicesDumpEntryComputerSystemDelete, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002586}
2587
2588inline void requestRoutesSystemDumpCreate(App& app)
2589{
George Liu0fda0f12021-11-16 10:06:17 +08002590 BMCWEB_ROUTE(
2591 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002592 "/redfish/v1/Systems/<str>/LogServices/Dump/Actions/LogService.CollectDiagnosticData/")
Ed Tanoused398212021-06-09 17:05:54 -07002593 .privileges(redfish::privileges::postLogService)
Ed Tanous22d268c2022-05-19 09:39:07 -07002594 .methods(boost::beast::http::verb::post)(std::bind_front(
2595 handleLogServicesDumpCollectDiagnosticDataComputerSystemPost,
2596 std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002597}
2598
2599inline void requestRoutesSystemDumpClear(App& app)
2600{
George Liu0fda0f12021-11-16 10:06:17 +08002601 BMCWEB_ROUTE(
2602 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002603 "/redfish/v1/Systems/<str>/LogServices/Dump/Actions/LogService.ClearLog/")
Ed Tanoused398212021-06-09 17:05:54 -07002604 .privileges(redfish::privileges::postLogService)
Claire Weinan6ab9ad52022-08-12 18:20:17 -07002605 .methods(boost::beast::http::verb::post)(std::bind_front(
Ed Tanous22d268c2022-05-19 09:39:07 -07002606 handleLogServicesDumpClearLogComputerSystemPost, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002607}
2608
2609inline void requestRoutesCrashdumpService(App& app)
2610{
2611 // Note: Deviated from redfish privilege registry for GET & HEAD
2612 // method for security reasons.
2613 /**
2614 * Functions triggers appropriate requests on DBus
2615 */
Ed Tanous22d268c2022-05-19 09:39:07 -07002616 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Crashdump/")
Ed Tanoused398212021-06-09 17:05:54 -07002617 // This is incorrect, should be:
2618 //.privileges(redfish::privileges::getLogService)
Ed Tanous432a8902021-06-14 15:28:56 -07002619 .privileges({{"ConfigureManager"}})
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002620 .methods(
2621 boost::beast::http::verb::
2622 get)([&app](const crow::Request& req,
2623 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2624 const std::string& systemName) {
2625 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2626 {
2627 return;
2628 }
2629 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
2630 {
2631 // Option currently returns no systems. TBD
2632 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2633 systemName);
2634 return;
2635 }
2636 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2637 {
2638 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2639 systemName);
2640 return;
2641 }
Ed Tanous22d268c2022-05-19 09:39:07 -07002642
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002643 // Copy over the static data to include the entries added by
2644 // SubRoute
2645 asyncResp->res.jsonValue["@odata.id"] =
2646 std::format("/redfish/v1/Systems/{}/LogServices/Crashdump",
2647 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2648 asyncResp->res.jsonValue["@odata.type"] =
2649 "#LogService.v1_2_0.LogService";
2650 asyncResp->res.jsonValue["Name"] = "Open BMC Oem Crashdump Service";
2651 asyncResp->res.jsonValue["Description"] = "Oem Crashdump Service";
2652 asyncResp->res.jsonValue["Id"] = "Crashdump";
2653 asyncResp->res.jsonValue["OverWritePolicy"] =
2654 log_service::OverWritePolicy::WrapsWhenFull;
2655 asyncResp->res.jsonValue["MaxNumberOfRecords"] = 3;
Tejas Patil7c8c4052021-06-04 17:43:14 +05302656
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002657 std::pair<std::string, std::string> redfishDateTimeOffset =
2658 redfish::time_utils::getDateTimeOffsetNow();
2659 asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
2660 asyncResp->res.jsonValue["DateTimeLocalOffset"] =
2661 redfishDateTimeOffset.second;
Tejas Patil7c8c4052021-06-04 17:43:14 +05302662
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002663 asyncResp->res.jsonValue["Entries"]["@odata.id"] = std::format(
2664 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries",
2665 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2666 asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"]
2667 ["target"] = std::format(
2668 "/redfish/v1/Systems/{}/LogServices/Crashdump/Actions/LogService.ClearLog",
2669 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2670 asyncResp->res
2671 .jsonValue["Actions"]["#LogService.CollectDiagnosticData"]
2672 ["target"] = std::format(
2673 "/redfish/v1/Systems/{}/LogServices/Crashdump/Actions/LogService.CollectDiagnosticData",
2674 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2675 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002676}
2677
2678void inline requestRoutesCrashdumpClear(App& app)
2679{
George Liu0fda0f12021-11-16 10:06:17 +08002680 BMCWEB_ROUTE(
2681 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002682 "/redfish/v1/Systems/<str>/LogServices/Crashdump/Actions/LogService.ClearLog/")
Ed Tanoused398212021-06-09 17:05:54 -07002683 // This is incorrect, should be:
2684 //.privileges(redfish::privileges::postLogService)
Ed Tanous432a8902021-06-14 15:28:56 -07002685 .privileges({{"ConfigureComponents"}})
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002686 .methods(boost::beast::http::verb::post)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07002687 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07002688 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2689 const std::string& systemName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002690 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2691 {
2692 return;
2693 }
2694 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
2695 {
2696 // Option currently returns no systems. TBD
2697 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2698 systemName);
2699 return;
2700 }
2701 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2702 {
2703 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2704 systemName);
2705 return;
2706 }
2707 crow::connections::systemBus->async_method_call(
2708 [asyncResp](const boost::system::error_code& ec,
2709 const std::string&) {
2710 if (ec)
2711 {
2712 messages::internalError(asyncResp->res);
2713 return;
2714 }
2715 messages::success(asyncResp->res);
2716 },
2717 crashdumpObject, crashdumpPath, deleteAllInterface,
2718 "DeleteAll");
2719 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002720}
Jason M. Bills5b61b5e2019-10-16 10:59:02 -07002721
Ed Tanous4ff0f1f2024-09-04 17:27:37 -07002722inline void
zhanghch058d1b46d2021-04-01 11:18:24 +08002723 logCrashdumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2724 const std::string& logID, nlohmann::json& logEntryJson)
Jason M. Billse855dd22019-10-08 11:37:48 -07002725{
Johnathan Mantey043a0532020-03-10 17:15:28 -07002726 auto getStoredLogCallback =
Ed Tanousb9d36b42022-02-26 21:42:46 -08002727 [asyncResp, logID,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002728 &logEntryJson](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002729 const dbus::utility::DBusPropertiesMap& params) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002730 if (ec)
2731 {
2732 BMCWEB_LOG_DEBUG("failed to get log ec: {}", ec.message());
2733 if (ec.value() ==
2734 boost::system::linux_error::bad_request_descriptor)
2735 {
2736 messages::resourceNotFound(asyncResp->res, "LogEntry",
2737 logID);
2738 }
2739 else
2740 {
2741 messages::internalError(asyncResp->res);
2742 }
2743 return;
2744 }
2745
2746 std::string timestamp{};
2747 std::string filename{};
2748 std::string logfile{};
2749 parseCrashdumpParameters(params, filename, timestamp, logfile);
2750
2751 if (filename.empty() || timestamp.empty())
Jason M. Bills1ddcf012019-11-26 14:59:21 -08002752 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002753 messages::resourceNotFound(asyncResp->res, "LogEntry", logID);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002754 return;
2755 }
2756
2757 std::string crashdumpURI =
2758 std::format(
2759 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries/",
2760 BMCWEB_REDFISH_SYSTEM_URI_NAME) +
2761 logID + "/" + filename;
2762 nlohmann::json::object_t logEntry;
2763 logEntry["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
2764 logEntry["@odata.id"] = boost::urls::format(
2765 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries/{}",
2766 BMCWEB_REDFISH_SYSTEM_URI_NAME, logID);
2767 logEntry["Name"] = "CPU Crashdump";
2768 logEntry["Id"] = logID;
2769 logEntry["EntryType"] = log_entry::LogEntryType::Oem;
2770 logEntry["AdditionalDataURI"] = std::move(crashdumpURI);
2771 logEntry["DiagnosticDataType"] = "OEM";
2772 logEntry["OEMDiagnosticDataType"] = "PECICrashdump";
2773 logEntry["Created"] = std::move(timestamp);
2774
2775 // If logEntryJson references an array of LogEntry resources
2776 // ('Members' list), then push this as a new entry, otherwise set it
2777 // directly
2778 if (logEntryJson.is_array())
2779 {
2780 logEntryJson.push_back(logEntry);
2781 asyncResp->res.jsonValue["Members@odata.count"] =
2782 logEntryJson.size();
Jason M. Bills2b20ef62022-01-06 15:48:07 -08002783 }
2784 else
2785 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002786 logEntryJson.update(logEntry);
Jason M. Bills2b20ef62022-01-06 15:48:07 -08002787 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002788 };
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +02002789 sdbusplus::asio::getAllProperties(
2790 *crow::connections::systemBus, crashdumpObject,
2791 crashdumpPath + std::string("/") + logID, crashdumpInterface,
2792 std::move(getStoredLogCallback));
Jason M. Billse855dd22019-10-08 11:37:48 -07002793}
2794
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002795inline void requestRoutesCrashdumpEntryCollection(App& app)
Ed Tanous1da66f72018-07-27 16:13:37 -07002796{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002797 // Note: Deviated from redfish privilege registry for GET & HEAD
2798 // method for security reasons.
Ed Tanous1da66f72018-07-27 16:13:37 -07002799 /**
2800 * Functions triggers appropriate requests on DBus
2801 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002802 BMCWEB_ROUTE(app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002803 "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/")
Ed Tanoused398212021-06-09 17:05:54 -07002804 // This is incorrect, should be.
2805 //.privileges(redfish::privileges::postLogEntryCollection)
Ed Tanous432a8902021-06-14 15:28:56 -07002806 .privileges({{"ConfigureComponents"}})
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002807 .methods(
2808 boost::beast::http::verb::
2809 get)([&app](const crow::Request& req,
2810 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2811 const std::string& systemName) {
2812 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous45ca1b82022-03-25 13:07:27 -07002813 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002814 return;
Ed Tanous45ca1b82022-03-25 13:07:27 -07002815 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002816 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous002d39b2022-05-31 08:59:27 -07002817 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002818 // Option currently returns no systems. TBD
2819 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2820 systemName);
2821 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07002822 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002823 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2824 {
2825 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2826 systemName);
2827 return;
2828 }
2829
2830 constexpr std::array<std::string_view, 1> interfaces = {
2831 crashdumpInterface};
2832 dbus::utility::getSubTreePaths(
2833 "/", 0, interfaces,
2834 [asyncResp](const boost::system::error_code& ec,
2835 const std::vector<std::string>& resp) {
2836 if (ec)
2837 {
2838 if (ec.value() !=
2839 boost::system::errc::no_such_file_or_directory)
2840 {
2841 BMCWEB_LOG_DEBUG("failed to get entries ec: {}",
2842 ec.message());
2843 messages::internalError(asyncResp->res);
2844 return;
2845 }
2846 }
2847 asyncResp->res.jsonValue["@odata.type"] =
2848 "#LogEntryCollection.LogEntryCollection";
2849 asyncResp->res.jsonValue["@odata.id"] = std::format(
2850 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries",
2851 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2852 asyncResp->res.jsonValue["Name"] =
2853 "Open BMC Crashdump Entries";
2854 asyncResp->res.jsonValue["Description"] =
2855 "Collection of Crashdump Entries";
2856 asyncResp->res.jsonValue["Members"] =
2857 nlohmann::json::array();
2858 asyncResp->res.jsonValue["Members@odata.count"] = 0;
2859
2860 for (const std::string& path : resp)
2861 {
2862 const sdbusplus::message::object_path objPath(path);
2863 // Get the log ID
2864 std::string logID = objPath.filename();
2865 if (logID.empty())
2866 {
2867 continue;
2868 }
2869 // Add the log entry to the array
2870 logCrashdumpEntry(asyncResp, logID,
2871 asyncResp->res.jsonValue["Members"]);
2872 }
2873 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002874 });
2875}
Ed Tanous1da66f72018-07-27 16:13:37 -07002876
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002877inline void requestRoutesCrashdumpEntry(App& app)
Ed Tanous1da66f72018-07-27 16:13:37 -07002878{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002879 // Note: Deviated from redfish privilege registry for GET & HEAD
2880 // method for security reasons.
Ed Tanous1da66f72018-07-27 16:13:37 -07002881
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002882 BMCWEB_ROUTE(
Ed Tanous22d268c2022-05-19 09:39:07 -07002883 app, "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002884 // this is incorrect, should be
2885 // .privileges(redfish::privileges::getLogEntry)
Ed Tanous432a8902021-06-14 15:28:56 -07002886 .privileges({{"ConfigureComponents"}})
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002887 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07002888 [&app](const crow::Request& req,
2889 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -07002890 const std::string& systemName, const std::string& param) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002891 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2892 {
2893 return;
2894 }
2895 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
2896 {
2897 // Option currently returns no systems. TBD
2898 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2899 systemName);
2900 return;
2901 }
2902 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2903 {
2904 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2905 systemName);
2906 return;
2907 }
2908 const std::string& logID = param;
2909 logCrashdumpEntry(asyncResp, logID, asyncResp->res.jsonValue);
2910 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002911}
Ed Tanous1da66f72018-07-27 16:13:37 -07002912
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002913inline void requestRoutesCrashdumpFile(App& app)
2914{
2915 // Note: Deviated from redfish privilege registry for GET & HEAD
2916 // method for security reasons.
2917 BMCWEB_ROUTE(
2918 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002919 "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/<str>/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002920 .privileges(redfish::privileges::getLogEntry)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002921 .methods(boost::beast::http::verb::get)(
Nan Zhoua4ce1142022-08-02 18:45:25 +00002922 [](const crow::Request& req,
2923 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -07002924 const std::string& systemName, const std::string& logID,
2925 const std::string& fileName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002926 // Do not call getRedfishRoute here since the crashdump file is
2927 // not a Redfish resource.
Ed Tanous22d268c2022-05-19 09:39:07 -07002928
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002929 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
2930 {
2931 // Option currently returns no systems. TBD
2932 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2933 systemName);
2934 return;
2935 }
2936 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2937 {
2938 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2939 systemName);
2940 return;
2941 }
Ed Tanous22d268c2022-05-19 09:39:07 -07002942
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002943 auto getStoredLogCallback =
2944 [asyncResp, logID, fileName,
2945 url(boost::urls::url(req.url()))](
2946 const boost::system::error_code& ec,
2947 const std::vector<std::pair<
2948 std::string, dbus::utility::DbusVariantType>>&
2949 resp) {
2950 if (ec)
2951 {
2952 BMCWEB_LOG_DEBUG("failed to get log ec: {}",
2953 ec.message());
2954 messages::internalError(asyncResp->res);
2955 return;
2956 }
Jason M. Bills8e6c0992021-03-11 16:26:53 -08002957
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002958 std::string dbusFilename{};
2959 std::string dbusTimestamp{};
2960 std::string dbusFilepath{};
Jason M. Bills8e6c0992021-03-11 16:26:53 -08002961
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002962 parseCrashdumpParameters(resp, dbusFilename,
2963 dbusTimestamp, dbusFilepath);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002964
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002965 if (dbusFilename.empty() || dbusTimestamp.empty() ||
2966 dbusFilepath.empty())
2967 {
2968 messages::resourceNotFound(asyncResp->res,
2969 "LogEntry", logID);
2970 return;
2971 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002972
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002973 // Verify the file name parameter is correct
2974 if (fileName != dbusFilename)
2975 {
2976 messages::resourceNotFound(asyncResp->res,
2977 "LogEntry", logID);
2978 return;
2979 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002980
Myung Baed51c61b2024-09-13 10:35:34 -05002981 if (asyncResp->res.openFile(dbusFilepath) !=
2982 crow::OpenCode::Success)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002983 {
2984 messages::resourceNotFound(asyncResp->res,
2985 "LogEntry", logID);
2986 return;
2987 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002988
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002989 // Configure this to be a file download when accessed
2990 // from a browser
2991 asyncResp->res.addHeader(
2992 boost::beast::http::field::content_disposition,
2993 "attachment");
2994 };
2995 sdbusplus::asio::getAllProperties(
2996 *crow::connections::systemBus, crashdumpObject,
2997 crashdumpPath + std::string("/") + logID,
2998 crashdumpInterface, std::move(getStoredLogCallback));
2999 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003000}
3001
Jason M. Billsc5a4c822022-01-06 15:51:23 -08003002enum class OEMDiagnosticType
3003{
3004 onDemand,
3005 telemetry,
3006 invalid,
3007};
3008
Ed Tanous26ccae32023-02-16 10:28:44 -08003009inline OEMDiagnosticType getOEMDiagnosticType(std::string_view oemDiagStr)
Jason M. Billsc5a4c822022-01-06 15:51:23 -08003010{
3011 if (oemDiagStr == "OnDemand")
3012 {
3013 return OEMDiagnosticType::onDemand;
3014 }
3015 if (oemDiagStr == "Telemetry")
3016 {
3017 return OEMDiagnosticType::telemetry;
3018 }
3019
3020 return OEMDiagnosticType::invalid;
3021}
3022
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003023inline void requestRoutesCrashdumpCollect(App& app)
3024{
3025 // Note: Deviated from redfish privilege registry for GET & HEAD
3026 // method for security reasons.
George Liu0fda0f12021-11-16 10:06:17 +08003027 BMCWEB_ROUTE(
3028 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07003029 "/redfish/v1/Systems/<str>/LogServices/Crashdump/Actions/LogService.CollectDiagnosticData/")
Ed Tanoused398212021-06-09 17:05:54 -07003030 // The below is incorrect; Should be ConfigureManager
3031 //.privileges(redfish::privileges::postLogService)
Ed Tanous432a8902021-06-14 15:28:56 -07003032 .privileges({{"ConfigureComponents"}})
Ed Tanous002d39b2022-05-31 08:59:27 -07003033 .methods(boost::beast::http::verb::post)(
3034 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07003035 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3036 const std::string& systemName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003037 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07003038 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003039 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07003040 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003041
3042 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous002d39b2022-05-31 08:59:27 -07003043 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003044 // Option currently returns no systems. TBD
3045 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3046 systemName);
3047 return;
3048 }
3049 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
3050 {
3051 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3052 systemName);
3053 return;
3054 }
3055
3056 std::string diagnosticDataType;
3057 std::string oemDiagnosticDataType;
3058 if (!redfish::json_util::readJsonAction(
3059 req, asyncResp->res, "DiagnosticDataType",
3060 diagnosticDataType, "OEMDiagnosticDataType",
3061 oemDiagnosticDataType))
3062 {
3063 return;
3064 }
3065
3066 if (diagnosticDataType != "OEM")
3067 {
3068 BMCWEB_LOG_ERROR(
3069 "Only OEM DiagnosticDataType supported for Crashdump");
3070 messages::actionParameterValueFormatError(
3071 asyncResp->res, diagnosticDataType,
3072 "DiagnosticDataType", "CollectDiagnosticData");
3073 return;
3074 }
3075
3076 OEMDiagnosticType oemDiagType =
3077 getOEMDiagnosticType(oemDiagnosticDataType);
3078
3079 std::string iface;
3080 std::string method;
3081 std::string taskMatchStr;
3082 if (oemDiagType == OEMDiagnosticType::onDemand)
3083 {
3084 iface = crashdumpOnDemandInterface;
3085 method = "GenerateOnDemandLog";
3086 taskMatchStr =
3087 "type='signal',"
3088 "interface='org.freedesktop.DBus.Properties',"
3089 "member='PropertiesChanged',"
3090 "arg0namespace='com.intel.crashdump'";
3091 }
3092 else if (oemDiagType == OEMDiagnosticType::telemetry)
3093 {
3094 iface = crashdumpTelemetryInterface;
3095 method = "GenerateTelemetryLog";
3096 taskMatchStr =
3097 "type='signal',"
3098 "interface='org.freedesktop.DBus.Properties',"
3099 "member='PropertiesChanged',"
3100 "arg0namespace='com.intel.crashdump'";
Ed Tanous002d39b2022-05-31 08:59:27 -07003101 }
3102 else
3103 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003104 BMCWEB_LOG_ERROR("Unsupported OEMDiagnosticDataType: {}",
3105 oemDiagnosticDataType);
3106 messages::actionParameterValueFormatError(
3107 asyncResp->res, oemDiagnosticDataType,
3108 "OEMDiagnosticDataType", "CollectDiagnosticData");
3109 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07003110 }
Ed Tanous1da66f72018-07-27 16:13:37 -07003111
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003112 auto collectCrashdumpCallback =
3113 [asyncResp, payload(task::Payload(req)),
3114 taskMatchStr](const boost::system::error_code& ec,
3115 const std::string&) mutable {
3116 if (ec)
3117 {
3118 if (ec.value() ==
3119 boost::system::errc::operation_not_supported)
3120 {
3121 messages::resourceInStandby(asyncResp->res);
3122 }
3123 else if (ec.value() == boost::system::errc::
3124 device_or_resource_busy)
3125 {
3126 messages::serviceTemporarilyUnavailable(
3127 asyncResp->res, "60");
3128 }
3129 else
3130 {
3131 messages::internalError(asyncResp->res);
3132 }
3133 return;
3134 }
3135 std::shared_ptr<task::TaskData> task =
3136 task::TaskData::createTask(
3137 [](const boost::system::error_code& ec2,
3138 sdbusplus::message_t&,
3139 const std::shared_ptr<task::TaskData>&
3140 taskData) {
3141 if (!ec2)
3142 {
3143 taskData->messages.emplace_back(
3144 messages::taskCompletedOK(
3145 std::to_string(
3146 taskData->index)));
3147 taskData->state = "Completed";
3148 }
3149 return task::completed;
3150 },
3151 taskMatchStr);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003152
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003153 task->startTimer(std::chrono::minutes(5));
3154 task->populateResp(asyncResp->res);
3155 task->payload.emplace(std::move(payload));
3156 };
3157
3158 crow::connections::systemBus->async_method_call(
3159 std::move(collectCrashdumpCallback), crashdumpObject,
3160 crashdumpPath, iface, method);
3161 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003162}
Kenny L. Ku6eda7682020-06-19 09:48:36 -07003163
Alexander Hansen599b9af2024-08-06 15:11:57 +02003164inline void dBusLogServiceActionsClear(
3165 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
3166{
3167 BMCWEB_LOG_DEBUG("Do delete all entries.");
3168
3169 // Process response from Logging service.
3170 auto respHandler = [asyncResp](const boost::system::error_code& ec) {
3171 BMCWEB_LOG_DEBUG("doClearLog resp_handler callback: Done");
3172 if (ec)
3173 {
3174 // TODO Handle for specific error code
3175 BMCWEB_LOG_ERROR("doClearLog resp_handler got error {}", ec);
3176 asyncResp->res.result(
3177 boost::beast::http::status::internal_server_error);
3178 return;
3179 }
3180
3181 asyncResp->res.result(boost::beast::http::status::no_content);
3182 };
3183
3184 // Make call to Logging service to request Clear Log
3185 crow::connections::systemBus->async_method_call(
3186 respHandler, "xyz.openbmc_project.Logging",
3187 "/xyz/openbmc_project/logging",
3188 "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
3189}
3190
Andrew Geisslercb92c032018-08-17 07:56:14 -07003191/**
3192 * DBusLogServiceActionsClear class supports POST method for ClearLog action.
3193 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003194inline void requestRoutesDBusLogServiceActionsClear(App& app)
Andrew Geisslercb92c032018-08-17 07:56:14 -07003195{
Andrew Geisslercb92c032018-08-17 07:56:14 -07003196 /**
3197 * Function handles POST method request.
3198 * The Clear Log actions does not require any parameter.The action deletes
3199 * all entries found in the Entries collection for this Log Service.
3200 */
Andrew Geisslercb92c032018-08-17 07:56:14 -07003201
George Liu0fda0f12021-11-16 10:06:17 +08003202 BMCWEB_ROUTE(
3203 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07003204 "/redfish/v1/Systems/<str>/LogServices/EventLog/Actions/LogService.ClearLog/")
Ed Tanoused398212021-06-09 17:05:54 -07003205 .privileges(redfish::privileges::postLogService)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003206 .methods(boost::beast::http::verb::post)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07003207 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07003208 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3209 const std::string& systemName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003210 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3211 {
3212 return;
3213 }
3214 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
3215 {
3216 // Option currently returns no systems. TBD
3217 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3218 systemName);
3219 return;
3220 }
3221 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
3222 {
3223 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3224 systemName);
3225 return;
3226 }
3227 dBusLogServiceActionsClear(asyncResp);
3228 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003229}
ZhikuiRena3316fc2020-01-29 14:58:08 -08003230
Ed Tanous1da66f72018-07-27 16:13:37 -07003231} // namespace redfish