Files
OpenBMC/meta-luxshare/recipes-phosphor/interfaces/bmcweb/0001-Add-redfish-oem-rsyslog-api.patch
T

518 lines
22 KiB
Diff
Raw Normal View History

2026-04-23 17:07:55 +08:00
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