Initial commit

This commit is contained in:
Your Name
2026-04-23 17:07:55 +08:00
commit b7e39e063b
16725 changed files with 1625565 additions and 0 deletions
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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 \
"