blob: 0f5641f6bea5e2afde75e4493bf304a5885531de [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
Myung Baeafc474a2024-10-09 00:53:29 -0700944 if (!redfish::json_util::readJsonAction( //
945 req, asyncResp->res, //
946 "DiagnosticDataType", diagnosticDataType, //
947 "OEMDiagnosticDataType", oemDiagnosticDataType //
948 ))
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500949 {
950 return;
951 }
952
953 if (dumpType == "System")
954 {
955 if (!oemDiagnosticDataType || !diagnosticDataType)
956 {
Ed Tanous62598e32023-07-17 17:06:25 -0700957 BMCWEB_LOG_ERROR(
958 "CreateDump action parameter 'DiagnosticDataType'/'OEMDiagnosticDataType' value not found!");
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500959 messages::actionParameterMissing(
960 asyncResp->res, "CollectDiagnosticData",
961 "DiagnosticDataType & OEMDiagnosticDataType");
962 return;
963 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700964 if ((*oemDiagnosticDataType != "System") ||
965 (*diagnosticDataType != "OEM"))
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500966 {
Ed Tanous62598e32023-07-17 17:06:25 -0700967 BMCWEB_LOG_ERROR("Wrong parameter values passed");
Ed Tanousace85d62021-10-26 12:45:59 -0700968 messages::internalError(asyncResp->res);
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500969 return;
970 }
Ed Tanous253f11b2024-05-16 09:38:31 -0700971 dumpPath = std::format("/redfish/v1/Systems/{}/LogServices/Dump/",
972 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500973 }
974 else if (dumpType == "BMC")
975 {
976 if (!diagnosticDataType)
977 {
Ed Tanous62598e32023-07-17 17:06:25 -0700978 BMCWEB_LOG_ERROR(
979 "CreateDump action parameter 'DiagnosticDataType' not found!");
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500980 messages::actionParameterMissing(
981 asyncResp->res, "CollectDiagnosticData", "DiagnosticDataType");
982 return;
983 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700984 if (*diagnosticDataType != "Manager")
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500985 {
Ed Tanous62598e32023-07-17 17:06:25 -0700986 BMCWEB_LOG_ERROR(
987 "Wrong parameter value passed for 'DiagnosticDataType'");
Ed Tanousace85d62021-10-26 12:45:59 -0700988 messages::internalError(asyncResp->res);
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500989 return;
990 }
Ed Tanous253f11b2024-05-16 09:38:31 -0700991 dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/Dump/",
992 BMCWEB_REDFISH_MANAGER_URI_NAME);
Asmitha Karunanithi59075712021-10-22 01:17:41 -0500993 }
994 else
995 {
Ed Tanous62598e32023-07-17 17:06:25 -0700996 BMCWEB_LOG_ERROR("CreateDump failed. Unknown dump type");
Asmitha Karunanithi59075712021-10-22 01:17:41 -0500997 messages::internalError(asyncResp->res);
998 return;
Asmitha Karunanithia43be802020-05-07 05:05:36 -0500999 }
1000
Asmitha Karunanithi8e317782020-12-10 03:35:05 -06001001 std::vector<std::pair<std::string, std::variant<std::string, uint64_t>>>
1002 createDumpParamVec;
1003
Carson Labradof574a8e2023-03-22 02:26:00 +00001004 if (req.session != nullptr)
1005 {
1006 createDumpParamVec.emplace_back(
1007 "xyz.openbmc_project.Dump.Create.CreateParameters.OriginatorId",
1008 req.session->clientIp);
1009 createDumpParamVec.emplace_back(
1010 "xyz.openbmc_project.Dump.Create.CreateParameters.OriginatorType",
1011 "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Client");
1012 }
Asmitha Karunanithi68dd0752022-11-15 11:33:46 -06001013
Asmitha Karunanithia43be802020-05-07 05:05:36 -05001014 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001015 [asyncResp, payload(task::Payload(req)),
1016 dumpPath](const boost::system::error_code& ec,
1017 const sdbusplus::message_t& msg,
1018 const sdbusplus::message::object_path& objPath) mutable {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001019 if (ec)
Asmitha Karunanithi59075712021-10-22 01:17:41 -05001020 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001021 BMCWEB_LOG_ERROR("CreateDump resp_handler got error {}", ec);
1022 const sd_bus_error* dbusError = msg.get_error();
1023 if (dbusError == nullptr)
1024 {
1025 messages::internalError(asyncResp->res);
1026 return;
1027 }
1028
1029 BMCWEB_LOG_ERROR("CreateDump DBus error: {} and error msg: {}",
1030 dbusError->name, dbusError->message);
1031 if (std::string_view(
1032 "xyz.openbmc_project.Common.Error.NotAllowed") ==
1033 dbusError->name)
1034 {
1035 messages::resourceInStandby(asyncResp->res);
1036 return;
1037 }
1038 if (std::string_view(
1039 "xyz.openbmc_project.Dump.Create.Error.Disabled") ==
1040 dbusError->name)
1041 {
1042 messages::serviceDisabled(asyncResp->res, dumpPath);
1043 return;
1044 }
1045 if (std::string_view(
1046 "xyz.openbmc_project.Common.Error.Unavailable") ==
1047 dbusError->name)
1048 {
1049 messages::resourceInUse(asyncResp->res);
1050 return;
1051 }
1052 // Other Dbus errors such as:
1053 // xyz.openbmc_project.Common.Error.InvalidArgument &
1054 // org.freedesktop.DBus.Error.InvalidArgs are all related to
1055 // the dbus call that is made here in the bmcweb
1056 // implementation and has nothing to do with the client's
1057 // input in the request. Hence, returning internal error
1058 // back to the client.
Asmitha Karunanithi59075712021-10-22 01:17:41 -05001059 messages::internalError(asyncResp->res);
1060 return;
1061 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001062 BMCWEB_LOG_DEBUG("Dump Created. Path: {}", objPath.str);
1063 createDumpTaskCallback(std::move(payload), asyncResp, objPath);
1064 },
Ed Tanous18f8f602023-07-18 10:07:23 -07001065 "xyz.openbmc_project.Dump.Manager", getDumpPath(dumpType),
Asmitha Karunanithi8e317782020-12-10 03:35:05 -06001066 "xyz.openbmc_project.Dump.Create", "CreateDump", createDumpParamVec);
Asmitha Karunanithia43be802020-05-07 05:05:36 -05001067}
1068
zhanghch058d1b46d2021-04-01 11:18:24 +08001069inline void clearDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1070 const std::string& dumpType)
Asmitha Karunanithi80319af2020-05-07 05:30:21 -05001071{
Claire Weinan0d946212022-07-13 19:40:19 -07001072 crow::connections::systemBus->async_method_call(
1073 [asyncResp](const boost::system::error_code& ec) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001074 if (ec)
1075 {
1076 BMCWEB_LOG_ERROR("clearDump resp_handler got error {}", ec);
1077 messages::internalError(asyncResp->res);
1078 return;
1079 }
1080 },
Ed Tanous18f8f602023-07-18 10:07:23 -07001081 "xyz.openbmc_project.Dump.Manager", getDumpPath(dumpType),
Claire Weinan0d946212022-07-13 19:40:19 -07001082 "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
Asmitha Karunanithi80319af2020-05-07 05:30:21 -05001083}
1084
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001085inline void parseCrashdumpParameters(
1086 const dbus::utility::DBusPropertiesMap& params, std::string& filename,
1087 std::string& timestamp, std::string& logfile)
Johnathan Mantey043a0532020-03-10 17:15:28 -07001088{
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +02001089 const std::string* filenamePtr = nullptr;
1090 const std::string* timestampPtr = nullptr;
1091 const std::string* logfilePtr = nullptr;
1092
1093 const bool success = sdbusplus::unpackPropertiesNoThrow(
1094 dbus_utils::UnpackErrorPrinter(), params, "Timestamp", timestampPtr,
1095 "Filename", filenamePtr, "Log", logfilePtr);
1096
1097 if (!success)
Johnathan Mantey043a0532020-03-10 17:15:28 -07001098 {
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +02001099 return;
1100 }
1101
1102 if (filenamePtr != nullptr)
1103 {
1104 filename = *filenamePtr;
1105 }
1106
1107 if (timestampPtr != nullptr)
1108 {
1109 timestamp = *timestampPtr;
1110 }
1111
1112 if (logfilePtr != nullptr)
1113 {
1114 logfile = *logfilePtr;
Johnathan Mantey043a0532020-03-10 17:15:28 -07001115 }
1116}
1117
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001118inline void requestRoutesSystemLogServiceCollection(App& app)
Ed Tanous1da66f72018-07-27 16:13:37 -07001119{
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001120 /**
1121 * Functions triggers appropriate requests on DBus
1122 */
Ed Tanous22d268c2022-05-19 09:39:07 -07001123 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/")
Ed Tanoused398212021-06-09 17:05:54 -07001124 .privileges(redfish::privileges::getLogServiceCollection)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001125 .methods(
1126 boost::beast::http::verb::
1127 get)([&app](const crow::Request& req,
1128 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1129 const std::string& systemName) {
1130 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07001131 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001132 return;
1133 }
1134 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1135 {
1136 // Option currently returns no systems. TBD
1137 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1138 systemName);
1139 return;
1140 }
1141 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1142 {
1143 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1144 systemName);
Ed Tanous002d39b2022-05-31 08:59:27 -07001145 return;
1146 }
Ed Tanous45ca1b82022-03-25 13:07:27 -07001147
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001148 // Collections don't include the static data added by SubRoute
1149 // because it has a duplicate entry for members
1150 asyncResp->res.jsonValue["@odata.type"] =
1151 "#LogServiceCollection.LogServiceCollection";
1152 asyncResp->res.jsonValue["@odata.id"] =
1153 std::format("/redfish/v1/Systems/{}/LogServices",
1154 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1155 asyncResp->res.jsonValue["Name"] = "System Log Services Collection";
1156 asyncResp->res.jsonValue["Description"] =
1157 "Collection of LogServices for this Computer System";
1158 nlohmann::json& logServiceArray =
1159 asyncResp->res.jsonValue["Members"];
1160 logServiceArray = nlohmann::json::array();
1161 nlohmann::json::object_t eventLog;
1162 eventLog["@odata.id"] =
1163 std::format("/redfish/v1/Systems/{}/LogServices/EventLog",
1164 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1165 logServiceArray.emplace_back(std::move(eventLog));
1166 if constexpr (BMCWEB_REDFISH_DUMP_LOG)
Ed Tanous002d39b2022-05-31 08:59:27 -07001167 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001168 nlohmann::json::object_t dumpLog;
1169 dumpLog["@odata.id"] =
1170 std::format("/redfish/v1/Systems/{}/LogServices/Dump",
1171 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1172 logServiceArray.emplace_back(std::move(dumpLog));
Ed Tanous002d39b2022-05-31 08:59:27 -07001173 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001174
1175 if constexpr (BMCWEB_REDFISH_CPU_LOG)
1176 {
1177 nlohmann::json::object_t crashdump;
1178 crashdump["@odata.id"] =
1179 std::format("/redfish/v1/Systems/{}/LogServices/Crashdump",
1180 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1181 logServiceArray.emplace_back(std::move(crashdump));
1182 }
1183
1184 if constexpr (BMCWEB_REDFISH_HOST_LOGGER)
1185 {
1186 nlohmann::json::object_t hostlogger;
1187 hostlogger["@odata.id"] =
1188 std::format("/redfish/v1/Systems/{}/LogServices/HostLogger",
1189 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1190 logServiceArray.emplace_back(std::move(hostlogger));
1191 }
1192 asyncResp->res.jsonValue["Members@odata.count"] =
1193 logServiceArray.size();
1194
1195 constexpr std::array<std::string_view, 1> interfaces = {
1196 "xyz.openbmc_project.State.Boot.PostCode"};
1197 dbus::utility::getSubTreePaths(
1198 "/", 0, interfaces,
1199 [asyncResp](const boost::system::error_code& ec,
1200 const dbus::utility::MapperGetSubTreePathsResponse&
1201 subtreePath) {
1202 if (ec)
1203 {
1204 BMCWEB_LOG_ERROR("{}", ec);
1205 return;
1206 }
1207
1208 for (const auto& pathStr : subtreePath)
1209 {
1210 if (pathStr.find("PostCode") != std::string::npos)
1211 {
1212 nlohmann::json& logServiceArrayLocal =
1213 asyncResp->res.jsonValue["Members"];
1214 nlohmann::json::object_t member;
1215 member["@odata.id"] = std::format(
1216 "/redfish/v1/Systems/{}/LogServices/PostCodes",
1217 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1218
1219 logServiceArrayLocal.emplace_back(
1220 std::move(member));
1221
1222 asyncResp->res.jsonValue["Members@odata.count"] =
1223 logServiceArrayLocal.size();
1224 return;
1225 }
1226 }
1227 });
Ed Tanous45ca1b82022-03-25 13:07:27 -07001228 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001229}
1230
1231inline void requestRoutesEventLogService(App& app)
1232{
Ed Tanous22d268c2022-05-19 09:39:07 -07001233 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/")
Ed Tanoused398212021-06-09 17:05:54 -07001234 .privileges(redfish::privileges::getLogService)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001235 .methods(
1236 boost::beast::http::verb::
1237 get)([&app](const crow::Request& req,
1238 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1239 const std::string& systemName) {
1240 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1241 {
1242 return;
1243 }
1244 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1245 {
1246 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1247 systemName);
1248 return;
1249 }
1250 asyncResp->res.jsonValue["@odata.id"] =
1251 std::format("/redfish/v1/Systems/{}/LogServices/EventLog",
1252 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1253 asyncResp->res.jsonValue["@odata.type"] =
1254 "#LogService.v1_2_0.LogService";
1255 asyncResp->res.jsonValue["Name"] = "Event Log Service";
1256 asyncResp->res.jsonValue["Description"] =
1257 "System Event Log Service";
1258 asyncResp->res.jsonValue["Id"] = "EventLog";
1259 asyncResp->res.jsonValue["OverWritePolicy"] =
1260 log_service::OverWritePolicy::WrapsWhenFull;
Tejas Patil7c8c4052021-06-04 17:43:14 +05301261
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001262 std::pair<std::string, std::string> redfishDateTimeOffset =
1263 redfish::time_utils::getDateTimeOffsetNow();
Tejas Patil7c8c4052021-06-04 17:43:14 +05301264
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001265 asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
1266 asyncResp->res.jsonValue["DateTimeLocalOffset"] =
1267 redfishDateTimeOffset.second;
Tejas Patil7c8c4052021-06-04 17:43:14 +05301268
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001269 asyncResp->res.jsonValue["Entries"]["@odata.id"] = std::format(
1270 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
Ed Tanous20fa6a22024-05-20 18:02:58 -07001271 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001272 asyncResp->res
1273 .jsonValue["Actions"]["#LogService.ClearLog"]["target"]
1274
1275 = std::format(
1276 "/redfish/v1/Systems/{}/LogServices/EventLog/Actions/LogService.ClearLog",
1277 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1278 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001279}
1280
Alexander Hansen599b9af2024-08-06 15:11:57 +02001281inline void handleSystemsLogServicesEventLogActionsClearPost(
1282 App& app, const crow::Request& req,
1283 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1284 const std::string& systemName)
1285{
1286 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1287 {
1288 return;
1289 }
1290 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1291 {
1292 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1293 systemName);
1294 return;
1295 }
1296
1297 // Clear the EventLog by deleting the log files
1298 std::vector<std::filesystem::path> redfishLogFiles;
1299 if (getRedfishLogFiles(redfishLogFiles))
1300 {
1301 for (const std::filesystem::path& file : redfishLogFiles)
1302 {
1303 std::error_code ec;
1304 std::filesystem::remove(file, ec);
1305 }
1306 }
1307
1308 // Reload rsyslog so it knows to start new log files
1309 crow::connections::systemBus->async_method_call(
1310 [asyncResp](const boost::system::error_code& ec) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001311 if (ec)
1312 {
1313 BMCWEB_LOG_ERROR("Failed to reload rsyslog: {}", ec);
1314 messages::internalError(asyncResp->res);
1315 return;
1316 }
Alexander Hansen599b9af2024-08-06 15:11:57 +02001317
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001318 messages::success(asyncResp->res);
1319 },
Alexander Hansen599b9af2024-08-06 15:11:57 +02001320 "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
1321 "org.freedesktop.systemd1.Manager", "ReloadUnit", "rsyslog.service",
1322 "replace");
1323}
1324
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001325inline void requestRoutesJournalEventLogClear(App& app)
1326{
Jason M. Bills4978b632022-02-22 14:17:43 -08001327 BMCWEB_ROUTE(
1328 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07001329 "/redfish/v1/Systems/<str>/LogServices/EventLog/Actions/LogService.ClearLog/")
Ed Tanous432a8902021-06-14 15:28:56 -07001330 .privileges({{"ConfigureComponents"}})
Alexander Hansen599b9af2024-08-06 15:11:57 +02001331 .methods(boost::beast::http::verb::post)(std::bind_front(
1332 handleSystemsLogServicesEventLogActionsClearPost, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001333}
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001334
Jason M. Billsac992cd2022-06-24 13:31:46 -07001335enum class LogParseError
1336{
1337 success,
1338 parseFailed,
1339 messageIdNotInRegistry,
1340};
1341
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001342static LogParseError fillEventLogEntryJson(
1343 const std::string& logEntryID, const std::string& logEntry,
1344 nlohmann::json::object_t& logEntryJson)
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001345{
Jason M. Bills95820182019-04-22 16:25:34 -07001346 // The redfish log format is "<Timestamp> <MessageId>,<MessageArgs>"
Jason M. Billscd225da2019-05-08 15:31:57 -07001347 // First get the Timestamp
Ed Tanousf23b7292020-10-15 09:41:17 -07001348 size_t space = logEntry.find_first_of(' ');
Jason M. Billscd225da2019-05-08 15:31:57 -07001349 if (space == std::string::npos)
Jason M. Bills95820182019-04-22 16:25:34 -07001350 {
Jason M. Billsac992cd2022-06-24 13:31:46 -07001351 return LogParseError::parseFailed;
Jason M. Bills95820182019-04-22 16:25:34 -07001352 }
Jason M. Billscd225da2019-05-08 15:31:57 -07001353 std::string timestamp = logEntry.substr(0, space);
1354 // Then get the log contents
Ed Tanousf23b7292020-10-15 09:41:17 -07001355 size_t entryStart = logEntry.find_first_not_of(' ', space);
Jason M. Billscd225da2019-05-08 15:31:57 -07001356 if (entryStart == std::string::npos)
1357 {
Jason M. Billsac992cd2022-06-24 13:31:46 -07001358 return LogParseError::parseFailed;
Jason M. Billscd225da2019-05-08 15:31:57 -07001359 }
1360 std::string_view entry(logEntry);
1361 entry.remove_prefix(entryStart);
1362 // Use split to separate the entry into its fields
1363 std::vector<std::string> logEntryFields;
Ed Tanous50ebd4a2023-01-19 19:03:17 -08001364 bmcweb::split(logEntryFields, entry, ',');
Jason M. Billscd225da2019-05-08 15:31:57 -07001365 // We need at least a MessageId to be valid
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001366 auto logEntryIter = logEntryFields.begin();
1367 if (logEntryIter == logEntryFields.end())
Jason M. Billscd225da2019-05-08 15:31:57 -07001368 {
Jason M. Billsac992cd2022-06-24 13:31:46 -07001369 return LogParseError::parseFailed;
Jason M. Billscd225da2019-05-08 15:31:57 -07001370 }
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001371 std::string& messageID = *logEntryIter;
Jason M. Bills4851d452019-03-28 11:27:48 -07001372 // Get the Message from the MessageRegistry
Ed Tanousfffb8c12022-02-07 23:53:03 -08001373 const registries::Message* message = registries::getMessage(messageID);
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001374
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001375 logEntryIter++;
Sui Chen54417b02022-03-24 14:59:52 -07001376 if (message == nullptr)
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001377 {
Ed Tanous62598e32023-07-17 17:06:25 -07001378 BMCWEB_LOG_WARNING("Log entry not found in registry: {}", logEntry);
Jason M. Billsac992cd2022-06-24 13:31:46 -07001379 return LogParseError::messageIdNotInRegistry;
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001380 }
1381
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001382 std::vector<std::string_view> messageArgs(logEntryIter,
1383 logEntryFields.end());
Ed Tanousc05bba42023-06-28 08:33:29 -07001384 messageArgs.resize(message->numberOfArgs);
1385
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001386 std::string msg =
1387 redfish::registries::fillMessageArgs(messageArgs, message->message);
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001388 if (msg.empty())
Jason M. Bills4851d452019-03-28 11:27:48 -07001389 {
Ed Tanous1e6deaf2022-02-17 11:32:37 -08001390 return LogParseError::parseFailed;
Jason M. Bills4851d452019-03-28 11:27:48 -07001391 }
1392
Jason M. Bills95820182019-04-22 16:25:34 -07001393 // Get the Created time from the timestamp. The log timestamp is in RFC3339
1394 // format which matches the Redfish format except for the fractional seconds
1395 // between the '.' and the '+', so just remove them.
Ed Tanousf23b7292020-10-15 09:41:17 -07001396 std::size_t dot = timestamp.find_first_of('.');
1397 std::size_t plus = timestamp.find_first_of('+');
Jason M. Bills95820182019-04-22 16:25:34 -07001398 if (dot != std::string::npos && plus != std::string::npos)
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001399 {
Jason M. Bills95820182019-04-22 16:25:34 -07001400 timestamp.erase(dot, plus - dot);
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001401 }
1402
1403 // Fill in the log entry with the gathered data
Vijay Lobo9c11a172021-10-07 16:53:16 -05001404 logEntryJson["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
Ed Tanousef4c65b2023-04-24 15:28:50 -07001405 logEntryJson["@odata.id"] = boost::urls::format(
Ed Tanous253f11b2024-05-16 09:38:31 -07001406 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}",
1407 BMCWEB_REDFISH_SYSTEM_URI_NAME, logEntryID);
Jason M. Bills84afc482022-06-24 12:38:23 -07001408 logEntryJson["Name"] = "System Event Log Entry";
1409 logEntryJson["Id"] = logEntryID;
1410 logEntryJson["Message"] = std::move(msg);
1411 logEntryJson["MessageId"] = std::move(messageID);
1412 logEntryJson["MessageArgs"] = messageArgs;
1413 logEntryJson["EntryType"] = "Event";
1414 logEntryJson["Severity"] = message->messageSeverity;
1415 logEntryJson["Created"] = std::move(timestamp);
Jason M. Billsac992cd2022-06-24 13:31:46 -07001416 return LogParseError::success;
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001417}
1418
Ed Tanous898f2aa2024-08-07 12:18:22 -07001419inline void fillEventLogLogEntryFromPropertyMap(
1420 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1421 const dbus::utility::DBusPropertiesMap& resp,
1422 nlohmann::json& objectToFillOut)
1423{
Alexander Hansen262dcc12024-09-19 12:04:03 +02001424 std::optional<DbusEventLogEntry> optEntry =
1425 fillDbusEventLogEntryFromPropertyMap(resp);
Ed Tanous898f2aa2024-08-07 12:18:22 -07001426
Alexander Hansen262dcc12024-09-19 12:04:03 +02001427 if (!optEntry.has_value())
Ed Tanous898f2aa2024-08-07 12:18:22 -07001428 {
1429 messages::internalError(asyncResp->res);
1430 return;
1431 }
Alexander Hansen262dcc12024-09-19 12:04:03 +02001432 DbusEventLogEntry entry = optEntry.value();
Ed Tanous898f2aa2024-08-07 12:18:22 -07001433
1434 objectToFillOut["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
1435 objectToFillOut["@odata.id"] = boost::urls::format(
1436 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}",
Alexander Hansen262dcc12024-09-19 12:04:03 +02001437 BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(entry.Id));
Ed Tanous898f2aa2024-08-07 12:18:22 -07001438 objectToFillOut["Name"] = "System Event Log Entry";
Alexander Hansen262dcc12024-09-19 12:04:03 +02001439 objectToFillOut["Id"] = std::to_string(entry.Id);
1440 objectToFillOut["Message"] = entry.Message;
1441 objectToFillOut["Resolved"] = entry.Resolved;
1442 std::optional<bool> notifyAction =
1443 getProviderNotifyAction(entry.ServiceProviderNotify);
Ed Tanous898f2aa2024-08-07 12:18:22 -07001444 if (notifyAction)
1445 {
1446 objectToFillOut["ServiceProviderNotified"] = *notifyAction;
1447 }
Alexander Hansen262dcc12024-09-19 12:04:03 +02001448 if ((entry.Resolution != nullptr) && !entry.Resolution->empty())
Ed Tanous898f2aa2024-08-07 12:18:22 -07001449 {
Alexander Hansen262dcc12024-09-19 12:04:03 +02001450 objectToFillOut["Resolution"] = *entry.Resolution;
Ed Tanous898f2aa2024-08-07 12:18:22 -07001451 }
1452 objectToFillOut["EntryType"] = "Event";
Alexander Hansen262dcc12024-09-19 12:04:03 +02001453 objectToFillOut["Severity"] =
1454 translateSeverityDbusToRedfish(entry.Severity);
Ed Tanous898f2aa2024-08-07 12:18:22 -07001455 objectToFillOut["Created"] =
Alexander Hansen262dcc12024-09-19 12:04:03 +02001456 redfish::time_utils::getDateTimeUintMs(entry.Timestamp);
Ed Tanous898f2aa2024-08-07 12:18:22 -07001457 objectToFillOut["Modified"] =
Alexander Hansen262dcc12024-09-19 12:04:03 +02001458 redfish::time_utils::getDateTimeUintMs(entry.UpdateTimestamp);
1459 if (entry.Path != nullptr)
Ed Tanous898f2aa2024-08-07 12:18:22 -07001460 {
1461 objectToFillOut["AdditionalDataURI"] = boost::urls::format(
1462 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}/attachment",
Alexander Hansen262dcc12024-09-19 12:04:03 +02001463 BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(entry.Id));
Ed Tanous898f2aa2024-08-07 12:18:22 -07001464 }
1465}
1466
Ed Tanousb7290962024-08-07 11:09:51 -07001467inline void afterLogEntriesGetManagedObjects(
1468 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1469 const boost::system::error_code& ec,
1470 const dbus::utility::ManagedObjectType& resp)
1471{
1472 if (ec)
1473 {
1474 // TODO Handle for specific error code
1475 BMCWEB_LOG_ERROR("getLogEntriesIfaceData resp_handler got error {}",
1476 ec);
1477 messages::internalError(asyncResp->res);
1478 return;
1479 }
1480 nlohmann::json::array_t entriesArray;
1481 for (const auto& objectPath : resp)
1482 {
Ed Tanous898f2aa2024-08-07 12:18:22 -07001483 dbus::utility::DBusPropertiesMap propsFlattened;
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001484 auto isEntry =
1485 std::ranges::find_if(objectPath.second, [](const auto& object) {
1486 return object.first == "xyz.openbmc_project.Logging.Entry";
1487 });
Ed Tanous898f2aa2024-08-07 12:18:22 -07001488 if (isEntry == objectPath.second.end())
Ed Tanousb7290962024-08-07 11:09:51 -07001489 {
1490 continue;
1491 }
Ed Tanous898f2aa2024-08-07 12:18:22 -07001492 for (const auto& interfaceMap : objectPath.second)
Ed Tanousb7290962024-08-07 11:09:51 -07001493 {
Ed Tanous898f2aa2024-08-07 12:18:22 -07001494 for (const auto& propertyMap : interfaceMap.second)
Ed Tanousb7290962024-08-07 11:09:51 -07001495 {
Ed Tanous898f2aa2024-08-07 12:18:22 -07001496 propsFlattened.emplace_back(propertyMap.first,
1497 propertyMap.second);
Ed Tanousb7290962024-08-07 11:09:51 -07001498 }
1499 }
Ed Tanous898f2aa2024-08-07 12:18:22 -07001500 fillEventLogLogEntryFromPropertyMap(asyncResp, propsFlattened,
1501 entriesArray.emplace_back());
Ed Tanousb7290962024-08-07 11:09:51 -07001502 }
Ed Tanous898f2aa2024-08-07 12:18:22 -07001503
Ed Tanousb7290962024-08-07 11:09:51 -07001504 std::ranges::sort(entriesArray, [](const nlohmann::json& left,
1505 const nlohmann::json& right) {
1506 return (left["Id"] <= right["Id"]);
1507 });
1508 asyncResp->res.jsonValue["Members@odata.count"] = entriesArray.size();
1509 asyncResp->res.jsonValue["Members"] = std::move(entriesArray);
1510}
1511
Alexander Hansen599b9af2024-08-06 15:11:57 +02001512inline void handleSystemsLogServiceEventLogLogEntryCollection(
1513 App& app, const crow::Request& req,
1514 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1515 const std::string& systemName)
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001516{
Alexander Hansen599b9af2024-08-06 15:11:57 +02001517 query_param::QueryCapabilities capabilities = {
1518 .canDelegateTop = true,
1519 .canDelegateSkip = true,
1520 };
1521 query_param::Query delegatedQuery;
1522 if (!redfish::setUpRedfishRouteWithDelegation(app, req, asyncResp,
1523 delegatedQuery, capabilities))
1524 {
1525 return;
1526 }
1527 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1528 {
1529 // Option currently returns no systems. TBD
1530 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1531 systemName);
1532 return;
1533 }
1534 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1535 {
1536 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1537 systemName);
1538 return;
1539 }
1540
1541 size_t top = delegatedQuery.top.value_or(query_param::Query::maxTop);
1542 size_t skip = delegatedQuery.skip.value_or(0);
1543
1544 // Collections don't include the static data added by SubRoute
1545 // because it has a duplicate entry for members
1546 asyncResp->res.jsonValue["@odata.type"] =
1547 "#LogEntryCollection.LogEntryCollection";
1548 asyncResp->res.jsonValue["@odata.id"] =
1549 std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
1550 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1551 asyncResp->res.jsonValue["Name"] = "System Event Log Entries";
1552 asyncResp->res.jsonValue["Description"] =
1553 "Collection of System Event Log Entries";
1554
1555 nlohmann::json& logEntryArray = asyncResp->res.jsonValue["Members"];
1556 logEntryArray = nlohmann::json::array();
1557 // Go through the log files and create a unique ID for each
1558 // entry
1559 std::vector<std::filesystem::path> redfishLogFiles;
1560 getRedfishLogFiles(redfishLogFiles);
1561 uint64_t entryCount = 0;
1562 std::string logEntry;
1563
1564 // Oldest logs are in the last file, so start there and loop
1565 // backwards
1566 for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend(); it++)
1567 {
1568 std::ifstream logStream(*it);
1569 if (!logStream.is_open())
Ed Tanous002d39b2022-05-31 08:59:27 -07001570 {
Alexander Hansen599b9af2024-08-06 15:11:57 +02001571 continue;
Ed Tanous22d268c2022-05-19 09:39:07 -07001572 }
1573
Alexander Hansen599b9af2024-08-06 15:11:57 +02001574 // Reset the unique ID on the first entry
1575 bool firstEntry = true;
1576 while (std::getline(logStream, logEntry))
Ed Tanous002d39b2022-05-31 08:59:27 -07001577 {
Alexander Hansen599b9af2024-08-06 15:11:57 +02001578 std::string idStr;
1579 if (!getUniqueEntryID(logEntry, idStr, firstEntry))
1580 {
1581 continue;
1582 }
1583 firstEntry = false;
1584
1585 nlohmann::json::object_t bmcLogEntry;
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001586 LogParseError status =
1587 fillEventLogEntryJson(idStr, logEntry, bmcLogEntry);
Alexander Hansen599b9af2024-08-06 15:11:57 +02001588 if (status == LogParseError::messageIdNotInRegistry)
1589 {
1590 continue;
1591 }
1592 if (status != LogParseError::success)
1593 {
1594 messages::internalError(asyncResp->res);
1595 return;
1596 }
1597
1598 entryCount++;
1599 // Handle paging using skip (number of entries to skip from the
1600 // start) and top (number of entries to display)
1601 if (entryCount <= skip || entryCount > skip + top)
Jason M. Bills4978b632022-02-22 14:17:43 -08001602 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001603 continue;
Jason M. Bills4978b632022-02-22 14:17:43 -08001604 }
Jason M. Bills897967d2019-07-29 17:05:30 -07001605
Alexander Hansen599b9af2024-08-06 15:11:57 +02001606 logEntryArray.emplace_back(std::move(bmcLogEntry));
1607 }
1608 }
1609 asyncResp->res.jsonValue["Members@odata.count"] = entryCount;
1610 if (skip + top < entryCount)
1611 {
1612 asyncResp->res.jsonValue["Members@odata.nextLink"] =
1613 boost::urls::format(
1614 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries?$skip={}",
1615 BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(skip + top));
1616 }
1617}
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001618
Alexander Hansen599b9af2024-08-06 15:11:57 +02001619inline void requestRoutesJournalEventLogEntryCollection(App& app)
1620{
1621 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/")
1622 .privileges(redfish::privileges::getLogEntryCollection)
1623 .methods(boost::beast::http::verb::get)(std::bind_front(
1624 handleSystemsLogServiceEventLogLogEntryCollection, std::ref(app)));
1625}
1626
1627inline void handleSystemsLogServiceEventLogEntriesGet(
1628 App& app, const crow::Request& req,
1629 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1630 const std::string& systemName, const std::string& param)
1631{
1632 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1633 {
1634 return;
1635 }
1636 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1637 {
1638 // Option currently returns no systems. TBD
1639 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1640 systemName);
1641 return;
1642 }
1643
1644 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1645 {
1646 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1647 systemName);
1648 return;
1649 }
1650
1651 const std::string& targetID = param;
1652
1653 // Go through the log files and check the unique ID for each
1654 // entry to find the target entry
1655 std::vector<std::filesystem::path> redfishLogFiles;
1656 getRedfishLogFiles(redfishLogFiles);
1657 std::string logEntry;
1658
1659 // Oldest logs are in the last file, so start there and loop
1660 // backwards
1661 for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend(); it++)
1662 {
1663 std::ifstream logStream(*it);
1664 if (!logStream.is_open())
1665 {
1666 continue;
1667 }
1668
1669 // Reset the unique ID on the first entry
1670 bool firstEntry = true;
1671 while (std::getline(logStream, logEntry))
1672 {
1673 std::string idStr;
1674 if (!getUniqueEntryID(logEntry, idStr, firstEntry))
1675 {
1676 continue;
1677 }
1678 firstEntry = false;
1679
1680 if (idStr == targetID)
1681 {
Jason M. Billsde703c52022-06-23 14:19:04 -07001682 nlohmann::json::object_t bmcLogEntry;
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001683 LogParseError status =
1684 fillEventLogEntryJson(idStr, logEntry, bmcLogEntry);
Jason M. Billsac992cd2022-06-24 13:31:46 -07001685 if (status != LogParseError::success)
Ed Tanous002d39b2022-05-31 08:59:27 -07001686 {
1687 messages::internalError(asyncResp->res);
1688 return;
Andrew Geisslercb92c032018-08-17 07:56:14 -07001689 }
Alexander Hansen599b9af2024-08-06 15:11:57 +02001690 asyncResp->res.jsonValue.update(bmcLogEntry);
1691 return;
Jason M. Bills4978b632022-02-22 14:17:43 -08001692 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001693 }
Alexander Hansen599b9af2024-08-06 15:11:57 +02001694 }
1695 // Requested ID was not found
1696 messages::resourceNotFound(asyncResp->res, "LogEntry", targetID);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001697}
Chicago Duan336e96c2019-07-15 14:22:08 +08001698
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001699inline void requestRoutesJournalEventLogEntry(App& app)
1700{
1701 BMCWEB_ROUTE(
Ed Tanous22d268c2022-05-19 09:39:07 -07001702 app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001703 .privileges(redfish::privileges::getLogEntry)
Alexander Hansen599b9af2024-08-06 15:11:57 +02001704 .methods(boost::beast::http::verb::get)(std::bind_front(
1705 handleSystemsLogServiceEventLogEntriesGet, std::ref(app)));
1706}
1707
1708inline void dBusEventLogEntryCollection(
1709 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1710{
1711 // Collections don't include the static data added by SubRoute
1712 // because it has a duplicate entry for members
1713 asyncResp->res.jsonValue["@odata.type"] =
1714 "#LogEntryCollection.LogEntryCollection";
1715 asyncResp->res.jsonValue["@odata.id"] =
1716 std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
1717 BMCWEB_REDFISH_SYSTEM_URI_NAME);
1718 asyncResp->res.jsonValue["Name"] = "System Event Log Entries";
1719 asyncResp->res.jsonValue["Description"] =
1720 "Collection of System Event Log Entries";
1721
1722 // DBus implementation of EventLog/Entries
1723 // Make call to Logging Service to find all log entry objects
1724 sdbusplus::message::object_path path("/xyz/openbmc_project/logging");
1725 dbus::utility::getManagedObjects(
1726 "xyz.openbmc_project.Logging", path,
1727 [asyncResp](const boost::system::error_code& ec,
1728 const dbus::utility::ManagedObjectType& resp) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001729 afterLogEntriesGetManagedObjects(asyncResp, ec, resp);
1730 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001731}
1732
1733inline void requestRoutesDBusEventLogEntryCollection(App& app)
1734{
Ed Tanous22d268c2022-05-19 09:39:07 -07001735 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/")
Ed Tanoused398212021-06-09 17:05:54 -07001736 .privileges(redfish::privileges::getLogEntryCollection)
Ed Tanous002d39b2022-05-31 08:59:27 -07001737 .methods(boost::beast::http::verb::get)(
1738 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07001739 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1740 const std::string& systemName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001741 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1742 {
1743 return;
1744 }
1745 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1746 {
1747 // Option currently returns no systems. TBD
1748 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1749 systemName);
1750 return;
1751 }
1752 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1753 {
1754 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1755 systemName);
1756 return;
1757 }
1758 dBusEventLogEntryCollection(asyncResp);
1759 });
Alexander Hansen599b9af2024-08-06 15:11:57 +02001760}
Ed Tanous22d268c2022-05-19 09:39:07 -07001761
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001762inline void dBusEventLogEntryGet(
1763 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID)
Alexander Hansen599b9af2024-08-06 15:11:57 +02001764{
1765 dbus::utility::escapePathForDbus(entryID);
Ed Tanous002d39b2022-05-31 08:59:27 -07001766
Alexander Hansen599b9af2024-08-06 15:11:57 +02001767 // DBus implementation of EventLog/Entries
1768 // Make call to Logging Service to find all log entry objects
Ed Tanousdeae6a72024-11-11 21:58:57 -08001769 dbus::utility::getAllProperties(
1770 "xyz.openbmc_project.Logging",
Alexander Hansen599b9af2024-08-06 15:11:57 +02001771 "/xyz/openbmc_project/logging/entry/" + entryID, "",
1772 [asyncResp, entryID](const boost::system::error_code& ec,
1773 const dbus::utility::DBusPropertiesMap& resp) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001774 if (ec.value() == EBADR)
1775 {
1776 messages::resourceNotFound(asyncResp->res, "EventLogEntry",
1777 entryID);
1778 return;
1779 }
1780 if (ec)
1781 {
1782 BMCWEB_LOG_ERROR(
1783 "EventLogEntry (DBus) resp_handler got error {}", ec);
1784 messages::internalError(asyncResp->res);
1785 return;
1786 }
Alexander Hansen599b9af2024-08-06 15:11:57 +02001787
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001788 fillEventLogLogEntryFromPropertyMap(asyncResp, resp,
1789 asyncResp->res.jsonValue);
1790 });
Alexander Hansen599b9af2024-08-06 15:11:57 +02001791}
1792
1793inline void
1794 dBusEventLogEntryPatch(const crow::Request& req,
1795 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1796 const std::string& entryId)
1797{
1798 std::optional<bool> resolved;
1799
1800 if (!json_util::readJsonPatch(req, asyncResp->res, "Resolved", resolved))
1801 {
1802 return;
1803 }
1804 BMCWEB_LOG_DEBUG("Set Resolved");
1805
1806 setDbusProperty(asyncResp, "Resolved", "xyz.openbmc_project.Logging",
1807 "/xyz/openbmc_project/logging/entry/" + entryId,
1808 "xyz.openbmc_project.Logging.Entry", "Resolved",
1809 resolved.value_or(false));
1810}
1811
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001812inline void dBusEventLogEntryDelete(
1813 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID)
Alexander Hansen599b9af2024-08-06 15:11:57 +02001814{
1815 BMCWEB_LOG_DEBUG("Do delete single event entries.");
1816
1817 dbus::utility::escapePathForDbus(entryID);
1818
1819 // Process response from Logging service.
1820 auto respHandler = [asyncResp,
1821 entryID](const boost::system::error_code& ec) {
1822 BMCWEB_LOG_DEBUG("EventLogEntry (DBus) doDelete callback: Done");
1823 if (ec)
1824 {
1825 if (ec.value() == EBADR)
Ed Tanous45ca1b82022-03-25 13:07:27 -07001826 {
Alexander Hansen599b9af2024-08-06 15:11:57 +02001827 messages::resourceNotFound(asyncResp->res, "LogEntry", entryID);
Ed Tanous45ca1b82022-03-25 13:07:27 -07001828 return;
1829 }
Alexander Hansen599b9af2024-08-06 15:11:57 +02001830 // TODO Handle for specific error code
1831 BMCWEB_LOG_ERROR(
1832 "EventLogEntry (DBus) doDelete respHandler got error {}", ec);
1833 asyncResp->res.result(
1834 boost::beast::http::status::internal_server_error);
1835 return;
1836 }
Abhishek Patel9017faf2021-09-14 22:48:55 -05001837
Alexander Hansen599b9af2024-08-06 15:11:57 +02001838 asyncResp->res.result(boost::beast::http::status::ok);
1839 };
1840
1841 // Make call to Logging service to request Delete Log
1842 crow::connections::systemBus->async_method_call(
1843 respHandler, "xyz.openbmc_project.Logging",
1844 "/xyz/openbmc_project/logging/entry/" + entryID,
1845 "xyz.openbmc_project.Object.Delete", "Delete");
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001846}
Xiaochao Ma75710de2021-01-21 17:56:02 +08001847
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001848inline void requestRoutesDBusEventLogEntry(App& app)
Adriana Kobylak400fd1f2021-01-29 09:01:30 -06001849{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001850 BMCWEB_ROUTE(
Ed Tanous22d268c2022-05-19 09:39:07 -07001851 app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001852 .privileges(redfish::privileges::getLogEntry)
Ed Tanous002d39b2022-05-31 08:59:27 -07001853 .methods(boost::beast::http::verb::get)(
1854 [&app](const crow::Request& req,
1855 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous898f2aa2024-08-07 12:18:22 -07001856 const std::string& systemName, const std::string& entryId) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001857 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1858 {
1859 return;
1860 }
1861 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1862 {
1863 // Option currently returns no systems. TBD
1864 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1865 systemName);
1866 return;
1867 }
1868 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1869 {
1870 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1871 systemName);
1872 return;
1873 }
Ed Tanous22d268c2022-05-19 09:39:07 -07001874
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001875 dBusEventLogEntryGet(asyncResp, entryId);
1876 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001877
1878 BMCWEB_ROUTE(
Ed Tanous22d268c2022-05-19 09:39:07 -07001879 app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001880 .privileges(redfish::privileges::patchLogEntry)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001881 .methods(boost::beast::http::verb::patch)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07001882 [&app](const crow::Request& req,
1883 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -07001884 const std::string& systemName, const std::string& entryId) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001885 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1886 {
1887 return;
1888 }
1889 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1890 {
1891 // Option currently returns no systems. TBD
1892 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1893 systemName);
1894 return;
1895 }
1896 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1897 {
1898 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1899 systemName);
1900 return;
1901 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001902
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001903 dBusEventLogEntryPatch(req, asyncResp, entryId);
1904 });
Adriana Kobylak400fd1f2021-01-29 09:01:30 -06001905
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001906 BMCWEB_ROUTE(
Ed Tanous22d268c2022-05-19 09:39:07 -07001907 app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001908 .privileges(redfish::privileges::deleteLogEntry)
1909
Ed Tanous002d39b2022-05-31 08:59:27 -07001910 .methods(boost::beast::http::verb::delete_)(
1911 [&app](const crow::Request& req,
1912 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -07001913 const std::string& systemName, const std::string& param) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001914 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1915 {
1916 return;
1917 }
1918 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1919 {
1920 // Option currently returns no systems. TBD
1921 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1922 systemName);
1923 return;
1924 }
1925 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
1926 {
1927 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
1928 systemName);
1929 return;
1930 }
1931 dBusEventLogEntryDelete(asyncResp, param);
1932 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001933}
1934
Spencer Kub7028eb2021-10-26 15:27:35 +08001935constexpr const char* hostLoggerFolderPath = "/var/log/console";
1936
1937inline bool
1938 getHostLoggerFiles(const std::string& hostLoggerFilePath,
1939 std::vector<std::filesystem::path>& hostLoggerFiles)
1940{
1941 std::error_code ec;
1942 std::filesystem::directory_iterator logPath(hostLoggerFilePath, ec);
1943 if (ec)
1944 {
Carson Labradobf2dded2023-08-10 00:37:06 +00001945 BMCWEB_LOG_WARNING("{}", ec.message());
Spencer Kub7028eb2021-10-26 15:27:35 +08001946 return false;
1947 }
1948 for (const std::filesystem::directory_entry& it : logPath)
1949 {
1950 std::string filename = it.path().filename();
1951 // Prefix of each log files is "log". Find the file and save the
1952 // path
Ed Tanous11ba3972022-07-11 09:50:41 -07001953 if (filename.starts_with("log"))
Spencer Kub7028eb2021-10-26 15:27:35 +08001954 {
1955 hostLoggerFiles.emplace_back(it.path());
1956 }
1957 }
1958 // As the log files rotate, they are appended with a ".#" that is higher for
1959 // the older logs. Since we start from oldest logs, sort the name in
1960 // descending order.
1961 std::sort(hostLoggerFiles.rbegin(), hostLoggerFiles.rend(),
1962 AlphanumLess<std::string>());
1963
1964 return true;
1965}
1966
Ed Tanous02cad962022-06-30 16:50:15 -07001967inline bool getHostLoggerEntries(
1968 const std::vector<std::filesystem::path>& hostLoggerFiles, uint64_t skip,
1969 uint64_t top, std::vector<std::string>& logEntries, size_t& logCount)
Spencer Kub7028eb2021-10-26 15:27:35 +08001970{
1971 GzFileReader logFile;
1972
1973 // Go though all log files and expose host logs.
1974 for (const std::filesystem::path& it : hostLoggerFiles)
1975 {
1976 if (!logFile.gzGetLines(it.string(), skip, top, logEntries, logCount))
1977 {
Ed Tanous62598e32023-07-17 17:06:25 -07001978 BMCWEB_LOG_ERROR("fail to expose host logs");
Spencer Kub7028eb2021-10-26 15:27:35 +08001979 return false;
1980 }
1981 }
1982 // Get lastMessage from constructor by getter
1983 std::string lastMessage = logFile.getLastMessage();
1984 if (!lastMessage.empty())
1985 {
1986 logCount++;
1987 if (logCount > skip && logCount <= (skip + top))
1988 {
1989 logEntries.push_back(lastMessage);
1990 }
1991 }
1992 return true;
1993}
1994
Claire Weinandd72e872022-08-15 14:20:06 -07001995inline void handleBMCLogServicesCollectionGet(
Claire Weinanfdd26902022-03-01 14:18:25 -08001996 crow::App& app, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07001997 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1998 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08001999{
2000 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2001 {
2002 return;
2003 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002004
2005 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2006 {
2007 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2008 return;
2009 }
2010
Claire Weinanfdd26902022-03-01 14:18:25 -08002011 // Collections don't include the static data added by SubRoute
2012 // because it has a duplicate entry for members
2013 asyncResp->res.jsonValue["@odata.type"] =
2014 "#LogServiceCollection.LogServiceCollection";
Ed Tanous253f11b2024-05-16 09:38:31 -07002015 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
2016 "/redfish/v1/Managers/{}/LogServices", BMCWEB_REDFISH_MANAGER_URI_NAME);
Claire Weinanfdd26902022-03-01 14:18:25 -08002017 asyncResp->res.jsonValue["Name"] = "Open BMC Log Services Collection";
2018 asyncResp->res.jsonValue["Description"] =
2019 "Collection of LogServices for this Manager";
2020 nlohmann::json& logServiceArray = asyncResp->res.jsonValue["Members"];
2021 logServiceArray = nlohmann::json::array();
2022
Ed Tanous25b54db2024-04-17 15:40:31 -07002023 if constexpr (BMCWEB_REDFISH_BMC_JOURNAL)
2024 {
2025 nlohmann::json::object_t journal;
Ed Tanous253f11b2024-05-16 09:38:31 -07002026 journal["@odata.id"] =
2027 boost::urls::format("/redfish/v1/Managers/{}/LogServices/Journal",
2028 BMCWEB_REDFISH_MANAGER_URI_NAME);
Ed Tanous25b54db2024-04-17 15:40:31 -07002029 logServiceArray.emplace_back(std::move(journal));
2030 }
Claire Weinanfdd26902022-03-01 14:18:25 -08002031
2032 asyncResp->res.jsonValue["Members@odata.count"] = logServiceArray.size();
2033
Ed Tanous25b54db2024-04-17 15:40:31 -07002034 if constexpr (BMCWEB_REDFISH_DUMP_LOG)
2035 {
2036 constexpr std::array<std::string_view, 1> interfaces = {
2037 "xyz.openbmc_project.Collection.DeleteAll"};
2038 dbus::utility::getSubTreePaths(
2039 "/xyz/openbmc_project/dump", 0, interfaces,
2040 [asyncResp](const boost::system::error_code& ec,
2041 const dbus::utility::MapperGetSubTreePathsResponse&
2042 subTreePaths) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002043 if (ec)
Ed Tanous25b54db2024-04-17 15:40:31 -07002044 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002045 BMCWEB_LOG_ERROR(
2046 "handleBMCLogServicesCollectionGet respHandler got error {}",
2047 ec);
2048 // Assume that getting an error simply means there are no
2049 // dump LogServices. Return without adding any error
2050 // response.
2051 return;
Ed Tanous25b54db2024-04-17 15:40:31 -07002052 }
Ed Tanous25b54db2024-04-17 15:40:31 -07002053
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002054 nlohmann::json& logServiceArrayLocal =
2055 asyncResp->res.jsonValue["Members"];
2056
2057 for (const std::string& path : subTreePaths)
2058 {
2059 if (path == "/xyz/openbmc_project/dump/bmc")
2060 {
2061 nlohmann::json::object_t member;
2062 member["@odata.id"] = boost::urls::format(
2063 "/redfish/v1/Managers/{}/LogServices/Dump",
2064 BMCWEB_REDFISH_MANAGER_URI_NAME);
2065 logServiceArrayLocal.emplace_back(std::move(member));
2066 }
2067 else if (path == "/xyz/openbmc_project/dump/faultlog")
2068 {
2069 nlohmann::json::object_t member;
2070 member["@odata.id"] = boost::urls::format(
2071 "/redfish/v1/Managers/{}/LogServices/FaultLog",
2072 BMCWEB_REDFISH_MANAGER_URI_NAME);
2073 logServiceArrayLocal.emplace_back(std::move(member));
2074 }
2075 }
2076
2077 asyncResp->res.jsonValue["Members@odata.count"] =
2078 logServiceArrayLocal.size();
2079 });
Ed Tanous25b54db2024-04-17 15:40:31 -07002080 }
Claire Weinanfdd26902022-03-01 14:18:25 -08002081}
2082
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002083inline void requestRoutesBMCLogServiceCollection(App& app)
2084{
Ed Tanous253f11b2024-05-16 09:38:31 -07002085 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/")
Gunnar Millsad89dcf2021-07-30 14:40:11 -05002086 .privileges(redfish::privileges::getLogServiceCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002087 .methods(boost::beast::http::verb::get)(
Claire Weinandd72e872022-08-15 14:20:06 -07002088 std::bind_front(handleBMCLogServicesCollectionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002089}
Ed Tanous1da66f72018-07-27 16:13:37 -07002090
Claire Weinanfdd26902022-03-01 14:18:25 -08002091inline void
2092 getDumpServiceInfo(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2093 const std::string& dumpType)
2094{
2095 std::string dumpPath;
Ed Tanous539d8c62024-06-19 14:38:27 -07002096 log_service::OverWritePolicy overWritePolicy =
2097 log_service::OverWritePolicy::Invalid;
Claire Weinanfdd26902022-03-01 14:18:25 -08002098 bool collectDiagnosticDataSupported = false;
2099
2100 if (dumpType == "BMC")
2101 {
Ed Tanous253f11b2024-05-16 09:38:31 -07002102 dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/Dump",
2103 BMCWEB_REDFISH_MANAGER_URI_NAME);
Ed Tanous539d8c62024-06-19 14:38:27 -07002104 overWritePolicy = log_service::OverWritePolicy::WrapsWhenFull;
Claire Weinanfdd26902022-03-01 14:18:25 -08002105 collectDiagnosticDataSupported = true;
2106 }
2107 else if (dumpType == "FaultLog")
2108 {
Ed Tanous253f11b2024-05-16 09:38:31 -07002109 dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/FaultLog",
2110 BMCWEB_REDFISH_MANAGER_URI_NAME);
Ed Tanous539d8c62024-06-19 14:38:27 -07002111 overWritePolicy = log_service::OverWritePolicy::Unknown;
Claire Weinanfdd26902022-03-01 14:18:25 -08002112 collectDiagnosticDataSupported = false;
2113 }
2114 else if (dumpType == "System")
2115 {
Ed Tanous253f11b2024-05-16 09:38:31 -07002116 dumpPath = std::format("/redfish/v1/Systems/{}/LogServices/Dump",
2117 BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanous539d8c62024-06-19 14:38:27 -07002118 overWritePolicy = log_service::OverWritePolicy::WrapsWhenFull;
Claire Weinanfdd26902022-03-01 14:18:25 -08002119 collectDiagnosticDataSupported = true;
2120 }
2121 else
2122 {
Ed Tanous62598e32023-07-17 17:06:25 -07002123 BMCWEB_LOG_ERROR("getDumpServiceInfo() invalid dump type: {}",
2124 dumpType);
Claire Weinanfdd26902022-03-01 14:18:25 -08002125 messages::internalError(asyncResp->res);
2126 return;
2127 }
2128
2129 asyncResp->res.jsonValue["@odata.id"] = dumpPath;
2130 asyncResp->res.jsonValue["@odata.type"] = "#LogService.v1_2_0.LogService";
2131 asyncResp->res.jsonValue["Name"] = "Dump LogService";
2132 asyncResp->res.jsonValue["Description"] = dumpType + " Dump LogService";
2133 asyncResp->res.jsonValue["Id"] = std::filesystem::path(dumpPath).filename();
Ed Tanous539d8c62024-06-19 14:38:27 -07002134 asyncResp->res.jsonValue["OverWritePolicy"] = overWritePolicy;
Claire Weinanfdd26902022-03-01 14:18:25 -08002135
2136 std::pair<std::string, std::string> redfishDateTimeOffset =
Ed Tanous2b829372022-08-03 14:22:34 -07002137 redfish::time_utils::getDateTimeOffsetNow();
Claire Weinanfdd26902022-03-01 14:18:25 -08002138 asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
2139 asyncResp->res.jsonValue["DateTimeLocalOffset"] =
2140 redfishDateTimeOffset.second;
2141
2142 asyncResp->res.jsonValue["Entries"]["@odata.id"] = dumpPath + "/Entries";
Claire Weinanfdd26902022-03-01 14:18:25 -08002143
2144 if (collectDiagnosticDataSupported)
2145 {
2146 asyncResp->res.jsonValue["Actions"]["#LogService.CollectDiagnosticData"]
2147 ["target"] =
2148 dumpPath + "/Actions/LogService.CollectDiagnosticData";
2149 }
Claire Weinan0d946212022-07-13 19:40:19 -07002150
2151 constexpr std::array<std::string_view, 1> interfaces = {deleteAllInterface};
2152 dbus::utility::getSubTreePaths(
2153 "/xyz/openbmc_project/dump", 0, interfaces,
2154 [asyncResp, dumpType, dumpPath](
2155 const boost::system::error_code& ec,
2156 const dbus::utility::MapperGetSubTreePathsResponse& subTreePaths) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002157 if (ec)
Claire Weinan0d946212022-07-13 19:40:19 -07002158 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002159 BMCWEB_LOG_ERROR("getDumpServiceInfo respHandler got error {}",
2160 ec);
2161 // Assume that getting an error simply means there are no dump
2162 // LogServices. Return without adding any error response.
2163 return;
Claire Weinan0d946212022-07-13 19:40:19 -07002164 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002165 std::string dbusDumpPath = getDumpPath(dumpType);
2166 for (const std::string& path : subTreePaths)
2167 {
2168 if (path == dbusDumpPath)
2169 {
2170 asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"]
2171 ["target"] =
2172 dumpPath + "/Actions/LogService.ClearLog";
2173 break;
2174 }
2175 }
2176 });
Claire Weinanfdd26902022-03-01 14:18:25 -08002177}
2178
2179inline void handleLogServicesDumpServiceGet(
2180 crow::App& app, const std::string& dumpType, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07002181 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2182 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002183{
2184 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2185 {
2186 return;
2187 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002188
2189 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2190 {
2191 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2192 return;
2193 }
2194
Claire Weinanfdd26902022-03-01 14:18:25 -08002195 getDumpServiceInfo(asyncResp, dumpType);
2196}
2197
Ed Tanous22d268c2022-05-19 09:39:07 -07002198inline void handleLogServicesDumpServiceComputerSystemGet(
2199 crow::App& app, const crow::Request& req,
2200 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2201 const std::string& chassisId)
2202{
2203 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2204 {
2205 return;
2206 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002207 if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous22d268c2022-05-19 09:39:07 -07002208 {
2209 messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
2210 return;
2211 }
2212 getDumpServiceInfo(asyncResp, "System");
2213}
2214
Claire Weinanfdd26902022-03-01 14:18:25 -08002215inline void handleLogServicesDumpEntriesCollectionGet(
2216 crow::App& app, const std::string& dumpType, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07002217 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2218 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002219{
2220 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2221 {
2222 return;
2223 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002224
2225 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2226 {
2227 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2228 return;
2229 }
Claire Weinanfdd26902022-03-01 14:18:25 -08002230 getDumpEntryCollection(asyncResp, dumpType);
2231}
2232
Ed Tanous22d268c2022-05-19 09:39:07 -07002233inline void handleLogServicesDumpEntriesCollectionComputerSystemGet(
2234 crow::App& app, const crow::Request& req,
2235 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2236 const std::string& chassisId)
2237{
2238 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2239 {
2240 return;
2241 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002242 if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous22d268c2022-05-19 09:39:07 -07002243 {
2244 messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
2245 return;
2246 }
2247 getDumpEntryCollection(asyncResp, "System");
2248}
2249
Claire Weinanfdd26902022-03-01 14:18:25 -08002250inline void handleLogServicesDumpEntryGet(
2251 crow::App& app, const std::string& dumpType, const crow::Request& req,
2252 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous253f11b2024-05-16 09:38:31 -07002253 const std::string& managerId, const std::string& dumpId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002254{
2255 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2256 {
2257 return;
2258 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002259 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2260 {
2261 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2262 return;
2263 }
Claire Weinanfdd26902022-03-01 14:18:25 -08002264 getDumpEntryById(asyncResp, dumpId, dumpType);
2265}
Carson Labrado168d1b12023-03-27 17:04:46 +00002266
Ed Tanous22d268c2022-05-19 09:39:07 -07002267inline void handleLogServicesDumpEntryComputerSystemGet(
2268 crow::App& app, const crow::Request& req,
2269 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2270 const std::string& chassisId, const std::string& dumpId)
2271{
2272 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2273 {
2274 return;
2275 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002276 if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous22d268c2022-05-19 09:39:07 -07002277 {
2278 messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
2279 return;
2280 }
2281 getDumpEntryById(asyncResp, dumpId, "System");
2282}
Claire Weinanfdd26902022-03-01 14:18:25 -08002283
2284inline void handleLogServicesDumpEntryDelete(
2285 crow::App& app, const std::string& dumpType, const crow::Request& req,
2286 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous253f11b2024-05-16 09:38:31 -07002287 const std::string& managerId, const std::string& dumpId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002288{
2289 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2290 {
2291 return;
2292 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002293
2294 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2295 {
2296 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2297 return;
2298 }
Claire Weinanfdd26902022-03-01 14:18:25 -08002299 deleteDumpEntry(asyncResp, dumpId, dumpType);
2300}
2301
Ed Tanous22d268c2022-05-19 09:39:07 -07002302inline void handleLogServicesDumpEntryComputerSystemDelete(
2303 crow::App& app, const crow::Request& req,
2304 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2305 const std::string& chassisId, const std::string& dumpId)
2306{
2307 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2308 {
2309 return;
2310 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002311 if (chassisId != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous22d268c2022-05-19 09:39:07 -07002312 {
2313 messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
2314 return;
2315 }
2316 deleteDumpEntry(asyncResp, dumpId, "System");
2317}
2318
Carson Labrado168d1b12023-03-27 17:04:46 +00002319inline void handleLogServicesDumpEntryDownloadGet(
2320 crow::App& app, const std::string& dumpType, const crow::Request& req,
2321 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous253f11b2024-05-16 09:38:31 -07002322 const std::string& managerId, const std::string& dumpId)
Carson Labrado168d1b12023-03-27 17:04:46 +00002323{
2324 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2325 {
2326 return;
2327 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002328
2329 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2330 {
2331 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2332 return;
2333 }
Carson Labrado168d1b12023-03-27 17:04:46 +00002334 downloadDumpEntry(asyncResp, dumpId, dumpType);
2335}
2336
2337inline void handleDBusEventLogEntryDownloadGet(
2338 crow::App& app, const std::string& dumpType, const crow::Request& req,
2339 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2340 const std::string& systemName, const std::string& entryID)
2341{
2342 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2343 {
2344 return;
2345 }
2346 if (!http_helpers::isContentTypeAllowed(
2347 req.getHeaderValue("Accept"),
2348 http_helpers::ContentType::OctetStream, true))
2349 {
2350 asyncResp->res.result(boost::beast::http::status::bad_request);
2351 return;
2352 }
2353 downloadEventLogEntry(asyncResp, systemName, entryID, dumpType);
2354}
2355
Claire Weinanfdd26902022-03-01 14:18:25 -08002356inline void handleLogServicesDumpCollectDiagnosticDataPost(
2357 crow::App& app, const std::string& dumpType, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07002358 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2359 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002360{
2361 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2362 {
2363 return;
2364 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002365 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2366 {
2367 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2368 return;
2369 }
2370
Claire Weinanfdd26902022-03-01 14:18:25 -08002371 createDump(asyncResp, req, dumpType);
2372}
2373
Ed Tanous22d268c2022-05-19 09:39:07 -07002374inline void handleLogServicesDumpCollectDiagnosticDataComputerSystemPost(
2375 crow::App& app, const crow::Request& req,
2376 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002377 const std::string& systemName)
Ed Tanous22d268c2022-05-19 09:39:07 -07002378{
2379 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2380 {
2381 return;
2382 }
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002383
Ed Tanous25b54db2024-04-17 15:40:31 -07002384 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous22d268c2022-05-19 09:39:07 -07002385 {
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002386 // Option currently returns no systems. TBD
2387 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2388 systemName);
2389 return;
2390 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002391 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002392 {
2393 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2394 systemName);
Ed Tanous22d268c2022-05-19 09:39:07 -07002395 return;
2396 }
2397 createDump(asyncResp, req, "System");
2398}
2399
Claire Weinanfdd26902022-03-01 14:18:25 -08002400inline void handleLogServicesDumpClearLogPost(
2401 crow::App& app, const std::string& dumpType, const crow::Request& req,
Ed Tanous253f11b2024-05-16 09:38:31 -07002402 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2403 const std::string& managerId)
Claire Weinanfdd26902022-03-01 14:18:25 -08002404{
2405 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2406 {
2407 return;
2408 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002409
2410 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2411 {
2412 messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2413 return;
2414 }
Claire Weinanfdd26902022-03-01 14:18:25 -08002415 clearDump(asyncResp, dumpType);
2416}
2417
Ed Tanous22d268c2022-05-19 09:39:07 -07002418inline void handleLogServicesDumpClearLogComputerSystemPost(
2419 crow::App& app, const crow::Request& req,
2420 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002421 const std::string& systemName)
Ed Tanous22d268c2022-05-19 09:39:07 -07002422{
2423 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2424 {
2425 return;
2426 }
Ed Tanous25b54db2024-04-17 15:40:31 -07002427 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous22d268c2022-05-19 09:39:07 -07002428 {
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002429 // Option currently returns no systems. TBD
2430 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2431 systemName);
2432 return;
2433 }
Ed Tanous253f11b2024-05-16 09:38:31 -07002434 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002435 {
2436 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2437 systemName);
Ed Tanous22d268c2022-05-19 09:39:07 -07002438 return;
2439 }
2440 clearDump(asyncResp, "System");
2441}
2442
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002443inline void requestRoutesBMCDumpService(App& app)
2444{
Ed Tanous253f11b2024-05-16 09:38:31 -07002445 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/Dump/")
Ed Tanoused398212021-06-09 17:05:54 -07002446 .privileges(redfish::privileges::getLogService)
Claire Weinanfdd26902022-03-01 14:18:25 -08002447 .methods(boost::beast::http::verb::get)(std::bind_front(
2448 handleLogServicesDumpServiceGet, std::ref(app), "BMC"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002449}
2450
2451inline void requestRoutesBMCDumpEntryCollection(App& app)
2452{
Ed Tanous253f11b2024-05-16 09:38:31 -07002453 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/")
Ed Tanoused398212021-06-09 17:05:54 -07002454 .privileges(redfish::privileges::getLogEntryCollection)
Claire Weinanfdd26902022-03-01 14:18:25 -08002455 .methods(boost::beast::http::verb::get)(std::bind_front(
2456 handleLogServicesDumpEntriesCollectionGet, std::ref(app), "BMC"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002457}
2458
2459inline void requestRoutesBMCDumpEntry(App& app)
2460{
2461 BMCWEB_ROUTE(app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002462 "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002463 .privileges(redfish::privileges::getLogEntry)
Claire Weinanfdd26902022-03-01 14:18:25 -08002464 .methods(boost::beast::http::verb::get)(std::bind_front(
2465 handleLogServicesDumpEntryGet, std::ref(app), "BMC"));
2466
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002467 BMCWEB_ROUTE(app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002468 "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002469 .privileges(redfish::privileges::deleteLogEntry)
Claire Weinanfdd26902022-03-01 14:18:25 -08002470 .methods(boost::beast::http::verb::delete_)(std::bind_front(
2471 handleLogServicesDumpEntryDelete, std::ref(app), "BMC"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002472}
2473
Carson Labrado168d1b12023-03-27 17:04:46 +00002474inline void requestRoutesBMCDumpEntryDownload(App& app)
2475{
2476 BMCWEB_ROUTE(
2477 app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002478 "/redfish/v1/Managers/<str>/LogServices/Dump/Entries/<str>/attachment/")
Carson Labrado168d1b12023-03-27 17:04:46 +00002479 .privileges(redfish::privileges::getLogEntry)
2480 .methods(boost::beast::http::verb::get)(std::bind_front(
2481 handleLogServicesDumpEntryDownloadGet, std::ref(app), "BMC"));
2482}
2483
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002484inline void requestRoutesBMCDumpCreate(App& app)
2485{
George Liu0fda0f12021-11-16 10:06:17 +08002486 BMCWEB_ROUTE(
2487 app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002488 "/redfish/v1/Managers/<str>/LogServices/Dump/Actions/LogService.CollectDiagnosticData/")
Ed Tanoused398212021-06-09 17:05:54 -07002489 .privileges(redfish::privileges::postLogService)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002490 .methods(boost::beast::http::verb::post)(
Claire Weinanfdd26902022-03-01 14:18:25 -08002491 std::bind_front(handleLogServicesDumpCollectDiagnosticDataPost,
2492 std::ref(app), "BMC"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002493}
2494
2495inline void requestRoutesBMCDumpClear(App& app)
2496{
George Liu0fda0f12021-11-16 10:06:17 +08002497 BMCWEB_ROUTE(
2498 app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002499 "/redfish/v1/Managers/<str>/LogServices/Dump/Actions/LogService.ClearLog/")
Ed Tanoused398212021-06-09 17:05:54 -07002500 .privileges(redfish::privileges::postLogService)
Claire Weinanfdd26902022-03-01 14:18:25 -08002501 .methods(boost::beast::http::verb::post)(std::bind_front(
2502 handleLogServicesDumpClearLogPost, std::ref(app), "BMC"));
2503}
2504
Carson Labrado168d1b12023-03-27 17:04:46 +00002505inline void requestRoutesDBusEventLogEntryDownload(App& app)
2506{
2507 BMCWEB_ROUTE(
2508 app,
Ravi Teja9e9d99d2023-11-08 05:33:59 -06002509 "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/attachment/")
Carson Labrado168d1b12023-03-27 17:04:46 +00002510 .privileges(redfish::privileges::getLogEntry)
2511 .methods(boost::beast::http::verb::get)(std::bind_front(
2512 handleDBusEventLogEntryDownloadGet, std::ref(app), "System"));
2513}
2514
Claire Weinanfdd26902022-03-01 14:18:25 -08002515inline void requestRoutesFaultLogDumpService(App& app)
2516{
Ed Tanous253f11b2024-05-16 09:38:31 -07002517 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/")
Claire Weinanfdd26902022-03-01 14:18:25 -08002518 .privileges(redfish::privileges::getLogService)
2519 .methods(boost::beast::http::verb::get)(std::bind_front(
2520 handleLogServicesDumpServiceGet, std::ref(app), "FaultLog"));
2521}
2522
2523inline void requestRoutesFaultLogDumpEntryCollection(App& app)
2524{
Ed Tanous253f11b2024-05-16 09:38:31 -07002525 BMCWEB_ROUTE(app,
2526 "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/")
Claire Weinanfdd26902022-03-01 14:18:25 -08002527 .privileges(redfish::privileges::getLogEntryCollection)
2528 .methods(boost::beast::http::verb::get)(
2529 std::bind_front(handleLogServicesDumpEntriesCollectionGet,
2530 std::ref(app), "FaultLog"));
2531}
2532
2533inline void requestRoutesFaultLogDumpEntry(App& app)
2534{
Ed Tanous253f11b2024-05-16 09:38:31 -07002535 BMCWEB_ROUTE(
2536 app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/<str>/")
Claire Weinanfdd26902022-03-01 14:18:25 -08002537 .privileges(redfish::privileges::getLogEntry)
2538 .methods(boost::beast::http::verb::get)(std::bind_front(
2539 handleLogServicesDumpEntryGet, std::ref(app), "FaultLog"));
2540
Ed Tanous253f11b2024-05-16 09:38:31 -07002541 BMCWEB_ROUTE(
2542 app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/Entries/<str>/")
Claire Weinanfdd26902022-03-01 14:18:25 -08002543 .privileges(redfish::privileges::deleteLogEntry)
2544 .methods(boost::beast::http::verb::delete_)(std::bind_front(
2545 handleLogServicesDumpEntryDelete, std::ref(app), "FaultLog"));
2546}
2547
2548inline void requestRoutesFaultLogDumpClear(App& app)
2549{
2550 BMCWEB_ROUTE(
2551 app,
Ed Tanous253f11b2024-05-16 09:38:31 -07002552 "/redfish/v1/Managers/<str>/LogServices/FaultLog/Actions/LogService.ClearLog/")
Claire Weinanfdd26902022-03-01 14:18:25 -08002553 .privileges(redfish::privileges::postLogService)
2554 .methods(boost::beast::http::verb::post)(std::bind_front(
2555 handleLogServicesDumpClearLogPost, std::ref(app), "FaultLog"));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002556}
2557
2558inline void requestRoutesSystemDumpService(App& app)
2559{
Ed Tanous22d268c2022-05-19 09:39:07 -07002560 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Dump/")
Ed Tanoused398212021-06-09 17:05:54 -07002561 .privileges(redfish::privileges::getLogService)
Claire Weinan6ab9ad52022-08-12 18:20:17 -07002562 .methods(boost::beast::http::verb::get)(std::bind_front(
Ed Tanous22d268c2022-05-19 09:39:07 -07002563 handleLogServicesDumpServiceComputerSystemGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002564}
2565
2566inline void requestRoutesSystemDumpEntryCollection(App& app)
2567{
Ed Tanous22d268c2022-05-19 09:39:07 -07002568 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/")
Ed Tanoused398212021-06-09 17:05:54 -07002569 .privileges(redfish::privileges::getLogEntryCollection)
Ed Tanous22d268c2022-05-19 09:39:07 -07002570 .methods(boost::beast::http::verb::get)(std::bind_front(
2571 handleLogServicesDumpEntriesCollectionComputerSystemGet,
2572 std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002573}
2574
2575inline void requestRoutesSystemDumpEntry(App& app)
2576{
2577 BMCWEB_ROUTE(app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002578 "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002579 .privileges(redfish::privileges::getLogEntry)
Claire Weinan6ab9ad52022-08-12 18:20:17 -07002580 .methods(boost::beast::http::verb::get)(std::bind_front(
Ed Tanous22d268c2022-05-19 09:39:07 -07002581 handleLogServicesDumpEntryComputerSystemGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002582
2583 BMCWEB_ROUTE(app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002584 "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002585 .privileges(redfish::privileges::deleteLogEntry)
Claire Weinan6ab9ad52022-08-12 18:20:17 -07002586 .methods(boost::beast::http::verb::delete_)(std::bind_front(
Ed Tanous22d268c2022-05-19 09:39:07 -07002587 handleLogServicesDumpEntryComputerSystemDelete, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002588}
2589
2590inline void requestRoutesSystemDumpCreate(App& app)
2591{
George Liu0fda0f12021-11-16 10:06:17 +08002592 BMCWEB_ROUTE(
2593 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002594 "/redfish/v1/Systems/<str>/LogServices/Dump/Actions/LogService.CollectDiagnosticData/")
Ed Tanoused398212021-06-09 17:05:54 -07002595 .privileges(redfish::privileges::postLogService)
Ed Tanous22d268c2022-05-19 09:39:07 -07002596 .methods(boost::beast::http::verb::post)(std::bind_front(
2597 handleLogServicesDumpCollectDiagnosticDataComputerSystemPost,
2598 std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002599}
2600
2601inline void requestRoutesSystemDumpClear(App& app)
2602{
George Liu0fda0f12021-11-16 10:06:17 +08002603 BMCWEB_ROUTE(
2604 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002605 "/redfish/v1/Systems/<str>/LogServices/Dump/Actions/LogService.ClearLog/")
Ed Tanoused398212021-06-09 17:05:54 -07002606 .privileges(redfish::privileges::postLogService)
Claire Weinan6ab9ad52022-08-12 18:20:17 -07002607 .methods(boost::beast::http::verb::post)(std::bind_front(
Ed Tanous22d268c2022-05-19 09:39:07 -07002608 handleLogServicesDumpClearLogComputerSystemPost, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002609}
2610
2611inline void requestRoutesCrashdumpService(App& app)
2612{
2613 // Note: Deviated from redfish privilege registry for GET & HEAD
2614 // method for security reasons.
2615 /**
2616 * Functions triggers appropriate requests on DBus
2617 */
Ed Tanous22d268c2022-05-19 09:39:07 -07002618 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Crashdump/")
Ed Tanoused398212021-06-09 17:05:54 -07002619 // This is incorrect, should be:
2620 //.privileges(redfish::privileges::getLogService)
Ed Tanous432a8902021-06-14 15:28:56 -07002621 .privileges({{"ConfigureManager"}})
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002622 .methods(
2623 boost::beast::http::verb::
2624 get)([&app](const crow::Request& req,
2625 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2626 const std::string& systemName) {
2627 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2628 {
2629 return;
2630 }
2631 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
2632 {
2633 // Option currently returns no systems. TBD
2634 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2635 systemName);
2636 return;
2637 }
2638 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2639 {
2640 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2641 systemName);
2642 return;
2643 }
Ed Tanous22d268c2022-05-19 09:39:07 -07002644
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002645 // Copy over the static data to include the entries added by
2646 // SubRoute
2647 asyncResp->res.jsonValue["@odata.id"] =
2648 std::format("/redfish/v1/Systems/{}/LogServices/Crashdump",
2649 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2650 asyncResp->res.jsonValue["@odata.type"] =
2651 "#LogService.v1_2_0.LogService";
2652 asyncResp->res.jsonValue["Name"] = "Open BMC Oem Crashdump Service";
2653 asyncResp->res.jsonValue["Description"] = "Oem Crashdump Service";
2654 asyncResp->res.jsonValue["Id"] = "Crashdump";
2655 asyncResp->res.jsonValue["OverWritePolicy"] =
2656 log_service::OverWritePolicy::WrapsWhenFull;
2657 asyncResp->res.jsonValue["MaxNumberOfRecords"] = 3;
Tejas Patil7c8c4052021-06-04 17:43:14 +05302658
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002659 std::pair<std::string, std::string> redfishDateTimeOffset =
2660 redfish::time_utils::getDateTimeOffsetNow();
2661 asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
2662 asyncResp->res.jsonValue["DateTimeLocalOffset"] =
2663 redfishDateTimeOffset.second;
Tejas Patil7c8c4052021-06-04 17:43:14 +05302664
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002665 asyncResp->res.jsonValue["Entries"]["@odata.id"] = std::format(
2666 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries",
2667 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2668 asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"]
2669 ["target"] = std::format(
2670 "/redfish/v1/Systems/{}/LogServices/Crashdump/Actions/LogService.ClearLog",
2671 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2672 asyncResp->res
2673 .jsonValue["Actions"]["#LogService.CollectDiagnosticData"]
2674 ["target"] = std::format(
2675 "/redfish/v1/Systems/{}/LogServices/Crashdump/Actions/LogService.CollectDiagnosticData",
2676 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2677 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002678}
2679
2680void inline requestRoutesCrashdumpClear(App& app)
2681{
George Liu0fda0f12021-11-16 10:06:17 +08002682 BMCWEB_ROUTE(
2683 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002684 "/redfish/v1/Systems/<str>/LogServices/Crashdump/Actions/LogService.ClearLog/")
Ed Tanoused398212021-06-09 17:05:54 -07002685 // This is incorrect, should be:
2686 //.privileges(redfish::privileges::postLogService)
Ed Tanous432a8902021-06-14 15:28:56 -07002687 .privileges({{"ConfigureComponents"}})
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002688 .methods(boost::beast::http::verb::post)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07002689 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07002690 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2691 const std::string& systemName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002692 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2693 {
2694 return;
2695 }
2696 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
2697 {
2698 // Option currently returns no systems. TBD
2699 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2700 systemName);
2701 return;
2702 }
2703 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2704 {
2705 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2706 systemName);
2707 return;
2708 }
2709 crow::connections::systemBus->async_method_call(
2710 [asyncResp](const boost::system::error_code& ec,
2711 const std::string&) {
2712 if (ec)
2713 {
2714 messages::internalError(asyncResp->res);
2715 return;
2716 }
2717 messages::success(asyncResp->res);
2718 },
2719 crashdumpObject, crashdumpPath, deleteAllInterface,
2720 "DeleteAll");
2721 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002722}
Jason M. Bills5b61b5e2019-10-16 10:59:02 -07002723
Ed Tanous4ff0f1f2024-09-04 17:27:37 -07002724inline void
zhanghch058d1b46d2021-04-01 11:18:24 +08002725 logCrashdumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2726 const std::string& logID, nlohmann::json& logEntryJson)
Jason M. Billse855dd22019-10-08 11:37:48 -07002727{
Johnathan Mantey043a0532020-03-10 17:15:28 -07002728 auto getStoredLogCallback =
Ed Tanousb9d36b42022-02-26 21:42:46 -08002729 [asyncResp, logID,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002730 &logEntryJson](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002731 const dbus::utility::DBusPropertiesMap& params) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002732 if (ec)
2733 {
2734 BMCWEB_LOG_DEBUG("failed to get log ec: {}", ec.message());
2735 if (ec.value() ==
2736 boost::system::linux_error::bad_request_descriptor)
2737 {
2738 messages::resourceNotFound(asyncResp->res, "LogEntry",
2739 logID);
2740 }
2741 else
2742 {
2743 messages::internalError(asyncResp->res);
2744 }
2745 return;
2746 }
2747
2748 std::string timestamp{};
2749 std::string filename{};
2750 std::string logfile{};
2751 parseCrashdumpParameters(params, filename, timestamp, logfile);
2752
2753 if (filename.empty() || timestamp.empty())
Jason M. Bills1ddcf012019-11-26 14:59:21 -08002754 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002755 messages::resourceNotFound(asyncResp->res, "LogEntry", logID);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002756 return;
2757 }
2758
2759 std::string crashdumpURI =
2760 std::format(
2761 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries/",
2762 BMCWEB_REDFISH_SYSTEM_URI_NAME) +
2763 logID + "/" + filename;
2764 nlohmann::json::object_t logEntry;
2765 logEntry["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
2766 logEntry["@odata.id"] = boost::urls::format(
2767 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries/{}",
2768 BMCWEB_REDFISH_SYSTEM_URI_NAME, logID);
2769 logEntry["Name"] = "CPU Crashdump";
2770 logEntry["Id"] = logID;
2771 logEntry["EntryType"] = log_entry::LogEntryType::Oem;
2772 logEntry["AdditionalDataURI"] = std::move(crashdumpURI);
2773 logEntry["DiagnosticDataType"] = "OEM";
2774 logEntry["OEMDiagnosticDataType"] = "PECICrashdump";
2775 logEntry["Created"] = std::move(timestamp);
2776
2777 // If logEntryJson references an array of LogEntry resources
2778 // ('Members' list), then push this as a new entry, otherwise set it
2779 // directly
2780 if (logEntryJson.is_array())
2781 {
2782 logEntryJson.push_back(logEntry);
2783 asyncResp->res.jsonValue["Members@odata.count"] =
2784 logEntryJson.size();
Jason M. Bills2b20ef62022-01-06 15:48:07 -08002785 }
2786 else
2787 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002788 logEntryJson.update(logEntry);
Jason M. Bills2b20ef62022-01-06 15:48:07 -08002789 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002790 };
Ed Tanousdeae6a72024-11-11 21:58:57 -08002791 dbus::utility::getAllProperties(
2792 crashdumpObject, crashdumpPath + std::string("/") + logID,
2793 crashdumpInterface, std::move(getStoredLogCallback));
Jason M. Billse855dd22019-10-08 11:37:48 -07002794}
2795
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002796inline void requestRoutesCrashdumpEntryCollection(App& app)
Ed Tanous1da66f72018-07-27 16:13:37 -07002797{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002798 // Note: Deviated from redfish privilege registry for GET & HEAD
2799 // method for security reasons.
Ed Tanous1da66f72018-07-27 16:13:37 -07002800 /**
2801 * Functions triggers appropriate requests on DBus
2802 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002803 BMCWEB_ROUTE(app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002804 "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/")
Ed Tanoused398212021-06-09 17:05:54 -07002805 // This is incorrect, should be.
2806 //.privileges(redfish::privileges::postLogEntryCollection)
Ed Tanous432a8902021-06-14 15:28:56 -07002807 .privileges({{"ConfigureComponents"}})
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002808 .methods(
2809 boost::beast::http::verb::
2810 get)([&app](const crow::Request& req,
2811 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2812 const std::string& systemName) {
2813 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous45ca1b82022-03-25 13:07:27 -07002814 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002815 return;
Ed Tanous45ca1b82022-03-25 13:07:27 -07002816 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002817 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous002d39b2022-05-31 08:59:27 -07002818 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002819 // Option currently returns no systems. TBD
2820 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2821 systemName);
2822 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07002823 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002824 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2825 {
2826 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2827 systemName);
2828 return;
2829 }
2830
2831 constexpr std::array<std::string_view, 1> interfaces = {
2832 crashdumpInterface};
2833 dbus::utility::getSubTreePaths(
2834 "/", 0, interfaces,
2835 [asyncResp](const boost::system::error_code& ec,
2836 const std::vector<std::string>& resp) {
2837 if (ec)
2838 {
2839 if (ec.value() !=
2840 boost::system::errc::no_such_file_or_directory)
2841 {
2842 BMCWEB_LOG_DEBUG("failed to get entries ec: {}",
2843 ec.message());
2844 messages::internalError(asyncResp->res);
2845 return;
2846 }
2847 }
2848 asyncResp->res.jsonValue["@odata.type"] =
2849 "#LogEntryCollection.LogEntryCollection";
2850 asyncResp->res.jsonValue["@odata.id"] = std::format(
2851 "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries",
2852 BMCWEB_REDFISH_SYSTEM_URI_NAME);
2853 asyncResp->res.jsonValue["Name"] =
2854 "Open BMC Crashdump Entries";
2855 asyncResp->res.jsonValue["Description"] =
2856 "Collection of Crashdump Entries";
2857 asyncResp->res.jsonValue["Members"] =
2858 nlohmann::json::array();
2859 asyncResp->res.jsonValue["Members@odata.count"] = 0;
2860
2861 for (const std::string& path : resp)
2862 {
2863 const sdbusplus::message::object_path objPath(path);
2864 // Get the log ID
2865 std::string logID = objPath.filename();
2866 if (logID.empty())
2867 {
2868 continue;
2869 }
2870 // Add the log entry to the array
2871 logCrashdumpEntry(asyncResp, logID,
2872 asyncResp->res.jsonValue["Members"]);
2873 }
2874 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002875 });
2876}
Ed Tanous1da66f72018-07-27 16:13:37 -07002877
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002878inline void requestRoutesCrashdumpEntry(App& app)
Ed Tanous1da66f72018-07-27 16:13:37 -07002879{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002880 // Note: Deviated from redfish privilege registry for GET & HEAD
2881 // method for security reasons.
Ed Tanous1da66f72018-07-27 16:13:37 -07002882
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002883 BMCWEB_ROUTE(
Ed Tanous22d268c2022-05-19 09:39:07 -07002884 app, "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002885 // this is incorrect, should be
2886 // .privileges(redfish::privileges::getLogEntry)
Ed Tanous432a8902021-06-14 15:28:56 -07002887 .privileges({{"ConfigureComponents"}})
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002888 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07002889 [&app](const crow::Request& req,
2890 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -07002891 const std::string& systemName, const std::string& param) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002892 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2893 {
2894 return;
2895 }
2896 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
2897 {
2898 // Option currently returns no systems. TBD
2899 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2900 systemName);
2901 return;
2902 }
2903 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2904 {
2905 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2906 systemName);
2907 return;
2908 }
2909 const std::string& logID = param;
2910 logCrashdumpEntry(asyncResp, logID, asyncResp->res.jsonValue);
2911 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002912}
Ed Tanous1da66f72018-07-27 16:13:37 -07002913
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002914inline void requestRoutesCrashdumpFile(App& app)
2915{
2916 // Note: Deviated from redfish privilege registry for GET & HEAD
2917 // method for security reasons.
2918 BMCWEB_ROUTE(
2919 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07002920 "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/<str>/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002921 .privileges(redfish::privileges::getLogEntry)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002922 .methods(boost::beast::http::verb::get)(
Nan Zhoua4ce1142022-08-02 18:45:25 +00002923 [](const crow::Request& req,
2924 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous22d268c2022-05-19 09:39:07 -07002925 const std::string& systemName, const std::string& logID,
2926 const std::string& fileName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002927 // Do not call getRedfishRoute here since the crashdump file is
2928 // not a Redfish resource.
Ed Tanous22d268c2022-05-19 09:39:07 -07002929
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002930 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
2931 {
2932 // Option currently returns no systems. TBD
2933 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2934 systemName);
2935 return;
2936 }
2937 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2938 {
2939 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2940 systemName);
2941 return;
2942 }
Ed Tanous22d268c2022-05-19 09:39:07 -07002943
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002944 auto getStoredLogCallback =
2945 [asyncResp, logID, fileName,
2946 url(boost::urls::url(req.url()))](
2947 const boost::system::error_code& ec,
2948 const std::vector<std::pair<
2949 std::string, dbus::utility::DbusVariantType>>&
2950 resp) {
2951 if (ec)
2952 {
2953 BMCWEB_LOG_DEBUG("failed to get log ec: {}",
2954 ec.message());
2955 messages::internalError(asyncResp->res);
2956 return;
2957 }
Jason M. Bills8e6c0992021-03-11 16:26:53 -08002958
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002959 std::string dbusFilename{};
2960 std::string dbusTimestamp{};
2961 std::string dbusFilepath{};
Jason M. Bills8e6c0992021-03-11 16:26:53 -08002962
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002963 parseCrashdumpParameters(resp, dbusFilename,
2964 dbusTimestamp, dbusFilepath);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002965
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002966 if (dbusFilename.empty() || dbusTimestamp.empty() ||
2967 dbusFilepath.empty())
2968 {
2969 messages::resourceNotFound(asyncResp->res,
2970 "LogEntry", logID);
2971 return;
2972 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002973
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002974 // Verify the file name parameter is correct
2975 if (fileName != dbusFilename)
2976 {
2977 messages::resourceNotFound(asyncResp->res,
2978 "LogEntry", logID);
2979 return;
2980 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002981
Myung Baed51c61b2024-09-13 10:35:34 -05002982 if (asyncResp->res.openFile(dbusFilepath) !=
2983 crow::OpenCode::Success)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002984 {
2985 messages::resourceNotFound(asyncResp->res,
2986 "LogEntry", logID);
2987 return;
2988 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002989
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002990 // Configure this to be a file download when accessed
2991 // from a browser
2992 asyncResp->res.addHeader(
2993 boost::beast::http::field::content_disposition,
2994 "attachment");
2995 };
Ed Tanousdeae6a72024-11-11 21:58:57 -08002996 dbus::utility::getAllProperties(
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002997 *crow::connections::systemBus, crashdumpObject,
2998 crashdumpPath + std::string("/") + logID,
2999 crashdumpInterface, std::move(getStoredLogCallback));
3000 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003001}
3002
Jason M. Billsc5a4c822022-01-06 15:51:23 -08003003enum class OEMDiagnosticType
3004{
3005 onDemand,
3006 telemetry,
3007 invalid,
3008};
3009
Ed Tanous26ccae32023-02-16 10:28:44 -08003010inline OEMDiagnosticType getOEMDiagnosticType(std::string_view oemDiagStr)
Jason M. Billsc5a4c822022-01-06 15:51:23 -08003011{
3012 if (oemDiagStr == "OnDemand")
3013 {
3014 return OEMDiagnosticType::onDemand;
3015 }
3016 if (oemDiagStr == "Telemetry")
3017 {
3018 return OEMDiagnosticType::telemetry;
3019 }
3020
3021 return OEMDiagnosticType::invalid;
3022}
3023
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003024inline void requestRoutesCrashdumpCollect(App& app)
3025{
3026 // Note: Deviated from redfish privilege registry for GET & HEAD
3027 // method for security reasons.
George Liu0fda0f12021-11-16 10:06:17 +08003028 BMCWEB_ROUTE(
3029 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07003030 "/redfish/v1/Systems/<str>/LogServices/Crashdump/Actions/LogService.CollectDiagnosticData/")
Ed Tanoused398212021-06-09 17:05:54 -07003031 // The below is incorrect; Should be ConfigureManager
3032 //.privileges(redfish::privileges::postLogService)
Ed Tanous432a8902021-06-14 15:28:56 -07003033 .privileges({{"ConfigureComponents"}})
Ed Tanous002d39b2022-05-31 08:59:27 -07003034 .methods(boost::beast::http::verb::post)(
3035 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07003036 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3037 const std::string& systemName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003038 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07003039 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003040 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07003041 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003042
3043 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous002d39b2022-05-31 08:59:27 -07003044 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003045 // Option currently returns no systems. TBD
3046 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3047 systemName);
3048 return;
3049 }
3050 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
3051 {
3052 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3053 systemName);
3054 return;
3055 }
3056
3057 std::string diagnosticDataType;
3058 std::string oemDiagnosticDataType;
Myung Baeafc474a2024-10-09 00:53:29 -07003059 if (!redfish::json_util::readJsonAction( //
3060 req, asyncResp->res, //
3061 "DiagnosticDataType", diagnosticDataType, //
3062 "OEMDiagnosticDataType", oemDiagnosticDataType //
3063 ))
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003064 {
3065 return;
3066 }
3067
3068 if (diagnosticDataType != "OEM")
3069 {
3070 BMCWEB_LOG_ERROR(
3071 "Only OEM DiagnosticDataType supported for Crashdump");
3072 messages::actionParameterValueFormatError(
3073 asyncResp->res, diagnosticDataType,
3074 "DiagnosticDataType", "CollectDiagnosticData");
3075 return;
3076 }
3077
3078 OEMDiagnosticType oemDiagType =
3079 getOEMDiagnosticType(oemDiagnosticDataType);
3080
3081 std::string iface;
3082 std::string method;
3083 std::string taskMatchStr;
3084 if (oemDiagType == OEMDiagnosticType::onDemand)
3085 {
3086 iface = crashdumpOnDemandInterface;
3087 method = "GenerateOnDemandLog";
3088 taskMatchStr =
3089 "type='signal',"
3090 "interface='org.freedesktop.DBus.Properties',"
3091 "member='PropertiesChanged',"
3092 "arg0namespace='com.intel.crashdump'";
3093 }
3094 else if (oemDiagType == OEMDiagnosticType::telemetry)
3095 {
3096 iface = crashdumpTelemetryInterface;
3097 method = "GenerateTelemetryLog";
3098 taskMatchStr =
3099 "type='signal',"
3100 "interface='org.freedesktop.DBus.Properties',"
3101 "member='PropertiesChanged',"
3102 "arg0namespace='com.intel.crashdump'";
Ed Tanous002d39b2022-05-31 08:59:27 -07003103 }
3104 else
3105 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003106 BMCWEB_LOG_ERROR("Unsupported OEMDiagnosticDataType: {}",
3107 oemDiagnosticDataType);
3108 messages::actionParameterValueFormatError(
3109 asyncResp->res, oemDiagnosticDataType,
3110 "OEMDiagnosticDataType", "CollectDiagnosticData");
3111 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07003112 }
Ed Tanous1da66f72018-07-27 16:13:37 -07003113
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003114 auto collectCrashdumpCallback =
3115 [asyncResp, payload(task::Payload(req)),
3116 taskMatchStr](const boost::system::error_code& ec,
3117 const std::string&) mutable {
3118 if (ec)
3119 {
3120 if (ec.value() ==
3121 boost::system::errc::operation_not_supported)
3122 {
3123 messages::resourceInStandby(asyncResp->res);
3124 }
3125 else if (ec.value() == boost::system::errc::
3126 device_or_resource_busy)
3127 {
3128 messages::serviceTemporarilyUnavailable(
3129 asyncResp->res, "60");
3130 }
3131 else
3132 {
3133 messages::internalError(asyncResp->res);
3134 }
3135 return;
3136 }
3137 std::shared_ptr<task::TaskData> task =
3138 task::TaskData::createTask(
3139 [](const boost::system::error_code& ec2,
3140 sdbusplus::message_t&,
3141 const std::shared_ptr<task::TaskData>&
3142 taskData) {
3143 if (!ec2)
3144 {
3145 taskData->messages.emplace_back(
3146 messages::taskCompletedOK(
3147 std::to_string(
3148 taskData->index)));
3149 taskData->state = "Completed";
3150 }
3151 return task::completed;
3152 },
3153 taskMatchStr);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003154
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003155 task->startTimer(std::chrono::minutes(5));
3156 task->populateResp(asyncResp->res);
3157 task->payload.emplace(std::move(payload));
3158 };
3159
3160 crow::connections::systemBus->async_method_call(
3161 std::move(collectCrashdumpCallback), crashdumpObject,
3162 crashdumpPath, iface, method);
3163 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003164}
Kenny L. Ku6eda7682020-06-19 09:48:36 -07003165
Alexander Hansen599b9af2024-08-06 15:11:57 +02003166inline void dBusLogServiceActionsClear(
3167 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
3168{
3169 BMCWEB_LOG_DEBUG("Do delete all entries.");
3170
3171 // Process response from Logging service.
3172 auto respHandler = [asyncResp](const boost::system::error_code& ec) {
3173 BMCWEB_LOG_DEBUG("doClearLog resp_handler callback: Done");
3174 if (ec)
3175 {
3176 // TODO Handle for specific error code
3177 BMCWEB_LOG_ERROR("doClearLog resp_handler got error {}", ec);
3178 asyncResp->res.result(
3179 boost::beast::http::status::internal_server_error);
3180 return;
3181 }
3182
3183 asyncResp->res.result(boost::beast::http::status::no_content);
3184 };
3185
3186 // Make call to Logging service to request Clear Log
3187 crow::connections::systemBus->async_method_call(
3188 respHandler, "xyz.openbmc_project.Logging",
3189 "/xyz/openbmc_project/logging",
3190 "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
3191}
3192
Andrew Geisslercb92c032018-08-17 07:56:14 -07003193/**
3194 * DBusLogServiceActionsClear class supports POST method for ClearLog action.
3195 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003196inline void requestRoutesDBusLogServiceActionsClear(App& app)
Andrew Geisslercb92c032018-08-17 07:56:14 -07003197{
Andrew Geisslercb92c032018-08-17 07:56:14 -07003198 /**
3199 * Function handles POST method request.
3200 * The Clear Log actions does not require any parameter.The action deletes
3201 * all entries found in the Entries collection for this Log Service.
3202 */
Andrew Geisslercb92c032018-08-17 07:56:14 -07003203
George Liu0fda0f12021-11-16 10:06:17 +08003204 BMCWEB_ROUTE(
3205 app,
Ed Tanous22d268c2022-05-19 09:39:07 -07003206 "/redfish/v1/Systems/<str>/LogServices/EventLog/Actions/LogService.ClearLog/")
Ed Tanoused398212021-06-09 17:05:54 -07003207 .privileges(redfish::privileges::postLogService)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003208 .methods(boost::beast::http::verb::post)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07003209 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07003210 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3211 const std::string& systemName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04003212 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3213 {
3214 return;
3215 }
3216 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
3217 {
3218 // Option currently returns no systems. TBD
3219 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3220 systemName);
3221 return;
3222 }
3223 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
3224 {
3225 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3226 systemName);
3227 return;
3228 }
3229 dBusLogServiceActionsClear(asyncResp);
3230 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003231}
ZhikuiRena3316fc2020-01-29 14:58:08 -08003232
Ed Tanous1da66f72018-07-27 16:13:37 -07003233} // namespace redfish