xref: /openbmc/bmcweb/features/redfish/include/utils/eventlog_utils.hpp (revision 7681b8a16fd75dc3424a6d70a76a906d128b8de9)
1*7681b8a1SOliver Brewka // SPDX-License-Identifier: Apache-2.0
2*7681b8a1SOliver Brewka // SPDX-FileCopyrightText: Copyright OpenBMC Authors
3*7681b8a1SOliver Brewka // SPDX-FileCopyrightText: Copyright 2018 Intel Corporation
4*7681b8a1SOliver Brewka #pragma once
5*7681b8a1SOliver Brewka 
6*7681b8a1SOliver Brewka #include "async_resp.hpp"
7*7681b8a1SOliver Brewka #include "dbus_utility.hpp"
8*7681b8a1SOliver Brewka #include "error_messages.hpp"
9*7681b8a1SOliver Brewka #include "http_response.hpp"
10*7681b8a1SOliver Brewka #include "logging.hpp"
11*7681b8a1SOliver Brewka #include "registries.hpp"
12*7681b8a1SOliver Brewka #include "str_utility.hpp"
13*7681b8a1SOliver Brewka #include "utils/query_param.hpp"
14*7681b8a1SOliver Brewka 
15*7681b8a1SOliver Brewka #include <boost/beast/http/field.hpp>
16*7681b8a1SOliver Brewka #include <boost/beast/http/status.hpp>
17*7681b8a1SOliver Brewka #include <boost/beast/http/verb.hpp>
18*7681b8a1SOliver Brewka #include <boost/system/linux_error.hpp>
19*7681b8a1SOliver Brewka #include <boost/url/format.hpp>
20*7681b8a1SOliver Brewka #include <boost/url/url.hpp>
21*7681b8a1SOliver Brewka #include <sdbusplus/message.hpp>
22*7681b8a1SOliver Brewka #include <sdbusplus/message/native_types.hpp>
23*7681b8a1SOliver Brewka #include <sdbusplus/unpack_properties.hpp>
24*7681b8a1SOliver Brewka 
25*7681b8a1SOliver Brewka #include <algorithm>
26*7681b8a1SOliver Brewka #include <cstddef>
27*7681b8a1SOliver Brewka #include <cstdint>
28*7681b8a1SOliver Brewka #include <cstdio>
29*7681b8a1SOliver Brewka #include <ctime>
30*7681b8a1SOliver Brewka #include <fstream>
31*7681b8a1SOliver Brewka #include <iomanip>
32*7681b8a1SOliver Brewka #include <sstream>
33*7681b8a1SOliver Brewka #include <string>
34*7681b8a1SOliver Brewka #include <utility>
35*7681b8a1SOliver Brewka 
36*7681b8a1SOliver Brewka namespace redfish
37*7681b8a1SOliver Brewka {
38*7681b8a1SOliver Brewka namespace eventlog_utils
39*7681b8a1SOliver Brewka {
40*7681b8a1SOliver Brewka 
41*7681b8a1SOliver Brewka /*
42*7681b8a1SOliver Brewka  * Journal EventLog utilities
43*7681b8a1SOliver Brewka  * */
44*7681b8a1SOliver Brewka 
45*7681b8a1SOliver Brewka inline bool getRedfishLogFiles(
46*7681b8a1SOliver Brewka     std::vector<std::filesystem::path>& redfishLogFiles)
47*7681b8a1SOliver Brewka {
48*7681b8a1SOliver Brewka     static const std::filesystem::path redfishLogDir = "/var/log";
49*7681b8a1SOliver Brewka     static const std::string redfishLogFilename = "redfish";
50*7681b8a1SOliver Brewka 
51*7681b8a1SOliver Brewka     // Loop through the directory looking for redfish log files
52*7681b8a1SOliver Brewka     for (const std::filesystem::directory_entry& dirEnt :
53*7681b8a1SOliver Brewka          std::filesystem::directory_iterator(redfishLogDir))
54*7681b8a1SOliver Brewka     {
55*7681b8a1SOliver Brewka         // If we find a redfish log file, save the path
56*7681b8a1SOliver Brewka         std::string filename = dirEnt.path().filename();
57*7681b8a1SOliver Brewka         if (filename.starts_with(redfishLogFilename))
58*7681b8a1SOliver Brewka         {
59*7681b8a1SOliver Brewka             redfishLogFiles.emplace_back(redfishLogDir / filename);
60*7681b8a1SOliver Brewka         }
61*7681b8a1SOliver Brewka     }
62*7681b8a1SOliver Brewka     // As the log files rotate, they are appended with a ".#" that is higher for
63*7681b8a1SOliver Brewka     // the older logs. Since we don't expect more than 10 log files, we
64*7681b8a1SOliver Brewka     // can just sort the list to get them in order from newest to oldest
65*7681b8a1SOliver Brewka     std::ranges::sort(redfishLogFiles);
66*7681b8a1SOliver Brewka 
67*7681b8a1SOliver Brewka     return !redfishLogFiles.empty();
68*7681b8a1SOliver Brewka }
69*7681b8a1SOliver Brewka 
70*7681b8a1SOliver Brewka inline bool getUniqueEntryID(const std::string& logEntry, std::string& entryID,
71*7681b8a1SOliver Brewka                              const bool firstEntry = true)
72*7681b8a1SOliver Brewka {
73*7681b8a1SOliver Brewka     static time_t prevTs = 0;
74*7681b8a1SOliver Brewka     static int index = 0;
75*7681b8a1SOliver Brewka     if (firstEntry)
76*7681b8a1SOliver Brewka     {
77*7681b8a1SOliver Brewka         prevTs = 0;
78*7681b8a1SOliver Brewka     }
79*7681b8a1SOliver Brewka 
80*7681b8a1SOliver Brewka     // Get the entry timestamp
81*7681b8a1SOliver Brewka     std::time_t curTs = 0;
82*7681b8a1SOliver Brewka     std::tm timeStruct = {};
83*7681b8a1SOliver Brewka     std::istringstream entryStream(logEntry);
84*7681b8a1SOliver Brewka     if (entryStream >> std::get_time(&timeStruct, "%Y-%m-%dT%H:%M:%S"))
85*7681b8a1SOliver Brewka     {
86*7681b8a1SOliver Brewka         curTs = std::mktime(&timeStruct);
87*7681b8a1SOliver Brewka     }
88*7681b8a1SOliver Brewka     // If the timestamp isn't unique, increment the index
89*7681b8a1SOliver Brewka     if (curTs == prevTs)
90*7681b8a1SOliver Brewka     {
91*7681b8a1SOliver Brewka         index++;
92*7681b8a1SOliver Brewka     }
93*7681b8a1SOliver Brewka     else
94*7681b8a1SOliver Brewka     {
95*7681b8a1SOliver Brewka         // Otherwise, reset it
96*7681b8a1SOliver Brewka         index = 0;
97*7681b8a1SOliver Brewka     }
98*7681b8a1SOliver Brewka     // Save the timestamp
99*7681b8a1SOliver Brewka     prevTs = curTs;
100*7681b8a1SOliver Brewka 
101*7681b8a1SOliver Brewka     entryID = std::to_string(curTs);
102*7681b8a1SOliver Brewka     if (index > 0)
103*7681b8a1SOliver Brewka     {
104*7681b8a1SOliver Brewka         entryID += "_" + std::to_string(index);
105*7681b8a1SOliver Brewka     }
106*7681b8a1SOliver Brewka     return true;
107*7681b8a1SOliver Brewka }
108*7681b8a1SOliver Brewka 
109*7681b8a1SOliver Brewka enum class LogParseError
110*7681b8a1SOliver Brewka {
111*7681b8a1SOliver Brewka     success,
112*7681b8a1SOliver Brewka     parseFailed,
113*7681b8a1SOliver Brewka     messageIdNotInRegistry,
114*7681b8a1SOliver Brewka };
115*7681b8a1SOliver Brewka 
116*7681b8a1SOliver Brewka static LogParseError fillEventLogEntryJson(
117*7681b8a1SOliver Brewka     const std::string& logEntryID, const std::string& logEntry,
118*7681b8a1SOliver Brewka     nlohmann::json::object_t& logEntryJson)
119*7681b8a1SOliver Brewka {
120*7681b8a1SOliver Brewka     // The redfish log format is "<Timestamp> <MessageId>,<MessageArgs>"
121*7681b8a1SOliver Brewka     // First get the Timestamp
122*7681b8a1SOliver Brewka     size_t space = logEntry.find_first_of(' ');
123*7681b8a1SOliver Brewka     if (space == std::string::npos)
124*7681b8a1SOliver Brewka     {
125*7681b8a1SOliver Brewka         return LogParseError::parseFailed;
126*7681b8a1SOliver Brewka     }
127*7681b8a1SOliver Brewka     std::string timestamp = logEntry.substr(0, space);
128*7681b8a1SOliver Brewka     // Then get the log contents
129*7681b8a1SOliver Brewka     size_t entryStart = logEntry.find_first_not_of(' ', space);
130*7681b8a1SOliver Brewka     if (entryStart == std::string::npos)
131*7681b8a1SOliver Brewka     {
132*7681b8a1SOliver Brewka         return LogParseError::parseFailed;
133*7681b8a1SOliver Brewka     }
134*7681b8a1SOliver Brewka     std::string_view entry(logEntry);
135*7681b8a1SOliver Brewka     entry.remove_prefix(entryStart);
136*7681b8a1SOliver Brewka     // Use split to separate the entry into its fields
137*7681b8a1SOliver Brewka     std::vector<std::string> logEntryFields;
138*7681b8a1SOliver Brewka     bmcweb::split(logEntryFields, entry, ',');
139*7681b8a1SOliver Brewka     // We need at least a MessageId to be valid
140*7681b8a1SOliver Brewka     auto logEntryIter = logEntryFields.begin();
141*7681b8a1SOliver Brewka     if (logEntryIter == logEntryFields.end())
142*7681b8a1SOliver Brewka     {
143*7681b8a1SOliver Brewka         return LogParseError::parseFailed;
144*7681b8a1SOliver Brewka     }
145*7681b8a1SOliver Brewka     std::string& messageID = *logEntryIter;
146*7681b8a1SOliver Brewka     // Get the Message from the MessageRegistry
147*7681b8a1SOliver Brewka     const registries::Message* message = registries::getMessage(messageID);
148*7681b8a1SOliver Brewka 
149*7681b8a1SOliver Brewka     logEntryIter++;
150*7681b8a1SOliver Brewka     if (message == nullptr)
151*7681b8a1SOliver Brewka     {
152*7681b8a1SOliver Brewka         BMCWEB_LOG_WARNING("Log entry not found in registry: {}", logEntry);
153*7681b8a1SOliver Brewka         return LogParseError::messageIdNotInRegistry;
154*7681b8a1SOliver Brewka     }
155*7681b8a1SOliver Brewka 
156*7681b8a1SOliver Brewka     std::vector<std::string_view> messageArgs(logEntryIter,
157*7681b8a1SOliver Brewka                                               logEntryFields.end());
158*7681b8a1SOliver Brewka     messageArgs.resize(message->numberOfArgs);
159*7681b8a1SOliver Brewka 
160*7681b8a1SOliver Brewka     std::string msg =
161*7681b8a1SOliver Brewka         redfish::registries::fillMessageArgs(messageArgs, message->message);
162*7681b8a1SOliver Brewka     if (msg.empty())
163*7681b8a1SOliver Brewka     {
164*7681b8a1SOliver Brewka         return LogParseError::parseFailed;
165*7681b8a1SOliver Brewka     }
166*7681b8a1SOliver Brewka 
167*7681b8a1SOliver Brewka     // Get the Created time from the timestamp. The log timestamp is in RFC3339
168*7681b8a1SOliver Brewka     // format which matches the Redfish format except for the fractional seconds
169*7681b8a1SOliver Brewka     // between the '.' and the '+', so just remove them.
170*7681b8a1SOliver Brewka     std::size_t dot = timestamp.find_first_of('.');
171*7681b8a1SOliver Brewka     std::size_t plus = timestamp.find_first_of('+');
172*7681b8a1SOliver Brewka     if (dot != std::string::npos && plus != std::string::npos)
173*7681b8a1SOliver Brewka     {
174*7681b8a1SOliver Brewka         timestamp.erase(dot, plus - dot);
175*7681b8a1SOliver Brewka     }
176*7681b8a1SOliver Brewka 
177*7681b8a1SOliver Brewka     // Fill in the log entry with the gathered data
178*7681b8a1SOliver Brewka     logEntryJson["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
179*7681b8a1SOliver Brewka     logEntryJson["@odata.id"] = boost::urls::format(
180*7681b8a1SOliver Brewka         "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}",
181*7681b8a1SOliver Brewka         BMCWEB_REDFISH_SYSTEM_URI_NAME, logEntryID);
182*7681b8a1SOliver Brewka     logEntryJson["Name"] = "System Event Log Entry";
183*7681b8a1SOliver Brewka     logEntryJson["Id"] = logEntryID;
184*7681b8a1SOliver Brewka     logEntryJson["Message"] = std::move(msg);
185*7681b8a1SOliver Brewka     logEntryJson["MessageId"] = std::move(messageID);
186*7681b8a1SOliver Brewka     logEntryJson["MessageArgs"] = messageArgs;
187*7681b8a1SOliver Brewka     logEntryJson["EntryType"] = "Event";
188*7681b8a1SOliver Brewka     logEntryJson["Severity"] = message->messageSeverity;
189*7681b8a1SOliver Brewka     logEntryJson["Created"] = std::move(timestamp);
190*7681b8a1SOliver Brewka     return LogParseError::success;
191*7681b8a1SOliver Brewka }
192*7681b8a1SOliver Brewka 
193*7681b8a1SOliver Brewka inline void handleRequestSystemsLogServiceEventLogLogEntryCollection(
194*7681b8a1SOliver Brewka     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
195*7681b8a1SOliver Brewka     query_param::Query& delegatedQuery)
196*7681b8a1SOliver Brewka {
197*7681b8a1SOliver Brewka     size_t top = delegatedQuery.top.value_or(query_param::Query::maxTop);
198*7681b8a1SOliver Brewka     size_t skip = delegatedQuery.skip.value_or(0);
199*7681b8a1SOliver Brewka 
200*7681b8a1SOliver Brewka     // Collections don't include the static data added by SubRoute
201*7681b8a1SOliver Brewka     // because it has a duplicate entry for members
202*7681b8a1SOliver Brewka     asyncResp->res.jsonValue["@odata.type"] =
203*7681b8a1SOliver Brewka         "#LogEntryCollection.LogEntryCollection";
204*7681b8a1SOliver Brewka     asyncResp->res.jsonValue["@odata.id"] =
205*7681b8a1SOliver Brewka         std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
206*7681b8a1SOliver Brewka                     BMCWEB_REDFISH_SYSTEM_URI_NAME);
207*7681b8a1SOliver Brewka     asyncResp->res.jsonValue["Name"] = "System Event Log Entries";
208*7681b8a1SOliver Brewka     asyncResp->res.jsonValue["Description"] =
209*7681b8a1SOliver Brewka         "Collection of System Event Log Entries";
210*7681b8a1SOliver Brewka 
211*7681b8a1SOliver Brewka     nlohmann::json& logEntryArray = asyncResp->res.jsonValue["Members"];
212*7681b8a1SOliver Brewka     logEntryArray = nlohmann::json::array();
213*7681b8a1SOliver Brewka     // Go through the log files and create a unique ID for each
214*7681b8a1SOliver Brewka     // entry
215*7681b8a1SOliver Brewka     std::vector<std::filesystem::path> redfishLogFiles;
216*7681b8a1SOliver Brewka     getRedfishLogFiles(redfishLogFiles);
217*7681b8a1SOliver Brewka     uint64_t entryCount = 0;
218*7681b8a1SOliver Brewka     std::string logEntry;
219*7681b8a1SOliver Brewka 
220*7681b8a1SOliver Brewka     // Oldest logs are in the last file, so start there and loop
221*7681b8a1SOliver Brewka     // backwards
222*7681b8a1SOliver Brewka     for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend(); it++)
223*7681b8a1SOliver Brewka     {
224*7681b8a1SOliver Brewka         std::ifstream logStream(*it);
225*7681b8a1SOliver Brewka         if (!logStream.is_open())
226*7681b8a1SOliver Brewka         {
227*7681b8a1SOliver Brewka             continue;
228*7681b8a1SOliver Brewka         }
229*7681b8a1SOliver Brewka 
230*7681b8a1SOliver Brewka         // Reset the unique ID on the first entry
231*7681b8a1SOliver Brewka         bool firstEntry = true;
232*7681b8a1SOliver Brewka         while (std::getline(logStream, logEntry))
233*7681b8a1SOliver Brewka         {
234*7681b8a1SOliver Brewka             std::string idStr;
235*7681b8a1SOliver Brewka             if (!getUniqueEntryID(logEntry, idStr, firstEntry))
236*7681b8a1SOliver Brewka             {
237*7681b8a1SOliver Brewka                 continue;
238*7681b8a1SOliver Brewka             }
239*7681b8a1SOliver Brewka             firstEntry = false;
240*7681b8a1SOliver Brewka 
241*7681b8a1SOliver Brewka             nlohmann::json::object_t bmcLogEntry;
242*7681b8a1SOliver Brewka             LogParseError status =
243*7681b8a1SOliver Brewka                 fillEventLogEntryJson(idStr, logEntry, bmcLogEntry);
244*7681b8a1SOliver Brewka             if (status == LogParseError::messageIdNotInRegistry)
245*7681b8a1SOliver Brewka             {
246*7681b8a1SOliver Brewka                 continue;
247*7681b8a1SOliver Brewka             }
248*7681b8a1SOliver Brewka             if (status != LogParseError::success)
249*7681b8a1SOliver Brewka             {
250*7681b8a1SOliver Brewka                 messages::internalError(asyncResp->res);
251*7681b8a1SOliver Brewka                 return;
252*7681b8a1SOliver Brewka             }
253*7681b8a1SOliver Brewka 
254*7681b8a1SOliver Brewka             entryCount++;
255*7681b8a1SOliver Brewka             // Handle paging using skip (number of entries to skip from the
256*7681b8a1SOliver Brewka             // start) and top (number of entries to display)
257*7681b8a1SOliver Brewka             if (entryCount <= skip || entryCount > skip + top)
258*7681b8a1SOliver Brewka             {
259*7681b8a1SOliver Brewka                 continue;
260*7681b8a1SOliver Brewka             }
261*7681b8a1SOliver Brewka 
262*7681b8a1SOliver Brewka             logEntryArray.emplace_back(std::move(bmcLogEntry));
263*7681b8a1SOliver Brewka         }
264*7681b8a1SOliver Brewka     }
265*7681b8a1SOliver Brewka     asyncResp->res.jsonValue["Members@odata.count"] = entryCount;
266*7681b8a1SOliver Brewka     if (skip + top < entryCount)
267*7681b8a1SOliver Brewka     {
268*7681b8a1SOliver Brewka         asyncResp->res.jsonValue["Members@odata.nextLink"] =
269*7681b8a1SOliver Brewka             boost::urls::format(
270*7681b8a1SOliver Brewka                 "/redfish/v1/Systems/{}/LogServices/EventLog/Entries?$skip={}",
271*7681b8a1SOliver Brewka                 BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(skip + top));
272*7681b8a1SOliver Brewka     }
273*7681b8a1SOliver Brewka }
274*7681b8a1SOliver Brewka 
275*7681b8a1SOliver Brewka inline void handleRequestSystemsLogServiceEventLogEntriesGet(
276*7681b8a1SOliver Brewka     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
277*7681b8a1SOliver Brewka     const std::string& param)
278*7681b8a1SOliver Brewka {
279*7681b8a1SOliver Brewka     const std::string& targetID = param;
280*7681b8a1SOliver Brewka 
281*7681b8a1SOliver Brewka     // Go through the log files and check the unique ID for each
282*7681b8a1SOliver Brewka     // entry to find the target entry
283*7681b8a1SOliver Brewka     std::vector<std::filesystem::path> redfishLogFiles;
284*7681b8a1SOliver Brewka     getRedfishLogFiles(redfishLogFiles);
285*7681b8a1SOliver Brewka     std::string logEntry;
286*7681b8a1SOliver Brewka 
287*7681b8a1SOliver Brewka     // Oldest logs are in the last file, so start there and loop
288*7681b8a1SOliver Brewka     // backwards
289*7681b8a1SOliver Brewka     for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend(); it++)
290*7681b8a1SOliver Brewka     {
291*7681b8a1SOliver Brewka         std::ifstream logStream(*it);
292*7681b8a1SOliver Brewka         if (!logStream.is_open())
293*7681b8a1SOliver Brewka         {
294*7681b8a1SOliver Brewka             continue;
295*7681b8a1SOliver Brewka         }
296*7681b8a1SOliver Brewka 
297*7681b8a1SOliver Brewka         // Reset the unique ID on the first entry
298*7681b8a1SOliver Brewka         bool firstEntry = true;
299*7681b8a1SOliver Brewka         while (std::getline(logStream, logEntry))
300*7681b8a1SOliver Brewka         {
301*7681b8a1SOliver Brewka             std::string idStr;
302*7681b8a1SOliver Brewka             if (!getUniqueEntryID(logEntry, idStr, firstEntry))
303*7681b8a1SOliver Brewka             {
304*7681b8a1SOliver Brewka                 continue;
305*7681b8a1SOliver Brewka             }
306*7681b8a1SOliver Brewka             firstEntry = false;
307*7681b8a1SOliver Brewka 
308*7681b8a1SOliver Brewka             if (idStr == targetID)
309*7681b8a1SOliver Brewka             {
310*7681b8a1SOliver Brewka                 nlohmann::json::object_t bmcLogEntry;
311*7681b8a1SOliver Brewka                 LogParseError status =
312*7681b8a1SOliver Brewka                     fillEventLogEntryJson(idStr, logEntry, bmcLogEntry);
313*7681b8a1SOliver Brewka                 if (status != LogParseError::success)
314*7681b8a1SOliver Brewka                 {
315*7681b8a1SOliver Brewka                     messages::internalError(asyncResp->res);
316*7681b8a1SOliver Brewka                     return;
317*7681b8a1SOliver Brewka                 }
318*7681b8a1SOliver Brewka                 asyncResp->res.jsonValue.update(bmcLogEntry);
319*7681b8a1SOliver Brewka                 return;
320*7681b8a1SOliver Brewka             }
321*7681b8a1SOliver Brewka         }
322*7681b8a1SOliver Brewka     }
323*7681b8a1SOliver Brewka     // Requested ID was not found
324*7681b8a1SOliver Brewka     messages::resourceNotFound(asyncResp->res, "LogEntry", targetID);
325*7681b8a1SOliver Brewka }
326*7681b8a1SOliver Brewka 
327*7681b8a1SOliver Brewka inline void handleRequestSystemsLogServicesEventLogActionsClearPost(
328*7681b8a1SOliver Brewka     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
329*7681b8a1SOliver Brewka {
330*7681b8a1SOliver Brewka     // Clear the EventLog by deleting the log files
331*7681b8a1SOliver Brewka     std::vector<std::filesystem::path> redfishLogFiles;
332*7681b8a1SOliver Brewka     if (getRedfishLogFiles(redfishLogFiles))
333*7681b8a1SOliver Brewka     {
334*7681b8a1SOliver Brewka         for (const std::filesystem::path& file : redfishLogFiles)
335*7681b8a1SOliver Brewka         {
336*7681b8a1SOliver Brewka             std::error_code ec;
337*7681b8a1SOliver Brewka             std::filesystem::remove(file, ec);
338*7681b8a1SOliver Brewka         }
339*7681b8a1SOliver Brewka     }
340*7681b8a1SOliver Brewka 
341*7681b8a1SOliver Brewka     // Reload rsyslog so it knows to start new log files
342*7681b8a1SOliver Brewka     dbus::utility::async_method_call(
343*7681b8a1SOliver Brewka         asyncResp,
344*7681b8a1SOliver Brewka         [asyncResp](const boost::system::error_code& ec) {
345*7681b8a1SOliver Brewka             if (ec)
346*7681b8a1SOliver Brewka             {
347*7681b8a1SOliver Brewka                 BMCWEB_LOG_ERROR("Failed to reload rsyslog: {}", ec);
348*7681b8a1SOliver Brewka                 messages::internalError(asyncResp->res);
349*7681b8a1SOliver Brewka                 return;
350*7681b8a1SOliver Brewka             }
351*7681b8a1SOliver Brewka 
352*7681b8a1SOliver Brewka             messages::success(asyncResp->res);
353*7681b8a1SOliver Brewka         },
354*7681b8a1SOliver Brewka         "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
355*7681b8a1SOliver Brewka         "org.freedesktop.systemd1.Manager", "ReloadUnit", "rsyslog.service",
356*7681b8a1SOliver Brewka         "replace");
357*7681b8a1SOliver Brewka }
358*7681b8a1SOliver Brewka } // namespace eventlog_utils
359*7681b8a1SOliver Brewka } // namespace redfish
360