Break out DBus EventLog
As part of a EventLog refactor, break out all code
used for Systems DBus EventLog, in order to make the code base
more maintainable in the long run.
Tested: Only code extraction. Code compiles.
Change-Id: I94de7bf3171fd3963eebec6608438f8d07cee44c
Signed-off-by: Oliver Brewka <oliver.brewka@9elements.com>
diff --git a/redfish-core/lib/log_services.hpp b/redfish-core/lib/log_services.hpp
index 6b8d075..015360c 100644
--- a/redfish-core/lib/log_services.hpp
+++ b/redfish-core/lib/log_services.hpp
@@ -15,7 +15,6 @@
#include "http_body.hpp"
#include "http_request.hpp"
#include "http_response.hpp"
-#include "http_utility.hpp"
#include "human_sort.hpp"
#include "logging.hpp"
#include "query.hpp"
@@ -23,7 +22,6 @@
#include "str_utility.hpp"
#include "task.hpp"
#include "task_messages.hpp"
-#include "utils/dbus_event_log_entry.hpp"
#include "utils/dbus_utils.hpp"
#include "utils/etag_utils.hpp"
#include "utils/json_utils.hpp"
@@ -83,43 +81,6 @@
DUMP_CREATE_INPROGRESS
};
-inline std::string translateSeverityDbusToRedfish(const std::string& s)
-{
- if ((s == "xyz.openbmc_project.Logging.Entry.Level.Alert") ||
- (s == "xyz.openbmc_project.Logging.Entry.Level.Critical") ||
- (s == "xyz.openbmc_project.Logging.Entry.Level.Emergency") ||
- (s == "xyz.openbmc_project.Logging.Entry.Level.Error"))
- {
- return "Critical";
- }
- if ((s == "xyz.openbmc_project.Logging.Entry.Level.Debug") ||
- (s == "xyz.openbmc_project.Logging.Entry.Level.Informational") ||
- (s == "xyz.openbmc_project.Logging.Entry.Level.Notice"))
- {
- return "OK";
- }
- if (s == "xyz.openbmc_project.Logging.Entry.Level.Warning")
- {
- return "Warning";
- }
- return "";
-}
-
-inline std::optional<bool> getProviderNotifyAction(const std::string& notify)
-{
- std::optional<bool> notifyAction;
- if (notify == "xyz.openbmc_project.Logging.Entry.Notify.Notify")
- {
- notifyAction = true;
- }
- else if (notify == "xyz.openbmc_project.Logging.Entry.Notify.Inhibit")
- {
- notifyAction = false;
- }
-
- return notifyAction;
-}
-
inline std::string getDumpPath(std::string_view dumpType)
{
std::string dbusDumpPath = "/xyz/openbmc_project/dump/";
@@ -553,43 +514,6 @@
"xyz.openbmc_project.Dump.Entry", "GetFileHandle");
}
-inline void downloadEventLogEntry(
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& systemName, const std::string& entryID,
- const std::string& dumpType)
-{
- if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
- {
- // Option currently returns no systems. TBD
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
- if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
-
- std::string entryPath =
- sdbusplus::message::object_path("/xyz/openbmc_project/logging/entry") /
- entryID;
-
- auto downloadEventLogEntryHandler =
- [asyncResp, entryID,
- dumpType](const boost::system::error_code& ec,
- const sdbusplus::message::unix_fd& unixfd) {
- log_services_utils::downloadEntryCallback(asyncResp, entryID,
- dumpType, ec, unixfd);
- };
-
- dbus::utility::async_method_call(
- asyncResp, std::move(downloadEventLogEntryHandler),
- "xyz.openbmc_project.Logging", entryPath,
- "xyz.openbmc_project.Logging.Entry", "GetEntry");
-}
-
inline DumpCreationProgress mapDbusStatusToDumpProgress(
const std::string& status)
{
@@ -1138,332 +1062,6 @@
});
}
-inline void fillEventLogLogEntryFromDbusLogEntry(
- const DbusEventLogEntry& entry, nlohmann::json& objectToFillOut)
-{
- objectToFillOut["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
- objectToFillOut["@odata.id"] = boost::urls::format(
- "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}",
- BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(entry.Id));
- objectToFillOut["Name"] = "System Event Log Entry";
- objectToFillOut["Id"] = std::to_string(entry.Id);
- objectToFillOut["Message"] = entry.Message;
- objectToFillOut["Resolved"] = entry.Resolved;
- std::optional<bool> notifyAction =
- getProviderNotifyAction(entry.ServiceProviderNotify);
- if (notifyAction)
- {
- objectToFillOut["ServiceProviderNotified"] = *notifyAction;
- }
- if ((entry.Resolution != nullptr) && !entry.Resolution->empty())
- {
- objectToFillOut["Resolution"] = *entry.Resolution;
- }
- objectToFillOut["EntryType"] = "Event";
- objectToFillOut["Severity"] =
- translateSeverityDbusToRedfish(entry.Severity);
- objectToFillOut["Created"] =
- redfish::time_utils::getDateTimeUintMs(entry.Timestamp);
- objectToFillOut["Modified"] =
- redfish::time_utils::getDateTimeUintMs(entry.UpdateTimestamp);
- if (entry.Path != nullptr)
- {
- objectToFillOut["AdditionalDataURI"] = boost::urls::format(
- "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}/attachment",
- BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(entry.Id));
- }
-}
-
-inline void afterLogEntriesGetManagedObjects(
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const boost::system::error_code& ec,
- const dbus::utility::ManagedObjectType& resp)
-{
- if (ec)
- {
- // TODO Handle for specific error code
- BMCWEB_LOG_ERROR("getLogEntriesIfaceData resp_handler got error {}",
- ec);
- messages::internalError(asyncResp->res);
- return;
- }
- nlohmann::json::array_t entriesArray;
- for (const auto& objectPath : resp)
- {
- dbus::utility::DBusPropertiesMap propsFlattened;
- auto isEntry =
- std::ranges::find_if(objectPath.second, [](const auto& object) {
- return object.first == "xyz.openbmc_project.Logging.Entry";
- });
- if (isEntry == objectPath.second.end())
- {
- continue;
- }
-
- for (const auto& interfaceMap : objectPath.second)
- {
- for (const auto& propertyMap : interfaceMap.second)
- {
- propsFlattened.emplace_back(propertyMap.first,
- propertyMap.second);
- }
- }
- std::optional<DbusEventLogEntry> optEntry =
- fillDbusEventLogEntryFromPropertyMap(propsFlattened);
-
- if (!optEntry.has_value())
- {
- messages::internalError(asyncResp->res);
- return;
- }
- fillEventLogLogEntryFromDbusLogEntry(*optEntry,
- entriesArray.emplace_back());
- }
-
- redfish::json_util::sortJsonArrayByKey(entriesArray, "Id");
- asyncResp->res.jsonValue["Members@odata.count"] = entriesArray.size();
- asyncResp->res.jsonValue["Members"] = std::move(entriesArray);
-}
-
-inline void dBusEventLogEntryCollection(
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
-{
- // Collections don't include the static data added by SubRoute
- // because it has a duplicate entry for members
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogEntryCollection.LogEntryCollection";
- asyncResp->res.jsonValue["@odata.id"] =
- std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
- BMCWEB_REDFISH_SYSTEM_URI_NAME);
- asyncResp->res.jsonValue["Name"] = "System Event Log Entries";
- asyncResp->res.jsonValue["Description"] =
- "Collection of System Event Log Entries";
-
- // DBus implementation of EventLog/Entries
- // Make call to Logging Service to find all log entry objects
- sdbusplus::message::object_path path("/xyz/openbmc_project/logging");
- dbus::utility::getManagedObjects(
- "xyz.openbmc_project.Logging", path,
- [asyncResp](const boost::system::error_code& ec,
- const dbus::utility::ManagedObjectType& resp) {
- afterLogEntriesGetManagedObjects(asyncResp, ec, resp);
- });
-}
-
-inline void requestRoutesDBusEventLogEntryCollection(App& app)
-{
- BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/")
- .privileges(redfish::privileges::getLogEntryCollection)
- .methods(boost::beast::http::verb::get)(
- [&app](const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& systemName) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
- {
- // Option currently returns no systems. TBD
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
- if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
- dBusEventLogEntryCollection(asyncResp);
- });
-}
-
-inline void afterDBusEventLogEntryGet(
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& entryID, const boost::system::error_code& ec,
- const dbus::utility::DBusPropertiesMap& resp)
-{
- if (ec.value() == EBADR)
- {
- messages::resourceNotFound(asyncResp->res, "EventLogEntry", entryID);
- return;
- }
- if (ec)
- {
- BMCWEB_LOG_ERROR("EventLogEntry (DBus) resp_handler got error {}", ec);
- messages::internalError(asyncResp->res);
- return;
- }
-
- std::optional<DbusEventLogEntry> optEntry =
- fillDbusEventLogEntryFromPropertyMap(resp);
-
- if (!optEntry.has_value())
- {
- messages::internalError(asyncResp->res);
- return;
- }
-
- fillEventLogLogEntryFromDbusLogEntry(*optEntry, asyncResp->res.jsonValue);
-}
-
-inline void dBusEventLogEntryGet(
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID)
-{
- dbus::utility::escapePathForDbus(entryID);
-
- // DBus implementation of EventLog/Entries
- // Make call to Logging Service to find all log entry objects
- dbus::utility::getAllProperties(
- "xyz.openbmc_project.Logging",
- "/xyz/openbmc_project/logging/entry/" + entryID, "",
- std::bind_front(afterDBusEventLogEntryGet, asyncResp, entryID));
-}
-
-inline void dBusEventLogEntryPatch(
- const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& entryId)
-{
- std::optional<bool> resolved;
-
- if (!json_util::readJsonPatch(req, asyncResp->res, "Resolved", resolved))
- {
- return;
- }
- BMCWEB_LOG_DEBUG("Set Resolved");
-
- setDbusProperty(asyncResp, "Resolved", "xyz.openbmc_project.Logging",
- "/xyz/openbmc_project/logging/entry/" + entryId,
- "xyz.openbmc_project.Logging.Entry", "Resolved",
- resolved.value_or(false));
-}
-
-inline void dBusEventLogEntryDelete(
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID)
-{
- BMCWEB_LOG_DEBUG("Do delete single event entries.");
-
- dbus::utility::escapePathForDbus(entryID);
-
- // Process response from Logging service.
- auto respHandler = [asyncResp,
- entryID](const boost::system::error_code& ec) {
- BMCWEB_LOG_DEBUG("EventLogEntry (DBus) doDelete callback: Done");
- if (ec)
- {
- if (ec.value() == EBADR)
- {
- messages::resourceNotFound(asyncResp->res, "LogEntry", entryID);
- return;
- }
- // TODO Handle for specific error code
- BMCWEB_LOG_ERROR(
- "EventLogEntry (DBus) doDelete respHandler got error {}", ec);
- asyncResp->res.result(
- boost::beast::http::status::internal_server_error);
- return;
- }
-
- messages::success(asyncResp->res);
- };
-
- // Make call to Logging service to request Delete Log
- dbus::utility::async_method_call(
- asyncResp, respHandler, "xyz.openbmc_project.Logging",
- "/xyz/openbmc_project/logging/entry/" + entryID,
- "xyz.openbmc_project.Object.Delete", "Delete");
-}
-
-inline void requestRoutesDBusEventLogEntry(App& app)
-{
- BMCWEB_ROUTE(
- app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
- .privileges(redfish::privileges::getLogEntry)
- .methods(boost::beast::http::verb::get)(
- [&app](const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& systemName, const std::string& entryId) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
- {
- // Option currently returns no systems. TBD
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
- if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
-
- dBusEventLogEntryGet(asyncResp, entryId);
- });
-
- BMCWEB_ROUTE(
- app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
- .privileges(redfish::privileges::patchLogEntry)
- .methods(boost::beast::http::verb::patch)(
- [&app](const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& systemName, const std::string& entryId) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
- {
- // Option currently returns no systems. TBD
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
- if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
-
- dBusEventLogEntryPatch(req, asyncResp, entryId);
- });
-
- BMCWEB_ROUTE(
- app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
- .privileges(
- redfish::privileges::
- deleteLogEntrySubOverComputerSystemLogServiceCollectionLogServiceLogEntryCollection)
- .methods(boost::beast::http::verb::delete_)(
- [&app](const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& systemName, const std::string& param) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
- {
- // Option currently returns no systems. TBD
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
- if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
- dBusEventLogEntryDelete(asyncResp, param);
- });
-}
-
inline void handleBMCLogServicesCollectionGet(
crow::App& app, const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
@@ -1808,25 +1406,6 @@
downloadDumpEntry(asyncResp, dumpId, dumpType);
}
-inline void handleDBusEventLogEntryDownloadGet(
- crow::App& app, const std::string& dumpType, const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& systemName, const std::string& entryID)
-{
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- if (!http_helpers::isContentTypeAllowed(
- req.getHeaderValue("Accept"),
- http_helpers::ContentType::OctetStream, true))
- {
- asyncResp->res.result(boost::beast::http::status::bad_request);
- return;
- }
- downloadEventLogEntry(asyncResp, systemName, entryID, dumpType);
-}
-
inline void handleLogServicesDumpCollectDiagnosticDataPost(
crow::App& app, const std::string& dumpType, const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
@@ -1976,16 +1555,6 @@
handleLogServicesDumpClearLogPost, std::ref(app), "BMC"));
}
-inline void requestRoutesDBusEventLogEntryDownload(App& app)
-{
- BMCWEB_ROUTE(
- app,
- "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/attachment/")
- .privileges(redfish::privileges::getLogEntry)
- .methods(boost::beast::http::verb::get)(std::bind_front(
- handleDBusEventLogEntryDownloadGet, std::ref(app), "System"));
-}
-
inline void requestRoutesFaultLogDumpService(App& app)
{
BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/")
@@ -2622,73 +2191,4 @@
crashdumpObject, crashdumpPath, iface, method);
});
}
-
-inline void dBusLogServiceActionsClear(
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
-{
- BMCWEB_LOG_DEBUG("Do delete all entries.");
-
- // Process response from Logging service.
- auto respHandler = [asyncResp](const boost::system::error_code& ec) {
- BMCWEB_LOG_DEBUG("doClearLog resp_handler callback: Done");
- if (ec)
- {
- // TODO Handle for specific error code
- BMCWEB_LOG_ERROR("doClearLog resp_handler got error {}", ec);
- asyncResp->res.result(
- boost::beast::http::status::internal_server_error);
- return;
- }
-
- messages::success(asyncResp->res);
- };
-
- // Make call to Logging service to request Clear Log
- dbus::utility::async_method_call(
- asyncResp, respHandler, "xyz.openbmc_project.Logging",
- "/xyz/openbmc_project/logging",
- "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
-}
-
-/**
- * DBusLogServiceActionsClear class supports POST method for ClearLog action.
- */
-inline void requestRoutesDBusLogServiceActionsClear(App& app)
-{
- /**
- * Function handles POST method request.
- * The Clear Log actions does not require any parameter.The action deletes
- * all entries found in the Entries collection for this Log Service.
- */
-
- BMCWEB_ROUTE(
- app,
- "/redfish/v1/Systems/<str>/LogServices/EventLog/Actions/LogService.ClearLog/")
- .privileges(redfish::privileges::
- postLogServiceSubOverComputerSystemLogServiceCollection)
- .methods(boost::beast::http::verb::post)(
- [&app](const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& systemName) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
- {
- // Option currently returns no systems. TBD
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
- if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
- dBusLogServiceActionsClear(asyncResp);
- });
-}
-
} // namespace redfish
diff --git a/redfish-core/lib/systems_logservices_dbus_eventlog.hpp b/redfish-core/lib/systems_logservices_dbus_eventlog.hpp
new file mode 100644
index 0000000..64f87da
--- /dev/null
+++ b/redfish-core/lib/systems_logservices_dbus_eventlog.hpp
@@ -0,0 +1,548 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: Copyright OpenBMC Authors
+// SPDX-FileCopyrightText: Copyright 2018 Intel Corporation
+#pragma once
+
+#include "bmcweb_config.h"
+
+#include "app.hpp"
+#include "async_resp.hpp"
+#include "dbus_utility.hpp"
+#include "error_messages.hpp"
+#include "http_body.hpp"
+#include "http_request.hpp"
+#include "http_response.hpp"
+#include "http_utility.hpp"
+#include "logging.hpp"
+#include "query.hpp"
+#include "registries/privilege_registry.hpp"
+#include "utils/dbus_event_log_entry.hpp"
+#include "utils/dbus_utils.hpp"
+#include "utils/json_utils.hpp"
+#include "utils/log_services_utils.hpp"
+#include "utils/time_utils.hpp"
+
+#include <asm-generic/errno.h>
+#include <systemd/sd-bus.h>
+#include <unistd.h>
+
+#include <boost/beast/http/field.hpp>
+#include <boost/beast/http/status.hpp>
+#include <boost/beast/http/verb.hpp>
+#include <boost/system/linux_error.hpp>
+#include <boost/url/format.hpp>
+#include <boost/url/url.hpp>
+#include <sdbusplus/message.hpp>
+#include <sdbusplus/message/native_types.hpp>
+#include <sdbusplus/unpack_properties.hpp>
+
+#include <algorithm>
+#include <format>
+#include <functional>
+#include <memory>
+#include <optional>
+#include <string>
+#include <string_view>
+#include <utility>
+#include <vector>
+
+namespace redfish
+{
+
+inline std::optional<bool> getProviderNotifyAction(const std::string& notify)
+{
+ std::optional<bool> notifyAction;
+ if (notify == "xyz.openbmc_project.Logging.Entry.Notify.Notify")
+ {
+ notifyAction = true;
+ }
+ else if (notify == "xyz.openbmc_project.Logging.Entry.Notify.Inhibit")
+ {
+ notifyAction = false;
+ }
+
+ return notifyAction;
+}
+
+inline std::string translateSeverityDbusToRedfish(const std::string& s)
+{
+ if ((s == "xyz.openbmc_project.Logging.Entry.Level.Alert") ||
+ (s == "xyz.openbmc_project.Logging.Entry.Level.Critical") ||
+ (s == "xyz.openbmc_project.Logging.Entry.Level.Emergency") ||
+ (s == "xyz.openbmc_project.Logging.Entry.Level.Error"))
+ {
+ return "Critical";
+ }
+ if ((s == "xyz.openbmc_project.Logging.Entry.Level.Debug") ||
+ (s == "xyz.openbmc_project.Logging.Entry.Level.Informational") ||
+ (s == "xyz.openbmc_project.Logging.Entry.Level.Notice"))
+ {
+ return "OK";
+ }
+ if (s == "xyz.openbmc_project.Logging.Entry.Level.Warning")
+ {
+ return "Warning";
+ }
+ return "";
+}
+
+inline void fillEventLogLogEntryFromDbusLogEntry(
+ const DbusEventLogEntry& entry, nlohmann::json& objectToFillOut)
+{
+ objectToFillOut["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
+ objectToFillOut["@odata.id"] = boost::urls::format(
+ "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}",
+ BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(entry.Id));
+ objectToFillOut["Name"] = "System Event Log Entry";
+ objectToFillOut["Id"] = std::to_string(entry.Id);
+ objectToFillOut["Message"] = entry.Message;
+ objectToFillOut["Resolved"] = entry.Resolved;
+ std::optional<bool> notifyAction =
+ getProviderNotifyAction(entry.ServiceProviderNotify);
+ if (notifyAction)
+ {
+ objectToFillOut["ServiceProviderNotified"] = *notifyAction;
+ }
+ if ((entry.Resolution != nullptr) && !entry.Resolution->empty())
+ {
+ objectToFillOut["Resolution"] = *entry.Resolution;
+ }
+ objectToFillOut["EntryType"] = "Event";
+ objectToFillOut["Severity"] =
+ translateSeverityDbusToRedfish(entry.Severity);
+ objectToFillOut["Created"] =
+ redfish::time_utils::getDateTimeUintMs(entry.Timestamp);
+ objectToFillOut["Modified"] =
+ redfish::time_utils::getDateTimeUintMs(entry.UpdateTimestamp);
+ if (entry.Path != nullptr)
+ {
+ objectToFillOut["AdditionalDataURI"] = boost::urls::format(
+ "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}/attachment",
+ BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(entry.Id));
+ }
+}
+
+inline void afterLogEntriesGetManagedObjects(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const boost::system::error_code& ec,
+ const dbus::utility::ManagedObjectType& resp)
+{
+ if (ec)
+ {
+ // TODO Handle for specific error code
+ BMCWEB_LOG_ERROR("getLogEntriesIfaceData resp_handler got error {}",
+ ec);
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ nlohmann::json::array_t entriesArray;
+ for (const auto& objectPath : resp)
+ {
+ dbus::utility::DBusPropertiesMap propsFlattened;
+ auto isEntry =
+ std::ranges::find_if(objectPath.second, [](const auto& object) {
+ return object.first == "xyz.openbmc_project.Logging.Entry";
+ });
+ if (isEntry == objectPath.second.end())
+ {
+ continue;
+ }
+
+ for (const auto& interfaceMap : objectPath.second)
+ {
+ for (const auto& propertyMap : interfaceMap.second)
+ {
+ propsFlattened.emplace_back(propertyMap.first,
+ propertyMap.second);
+ }
+ }
+ std::optional<DbusEventLogEntry> optEntry =
+ fillDbusEventLogEntryFromPropertyMap(propsFlattened);
+
+ if (!optEntry.has_value())
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ fillEventLogLogEntryFromDbusLogEntry(*optEntry,
+ entriesArray.emplace_back());
+ }
+
+ redfish::json_util::sortJsonArrayByKey(entriesArray, "Id");
+ asyncResp->res.jsonValue["Members@odata.count"] = entriesArray.size();
+ asyncResp->res.jsonValue["Members"] = std::move(entriesArray);
+}
+
+inline void dBusEventLogEntryCollection(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+{
+ // Collections don't include the static data added by SubRoute
+ // because it has a duplicate entry for members
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogEntryCollection.LogEntryCollection";
+ asyncResp->res.jsonValue["@odata.id"] =
+ std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
+ BMCWEB_REDFISH_SYSTEM_URI_NAME);
+ asyncResp->res.jsonValue["Name"] = "System Event Log Entries";
+ asyncResp->res.jsonValue["Description"] =
+ "Collection of System Event Log Entries";
+
+ // DBus implementation of EventLog/Entries
+ // Make call to Logging Service to find all log entry objects
+ sdbusplus::message::object_path path("/xyz/openbmc_project/logging");
+ dbus::utility::getManagedObjects(
+ "xyz.openbmc_project.Logging", path,
+ [asyncResp](const boost::system::error_code& ec,
+ const dbus::utility::ManagedObjectType& resp) {
+ afterLogEntriesGetManagedObjects(asyncResp, ec, resp);
+ });
+}
+
+inline void afterDBusEventLogEntryGet(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& entryID, const boost::system::error_code& ec,
+ const dbus::utility::DBusPropertiesMap& resp)
+{
+ if (ec.value() == EBADR)
+ {
+ messages::resourceNotFound(asyncResp->res, "EventLogEntry", entryID);
+ return;
+ }
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("EventLogEntry (DBus) resp_handler got error {}", ec);
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ std::optional<DbusEventLogEntry> optEntry =
+ fillDbusEventLogEntryFromPropertyMap(resp);
+
+ if (!optEntry.has_value())
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ fillEventLogLogEntryFromDbusLogEntry(*optEntry, asyncResp->res.jsonValue);
+}
+
+inline void dBusEventLogEntryGet(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID)
+{
+ dbus::utility::escapePathForDbus(entryID);
+
+ // DBus implementation of EventLog/Entries
+ // Make call to Logging Service to find all log entry objects
+ dbus::utility::getAllProperties(
+ "xyz.openbmc_project.Logging",
+ "/xyz/openbmc_project/logging/entry/" + entryID, "",
+ std::bind_front(afterDBusEventLogEntryGet, asyncResp, entryID));
+}
+
+inline void dBusEventLogEntryPatch(
+ const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& entryId)
+{
+ std::optional<bool> resolved;
+
+ if (!json_util::readJsonPatch(req, asyncResp->res, "Resolved", resolved))
+ {
+ return;
+ }
+ BMCWEB_LOG_DEBUG("Set Resolved");
+
+ setDbusProperty(asyncResp, "Resolved", "xyz.openbmc_project.Logging",
+ "/xyz/openbmc_project/logging/entry/" + entryId,
+ "xyz.openbmc_project.Logging.Entry", "Resolved",
+ resolved.value_or(false));
+}
+
+inline void dBusEventLogEntryDelete(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID)
+{
+ BMCWEB_LOG_DEBUG("Do delete single event entries.");
+
+ dbus::utility::escapePathForDbus(entryID);
+
+ // Process response from Logging service.
+ auto respHandler = [asyncResp,
+ entryID](const boost::system::error_code& ec) {
+ BMCWEB_LOG_DEBUG("EventLogEntry (DBus) doDelete callback: Done");
+ if (ec)
+ {
+ if (ec.value() == EBADR)
+ {
+ messages::resourceNotFound(asyncResp->res, "LogEntry", entryID);
+ return;
+ }
+ // TODO Handle for specific error code
+ BMCWEB_LOG_ERROR(
+ "EventLogEntry (DBus) doDelete respHandler got error {}", ec);
+ asyncResp->res.result(
+ boost::beast::http::status::internal_server_error);
+ return;
+ }
+
+ messages::success(asyncResp->res);
+ };
+
+ // Make call to Logging service to request Delete Log
+ dbus::utility::async_method_call(
+ asyncResp, respHandler, "xyz.openbmc_project.Logging",
+ "/xyz/openbmc_project/logging/entry/" + entryID,
+ "xyz.openbmc_project.Object.Delete", "Delete");
+}
+
+inline void dBusLogServiceActionsClear(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+{
+ BMCWEB_LOG_DEBUG("Do delete all entries.");
+
+ // Process response from Logging service.
+ auto respHandler = [asyncResp](const boost::system::error_code& ec) {
+ BMCWEB_LOG_DEBUG("doClearLog resp_handler callback: Done");
+ if (ec)
+ {
+ // TODO Handle for specific error code
+ BMCWEB_LOG_ERROR("doClearLog resp_handler got error {}", ec);
+ asyncResp->res.result(
+ boost::beast::http::status::internal_server_error);
+ return;
+ }
+
+ messages::success(asyncResp->res);
+ };
+
+ // Make call to Logging service to request Clear Log
+ dbus::utility::async_method_call(
+ asyncResp, respHandler, "xyz.openbmc_project.Logging",
+ "/xyz/openbmc_project/logging",
+ "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
+}
+
+inline void downloadEventLogEntry(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& systemName, const std::string& entryID,
+ const std::string& dumpType)
+{
+ if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
+ {
+ // Option currently returns no systems. TBD
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+ if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+
+ std::string entryPath =
+ sdbusplus::message::object_path("/xyz/openbmc_project/logging/entry") /
+ entryID;
+
+ auto downloadEventLogEntryHandler =
+ [asyncResp, entryID,
+ dumpType](const boost::system::error_code& ec,
+ const sdbusplus::message::unix_fd& unixfd) {
+ log_services_utils::downloadEntryCallback(asyncResp, entryID,
+ dumpType, ec, unixfd);
+ };
+
+ dbus::utility::async_method_call(
+ asyncResp, std::move(downloadEventLogEntryHandler),
+ "xyz.openbmc_project.Logging", entryPath,
+ "xyz.openbmc_project.Logging.Entry", "GetEntry");
+}
+
+inline void handleDBusEventLogEntryDownloadGet(
+ crow::App& app, const std::string& dumpType, const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& systemName, const std::string& entryID)
+{
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+ if (!http_helpers::isContentTypeAllowed(
+ req.getHeaderValue("Accept"),
+ http_helpers::ContentType::OctetStream, true))
+ {
+ asyncResp->res.result(boost::beast::http::status::bad_request);
+ return;
+ }
+ downloadEventLogEntry(asyncResp, systemName, entryID, dumpType);
+}
+
+inline void requestRoutesDBusEventLogEntryCollection(App& app)
+{
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/")
+ .privileges(redfish::privileges::getLogEntryCollection)
+ .methods(boost::beast::http::verb::get)(
+ [&app](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& systemName) {
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+ if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
+ {
+ // Option currently returns no systems. TBD
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+ if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+ dBusEventLogEntryCollection(asyncResp);
+ });
+}
+
+inline void requestRoutesDBusEventLogEntry(App& app)
+{
+ BMCWEB_ROUTE(
+ app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
+ .privileges(redfish::privileges::getLogEntry)
+ .methods(boost::beast::http::verb::get)(
+ [&app](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& systemName, const std::string& entryId) {
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+ if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
+ {
+ // Option currently returns no systems. TBD
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+ if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+
+ dBusEventLogEntryGet(asyncResp, entryId);
+ });
+
+ BMCWEB_ROUTE(
+ app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
+ .privileges(redfish::privileges::patchLogEntry)
+ .methods(boost::beast::http::verb::patch)(
+ [&app](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& systemName, const std::string& entryId) {
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+ if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
+ {
+ // Option currently returns no systems. TBD
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+ if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+
+ dBusEventLogEntryPatch(req, asyncResp, entryId);
+ });
+
+ BMCWEB_ROUTE(
+ app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
+ .privileges(
+ redfish::privileges::
+ deleteLogEntrySubOverComputerSystemLogServiceCollectionLogServiceLogEntryCollection)
+ .methods(boost::beast::http::verb::delete_)(
+ [&app](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& systemName, const std::string& param) {
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+ if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
+ {
+ // Option currently returns no systems. TBD
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+ if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+ dBusEventLogEntryDelete(asyncResp, param);
+ });
+}
+
+/**
+ * DBusLogServiceActionsClear class supports POST method for ClearLog action.
+ */
+inline void requestRoutesDBusLogServiceActionsClear(App& app)
+{
+ /**
+ * Function handles POST method request.
+ * The Clear Log actions does not require any parameter.The action deletes
+ * all entries found in the Entries collection for this Log Service.
+ */
+
+ BMCWEB_ROUTE(
+ app,
+ "/redfish/v1/Systems/<str>/LogServices/EventLog/Actions/LogService.ClearLog/")
+ .privileges(redfish::privileges::
+ postLogServiceSubOverComputerSystemLogServiceCollection)
+ .methods(boost::beast::http::verb::post)(
+ [&app](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& systemName) {
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+ if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
+ {
+ // Option currently returns no systems. TBD
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+ if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+ dBusLogServiceActionsClear(asyncResp);
+ });
+}
+
+inline void requestRoutesDBusEventLogEntryDownload(App& app)
+{
+ BMCWEB_ROUTE(
+ app,
+ "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/attachment/")
+ .privileges(redfish::privileges::getLogEntry)
+ .methods(boost::beast::http::verb::get)(std::bind_front(
+ handleDBusEventLogEntryDownloadGet, std::ref(app), "System"));
+}
+} // namespace redfish
diff --git a/redfish-core/src/redfish.cpp b/redfish-core/src/redfish.cpp
index f189770..9ee2280 100644
--- a/redfish-core/src/redfish.cpp
+++ b/redfish-core/src/redfish.cpp
@@ -43,6 +43,7 @@
#include "service_root.hpp"
#include "storage.hpp"
#include "systems.hpp"
+#include "systems_logservices_dbus_eventlog.hpp"
#include "systems_logservices_hostlogger.hpp"
#include "systems_logservices_journal_eventlog.hpp"
#include "systems_logservices_postcodes.hpp"