From b814ff4bd75cc7ac9eac4b2b0214d1947d8d05b7 Mon Sep 17 00:00:00 2001 From: roly 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 +#include +#include +#include +#include +#include + +#include +#include + +namespace crow +{ +namespace luxshare_dump_api +{ + +namespace fs = std::filesystem; + +static const std::map rsyslogIndexTranslation = { + {"index0", "Index0"}, + {"index1", "Index1"}, + {"index2", "Index2"}, + {"index3", "Index3"}}; + + +inline std::string getRsyslogSettingsHelper( + const boost::asio::yield_context& yield, + const std::shared_ptr& asyncResp, + const std::string& dbusObj, const std::string& propertyName) +{ + boost::system::error_code ec; + auto response = crow::connections::systemBus + ->yield_method_call>( + 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(&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 +inline void setRsyslogSettingsHelper( + const boost::asio::yield_context& yield, + const std::shared_ptr& asyncResp, + const std::string& dbusObj, const std::string& propertyName, + const PropertyType& propertyValue) +{ + boost::system::error_code ec; + crow::connections::systemBus->yield_method_call( + yield, ec, "xyz.openbmc_project.Settings", dbusObj, + "org.freedesktop.DBus.Properties", "Set", + "xyz.openbmc_project.Logging.Rsyslog", propertyName, + std::variant(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& asyncResp) { + if (!redfish::setUpRedfishRoute(app, req, asyncResp)) + { + return; + } + + crow::connections::systemBus->async_method_call( + [asyncResp](const boost::system::error_code ec, + const std::vector& 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{"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& 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 oemLuxshareObject; + using InputMap = + std::map>; + 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 status; + std::optional addressType; + std::optional address; + std::optional ports; + std::optional protocolType; + const std::map 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 #include +#include #include #include @@ -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