576 lines
23 KiB
Diff
Executable File
576 lines
23 KiB
Diff
Executable File
From 76889ebb1cdc9d5cc2e29c065d1ab0c906b88f47 Mon Sep 17 00:00:00 2001
|
|
From: roly <Rolyli.Li@luxshare-ict.com>
|
|
Date: Mon, 9 Dec 2024 14:30:51 +0800
|
|
Subject: [PATCH] Add Managers SEL log service
|
|
|
|
---
|
|
include/luxshare/sel.hpp | 434 ++++++++++++++++++++++++++++++
|
|
include/luxshare/utils.hpp | 38 +++
|
|
meson.build | 1 +
|
|
meson_options.txt | 8 +
|
|
redfish-core/lib/log_services.hpp | 6 +
|
|
src/webserver_main.cpp | 6 +
|
|
6 files changed, 493 insertions(+)
|
|
create mode 100755 include/luxshare/sel.hpp
|
|
create mode 100755 include/luxshare/utils.hpp
|
|
|
|
diff --git a/include/luxshare/sel.hpp b/include/luxshare/sel.hpp
|
|
new file mode 100755
|
|
index 00000000..cbaa1cd5
|
|
--- /dev/null
|
|
+++ b/include/luxshare/sel.hpp
|
|
@@ -0,0 +1,434 @@
|
|
+#pragma once
|
|
+#include <app.hpp>
|
|
+#include <async_resp.hpp>
|
|
+#include <luxshare/utils.hpp>
|
|
+#include <error_messages.hpp>
|
|
+#include <registries/privilege_registry.hpp>
|
|
+
|
|
+namespace crow
|
|
+{
|
|
+namespace luxshare_sel_api
|
|
+{
|
|
+
|
|
+enum class SELStatus
|
|
+{
|
|
+ DEASSERTED,
|
|
+ ASSERTED,
|
|
+ UNKNOWN
|
|
+};
|
|
+
|
|
+
|
|
+
|
|
+inline std::string translateSeverityDbusToRedfish(const std::string& s)
|
|
+{
|
|
+ if ((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";
|
|
+ }
|
|
+ if (s == "xyz.openbmc_project.Logging.Entry.Level.Alert")
|
|
+ {
|
|
+ return "NonRecoverable";
|
|
+ }
|
|
+ return "";
|
|
+}
|
|
+
|
|
+inline void requestRoutesSelClear(App& app)
|
|
+{
|
|
+ BMCWEB_ROUTE(
|
|
+ app,
|
|
+ "/redfish/v1/Managers/bmc/LogServices/SEL/Actions/LogService.ClearLog/")
|
|
+ .privileges(redfish::privileges::privilegeSetConfigureComponents)
|
|
+ .methods(boost::beast::http::verb::post)(
|
|
+ [](const crow::Request& req,
|
|
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
|
|
+ if (!redfish::luxshare::checkPostRequestBodyEmpty(req))
|
|
+ {
|
|
+ redfish::messages::actionParameterNotSupported(
|
|
+ asyncResp->res, req.body(), "ClearLog");
|
|
+ return;
|
|
+ }
|
|
+ using IpmiDbusRspType = std::tuple<uint8_t, uint8_t, uint8_t,
|
|
+ uint8_t, std::vector<uint8_t>>;
|
|
+ crow::connections::systemBus->async_method_call(
|
|
+ [asyncResp](const boost::system::error_code &ec, IpmiDbusRspType response1) {
|
|
+ // Handle the response of the first method call
|
|
+ if (ec) {
|
|
+ BMCWEB_LOG_ERROR("Error calling execute method: {}", ec.message());
|
|
+ redfish::messages::internalError(asyncResp->res);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ const uint8_t& cc1 = std::get<3>(response1);
|
|
+ if (cc1 != 0) {
|
|
+ BMCWEB_LOG_ERROR("Failed to reserve sel: cc: {}", cc1);
|
|
+ redfish::messages::internalError(asyncResp->res);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ // Extract reservation ID from the response
|
|
+ std::vector<uint8_t> reservationId = std::get<4>(response1);
|
|
+ std::vector<uint8_t> commandData = {0x43, 0x4C, 0x52, 0xAA};
|
|
+ commandData.insert(commandData.begin(), reservationId.begin(), reservationId.end());
|
|
+
|
|
+ // Execute "Clear SEL" IPMI command
|
|
+ crow::connections::systemBus->async_method_call(
|
|
+ [asyncResp](const boost::system::error_code &ec1,IpmiDbusRspType response2) {
|
|
+ // Handle the response of the clear SEL command
|
|
+ if (ec1) {
|
|
+ BMCWEB_LOG_ERROR("Error calling execute method: {}", ec1.message());
|
|
+ redfish::messages::internalError(asyncResp->res);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ const uint8_t& cc2 = std::get<3>(response2);
|
|
+ if (cc2 != 0) {
|
|
+ BMCWEB_LOG_ERROR("Failed to clear sel: cc: {}", cc2);
|
|
+ redfish::messages::internalError(asyncResp->res);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ // Success logic for clearing SEL can go here
|
|
+ BMCWEB_LOG_INFO("Successfully cleared SEL.");
|
|
+ },
|
|
+ "xyz.openbmc_project.Ipmi.Host",
|
|
+ "/xyz/openbmc_project/Ipmi",
|
|
+ "xyz.openbmc_project.Ipmi.Server", "execute",
|
|
+ uint8_t{0x0a}, uint8_t{0x00}, uint8_t{0x47}, // Command to clear SEL
|
|
+ commandData,
|
|
+ std::map<std::string, std::variant<uint8_t>>{}
|
|
+ );
|
|
+ },
|
|
+ "xyz.openbmc_project.Ipmi.Host",
|
|
+ "/xyz/openbmc_project/Ipmi",
|
|
+ "xyz.openbmc_project.Ipmi.Server", "execute",
|
|
+ uint8_t{0x0a}, uint8_t{0x00}, uint8_t{0x42}, // Command to reserve SEL
|
|
+ std::vector<uint8_t>{},
|
|
+ std::map<std::string, std::variant<uint8_t>>{});
|
|
+ });
|
|
+}
|
|
+
|
|
+inline void requestRoutesSelEntries(App& app)
|
|
+{
|
|
+ BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/LogServices/SEL/Entries/")
|
|
+ .privileges(redfish::privileges::getLogService)
|
|
+ .methods(boost::beast::http::verb::get)(
|
|
+ [&app](const crow::Request& req,
|
|
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
|
|
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
|
|
+ {
|
|
+ return;
|
|
+ }
|
|
+ // Get sensor info from xyz.openbmc_project.Ipmi.Host
|
|
+ auto respHandler =
|
|
+ [asyncResp](
|
|
+ const boost::system::error_code& ec,
|
|
+ const std::unordered_map<std::string, std::vector<uint8_t>>&
|
|
+ sensorInfo) {
|
|
+ if (ec)
|
|
+ {
|
|
+ BMCWEB_LOG_ERROR("Error getting SensorInfo property: {}",
|
|
+ ec.message());
|
|
+ redfish::messages::internalError(asyncResp->res);
|
|
+ return;
|
|
+ }
|
|
+ // Get all sel log from xyz.openbmc_project.Logging service.
|
|
+ sdbusplus::message::object_path path(
|
|
+ "/xyz/openbmc_project/logging");
|
|
+ dbus::utility::getManagedObjects(
|
|
+ "xyz.openbmc_project.Logging", path,
|
|
+ [asyncResp,
|
|
+ sensorInfo](const boost::system::error_code& errorCode,
|
|
+ const dbus::utility::ManagedObjectType& resp) {
|
|
+ if (errorCode)
|
|
+ {
|
|
+ BMCWEB_LOG_ERROR("Logging GetManagedObjects error: {}",
|
|
+ errorCode.message());
|
|
+ redfish::messages::internalError(asyncResp->res);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ nlohmann::json& entriesArray =
|
|
+ asyncResp->res.jsonValue["Members"];
|
|
+ entriesArray = nlohmann::json::array();
|
|
+ std::map<uint32_t, uint64_t> idToTimestamp;
|
|
+ for (const auto& objectPath : resp)
|
|
+ {
|
|
+ const uint32_t* id = nullptr;
|
|
+ const uint64_t* timestamp = nullptr;
|
|
+ const std::string* severity = nullptr;
|
|
+ const std::string* message = nullptr;
|
|
+ const std::vector<std::string>* additionalData = nullptr;
|
|
+ nlohmann::json sensorName;
|
|
+ nlohmann::json sensorValue;
|
|
+ nlohmann::json sensorNumber;
|
|
+ nlohmann::json sensorType;
|
|
+ nlohmann::json eventType;
|
|
+ std::string sensorPath;
|
|
+ SELStatus selStatus = SELStatus::UNKNOWN;
|
|
+
|
|
+ for (const auto& interfaceMap : objectPath.second)
|
|
+ {
|
|
+ if (interfaceMap.first ==
|
|
+ "xyz.openbmc_project.Logging.Entry")
|
|
+ {
|
|
+ for (const auto& propertyMap : interfaceMap.second)
|
|
+ {
|
|
+ if (propertyMap.first == "Id")
|
|
+ {
|
|
+ id = std::get_if<uint32_t>(
|
|
+ &propertyMap.second);
|
|
+ }
|
|
+ else if (propertyMap.first == "Timestamp")
|
|
+ {
|
|
+ timestamp = std::get_if<uint64_t>(
|
|
+ &propertyMap.second);
|
|
+ }
|
|
+ else if (propertyMap.first == "Severity")
|
|
+ {
|
|
+ severity = std::get_if<std::string>(
|
|
+ &propertyMap.second);
|
|
+ }
|
|
+ else if (propertyMap.first == "Message")
|
|
+ {
|
|
+ message = std::get_if<std::string>(
|
|
+ &propertyMap.second);
|
|
+ if (*message ==
|
|
+ "xyz.openbmc_project.Common.Error."
|
|
+ "InternalFailure")
|
|
+ {
|
|
+ // Skip this entry
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ else if (propertyMap.first == "AdditionalData")
|
|
+ {
|
|
+ additionalData =
|
|
+ std::get_if<std::vector<std::string>>(
|
|
+ &propertyMap.second);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (id == nullptr || message == nullptr ||
|
|
+ timestamp == nullptr || severity == nullptr ||
|
|
+ additionalData == nullptr)
|
|
+ {
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ idToTimestamp[*id] = *timestamp;
|
|
+
|
|
+ entriesArray.push_back({});
|
|
+ nlohmann::json& thisEntry = entriesArray.back();
|
|
+ thisEntry["@odata.id"] = boost::urls::format(
|
|
+ "/redfish/v1/Managers/bmc/LogServices/SEL/Entries/{}",
|
|
+ std::to_string(*id));
|
|
+ thisEntry["Id"] = *id;
|
|
+ thisEntry["Message"] = *message;
|
|
+
|
|
+ // Get the Created time from the timestamp.
|
|
+ thisEntry["Created"] =
|
|
+ redfish::time_utils::getDateTimeUintMs(*timestamp);
|
|
+ thisEntry["Severity"] =
|
|
+ translateSeverityDbusToRedfish(*severity);
|
|
+
|
|
+ for (const auto& data : *additionalData)
|
|
+ {
|
|
+ if (data.starts_with("SENSOR_PATH="))
|
|
+ {
|
|
+ sensorPath =
|
|
+ data.substr(data.find_first_of('=') + 1);
|
|
+ if (!sensorPath.empty())
|
|
+ {
|
|
+ // Get the sensor name from the last level of
|
|
+ // the path.
|
|
+ sensorName =
|
|
+ data.substr(data.find_last_of('/') + 1);
|
|
+ }
|
|
+ }
|
|
+ else if (data.starts_with("EVENT_DIR="))
|
|
+ {
|
|
+ selStatus = static_cast<SELStatus>(std::stoi(
|
|
+ data.substr(data.find_first_of('=') + 1)));
|
|
+ }
|
|
+ else if (data.starts_with("READING="))
|
|
+ {
|
|
+ sensorValue =
|
|
+ data.substr(data.find_first_of('=') + 1);
|
|
+ }
|
|
+ else if (data.starts_with("SENSOR_DATA="))
|
|
+ {
|
|
+ // The second character is the status of the
|
|
+ // discrete sensor. Convert to string format
|
|
+ // starting with 0x.
|
|
+ auto sensorValueStr =
|
|
+ data.substr(data.find_first_of('=') + 2, 1);
|
|
+
|
|
+ try
|
|
+ {
|
|
+ std::stringstream output;
|
|
+ output << "0x" << std::hex << std::setw(2)
|
|
+ << std::setfill('0')
|
|
+ << static_cast<uint16_t>(std::stoi(
|
|
+ sensorValueStr, nullptr, 16));
|
|
+
|
|
+ sensorValue = output.str();
|
|
+ }
|
|
+ catch (const std::exception&)
|
|
+ {
|
|
+ sensorValue = nlohmann::json::value_t::null;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (selStatus == SELStatus::UNKNOWN)
|
|
+ {
|
|
+ // Match SEL status in message property.
|
|
+ std::string messageStr = *message;
|
|
+ if (messageStr.find("deassert") != std::string::npos)
|
|
+ {
|
|
+ selStatus = SELStatus::DEASSERTED;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ selStatus = SELStatus::ASSERTED;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (sensorValue == nlohmann::json::value_t::null)
|
|
+ {
|
|
+ // Get SEL Reading in message properties.
|
|
+ std::string messageErased(*message);
|
|
+ std::string::size_type posString = 0;
|
|
+ posString = messageErased.find("Reading ");
|
|
+ if (posString == std::string::npos)
|
|
+ {
|
|
+ posString = messageErased.find("Reading=");
|
|
+ }
|
|
+
|
|
+ if (posString != std::string::npos)
|
|
+ {
|
|
+ // Offset the length of 'Reading ' or 'Reading=' to
|
|
+ // obtain the substring before the space.
|
|
+ messageErased = messageErased.substr(posString + 8);
|
|
+ auto posSpace = messageErased.find_last_of(' ');
|
|
+ if (posSpace != std::string::npos)
|
|
+ {
|
|
+ sensorValue = messageErased.substr(0, posSpace);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ auto sensorEntryInfo = sensorInfo.find(sensorPath);
|
|
+ if (sensorEntryInfo != sensorInfo.end())
|
|
+ {
|
|
+ std::stringstream output;
|
|
+ // Sensor number subscript in the vector is 6.
|
|
+ output << "0x" << std::hex << std::setw(2)
|
|
+ << std::setfill('0')
|
|
+ << static_cast<uint16_t>(
|
|
+ sensorEntryInfo->second[6]);
|
|
+ sensorNumber = output.str();
|
|
+ // Sensor type subscript in the vector is 0.
|
|
+ output.str("");
|
|
+ output << "0x" << std::hex << std::setw(2)
|
|
+ << std::setfill('0')
|
|
+ << static_cast<uint16_t>(
|
|
+ sensorEntryInfo->second[0]);
|
|
+ sensorType = output.str();
|
|
+ // Event type subscript in the vector is 1.
|
|
+ output.str("");
|
|
+ output << "0x" << std::hex << std::setw(2)
|
|
+ << std::setfill('0')
|
|
+ << static_cast<uint16_t>(
|
|
+ sensorEntryInfo->second[1]);
|
|
+ eventType = output.str();
|
|
+ }
|
|
+
|
|
+ thisEntry["SensorType"] = sensorType;
|
|
+ thisEntry["SensorName"] = sensorName;
|
|
+ thisEntry["SensorNumber"] = sensorNumber;
|
|
+ thisEntry["SensorValue"] = sensorValue;
|
|
+ thisEntry["EventType"] = eventType;
|
|
+ if (selStatus == SELStatus::DEASSERTED)
|
|
+ {
|
|
+ thisEntry["Status"] = "Deasserted";
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ thisEntry["Status"] = "Asserted";
|
|
+ }
|
|
+ }
|
|
+
|
|
+ std::sort(entriesArray.begin(), entriesArray.end(),
|
|
+ [&idToTimestamp](const nlohmann::json& left,
|
|
+ const nlohmann::json& right) {
|
|
+ return (idToTimestamp[left["Id"].get<uint32_t>()] >=
|
|
+ idToTimestamp[right["Id"].get<uint32_t>()]);
|
|
+ });
|
|
+ asyncResp->res.jsonValue["Members@odata.count"] =
|
|
+ entriesArray.size();
|
|
+ });
|
|
+ };
|
|
+
|
|
+ sdbusplus::asio::getProperty<
|
|
+ std::unordered_map<std::string, std::vector<uint8_t>>>(
|
|
+ *crow::connections::systemBus, "xyz.openbmc_project.Ipmi.Host",
|
|
+ "/xyz/openbmc_project/Ipmi/SensorInfo",
|
|
+ "xyz.openbmc_project.IPMI.SensorInfo", "SensorInfo",
|
|
+ std::move(respHandler));
|
|
+ });
|
|
+}
|
|
+
|
|
+inline void requestRoutesSel(App& app)
|
|
+{
|
|
+ BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/LogServices/SEL/")
|
|
+ .privileges(redfish::privileges::getLogService)
|
|
+ .methods(boost::beast::http::verb::get)(
|
|
+ [&app](const crow::Request& req,
|
|
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
|
|
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
|
|
+ {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ asyncResp->res.jsonValue["@odata.type"] =
|
|
+ "#LogService.v1_1_0.LogService";
|
|
+ asyncResp->res.jsonValue["@odata.id"] =
|
|
+ "/redfish/v1/Managers/bmc/LogServices/SEL";
|
|
+ asyncResp->res.jsonValue["Name"] = "Event Log Service";
|
|
+ asyncResp->res.jsonValue["Description"] = "System Event Log Service";
|
|
+ asyncResp->res.jsonValue["Id"] = "SEL";
|
|
+ std::pair<std::string, std::string> redfishDateTimeOffset =
|
|
+ redfish::time_utils::getDateTimeOffsetNow();
|
|
+ asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
|
|
+ asyncResp->res.jsonValue["DateTimeLocalOffset"] =
|
|
+ redfishDateTimeOffset.second;
|
|
+
|
|
+ asyncResp->res.jsonValue["Entries"]["@odata.id"] =
|
|
+ "/redfish/v1/Managers/bmc/LogServices/SEL/Entries";
|
|
+ });
|
|
+}
|
|
+
|
|
+inline void requestRoutes(App& app)
|
|
+{
|
|
+ requestRoutesSelClear(app);
|
|
+ requestRoutesSelEntries(app);
|
|
+ requestRoutesSel(app);
|
|
+}
|
|
+
|
|
+} // namespace luxshare_sel_api
|
|
+} // namespace crow
|
|
diff --git a/include/luxshare/utils.hpp b/include/luxshare/utils.hpp
|
|
new file mode 100755
|
|
index 00000000..d1d7b97a
|
|
--- /dev/null
|
|
+++ b/include/luxshare/utils.hpp
|
|
@@ -0,0 +1,38 @@
|
|
+#pragma once
|
|
+#include <utils/json_utils.hpp>
|
|
+#include <utils/sw_utils.hpp>
|
|
+
|
|
+
|
|
+namespace redfish
|
|
+{
|
|
+namespace luxshare
|
|
+{
|
|
+
|
|
+inline bool checkPostRequestBodyEmpty(const crow::Request& req)
|
|
+{
|
|
+ if (req.body().empty())
|
|
+ {
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ nlohmann::json jsonRequest = nlohmann::json::parse(req.body(), nullptr,
|
|
+ false);
|
|
+ if (jsonRequest.is_discarded())
|
|
+ {
|
|
+ BMCWEB_LOG_DEBUG("Failed to parse json in request");
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ nlohmann::json::object_t* object =
|
|
+ jsonRequest.get_ptr<nlohmann::json::object_t*>();
|
|
+ if (object == nullptr || (!object->empty()))
|
|
+ {
|
|
+ BMCWEB_LOG_DEBUG("Json value is not object or empty");
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
+} // namespace luxshare
|
|
+} // namespace redfish
|
|
diff --git a/meson.build b/meson.build
|
|
index fcc0d7c4..3afb44e1 100644
|
|
--- a/meson.build
|
|
+++ b/meson.build
|
|
@@ -94,6 +94,7 @@ feature_map = {
|
|
'experimental-redfish-multi-computer-system' : '-DBMCWEB_ENABLE_MULTI_COMPUTERSYSTEM',
|
|
'vm-websocket' : '-DBMCWEB_ENABLE_VM_WEBSOCKET',
|
|
'xtoken-auth' : '-DBMCWEB_ENABLE_XTOKEN_AUTHENTICATION',
|
|
+ 'luxshare-api' : '-DBMCWEB_ENABLE_LUXSHARE_API',
|
|
#'vm-nbdproxy' : '-DBMCWEB_ENABLE_VM_NBDPROXY',
|
|
}
|
|
|
|
diff --git a/meson_options.txt b/meson_options.txt
|
|
index 017c16bd..562ac55b 100644
|
|
--- a/meson_options.txt
|
|
+++ b/meson_options.txt
|
|
@@ -200,6 +200,14 @@ option(
|
|
/google/v1/'''
|
|
)
|
|
|
|
+# Luxshare redfish option
|
|
+option(
|
|
+ 'luxshare-api',
|
|
+ type: 'feature',
|
|
+ value : 'enabled',
|
|
+ description: 'Enable Luxshare readfish feature'
|
|
+)
|
|
+
|
|
option(
|
|
'http-body-limit',
|
|
type: 'integer',
|
|
diff --git a/redfish-core/lib/log_services.hpp b/redfish-core/lib/log_services.hpp
|
|
index 9cb1fe05..51fe2313 100644
|
|
--- a/redfish-core/lib/log_services.hpp
|
|
+++ b/redfish-core/lib/log_services.hpp
|
|
@@ -2365,6 +2365,12 @@ inline void handleBMCLogServicesCollectionGet(
|
|
nlohmann::json& logServiceArray = asyncResp->res.jsonValue["Members"];
|
|
logServiceArray = nlohmann::json::array();
|
|
|
|
+#ifdef BMCWEB_ENABLE_LUXSHARE_API
|
|
+ nlohmann::json::object_t eventLog;
|
|
+ eventLog["@odata.id"] = "/redfish/v1/Managers/bmc/LogServices/SEL";
|
|
+ logServiceArray.emplace_back(std::move(eventLog));
|
|
+#endif
|
|
+
|
|
#ifdef BMCWEB_ENABLE_REDFISH_BMC_JOURNAL
|
|
nlohmann::json::object_t journal;
|
|
journal["@odata.id"] = "/redfish/v1/Managers/bmc/LogServices/Journal";
|
|
diff --git a/src/webserver_main.cpp b/src/webserver_main.cpp
|
|
index 67e2aaef..0008ad52 100644
|
|
--- a/src/webserver_main.cpp
|
|
+++ b/src/webserver_main.cpp
|
|
@@ -28,6 +28,8 @@
|
|
#include <sdbusplus/bus.hpp>
|
|
#include <sdbusplus/server.hpp>
|
|
|
|
+#include <luxshare/sel.hpp>
|
|
+
|
|
#include <exception>
|
|
#include <memory>
|
|
#include <string>
|
|
@@ -116,6 +118,10 @@ static int run()
|
|
crow::google_api::requestRoutes(app);
|
|
#endif
|
|
|
|
+#ifdef BMCWEB_ENABLE_LUXSHARE_API
|
|
+ crow::luxshare_sel_api::requestRoutes(app);
|
|
+#endif
|
|
+
|
|
if (bmcwebInsecureDisableXssPrevention != 0)
|
|
{
|
|
cors_preflight::requestRoutes(app);
|
|
--
|
|
2.25.1
|
|
|