Initial commit
This commit is contained in:
+575
@@ -0,0 +1,575 @@
|
||||
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
|
||||
|
||||
Executable
+91
@@ -0,0 +1,91 @@
|
||||
From f8db58ca9b57df4e97d5775a9038011019299cb3 Mon Sep 17 00:00:00 2001
|
||||
From: roly <Rolyli.Li@luxshare-ict.com>
|
||||
Date: Thu, 14 Nov 2024 19:09:27 +0800
|
||||
Subject: [PATCH] Add ReleaseDate for BMC inventory
|
||||
|
||||
---
|
||||
redfish-core/lib/update_service.hpp | 47 +++++++++++++++++++++++++++--
|
||||
1 file changed, 44 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/redfish-core/lib/update_service.hpp b/redfish-core/lib/update_service.hpp
|
||||
index af2725aa..cc3d939a 100644
|
||||
--- a/redfish-core/lib/update_service.hpp
|
||||
+++ b/redfish-core/lib/update_service.hpp
|
||||
@@ -892,6 +892,45 @@ inline static void
|
||||
}
|
||||
}
|
||||
|
||||
+inline void
|
||||
+ getSoftwareReleaseDate(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
|
||||
+ const std::string& service, const std::string& path,
|
||||
+ const std::string& purpose)
|
||||
+{
|
||||
+ if (purpose == sw_util::bmcPurpose)
|
||||
+ {
|
||||
+ sdbusplus::asio::getProperty<std::string>(
|
||||
+ *crow::connections::systemBus, service, path,
|
||||
+ "xyz.openbmc_project.Software.ReleaseDate", "ReleaseDate",
|
||||
+ [asyncResp, path](const boost::system::error_code& ec,
|
||||
+ const std::string& relDate) {
|
||||
+ if (ec)
|
||||
+ {
|
||||
+ if (ec.value() ==
|
||||
+ boost::system::linux_error::bad_request_descriptor)
|
||||
+ {
|
||||
+ BMCWEB_LOG_DEBUG("Priority do not available in {} {}", path,
|
||||
+ ec.message());
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ BMCWEB_LOG_ERROR(
|
||||
+ "Error getting Priority property from {}: {}", path,
|
||||
+ ec.message());
|
||||
+ messages::internalError(asyncResp->res);
|
||||
+ }
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ asyncResp->res.jsonValue["ReleaseDate"] = relDate;
|
||||
+ });
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ BMCWEB_LOG_DEBUG("Unknown software purpose {}", purpose);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
inline void
|
||||
getSoftwareVersion(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
|
||||
const std::string& service, const std::string& path,
|
||||
@@ -900,7 +939,7 @@ inline void
|
||||
sdbusplus::asio::getAllProperties(
|
||||
*crow::connections::systemBus, service, path,
|
||||
"xyz.openbmc_project.Software.Version",
|
||||
- [asyncResp,
|
||||
+ [asyncResp, service, path,
|
||||
swId](const boost::system::error_code& ec,
|
||||
const dbus::utility::DBusPropertiesMap& propertiesList) {
|
||||
if (ec)
|
||||
@@ -961,7 +1000,8 @@ inline void
|
||||
std::string formatDesc = swInvPurpose->substr(endDesc);
|
||||
asyncResp->res.jsonValue["Description"] = formatDesc + " image";
|
||||
getRelatedItems(asyncResp, *swInvPurpose);
|
||||
- });
|
||||
+ getSoftwareReleaseDate(asyncResp, service, path, *swInvPurpose);
|
||||
+ });
|
||||
}
|
||||
|
||||
inline void requestRoutesSoftwareInventory(App& app)
|
||||
@@ -1003,7 +1043,8 @@ inline void requestRoutesSoftwareInventory(App& app)
|
||||
std::string, std::vector<std::string>>>>&
|
||||
obj : subtree)
|
||||
{
|
||||
- if (!obj.first.ends_with(*swId))
|
||||
+ if (sdbusplus::message::object_path(obj.first).filename() !=
|
||||
+ *swId)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
--
|
||||
2.25.1
|
||||
|
||||
+2233
File diff suppressed because it is too large
Load Diff
+517
@@ -0,0 +1,517 @@
|
||||
From b814ff4bd75cc7ac9eac4b2b0214d1947d8d05b7 Mon Sep 17 00:00:00 2001
|
||||
From: roly <Rolyli.Li@luxshare-ict.com>
|
||||
Date: Fri, 17 Jan 2025 10:25:19 +0800
|
||||
Subject: [PATCH] Add redfish oem rsyslog api
|
||||
|
||||
---
|
||||
include/luxshare/dump.hpp | 461 ++++++++++++++++++++++++++++++++++
|
||||
redfish-core/lib/managers.hpp | 4 +
|
||||
src/webserver_main.cpp | 2 +
|
||||
3 files changed, 467 insertions(+)
|
||||
create mode 100755 include/luxshare/dump.hpp
|
||||
|
||||
diff --git a/include/luxshare/dump.hpp b/include/luxshare/dump.hpp
|
||||
new file mode 100755
|
||||
index 00000000..060e948f
|
||||
--- /dev/null
|
||||
+++ b/include/luxshare/dump.hpp
|
||||
@@ -0,0 +1,461 @@
|
||||
+#pragma once
|
||||
+#include <app.hpp>
|
||||
+#include <async_resp.hpp>
|
||||
+#include <boost/asio/ip/address.hpp>
|
||||
+#include <error_messages.hpp>
|
||||
+#include <registries/privilege_registry.hpp>
|
||||
+#include <xyz/openbmc_project/Common/Progress/server.hpp>
|
||||
+
|
||||
+#include <filesystem>
|
||||
+#include <fstream>
|
||||
+
|
||||
+namespace crow
|
||||
+{
|
||||
+namespace luxshare_dump_api
|
||||
+{
|
||||
+
|
||||
+namespace fs = std::filesystem;
|
||||
+
|
||||
+static const std::map<std::string, std::string> rsyslogIndexTranslation = {
|
||||
+ {"index0", "Index0"},
|
||||
+ {"index1", "Index1"},
|
||||
+ {"index2", "Index2"},
|
||||
+ {"index3", "Index3"}};
|
||||
+
|
||||
+
|
||||
+inline std::string getRsyslogSettingsHelper(
|
||||
+ const boost::asio::yield_context& yield,
|
||||
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
|
||||
+ const std::string& dbusObj, const std::string& propertyName)
|
||||
+{
|
||||
+ boost::system::error_code ec;
|
||||
+ auto response = crow::connections::systemBus
|
||||
+ ->yield_method_call<std::variant<std::string>>(
|
||||
+ yield, ec, "xyz.openbmc_project.Settings", dbusObj,
|
||||
+ "org.freedesktop.DBus.Properties", "Get",
|
||||
+ "xyz.openbmc_project.Logging.Rsyslog",
|
||||
+ propertyName);
|
||||
+ if (ec)
|
||||
+ {
|
||||
+ BMCWEB_LOG_ERROR("Error getting {} property from {} : {}", propertyName,
|
||||
+ dbusObj, ec.message());
|
||||
+ redfish::messages::internalError(asyncResp->res);
|
||||
+ asyncResp->res.jsonValue["Oem"]["Luxshare"]["Status"] = 1;
|
||||
+ return std::string{};
|
||||
+ }
|
||||
+ const std::string* propertyValue = std::get_if<std::string>(&response);
|
||||
+ if (propertyValue == nullptr)
|
||||
+ {
|
||||
+ BMCWEB_LOG_ERROR("D-Bus response gets null property value");
|
||||
+ redfish::messages::internalError(asyncResp->res);
|
||||
+ asyncResp->res.jsonValue["Oem"]["Luxshare"]["Status"] = 1;
|
||||
+ return std::string{};
|
||||
+ }
|
||||
+ return *propertyValue;
|
||||
+}
|
||||
+
|
||||
+template <typename PropertyType>
|
||||
+inline void setRsyslogSettingsHelper(
|
||||
+ const boost::asio::yield_context& yield,
|
||||
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
|
||||
+ const std::string& dbusObj, const std::string& propertyName,
|
||||
+ const PropertyType& propertyValue)
|
||||
+{
|
||||
+ boost::system::error_code ec;
|
||||
+ crow::connections::systemBus->yield_method_call<void>(
|
||||
+ yield, ec, "xyz.openbmc_project.Settings", dbusObj,
|
||||
+ "org.freedesktop.DBus.Properties", "Set",
|
||||
+ "xyz.openbmc_project.Logging.Rsyslog", propertyName,
|
||||
+ std::variant<PropertyType>(propertyValue));
|
||||
+ if (ec)
|
||||
+ {
|
||||
+ BMCWEB_LOG_ERROR("Error setting {} property from {}: {}", propertyName,
|
||||
+ dbusObj, ec.message());
|
||||
+ redfish::messages::internalError(asyncResp->res);
|
||||
+ return;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+inline bool checkAddressTypeAndAddress(const std::string& dbusAddressType,
|
||||
+ const std::string& dbusAddress)
|
||||
+{
|
||||
+ boost::system::error_code ec;
|
||||
+ boost::asio::ip::address tmpAddress =
|
||||
+ boost::asio::ip::make_address(dbusAddress, ec);
|
||||
+ if (dbusAddressType == "xyz.openbmc_project.Logging.Rsyslog.Type.IPv4")
|
||||
+ {
|
||||
+ // check multicast address, broadcast address, and 0.x.x.x address.
|
||||
+ if (!ec && tmpAddress.is_v4() && !tmpAddress.is_multicast() &&
|
||||
+ (dbusAddress != "255.255.255.255") &&
|
||||
+ !dbusAddress.starts_with("0."))
|
||||
+ {
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+ else if (dbusAddressType == "xyz.openbmc_project.Logging.Rsyslog.Type.IPv6")
|
||||
+ {
|
||||
+ // check multicast address
|
||||
+ if (!ec && tmpAddress.is_v6() && !tmpAddress.is_multicast())
|
||||
+ {
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ BMCWEB_LOG_DEBUG(
|
||||
+ "address does not match addressType, or address is invalid");
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
+inline void requestRoutesOemLuxshareRsyslogSettings(App& app)
|
||||
+{
|
||||
+ BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Oem/Luxshare/RsyslogSettings/")
|
||||
+ .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;
|
||||
+ }
|
||||
+
|
||||
+ crow::connections::systemBus->async_method_call(
|
||||
+ [asyncResp](const boost::system::error_code ec,
|
||||
+ const std::vector<std::string>& subTreePaths) {
|
||||
+ if (ec)
|
||||
+ {
|
||||
+ BMCWEB_LOG_ERROR("Error calling GetSubTreePaths method: {}",
|
||||
+ ec.message());
|
||||
+ redfish::messages::internalError(asyncResp->res);
|
||||
+ return;
|
||||
+ }
|
||||
+ for (const auto& path : subTreePaths)
|
||||
+ {
|
||||
+ sdbusplus::asio::getAllProperties(
|
||||
+ *crow::connections::systemBus,
|
||||
+ "xyz.openbmc_project.Settings", path,
|
||||
+ "xyz.openbmc_project.Logging.Rsyslog",
|
||||
+ [asyncResp, path](const boost::system::error_code& ec1,
|
||||
+ const dbus::utility::DBusPropertiesMap&
|
||||
+ propertiesList) {
|
||||
+ if (ec1)
|
||||
+ {
|
||||
+ BMCWEB_LOG_ERROR(
|
||||
+ "Error getting Rsyslog properties from {}: {}",
|
||||
+ path, ec1.message());
|
||||
+ redfish::messages::internalError(asyncResp->res);
|
||||
+ return;
|
||||
+ }
|
||||
+ const std::string* addressType = nullptr;
|
||||
+ const std::string* address = nullptr;
|
||||
+ const std::string* protocolType = nullptr;
|
||||
+ const uint16_t* ports = nullptr;
|
||||
+ const bool* status = nullptr;
|
||||
+
|
||||
+ bool success = sdbusplus::unpackPropertiesNoThrow(
|
||||
+ redfish::dbus_utils::UnpackErrorPrinter(),
|
||||
+ propertiesList, "AddressType", addressType, "Address",
|
||||
+ address, "ProtocolType", protocolType, "Port", ports,
|
||||
+ "Status", status);
|
||||
+ if (!success)
|
||||
+ {
|
||||
+ BMCWEB_LOG_ERROR("Unpack error!");
|
||||
+ redfish::messages::internalError(asyncResp->res);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ nlohmann::json::object_t obj;
|
||||
+ if (addressType != nullptr)
|
||||
+ {
|
||||
+ obj["AddressType"] =
|
||||
+ (*addressType) ==
|
||||
+ "xyz.openbmc_project.Logging.Rsyslog.Type.IPv6"
|
||||
+ ? "IPv6"
|
||||
+ : "IPv4";
|
||||
+ }
|
||||
+ if (address != nullptr)
|
||||
+ {
|
||||
+ obj["Address"] = *address;
|
||||
+ }
|
||||
+ if (protocolType != nullptr)
|
||||
+ {
|
||||
+ obj["ProtocolType"] =
|
||||
+ (*protocolType) ==
|
||||
+ "xyz.openbmc_project.Logging.Rsyslog.Protocol.UDP"
|
||||
+ ? "UDP"
|
||||
+ : "TCP";
|
||||
+ }
|
||||
+ if (ports != nullptr)
|
||||
+ {
|
||||
+ obj["Port"] = *ports;
|
||||
+ }
|
||||
+ if (status != nullptr)
|
||||
+ {
|
||||
+ obj["Status"] = (*status) ? "Enabled" : "Disabled";
|
||||
+ }
|
||||
+ sdbusplus::message::object_path objectPath(path);
|
||||
+ std::string rsyslogIndex =
|
||||
+ rsyslogIndexTranslation.at(objectPath.filename());
|
||||
+ if (path.starts_with(
|
||||
+ "/xyz/openbmc_project/logging/rsyslog/audit_log/"))
|
||||
+ {
|
||||
+ asyncResp->res.jsonValue["Oem"]["Luxshare"]["AuditLog"]
|
||||
+ [rsyslogIndex] = obj;
|
||||
+ }
|
||||
+ else if (
|
||||
+ path.starts_with(
|
||||
+ "/xyz/openbmc_project/logging/rsyslog/sel_log/"))
|
||||
+ {
|
||||
+ asyncResp->res.jsonValue["Oem"]["Luxshare"]["SEL"]
|
||||
+ [rsyslogIndex] = obj;
|
||||
+ }
|
||||
+ else if (
|
||||
+ path.starts_with(
|
||||
+ "/xyz/openbmc_project/logging/rsyslog/sol_log/"))
|
||||
+ {
|
||||
+ asyncResp->res.jsonValue["Oem"]["Luxshare"]["SOL"]
|
||||
+ [rsyslogIndex] = obj;
|
||||
+ }
|
||||
+ else if (
|
||||
+ path.starts_with(
|
||||
+ "/xyz/openbmc_project/logging/rsyslog/syslog_log/"))
|
||||
+ {
|
||||
+ asyncResp->res.jsonValue["Oem"]["Luxshare"]["Syslog"]
|
||||
+ [rsyslogIndex] = obj;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ BMCWEB_LOG_ERROR("Can't find bmc D-Bus object!");
|
||||
+ redfish::messages::internalError(asyncResp->res);
|
||||
+ return;
|
||||
+ }
|
||||
+ });
|
||||
+ }
|
||||
+ },
|
||||
+ "xyz.openbmc_project.ObjectMapper",
|
||||
+ "/xyz/openbmc_project/object_mapper",
|
||||
+ "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
|
||||
+ "/xyz/openbmc_project/logging/rsyslog", 0,
|
||||
+ std::array<const char*, 1>{"xyz.openbmc_project.Logging.Rsyslog"});
|
||||
+ });
|
||||
+
|
||||
+ BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Oem/Luxshare/RsyslogSettings/")
|
||||
+ .privileges(redfish::privileges::privilegeSetConfigureComponents)
|
||||
+ .methods(boost::beast::http::verb::patch)(
|
||||
+ [&app](const crow::Request& req,
|
||||
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
|
||||
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
|
||||
+ {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ boost::asio::spawn(
|
||||
+ crow::connections::systemBus->get_io_context(),
|
||||
+ [asyncResp, &req](const boost::asio::yield_context& yield) {
|
||||
+ std::optional<nlohmann::json> oemLuxshareObject;
|
||||
+ using InputMap =
|
||||
+ std::map<std::string, std::optional<nlohmann::json>>;
|
||||
+ InputMap logTypeMap = {{"Syslog", std::nullopt},
|
||||
+ {"SEL", std::nullopt},
|
||||
+ {"AuditLog", std::nullopt},
|
||||
+ {"SOL", std::nullopt}};
|
||||
+ InputMap indexMap = {{"index0", std::nullopt},
|
||||
+ {"index1", std::nullopt},
|
||||
+ {"index2", std::nullopt},
|
||||
+ {"index3", std::nullopt}};
|
||||
+ std::optional<std::string> status;
|
||||
+ std::optional<std::string> addressType;
|
||||
+ std::optional<std::string> address;
|
||||
+ std::optional<uint16_t> ports;
|
||||
+ std::optional<std::string> protocolType;
|
||||
+ const std::map<std::string, std::string> dbusLogType = {
|
||||
+ {"Syslog", "syslog_log"},
|
||||
+ {"SEL", "sel_log"},
|
||||
+ {"AuditLog", "audit_log"},
|
||||
+ {"SOL", "sol_log"}};
|
||||
+
|
||||
+ if (!redfish::json_util::readJsonPatch(
|
||||
+ req, asyncResp->res, "Oem/Luxshare", oemLuxshareObject))
|
||||
+ {
|
||||
+ BMCWEB_LOG_ERROR("readJsonPatch error!");
|
||||
+ return;
|
||||
+ }
|
||||
+ if (!redfish::json_util::readJson(
|
||||
+ oemLuxshareObject.value(), asyncResp->res, "Syslog",
|
||||
+ logTypeMap["Syslog"], "SEL", logTypeMap["SEL"], "AuditLog",
|
||||
+ logTypeMap["AuditLog"], "SOL", logTypeMap["SOL"]))
|
||||
+ {
|
||||
+ BMCWEB_LOG_ERROR("readJsonPatch error!");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ for (auto& logType : logTypeMap)
|
||||
+ {
|
||||
+ if (logType.second)
|
||||
+ {
|
||||
+ if (!redfish::json_util::readJson(
|
||||
+ logType.second.value(), asyncResp->res, "Index0",
|
||||
+ indexMap["index0"], "Index1", indexMap["index1"],
|
||||
+ "Index2", indexMap["index2"], "Index3",
|
||||
+ indexMap["index3"]))
|
||||
+ {
|
||||
+ BMCWEB_LOG_ERROR("readJson error!");
|
||||
+ return;
|
||||
+ }
|
||||
+ for (auto& index : indexMap)
|
||||
+ {
|
||||
+ if (index.second)
|
||||
+ {
|
||||
+ status.reset();
|
||||
+ addressType.reset();
|
||||
+ address.reset();
|
||||
+ ports.reset();
|
||||
+ protocolType.reset();
|
||||
+
|
||||
+ if (!redfish::json_util::readJson(
|
||||
+ index.second.value(), asyncResp->res,
|
||||
+ "Status", status, "AddressType",
|
||||
+ addressType, "Address", address, "Port",
|
||||
+ ports, "ProtocolType", protocolType))
|
||||
+ {
|
||||
+ BMCWEB_LOG_ERROR("readJson error!");
|
||||
+ return;
|
||||
+ }
|
||||
+ std::string dbusObj =
|
||||
+ "/xyz/openbmc_project/logging/rsyslog/" +
|
||||
+ dbusLogType.at(logType.first) + "/" +
|
||||
+ index.first;
|
||||
+
|
||||
+ if (status)
|
||||
+ {
|
||||
+ if ((*status) != "Enabled" &&
|
||||
+ (*status) != "Disabled")
|
||||
+ {
|
||||
+ BMCWEB_LOG_ERROR("status error: {}",
|
||||
+ *status);
|
||||
+ redfish::messages::propertyValueNotInList(
|
||||
+ asyncResp->res, *status, "Status");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ bool dbusStatus = (*status) == "Enabled";
|
||||
+ setRsyslogSettingsHelper(yield, asyncResp,
|
||||
+ dbusObj, "Status",
|
||||
+ dbusStatus);
|
||||
+ }
|
||||
+ if (addressType || address)
|
||||
+ {
|
||||
+ std::string dbusAddressType;
|
||||
+ std::string dbusAddress;
|
||||
+ // get addressType
|
||||
+ if (addressType)
|
||||
+ {
|
||||
+ if (*addressType == "IPv6")
|
||||
+ {
|
||||
+ dbusAddressType =
|
||||
+ "xyz.openbmc_project.Logging.Rsyslog.Type.IPv6";
|
||||
+ }
|
||||
+ else if (*addressType == "IPv4")
|
||||
+ {
|
||||
+ dbusAddressType =
|
||||
+ "xyz.openbmc_project.Logging.Rsyslog.Type.IPv4";
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ BMCWEB_LOG_ERROR(
|
||||
+ "addresstype error: {}",
|
||||
+ *addressType);
|
||||
+ redfish::messages::
|
||||
+ propertyValueNotInList(
|
||||
+ asyncResp->res, *addressType,
|
||||
+ "AddressType");
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ dbusAddressType = getRsyslogSettingsHelper(
|
||||
+ yield, asyncResp, dbusObj,
|
||||
+ "AddressType");
|
||||
+ }
|
||||
+ // get address
|
||||
+ if (address)
|
||||
+ {
|
||||
+ dbusAddress = *address;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ dbusAddress = getRsyslogSettingsHelper(
|
||||
+ yield, asyncResp, dbusObj, "Address");
|
||||
+ }
|
||||
+ // check if addressType and address is
|
||||
+ // conflicted
|
||||
+ if (!checkAddressTypeAndAddress(dbusAddressType,
|
||||
+ dbusAddress))
|
||||
+ {
|
||||
+ BMCWEB_LOG_DEBUG(
|
||||
+ "AddressType and address is conflicted");
|
||||
+ redfish::messages::invalidObject(
|
||||
+ asyncResp->res, "Address");
|
||||
+ return;
|
||||
+ }
|
||||
+ // set addressType
|
||||
+ if (addressType)
|
||||
+ {
|
||||
+ setRsyslogSettingsHelper(
|
||||
+ yield, asyncResp, dbusObj,
|
||||
+ "AddressType", dbusAddressType);
|
||||
+ }
|
||||
+ // set address
|
||||
+ if (address)
|
||||
+ {
|
||||
+ setRsyslogSettingsHelper(yield, asyncResp,
|
||||
+ dbusObj, "Address",
|
||||
+ *address);
|
||||
+ }
|
||||
+ }
|
||||
+ if (ports)
|
||||
+ {
|
||||
+ setRsyslogSettingsHelper(
|
||||
+ yield, asyncResp, dbusObj, "Port", *ports);
|
||||
+ }
|
||||
+ if (protocolType)
|
||||
+ {
|
||||
+ std::string dbusProtocolType;
|
||||
+ if (*protocolType == "UDP")
|
||||
+ {
|
||||
+ dbusProtocolType =
|
||||
+ "xyz.openbmc_project.Logging.Rsyslog.Protocol.UDP";
|
||||
+ }
|
||||
+ else if (*protocolType == "TCP")
|
||||
+ {
|
||||
+ dbusProtocolType =
|
||||
+ "xyz.openbmc_project.Logging.Rsyslog.Protocol.TCP";
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ BMCWEB_LOG_ERROR("protocolType error: {}",
|
||||
+ *protocolType);
|
||||
+ redfish::messages::propertyValueNotInList(
|
||||
+ asyncResp->res, *protocolType,
|
||||
+ "ProtocolType");
|
||||
+ return;
|
||||
+ }
|
||||
+ setRsyslogSettingsHelper(
|
||||
+ yield, asyncResp, dbusObj, "ProtocolType",
|
||||
+ dbusProtocolType);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ });
|
||||
+ });
|
||||
+}
|
||||
+
|
||||
+inline void requestRoutes(App& app)
|
||||
+{
|
||||
+ requestRoutesOemLuxshareRsyslogSettings(app);
|
||||
+}
|
||||
+
|
||||
+} // namespace luxshare_dump_api
|
||||
+} // namespace crow
|
||||
diff --git a/redfish-core/lib/managers.hpp b/redfish-core/lib/managers.hpp
|
||||
index 05b8c292..7efe0335 100644
|
||||
--- a/redfish-core/lib/managers.hpp
|
||||
+++ b/redfish-core/lib/managers.hpp
|
||||
@@ -2106,6 +2106,10 @@ inline void requestRoutesManager(App& app)
|
||||
|
||||
sw_util::populateSoftwareInformation(asyncResp, sw_util::bmcPurpose,
|
||||
"FirmwareVersion", true);
|
||||
+ nlohmann::json& luxshareOemObject =
|
||||
+ asyncResp->res.jsonValue["Oem"]["Luxshare"];
|
||||
+ luxshareOemObject["RsyslogSettings"]["@odata.id"] =
|
||||
+ "/redfish/v1/Managers/bmc/Oem/Luxshare/RsyslogSettings";
|
||||
|
||||
managerGetLastResetTime(asyncResp);
|
||||
|
||||
diff --git a/src/webserver_main.cpp b/src/webserver_main.cpp
|
||||
index f4f43254..9edb9b78 100644
|
||||
--- a/src/webserver_main.cpp
|
||||
+++ b/src/webserver_main.cpp
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
#include <luxshare/sel.hpp>
|
||||
#include <luxshare/firmware_update.hpp>
|
||||
+#include <luxshare/dump.hpp>
|
||||
|
||||
#include <exception>
|
||||
#include <memory>
|
||||
@@ -122,6 +123,7 @@ static int run()
|
||||
#ifdef BMCWEB_ENABLE_LUXSHARE_API
|
||||
crow::luxshare_sel_api::requestRoutes(app);
|
||||
crow::luxshare_update_firmware::requestRoutes(app);
|
||||
+ crow::luxshare_dump_api::requestRoutes(app);
|
||||
#endif
|
||||
|
||||
if (bmcwebInsecureDisableXssPrevention != 0)
|
||||
--
|
||||
2.25.1
|
||||
|
||||
Executable
+27
@@ -0,0 +1,27 @@
|
||||
From fc722c287eb1186d66dc8be949e845decf3588e3 Mon Sep 17 00:00:00 2001
|
||||
From: roly <Rolyli.Li@luxshare-ict.com>
|
||||
Date: Tue, 12 Nov 2024 10:28:29 +0800
|
||||
Subject: [PATCH] Fix webui set static ip failed issue
|
||||
|
||||
---
|
||||
redfish-core/lib/ethernet.hpp | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/redfish-core/lib/ethernet.hpp b/redfish-core/lib/ethernet.hpp
|
||||
index 8de854f7..1c288e13 100644
|
||||
--- a/redfish-core/lib/ethernet.hpp
|
||||
+++ b/redfish-core/lib/ethernet.hpp
|
||||
@@ -1415,8 +1415,8 @@ inline void
|
||||
if (nicIpEntry != ipv4Data.cend())
|
||||
{
|
||||
deleteAndCreateIPAddress(IpVersion::IpV4, ifaceId,
|
||||
- nicIpEntry->id, prefixLength, *gateway,
|
||||
- *address, asyncResp);
|
||||
+ nicIpEntry->id, prefixLength, *address,
|
||||
+ *gateway, asyncResp);
|
||||
nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
|
||||
ipv4Data.cend());
|
||||
}
|
||||
--
|
||||
2.25.1
|
||||
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
From 13d1bbbba793c3fb2b81bdc2789a9bf2a3809cd9 Mon Sep 17 00:00:00 2001
|
||||
From: "Chen.Zhao" <zhao.chen@luxshare-ict.com>
|
||||
Date: Tue, 17 Dec 2024 21:25:10 +0800
|
||||
Subject: [PATCH] Modify nbd proxy path The path of nbd-proxy is modified from
|
||||
/usr/sbin to /usr/bin
|
||||
|
||||
---
|
||||
include/luxshare/sel.hpp | 0
|
||||
include/luxshare/utils.hpp | 0
|
||||
include/vm_websocket.hpp | 2 +-
|
||||
3 files changed, 1 insertion(+), 1 deletion(-)
|
||||
mode change 100755 => 100644 include/luxshare/sel.hpp
|
||||
mode change 100755 => 100644 include/luxshare/utils.hpp
|
||||
|
||||
diff --git a/include/luxshare/sel.hpp b/include/luxshare/sel.hpp
|
||||
old mode 100755
|
||||
new mode 100644
|
||||
diff --git a/include/luxshare/utils.hpp b/include/luxshare/utils.hpp
|
||||
old mode 100755
|
||||
new mode 100644
|
||||
diff --git a/include/vm_websocket.hpp b/include/vm_websocket.hpp
|
||||
index 1b06a93d..a8d6a149 100644
|
||||
--- a/include/vm_websocket.hpp
|
||||
+++ b/include/vm_websocket.hpp
|
||||
@@ -56,7 +56,7 @@ class Handler : public std::enable_shared_from_this<Handler>
|
||||
void connect()
|
||||
{
|
||||
std::error_code ec;
|
||||
- proxy = boost::process::child("/usr/sbin/nbd-proxy", media,
|
||||
+ proxy = boost::process::child("/usr/bin/nbd-proxy", media,
|
||||
boost::process::std_out > pipeOut,
|
||||
boost::process::std_in < pipeIn, ec);
|
||||
if (ec)
|
||||
--
|
||||
2.25.1
|
||||
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
From f2375ff9d5c343225163167d3ed52330ef1484e0 Mon Sep 17 00:00:00 2001
|
||||
From: "Chen.Zhao" <zhao.chen@luxshare-ict.com>
|
||||
Date: Wed, 18 Dec 2024 20:14:39 +0800
|
||||
Subject: [PATCH] Modify task max timeout time to 10 minutes When update bios,
|
||||
the update task time may over 5 minutes, get task status will return fail
|
||||
|
||||
---
|
||||
redfish-core/lib/update_service.hpp | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/redfish-core/lib/update_service.hpp b/redfish-core/lib/update_service.hpp
|
||||
index cc3d939a..53b65d0d 100644
|
||||
--- a/redfish-core/lib/update_service.hpp
|
||||
+++ b/redfish-core/lib/update_service.hpp
|
||||
@@ -240,7 +240,7 @@ static void
|
||||
|
||||
// if we're getting status updates it's
|
||||
// still alive, update timer
|
||||
- taskData->extendTimer(std::chrono::minutes(5));
|
||||
+ taskData->extendTimer(std::chrono::minutes(10));
|
||||
}
|
||||
|
||||
// as firmware update often results in a
|
||||
--
|
||||
2.25.1
|
||||
|
||||
+124
@@ -0,0 +1,124 @@
|
||||
From 7e909a983073baa858e0245adf7f7694cb13d88c Mon Sep 17 00:00:00 2001
|
||||
From: wangjue <jue.wang2@luxshare-ict.com>
|
||||
Date: Thu, 19 Dec 2024 19:23:12 +0800
|
||||
Subject: [PATCH] Only add sensors in ipmi sensor json file to active sensor
|
||||
list
|
||||
|
||||
Signed-off-by: wangjue <jue.wang2@luxshare-ict.com>
|
||||
---
|
||||
redfish-core/lib/sensors.hpp | 84 +++++++++++++++++++++++++++++++++++-
|
||||
1 file changed, 82 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/redfish-core/lib/sensors.hpp b/redfish-core/lib/sensors.hpp
|
||||
index 04e48c5c..20f21a93 100644
|
||||
--- a/redfish-core/lib/sensors.hpp
|
||||
+++ b/redfish-core/lib/sensors.hpp
|
||||
@@ -432,6 +432,81 @@ void getConnections(std::shared_ptr<SensorsAsyncResp> sensorsAsyncResp,
|
||||
std::move(objectsWithConnectionCb));
|
||||
}
|
||||
|
||||
+struct SensorInfo
|
||||
+{
|
||||
+ std::string sensorName;
|
||||
+ uint8_t readingType;
|
||||
+ uint8_t sensorType;
|
||||
+};
|
||||
+
|
||||
+using SensorMessages = std::unordered_map<std::string, SensorInfo>;
|
||||
+
|
||||
+static constexpr auto sensorJsonPath =
|
||||
+ "/usr/share/ipmi-providers/sensor-data-record.json";
|
||||
+
|
||||
+SensorMessages loadSensorFromJson()
|
||||
+{
|
||||
+ try
|
||||
+ {
|
||||
+ const std::filesystem::path path(sensorJsonPath);
|
||||
+ SensorMessages sensorMessages;
|
||||
+ const nlohmann::json empty{};
|
||||
+ nlohmann::json js;
|
||||
+ if (!std::filesystem::exists(path) || std::filesystem::is_empty(path))
|
||||
+ {
|
||||
+ std::cout << "Incorrect File Path or empty file, FILE_PATH = "
|
||||
+ << path << std::endl;
|
||||
+ return sensorMessages;
|
||||
+ }
|
||||
+
|
||||
+ try
|
||||
+ {
|
||||
+ std::ifstream jsonFile(path);
|
||||
+ js = nlohmann::json::parse(jsonFile);
|
||||
+ }
|
||||
+ catch (const std::exception& e)
|
||||
+ {
|
||||
+ std::cout << "Failed to parse config file, ERROR = " << e.what()
|
||||
+ << ", FILE_PATH = " << path << std::endl;
|
||||
+ throw std::runtime_error("Failed to parse config file");
|
||||
+ }
|
||||
+
|
||||
+ for (const auto& sensor : js.items())
|
||||
+ {
|
||||
+ SensorInfo info;
|
||||
+ std::string sensorPath = sensor.key();
|
||||
+ auto sensorParam = sensor.value();
|
||||
+ info.sensorName = sensorParam["sensorName"];
|
||||
+ info.readingType = sensorParam["sensorReadingType"];
|
||||
+ info.sensorType = sensorParam["sensorType"];
|
||||
+ sensorMessages.insert(std::make_pair(sensorPath, std::move(info)));
|
||||
+ }
|
||||
+ return sensorMessages;
|
||||
+ }
|
||||
+ catch (const std::exception& e)
|
||||
+ {
|
||||
+ throw std::runtime_error("Failed to parse sensor config file");
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+const SensorMessages& getSensorMessages()
|
||||
+{
|
||||
+ static const SensorMessages sensorMessages = loadSensorFromJson();
|
||||
+ return sensorMessages;
|
||||
+}
|
||||
+
|
||||
+std::optional<SensorInfo>
|
||||
+ getSensorInfo(const std::string& sensorPath)
|
||||
+{
|
||||
+ const auto& sensorMessages = getSensorMessages();
|
||||
+ auto ite = sensorMessages.find(sensorPath);
|
||||
+ if (ite == sensorMessages.end())
|
||||
+ {
|
||||
+ return std::nullopt;
|
||||
+ }
|
||||
+ return std::make_optional(ite->second);
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* @brief Shrinks the list of sensors for processing
|
||||
* @param SensorsAysncResp The class holding the Redfish response
|
||||
@@ -443,7 +518,7 @@ void getConnections(std::shared_ptr<SensorsAsyncResp> sensorsAsyncResp,
|
||||
*/
|
||||
inline void reduceSensorList(
|
||||
crow::Response& res, std::string_view chassisSubNode,
|
||||
- std::span<const std::string_view> sensorTypes,
|
||||
+ [[maybe_unused]] std::span<const std::string_view> sensorTypes,
|
||||
const std::vector<std::string>* allSensors,
|
||||
const std::shared_ptr<std::set<std::string>>& activeSensors)
|
||||
{
|
||||
@@ -468,8 +543,13 @@ inline void reduceSensorList(
|
||||
{
|
||||
if (sensor.starts_with(type))
|
||||
{
|
||||
- activeSensors->emplace(sensor);
|
||||
+ auto sensorInfo = getSensorInfo(sensor);
|
||||
+ if (sensorInfo != std::nullopt)
|
||||
+ {
|
||||
+ activeSensors->emplace(sensor);
|
||||
+ }
|
||||
}
|
||||
+
|
||||
}
|
||||
}
|
||||
}
|
||||
--
|
||||
2.34.1
|
||||
|
||||
Executable
+50
@@ -0,0 +1,50 @@
|
||||
From 15ec7caabeb6ed2bb01e8ef9e3d9bc6efd1415e0 Mon Sep 17 00:00:00 2001
|
||||
From: "Chen.Zhao" <zhao.chen@luxshare-ict.com>
|
||||
Date: Mon, 25 Nov 2024 21:49:32 +0800
|
||||
Subject: [PATCH] Remove web sensor underscores
|
||||
|
||||
---
|
||||
redfish-core/lib/sensors.hpp | 6 +-----
|
||||
1 file changed, 1 insertion(+), 5 deletions(-)
|
||||
|
||||
diff --git a/redfish-core/lib/sensors.hpp b/redfish-core/lib/sensors.hpp
|
||||
index 5bd846d6..04e48c5c 100644
|
||||
--- a/redfish-core/lib/sensors.hpp
|
||||
+++ b/redfish-core/lib/sensors.hpp
|
||||
@@ -744,7 +744,6 @@ inline void objectPropertiesToJson(
|
||||
sensorJson["Id"] = std::move(subNodeEscaped);
|
||||
|
||||
std::string sensorNameEs(sensorName);
|
||||
- std::replace(sensorNameEs.begin(), sensorNameEs.end(), '_', ' ');
|
||||
sensorJson["Name"] = std::move(sensorNameEs);
|
||||
}
|
||||
else if (sensorType != "power")
|
||||
@@ -753,7 +752,6 @@ inline void objectPropertiesToJson(
|
||||
// PowerControl, those properties have more general values because
|
||||
// multiple sensors can be stored in the same JSON object.
|
||||
std::string sensorNameEs(sensorName);
|
||||
- std::replace(sensorNameEs.begin(), sensorNameEs.end(), '_', ' ');
|
||||
sensorJson["Name"] = std::move(sensorNameEs);
|
||||
}
|
||||
|
||||
@@ -1074,7 +1072,6 @@ inline void populateFanRedundancy(
|
||||
sensorsAsyncResp->asyncResp->res);
|
||||
return;
|
||||
}
|
||||
- std::replace(name.begin(), name.end(), '_', ' ');
|
||||
|
||||
std::string health;
|
||||
|
||||
@@ -1103,8 +1100,7 @@ inline void populateFanRedundancy(
|
||||
}
|
||||
/*
|
||||
todo(ed): merge patch that fixes the names
|
||||
- std::replace(itemName.begin(),
|
||||
- itemName.end(), '_', ' ');*/
|
||||
+ */
|
||||
auto schemaItem =
|
||||
std::find_if(fanRedfish.begin(), fanRedfish.end(),
|
||||
[itemName](const nlohmann::json& fan) {
|
||||
--
|
||||
2.25.1
|
||||
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
From 2070b4aaf3eab4f4478ef30881e55a685523263f Mon Sep 17 00:00:00 2001
|
||||
From: roly <Rolyli.Li@luxshare-ict.com>
|
||||
Date: Fri, 8 Nov 2024 14:38:24 +0800
|
||||
Subject: [PATCH] Reset static ipv4 address when turn off dhcpv4
|
||||
|
||||
---
|
||||
redfish-core/lib/ethernet.hpp | 71 +++++++++++++++++++++++++++++------
|
||||
1 file changed, 59 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/redfish-core/lib/ethernet.hpp b/redfish-core/lib/ethernet.hpp
|
||||
index 57fe24c4..8de854f7 100644
|
||||
--- a/redfish-core/lib/ethernet.hpp
|
||||
+++ b/redfish-core/lib/ethernet.hpp
|
||||
@@ -1044,10 +1044,51 @@ inline void
|
||||
});
|
||||
}
|
||||
|
||||
-inline void setDHCPEnabled(const std::string& ifaceId,
|
||||
- const std::string& propertyName, const bool v4Value,
|
||||
- const bool v6Value,
|
||||
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
|
||||
+inline void handleIPv4DHCPDisableKeepIp(
|
||||
+ const std::string& ifaceId, const bool v4Value,
|
||||
+ const std::vector<IPv4AddressData>& ipv4Data,
|
||||
+ const std::optional<nlohmann::json::array_t> &
|
||||
+ ipv4StaticAddresses,
|
||||
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
|
||||
+{
|
||||
+ // If v4DHCP is disabled, and there is no incoming static address data,
|
||||
+ // if have any existing DHCP addresses, change them to static addresses
|
||||
+ if (!v4Value && !ipv4StaticAddresses)
|
||||
+ {
|
||||
+ auto it = std::find_if(
|
||||
+ ipv4Data.begin(), ipv4Data.end(),
|
||||
+ [](const IPv4AddressData& addr) { return addr.origin == "DHCP"; });
|
||||
+
|
||||
+ if (it == ipv4Data.end())
|
||||
+ {
|
||||
+ // Do nothing
|
||||
+ BMCWEB_LOG_INFO("No DHCP addresses to convert to static");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ uint8_t prefixLength = 0;
|
||||
+ std::string address = it->address;
|
||||
+ std::string gateway = it->gateway;
|
||||
+ std::string netmask = it->netmask;
|
||||
+
|
||||
+ if (!ip_util::ipv4VerifyIpAndGetBitcount(netmask, &prefixLength))
|
||||
+ {
|
||||
+ messages::internalError(asyncResp->res);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ createIPv4(ifaceId, prefixLength, gateway, address, asyncResp);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+inline void setDHCPEnabled(
|
||||
+ const std::string& ifaceId,
|
||||
+ const std::string& propertyName,const bool v4Value,
|
||||
+ const bool v6Value,
|
||||
+ const std::vector<IPv4AddressData>& ipv4Data,
|
||||
+ const std::optional<nlohmann::json::array_t> &
|
||||
+ ipv4StaticAddresses,
|
||||
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
|
||||
{
|
||||
const std::string dhcp = getDhcpEnabledEnumeration(v4Value, v6Value);
|
||||
sdbusplus::asio::setProperty(
|
||||
@@ -1063,6 +1104,8 @@ inline void setDHCPEnabled(const std::string& ifaceId,
|
||||
}
|
||||
messages::success(asyncResp->res);
|
||||
});
|
||||
+ handleIPv4DHCPDisableKeepIp(ifaceId, v4Value, ipv4Data, ipv4StaticAddresses,
|
||||
+ asyncResp);
|
||||
}
|
||||
|
||||
inline void setEthernetInterfaceBoolProperty(
|
||||
@@ -1122,11 +1165,15 @@ inline void handleSLAACAutoConfigPatch(
|
||||
});
|
||||
}
|
||||
|
||||
-inline void handleDHCPPatch(const std::string& ifaceId,
|
||||
- const EthernetInterfaceData& ethData,
|
||||
- const DHCPParameters& v4dhcpParms,
|
||||
- const DHCPParameters& v6dhcpParms,
|
||||
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
|
||||
+inline void handleDHCPPatch(
|
||||
+ const std::string& ifaceId,
|
||||
+ const EthernetInterfaceData& ethData,
|
||||
+ const std::optional<nlohmann::json::array_t> &
|
||||
+ ipv4StaticAddresses,
|
||||
+ const std::vector<IPv4AddressData>& ipv4Data,
|
||||
+ const DHCPParameters& v4dhcpParms,
|
||||
+ const DHCPParameters& v6dhcpParms,
|
||||
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
|
||||
{
|
||||
bool ipv4Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, true);
|
||||
bool ipv6Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, false);
|
||||
@@ -1223,7 +1270,7 @@ inline void handleDHCPPatch(const std::string& ifaceId,
|
||||
|
||||
BMCWEB_LOG_DEBUG("set DHCPEnabled...");
|
||||
setDHCPEnabled(ifaceId, "DHCPEnabled", nextv4DHCPState, nextv6DHCPState,
|
||||
- asyncResp);
|
||||
+ ipv4Data, ipv4StaticAddresses, asyncResp);
|
||||
BMCWEB_LOG_DEBUG("set DNSEnabled...");
|
||||
setDHCPv4Config("DNSEnabled", nextDNS, asyncResp);
|
||||
BMCWEB_LOG_DEBUG("set NTPEnabled...");
|
||||
@@ -2051,8 +2098,8 @@ inline void requestEthernetInterfacesRoutes(App& app)
|
||||
|
||||
if (dhcpv4 || dhcpv6)
|
||||
{
|
||||
- handleDHCPPatch(ifaceId, ethData, v4dhcpParms, v6dhcpParms,
|
||||
- asyncResp);
|
||||
+ handleDHCPPatch(ifaceId, ethData, ipv4StaticAddresses, ipv4Data,
|
||||
+ v4dhcpParms, v6dhcpParms, asyncResp);
|
||||
}
|
||||
|
||||
if (hostname)
|
||||
--
|
||||
2.25.1
|
||||
|
||||
Executable
+179
@@ -0,0 +1,179 @@
|
||||
From cfd7bb5a9175a2fa01aa314cace2c3fd0be85d07 Mon Sep 17 00:00:00 2001
|
||||
From: roly <Rolyli.Li@luxshare-ict.com>
|
||||
Date: Tue, 26 Nov 2024 16:49:35 +0800
|
||||
Subject: [PATCH] Support redfish set bmc timezone
|
||||
|
||||
---
|
||||
redfish-core/include/utils/time_utils.hpp | 40 ++++++++++++-
|
||||
redfish-core/lib/managers.hpp | 68 ++++++++++++++++++++++-
|
||||
2 files changed, 105 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/redfish-core/include/utils/time_utils.hpp b/redfish-core/include/utils/time_utils.hpp
|
||||
index 314ea85d..c69eec28 100644
|
||||
--- a/redfish-core/include/utils/time_utils.hpp
|
||||
+++ b/redfish-core/include/utils/time_utils.hpp
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <ratio>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
+#include <regex>
|
||||
|
||||
// IWYU pragma: no_include <stddef.h>
|
||||
// IWYU pragma: no_include <stdint.h>
|
||||
@@ -284,6 +285,15 @@ std::string toISO8061ExtendedStr(std::chrono::duration<IntType, Period> t)
|
||||
using days = std::chrono::duration<
|
||||
IntType, std::ratio_multiply<hours::period, std::ratio<24>>>;
|
||||
|
||||
+ time_t timep;
|
||||
+ time(&timep);
|
||||
+ struct tm* localTime = localtime(&timep);
|
||||
+ auto validLocalTime = mktime(localTime);
|
||||
+ struct tm* gmTime = gmtime(&timep);
|
||||
+ auto validGmTime = mktime(gmTime);
|
||||
+ auto timeEquation = validLocalTime - validGmTime;
|
||||
+
|
||||
+ t += std::chrono::seconds(timeEquation);
|
||||
// d is days since 1970-01-01
|
||||
days d = std::chrono::duration_cast<days>(t);
|
||||
|
||||
@@ -348,8 +358,9 @@ std::string toISO8061ExtendedStr(std::chrono::duration<IntType, Period> t)
|
||||
MicroDuration subsec = duration_cast<MicroDuration>(t);
|
||||
out += details::padZeros(subsec.count(), 6);
|
||||
}
|
||||
-
|
||||
- out += "+00:00";
|
||||
+ char tzstring[32] = {0};
|
||||
+ std::snprintf(tzstring, sizeof(tzstring), "%+03lld:00", timeEquation/3600);
|
||||
+ out += tzstring;
|
||||
return out;
|
||||
}
|
||||
} // namespace details
|
||||
@@ -445,5 +456,30 @@ inline std::optional<usSinceEpoch> dateStringToEpoch(std::string_view datetime)
|
||||
return std::chrono::duration<uint64_t, std::micro>{durMicroSecs};
|
||||
}
|
||||
|
||||
+inline bool isValidTimeOffset(const std::string& timeOffset) {
|
||||
+ std::regex timeOffsetRegex(R"(^([-+][0-1][0-9]:[0-5][0-9])$)");
|
||||
+
|
||||
+ return std::regex_match(timeOffset, timeOffsetRegex);
|
||||
+}
|
||||
+
|
||||
+int convertTimeOffsetToMinutes(const std::string& timeOffset) {
|
||||
+
|
||||
+ if (!isValidTimeOffset(timeOffset)) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ int hours = std::stoi(timeOffset.substr(1, 2));
|
||||
+ if(hours < -13 || hours > 12)
|
||||
+ {
|
||||
+ return -1;
|
||||
+ }
|
||||
+ int totalMinutes = hours * 60;
|
||||
+
|
||||
+ if (timeOffset[0] == '-') {
|
||||
+ totalMinutes = -totalMinutes;
|
||||
+ }
|
||||
+ return totalMinutes;
|
||||
+}
|
||||
+
|
||||
} // namespace time_utils
|
||||
} // namespace redfish
|
||||
diff --git a/redfish-core/lib/managers.hpp b/redfish-core/lib/managers.hpp
|
||||
index a114d440..30395284 100644
|
||||
--- a/redfish-core/lib/managers.hpp
|
||||
+++ b/redfish-core/lib/managers.hpp
|
||||
@@ -1879,6 +1879,67 @@ inline void setDateTime(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
|
||||
});
|
||||
}
|
||||
|
||||
+inline void setDateTimeLocalOffset(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
|
||||
+ std::string datetimelocaloffset)
|
||||
+{
|
||||
+ int hrs = 0;
|
||||
+ char ZoneInfoFile[128] = {0}, file[32] = {0};
|
||||
+ static constexpr int16_t SEL_UTC_MAX_RANGE = 1440;
|
||||
+ static constexpr int16_t SEL_UTC_MIN_RANGE = -1440;
|
||||
+ static constexpr int16_t UNSPECIFIED_UTC_OFFSET = 0x7ff;
|
||||
+ constexpr auto LOCALTIME = "/etc/localtime";
|
||||
+ int UTCOffset = redfish::time_utils::convertTimeOffsetToMinutes(datetimelocaloffset);
|
||||
+ if (((UTCOffset > SEL_UTC_MAX_RANGE ) || (UTCOffset < SEL_UTC_MIN_RANGE) || (UTCOffset % 60 != 0)) && UTCOffset != UNSPECIFIED_UTC_OFFSET)
|
||||
+ {
|
||||
+ messages::propertyValueOutOfRange(asyncResp->res, datetimelocaloffset,
|
||||
+ "DateTimeLocalOffset");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ hrs = UTCOffset / 60;
|
||||
+ if(UTCOffset == UNSPECIFIED_UTC_OFFSET)
|
||||
+ {
|
||||
+ hrs = 0;
|
||||
+ }
|
||||
+
|
||||
+ if (0 > UTCOffset)
|
||||
+ {
|
||||
+ if (snprintf(file,sizeof(file), "GMT+%d", -hrs) >= static_cast<long int>(sizeof(file)))
|
||||
+ {
|
||||
+ messages::internalError(asyncResp->res);
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ if (snprintf(file,sizeof(file), "GMT-%d", hrs) >= static_cast<long int>(sizeof(file)))
|
||||
+ {
|
||||
+ messages::internalError(asyncResp->res);
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (snprintf (ZoneInfoFile, sizeof(ZoneInfoFile), "%s/%s", "/usr/share/zoneinfo/Etc", file) >= static_cast<long int>(sizeof(ZoneInfoFile)))
|
||||
+ {
|
||||
+ messages::internalError(asyncResp->res);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if((0 > unlink(LOCALTIME)) && errno != ENOENT)
|
||||
+ {
|
||||
+ messages::internalError(asyncResp->res);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if(symlink(ZoneInfoFile, LOCALTIME) < 0)
|
||||
+ {
|
||||
+ messages::internalError(asyncResp->res);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ asyncResp->res.jsonValue["DateTimeLocalOffset"] = datetimelocaloffset;
|
||||
+}
|
||||
+
|
||||
inline void
|
||||
checkForQuiesced(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
|
||||
{
|
||||
@@ -2189,9 +2250,10 @@ inline void requestRoutesManager(App& app)
|
||||
std::optional<nlohmann::json> oem;
|
||||
std::optional<nlohmann::json> links;
|
||||
std::optional<std::string> datetime;
|
||||
+ std::optional<std::string> datatimelocaloffset;
|
||||
|
||||
if (!json_util::readJsonPatch(req, asyncResp->res, "Oem", oem,
|
||||
- "DateTime", datetime, "Links", links))
|
||||
+ "DateTime", datetime, "Links", links, "DateTimeLocalOffset", datatimelocaloffset))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -2252,6 +2314,10 @@ inline void requestRoutesManager(App& app)
|
||||
{
|
||||
setDateTime(asyncResp, std::move(*datetime));
|
||||
}
|
||||
+ if (datatimelocaloffset)
|
||||
+ {
|
||||
+ setDateTimeLocalOffset(asyncResp, std::move(*datatimelocaloffset));
|
||||
+ }
|
||||
});
|
||||
}
|
||||
|
||||
--
|
||||
2.25.1
|
||||
|
||||
Executable
+62
@@ -0,0 +1,62 @@
|
||||
From 925563a9f9ec895ffbc0c5db39f1d02258ceb1df Mon Sep 17 00:00:00 2001
|
||||
From: roly <Rolyli.Li@luxshare-ict.com>
|
||||
Date: Wed, 18 Dec 2024 13:59:12 +0800
|
||||
Subject: [PATCH] Support webui switch bmc boot source
|
||||
|
||||
---
|
||||
redfish-core/lib/managers.hpp | 31 ++++++++++++++++++++++++++++++-
|
||||
1 file changed, 30 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/redfish-core/lib/managers.hpp b/redfish-core/lib/managers.hpp
|
||||
index 30395284..0680e38d 100644
|
||||
--- a/redfish-core/lib/managers.hpp
|
||||
+++ b/redfish-core/lib/managers.hpp
|
||||
@@ -1739,6 +1739,8 @@ inline void
|
||||
});
|
||||
}
|
||||
|
||||
+#define MAIN_BMC_BOOT_SOURCE "/sys/devices/platform/ahb/1e620000.spi/access_primary"
|
||||
+#define BACKUP_BMC_BOOT_SOURCE "/sys/devices/platform/ahb/1e620000.spi/access_backup"
|
||||
/**
|
||||
* @brief Set the running firmware image
|
||||
*
|
||||
@@ -1843,9 +1845,35 @@ inline void
|
||||
messages::internalError(asyncResp->res);
|
||||
return;
|
||||
}
|
||||
- doBMCGracefulRestart(asyncResp);
|
||||
+ // doBMCGracefulRestart(asyncResp);
|
||||
});
|
||||
});
|
||||
+
|
||||
+ char cmd[256] = {0};
|
||||
+ std::string currentSelector;
|
||||
+ std::ifstream slotFile("/run/media/slot");
|
||||
+ std::getline(slotFile, currentSelector);
|
||||
+ if (currentSelector == "0")
|
||||
+ {
|
||||
+ memset(cmd, 0 , sizeof(cmd));
|
||||
+ snprintf(cmd, sizeof(cmd), "echo 1 > %s", BACKUP_BMC_BOOT_SOURCE);
|
||||
+ if(system(cmd))
|
||||
+ {
|
||||
+ BMCWEB_LOG_DEBUG("Set BMC boot from backup flash failed.");
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ if (currentSelector == "1")
|
||||
+ {
|
||||
+ memset(cmd, 0 , sizeof(cmd));
|
||||
+ snprintf(cmd, sizeof(cmd), "echo 1 > %s", MAIN_BMC_BOOT_SOURCE);
|
||||
+ if(system(cmd))
|
||||
+ {
|
||||
+ BMCWEB_LOG_DEBUG("Set BMC boot from main flash failed.");
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
}
|
||||
|
||||
inline void setDateTime(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
|
||||
--
|
||||
2.25.1
|
||||
|
||||
Executable
+188
@@ -0,0 +1,188 @@
|
||||
From 6fb46035f50ab26d177747df558d961bcbe2914a Mon Sep 17 00:00:00 2001
|
||||
From: wangjue <jue.wang2@luxshare-ict.com>
|
||||
Date: Tue, 24 Dec 2024 16:57:11 +0800
|
||||
Subject: [PATCH] Sync webui sensor status with ipmi
|
||||
|
||||
Signed-off-by: wangjue <jue.wang2@luxshare-ict.com>
|
||||
---
|
||||
redfish-core/lib/sensors.hpp | 122 +++++++++++++++++++++++++++++++++--
|
||||
1 file changed, 117 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/redfish-core/lib/sensors.hpp b/redfish-core/lib/sensors.hpp
|
||||
index 20f21a93..722a111d 100644
|
||||
--- a/redfish-core/lib/sensors.hpp
|
||||
+++ b/redfish-core/lib/sensors.hpp
|
||||
@@ -672,11 +672,12 @@ void getChassis(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
|
||||
}
|
||||
|
||||
/**
|
||||
- * @brief Returns the Redfish State value for the specified inventory item.
|
||||
+ * @brief Returns the Redfish PSU State value for the specified inventory item.
|
||||
* @param inventoryItem D-Bus inventory item associated with a sensor.
|
||||
+ * available.
|
||||
* @return State value for inventory item.
|
||||
*/
|
||||
-inline std::string getState(const InventoryItem* inventoryItem)
|
||||
+inline std::string getPsuState(const InventoryItem* inventoryItem)
|
||||
{
|
||||
if ((inventoryItem != nullptr) && !(inventoryItem->isPresent))
|
||||
{
|
||||
@@ -686,6 +687,76 @@ inline std::string getState(const InventoryItem* inventoryItem)
|
||||
return "Enabled";
|
||||
}
|
||||
|
||||
+/**
|
||||
+ * @brief Returns the Redfish State value for the specified inventory item.
|
||||
+ * @param inventoryItem D-Bus inventory item associated with a sensor.
|
||||
+ * @return State value for inventory item.
|
||||
+ */
|
||||
+inline std::string getState(const dbus::utility::DBusPropertiesMap& valuesDict,
|
||||
+ nlohmann::json& sensorJson)
|
||||
+{
|
||||
+ std::string currentstate;
|
||||
+ auto statusIt = sensorJson.find("Status");
|
||||
+ if (statusIt != sensorJson.end())
|
||||
+ {
|
||||
+ auto stateIt = statusIt->find("State");
|
||||
+ if (stateIt != statusIt->end())
|
||||
+ {
|
||||
+ std::string* state = stateIt->get_ptr<std::string*>();
|
||||
+ if (state != nullptr)
|
||||
+ {
|
||||
+ currentstate = *state;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ auto nameIt = sensorJson.find("Name");
|
||||
+ if (nameIt != sensorJson.end())
|
||||
+ {
|
||||
+ std::string* name = nameIt->get_ptr<std::string*>();
|
||||
+ if (name != nullptr && name->ends_with("_Supply"))
|
||||
+ {
|
||||
+ return currentstate;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (currentstate == "Disabled")
|
||||
+ {
|
||||
+ return "Disabled";
|
||||
+ }
|
||||
+
|
||||
+ for (const auto& [property, value] : valuesDict)
|
||||
+ {
|
||||
+ if (property == "Available")
|
||||
+ {
|
||||
+ const bool* available = std::get_if<bool>(&value);
|
||||
+ if ((available != nullptr) && !(*available))
|
||||
+ {
|
||||
+ return "Disabled";
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (currentstate == "No Reading")
|
||||
+ {
|
||||
+ return "No Reading";
|
||||
+ }
|
||||
+
|
||||
+ for (const auto& [property, value] : valuesDict)
|
||||
+ {
|
||||
+ if (property == "Functional")
|
||||
+ {
|
||||
+ const bool* functional = std::get_if<bool>(&value);
|
||||
+ if ((functional != nullptr) && !(*functional))
|
||||
+ {
|
||||
+ return "No Reading";
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return "Enabled";
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* @brief Returns the Redfish Health value for the specified sensor.
|
||||
* @param sensorJson Sensor JSON object.
|
||||
@@ -702,9 +773,20 @@ inline std::string getHealth(nlohmann::json& sensorJson,
|
||||
// objects contain multiple sensors (such as PowerSupplies). We want to set
|
||||
// the overall health to be the most severe of any of the sensors.
|
||||
std::string currentHealth;
|
||||
+ std::string currentstate;
|
||||
auto statusIt = sensorJson.find("Status");
|
||||
if (statusIt != sensorJson.end())
|
||||
{
|
||||
+ auto stateIt = statusIt->find("State");
|
||||
+ if (stateIt != statusIt->end())
|
||||
+ {
|
||||
+ std::string* state = stateIt->get_ptr<std::string*>();
|
||||
+ if (state != nullptr)
|
||||
+ {
|
||||
+ currentstate = *state;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
auto healthIt = statusIt->find("Health");
|
||||
if (healthIt != statusIt->end())
|
||||
{
|
||||
@@ -716,6 +798,36 @@ inline std::string getHealth(nlohmann::json& sensorJson,
|
||||
}
|
||||
}
|
||||
|
||||
+ if (currentstate == "Disabled" || currentstate == "No Reading")
|
||||
+ {
|
||||
+ return "ns";
|
||||
+ }
|
||||
+
|
||||
+ // If current health in JSON object is already NonRecoverable, return that.
|
||||
+ // This should override the sensor health, which might be less severe.
|
||||
+ if (currentHealth == "NonRecoverable")
|
||||
+ {
|
||||
+ return "NonRecoverable";
|
||||
+ }
|
||||
+
|
||||
+ // Check if sensor has NonRecoverable threshold alarm
|
||||
+ for (const auto& [prop, value] : valuesDict)
|
||||
+ {
|
||||
+ if (prop == "NonRecoverableAlarmHigh" ||
|
||||
+ prop == "NonRecoverableAlarmLow")
|
||||
+ {
|
||||
+ const bool* asserted = std::get_if<bool>(&value);
|
||||
+ if (asserted == nullptr)
|
||||
+ {
|
||||
+ BMCWEB_LOG_ERROR("Illegal sensor threshold");
|
||||
+ }
|
||||
+ else if (*asserted)
|
||||
+ {
|
||||
+ return "NonRecoverable";
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
// If current health in JSON object is already Critical, return that. This
|
||||
// should override the sensor health, which might be less severe.
|
||||
if (currentHealth == "Critical")
|
||||
@@ -835,9 +947,9 @@ inline void objectPropertiesToJson(
|
||||
sensorJson["Name"] = std::move(sensorNameEs);
|
||||
}
|
||||
|
||||
- sensorJson["Status"]["State"] = getState(inventoryItem);
|
||||
+ sensorJson["Status"]["State"] = getState(propertiesDict, sensorJson);
|
||||
sensorJson["Status"]["Health"] = getHealth(sensorJson, propertiesDict,
|
||||
- inventoryItem);
|
||||
+ nullptr);
|
||||
|
||||
// Parameter to set to override the type we get from dbus, and force it to
|
||||
// int, regardless of what is available. This is used for schemas like fan,
|
||||
@@ -2294,7 +2406,7 @@ inline nlohmann::json& getPowerSupply(nlohmann::json& powerSupplyArray,
|
||||
inventoryItem.powerSupplyEfficiencyPercent;
|
||||
}
|
||||
|
||||
- powerSupply["Status"]["State"] = getState(&inventoryItem);
|
||||
+ powerSupply["Status"]["State"] = getPsuState(&inventoryItem);
|
||||
const char* health = inventoryItem.isFunctional ? "OK" : "Critical";
|
||||
powerSupply["Status"]["Health"] = health;
|
||||
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
|
||||
|
||||
DEPENDS += " \
|
||||
phosphor-dbus-interfaces \
|
||||
"
|
||||
|
||||
SRC_URI:append = " \
|
||||
file://0001-Reset-static-ipv4-address-when-turn-off-dhcpv4.patch \
|
||||
file://0001-Fix-webui-set-static-ip-failed-issue.patch \
|
||||
file://0001-Remove-web-sensor-underscores.patch \
|
||||
file://0001-Support-redfish-set-bmc-timezone.patch \
|
||||
file://0001-Add-Managers-SEL-log-service.patch \
|
||||
file://0001-Modify-nbd-proxy-path.patch \
|
||||
file://0001-Support-webui-switch-bmc-boot-source.patch \
|
||||
file://0001-Modify-task-max-timeout-time-to-10-minutes.patch \
|
||||
file://0001-Only-add-sensors-in-ipmi-sensor-json-file-to-active-.patch \
|
||||
file://0001-Sync-webui-sensor-status-with-ipmi.patch \
|
||||
file://0001-Add-ReleaseDate-for-BMC-inventory.patch \
|
||||
file://0001-Add-luxshare-oem-redfish-update-interface.patch \
|
||||
file://0001-Add-redfish-oem-rsyslog-api.patch \
|
||||
"
|
||||
|
||||
EXTRA_OEMESON:append = " \
|
||||
-Dhttp-body-limit=65 \
|
||||
"
|
||||
Reference in New Issue
Block a user