diff options
author | John Edward Broadbent <jebr@google.com> | 2021-04-09 01:57:16 +0300 |
---|---|---|
committer | Ed Tanous <ed@tanous.net> | 2021-06-03 21:18:02 +0300 |
commit | 7e860f1550c8686eec42f7a75bc5f2ef51e756ad (patch) | |
tree | 989da47a8427bc1a60119f480e2523151b1433aa /redfish-core/lib/network_protocol.hpp | |
parent | eb75770c6c4369984cb150ded4f5ace410ed24a9 (diff) | |
download | bmcweb-7e860f1550c8686eec42f7a75bc5f2ef51e756ad.tar.xz |
Remove Redfish Node class
Reduces the total number of lines and will allow for easier testing of
the redfish responses.
A main purpose of the node class was to set app.routeDynamic(). However
now app.routeDynamic can handle the complexity that was once in critical
to node. The macro app.routeDynamic() provides a shorter cleaner
interface to the unerlying app.routeDyanic call. The old pattern set
permissions for 6 interfaces (get, head, patch, put, delete_, and post)
even if only one interface is created. That pattern creates unneeded
code that can be safely removed with no effect.
Unit test for the responses would have to mock the node the class in
order to fully test responses.
see https://github.com/openbmc/bmcweb/issues/181
The following files still need node to be extracted.
virtual_media.hpp
account_service.hpp
redfish_sessions.hpp
ethernet.hpp
The files above use a pattern that is not trivial to address. Often their
responses call an async lambda capturing the inherited class. ie
(https://github.com/openbmc/bmcweb/blob/ffed87b5ad1797ca966d030e7f979770
28d258fa/redfish-core/lib/account_service.hpp#L1393)
At a later point I plan to remove node from the files above.
Tested:
I ran the docker unit test with the following command.
WORKSPACE=$(pwd) UNIT_TEST_PKG=bmcweb
./openbmc-build-scripts/run-unit-test-docker.sh
I ran the validator and this change did not create any issues.
python3 RedfishServiceValidator.py -c config.ini
Signed-off-by: John Edward Broadbent <jebr@google.com>
Signed-off-by: Ed Tanous <edtanous@google.com>
Change-Id: I147a0289c52cb4198345b1ad9bfe6fdddf57f3df
Diffstat (limited to 'redfish-core/lib/network_protocol.hpp')
-rw-r--r-- | redfish-core/lib/network_protocol.hpp | 735 |
1 files changed, 358 insertions, 377 deletions
diff --git a/redfish-core/lib/network_protocol.hpp b/redfish-core/lib/network_protocol.hpp index 491204eab0..46b5405b08 100644 --- a/redfish-core/lib/network_protocol.hpp +++ b/redfish-core/lib/network_protocol.hpp @@ -16,9 +16,9 @@ #pragma once #include "error_messages.hpp" -#include "node.hpp" #include "openbmc_dbus_rest.hpp" +#include <app.hpp> #include <utils/json_utils.hpp> #include <optional> @@ -26,6 +26,9 @@ namespace redfish { +void getNTPProtocolEnabled(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp); +std::string getHostName(); + enum NetworkProtocolUnitStructFields { NET_PROTO_UNIT_NAME, @@ -125,428 +128,406 @@ void getEthernetIfaceData(CallbackFunc&& callback) "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); } -class NetworkProtocol : public Node +void getNetworkData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { - public: - NetworkProtocol(App& app) : - Node(app, "/redfish/v1/Managers/bmc/NetworkProtocol/") - { - entityPrivileges = { - {boost::beast::http::verb::get, {{"Login"}}}, - {boost::beast::http::verb::head, {{"Login"}}}, - {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, - {boost::beast::http::verb::put, {{"ConfigureManager"}}}, - {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, - {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; - } - - private: - void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, - const crow::Request&, const std::vector<std::string>&) override + asyncResp->res.jsonValue["@odata.type"] = + "#ManagerNetworkProtocol.v1_5_0.ManagerNetworkProtocol"; + asyncResp->res.jsonValue["@odata.id"] = + "/redfish/v1/Managers/bmc/NetworkProtocol"; + asyncResp->res.jsonValue["Id"] = "NetworkProtocol"; + asyncResp->res.jsonValue["Name"] = "Manager Network Protocol"; + asyncResp->res.jsonValue["Description"] = "Manager Network Service"; + asyncResp->res.jsonValue["Status"]["Health"] = "OK"; + asyncResp->res.jsonValue["Status"]["HealthRollup"] = "OK"; + asyncResp->res.jsonValue["Status"]["State"] = "Enabled"; + + // HTTP is Mandatory attribute as per OCP Baseline Profile - v1.0.0, + // but from security perspective it is not recommended to use. + // Hence using protocolEnabled as false to make it OCP and security-wise + // compliant + asyncResp->res.jsonValue["HTTP"]["Port"] = 0; + asyncResp->res.jsonValue["HTTP"]["ProtocolEnabled"] = false; + + for (auto& protocol : protocolToDBus) { - getData(asyncResp); + asyncResp->res.jsonValue[protocol.first]["Port"] = + nlohmann::detail::value_t::null; + asyncResp->res.jsonValue[protocol.first]["ProtocolEnabled"] = false; } - std::string getHostName() const - { - std::string hostName; - - std::array<char, HOST_NAME_MAX> hostNameCStr; - if (gethostname(hostNameCStr.data(), hostNameCStr.size()) == 0) - { - hostName = hostNameCStr.data(); - } - return hostName; - } + std::string hostName = getHostName(); - void getNTPProtocolEnabled( - const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) - { - crow::connections::systemBus->async_method_call( - [asyncResp](const boost::system::error_code errorCode, - const std::variant<std::string>& timeSyncMethod) { - if (errorCode) - { - return; - } + asyncResp->res.jsonValue["HostName"] = hostName; - const std::string* s = - std::get_if<std::string>(&timeSyncMethod); + getNTPProtocolEnabled(asyncResp); - if (*s == "xyz.openbmc_project.Time.Synchronization.Method.NTP") - { - asyncResp->res.jsonValue["NTP"]["ProtocolEnabled"] = true; - } - else if (*s == "xyz.openbmc_project.Time.Synchronization." - "Method.Manual") + // TODO Get eth0 interface data, and call the below callback for JSON + // preparation + getEthernetIfaceData( + [hostName, asyncResp](const bool& success, + const std::vector<std::string>& ntpServers, + const std::vector<std::string>& domainNames) { + if (!success) + { + messages::resourceNotFound(asyncResp->res, "EthernetInterface", + "eth0"); + return; + } + asyncResp->res.jsonValue["NTP"]["NTPServers"] = ntpServers; + if (hostName.empty() == false) + { + std::string fqdn = hostName; + if (domainNames.empty() == false) { - asyncResp->res.jsonValue["NTP"]["ProtocolEnabled"] = false; + fqdn += "."; + fqdn += domainNames[0]; } - }, - "xyz.openbmc_project.Settings", - "/xyz/openbmc_project/time/sync_method", - "org.freedesktop.DBus.Properties", "Get", - "xyz.openbmc_project.Time.Synchronization", "TimeSyncMethod"); - } - - void getData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) - { - asyncResp->res.jsonValue["@odata.type"] = - "#ManagerNetworkProtocol.v1_5_0.ManagerNetworkProtocol"; - asyncResp->res.jsonValue["@odata.id"] = - "/redfish/v1/Managers/bmc/NetworkProtocol"; - asyncResp->res.jsonValue["Id"] = "NetworkProtocol"; - asyncResp->res.jsonValue["Name"] = "Manager Network Protocol"; - asyncResp->res.jsonValue["Description"] = "Manager Network Service"; - asyncResp->res.jsonValue["Status"]["Health"] = "OK"; - asyncResp->res.jsonValue["Status"]["HealthRollup"] = "OK"; - asyncResp->res.jsonValue["Status"]["State"] = "Enabled"; - - // HTTP is Mandatory attribute as per OCP Baseline Profile - v1.0.0, - // but from security perspective it is not recommended to use. - // Hence using protocolEnabled as false to make it OCP and security-wise - // compliant - asyncResp->res.jsonValue["HTTP"]["Port"] = 0; - asyncResp->res.jsonValue["HTTP"]["ProtocolEnabled"] = false; - - for (auto& protocol : protocolToDBus) - { - asyncResp->res.jsonValue[protocol.first]["Port"] = - nlohmann::detail::value_t::null; - asyncResp->res.jsonValue[protocol.first]["ProtocolEnabled"] = false; - } - - std::string hostName = getHostName(); - - asyncResp->res.jsonValue["HostName"] = hostName; - - getNTPProtocolEnabled(asyncResp); + asyncResp->res.jsonValue["FQDN"] = std::move(fqdn); + } + }); - // TODO Get eth0 interface data, and call the below callback for JSON - // preparation - getEthernetIfaceData( - [hostName, asyncResp](const bool& success, - const std::vector<std::string>& ntpServers, - const std::vector<std::string>& domainNames) { - if (!success) - { - messages::resourceNotFound(asyncResp->res, - "EthernetInterface", "eth0"); - return; - } - asyncResp->res.jsonValue["NTP"]["NTPServers"] = ntpServers; - if (hostName.empty() == false) - { - std::string fqdn = hostName; - if (domainNames.empty() == false) - { - fqdn += "."; - fqdn += domainNames[0]; - } - asyncResp->res.jsonValue["FQDN"] = std::move(fqdn); - } - }); + crow::connections::systemBus->async_method_call( + [asyncResp](const boost::system::error_code e, + const std::vector<UnitStruct>& r) { + if (e) + { + asyncResp->res.jsonValue = nlohmann::json::object(); + messages::internalError(asyncResp->res); + return; + } + asyncResp->res.jsonValue["HTTPS"]["Certificates"] = { + {"@odata.id", "/redfish/v1/Managers/bmc/NetworkProtocol/" + "HTTPS/Certificates"}}; - crow::connections::systemBus->async_method_call( - [asyncResp](const boost::system::error_code e, - const std::vector<UnitStruct>& r) { - if (e) + for (auto& unit : r) + { + /* Only traverse through <xyz>.socket units */ + const std::string& unitName = + std::get<NET_PROTO_UNIT_NAME>(unit); + if (!boost::ends_with(unitName, ".socket")) { - asyncResp->res.jsonValue = nlohmann::json::object(); - messages::internalError(asyncResp->res); - return; + continue; } - asyncResp->res.jsonValue["HTTPS"]["Certificates"] = { - {"@odata.id", "/redfish/v1/Managers/bmc/NetworkProtocol/" - "HTTPS/Certificates"}}; - for (auto& unit : r) + for (auto& kv : protocolToDBus) { - /* Only traverse through <xyz>.socket units */ - const std::string& unitName = - std::get<NET_PROTO_UNIT_NAME>(unit); - if (!boost::ends_with(unitName, ".socket")) + // We are interested in services, which starts with + // mapped service name + if (!boost::starts_with(unitName, kv.second)) { continue; } - - for (auto& kv : protocolToDBus) - { - // We are interested in services, which starts with - // mapped service name - if (!boost::starts_with(unitName, kv.second)) - { - continue; - } - const char* rfServiceKey = kv.first; - const std::string& socketPath = - std::get<NET_PROTO_UNIT_OBJ_PATH>(unit); - const std::string& unitState = - std::get<NET_PROTO_UNIT_SUB_STATE>(unit); - - asyncResp->res - .jsonValue[rfServiceKey]["ProtocolEnabled"] = - (unitState == "running") || - (unitState == "listening"); - - crow::connections::systemBus->async_method_call( - [asyncResp, - rfServiceKey{std::string(rfServiceKey)}]( - const boost::system::error_code ec, - const std::variant<std::vector<std::tuple< - std::string, std::string>>>& resp) { - if (ec) - { - messages::internalError(asyncResp->res); - return; - } - const std::vector< - std::tuple<std::string, std::string>>* - responsePtr = std::get_if<std::vector< - std::tuple<std::string, std::string>>>( - &resp); - if (responsePtr == nullptr || - responsePtr->size() < 1) - { - return; - } - - const std::string& listenStream = - std::get<NET_PROTO_LISTEN_STREAM>( - (*responsePtr)[0]); - std::size_t lastColonPos = - listenStream.rfind(':'); - if (lastColonPos == std::string::npos) - { - // Not a port - return; - } - std::string portStr = - listenStream.substr(lastColonPos + 1); - if (portStr.empty()) - { - return; - } - char* endPtr = nullptr; - errno = 0; - // Use strtol instead of stroi to avoid - // exceptions - long port = - std::strtol(portStr.c_str(), &endPtr, 10); - if ((errno == 0) && (*endPtr == '\0')) - { - asyncResp->res - .jsonValue[rfServiceKey]["Port"] = port; - } + const char* rfServiceKey = kv.first; + const std::string& socketPath = + std::get<NET_PROTO_UNIT_OBJ_PATH>(unit); + const std::string& unitState = + std::get<NET_PROTO_UNIT_SUB_STATE>(unit); + + asyncResp->res.jsonValue[rfServiceKey]["ProtocolEnabled"] = + (unitState == "running") || (unitState == "listening"); + + crow::connections::systemBus->async_method_call( + [asyncResp, rfServiceKey{std::string(rfServiceKey)}]( + const boost::system::error_code ec, + const std::variant<std::vector< + std::tuple<std::string, std::string>>>& resp) { + if (ec) + { + messages::internalError(asyncResp->res); return; - }, - "org.freedesktop.systemd1", socketPath, - "org.freedesktop.DBus.Properties", "Get", - "org.freedesktop.systemd1.Socket", "Listen"); + } + const std::vector< + std::tuple<std::string, std::string>>* + responsePtr = std::get_if<std::vector< + std::tuple<std::string, std::string>>>( + &resp); + if (responsePtr == nullptr || + responsePtr->size() < 1) + { + return; + } - // We found service, break the inner loop. - break; - } + const std::string& listenStream = + std::get<NET_PROTO_LISTEN_STREAM>( + (*responsePtr)[0]); + std::size_t lastColonPos = listenStream.rfind(':'); + if (lastColonPos == std::string::npos) + { + // Not a port + return; + } + std::string portStr = + listenStream.substr(lastColonPos + 1); + if (portStr.empty()) + { + return; + } + char* endPtr = nullptr; + errno = 0; + // Use strtol instead of stroi to avoid + // exceptions + long port = + std::strtol(portStr.c_str(), &endPtr, 10); + if ((errno == 0) && (*endPtr == '\0')) + { + asyncResp->res.jsonValue[rfServiceKey]["Port"] = + port; + } + return; + }, + "org.freedesktop.systemd1", socketPath, + "org.freedesktop.DBus.Properties", "Get", + "org.freedesktop.systemd1.Socket", "Listen"); + + // We found service, break the inner loop. + break; } - }, - "org.freedesktop.systemd1", "/org/freedesktop/systemd1", - "org.freedesktop.systemd1.Manager", "ListUnits"); - } + } + }, + "org.freedesktop.systemd1", "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", "ListUnits"); +} #ifdef BMCWEB_ALLOW_DEPRECATED_HOSTNAME_PATCH - void - handleHostnamePatch(const std::string& hostName, - const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) - { - crow::connections::systemBus->async_method_call( - [asyncResp](const boost::system::error_code ec) { - if (ec) - { - messages::internalError(asyncResp->res); - return; - } - }, - "xyz.openbmc_project.Network", - "/xyz/openbmc_project/network/config", - "org.freedesktop.DBus.Properties", "Set", - "xyz.openbmc_project.Network.SystemConfiguration", "HostName", - std::variant<std::string>(hostName)); - } +void handleHostnamePatch(const std::string& hostName, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) +{ + crow::connections::systemBus->async_method_call( + [asyncResp](const boost::system::error_code ec) { + if (ec) + { + messages::internalError(asyncResp->res); + return; + } + }, + "xyz.openbmc_project.Network", "/xyz/openbmc_project/network/config", + "org.freedesktop.DBus.Properties", "Set", + "xyz.openbmc_project.Network.SystemConfiguration", "HostName", + std::variant<std::string>(hostName)); +} #endif - void handleNTPProtocolEnabled( - const bool& ntpEnabled, - const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) +void handleNTPProtocolEnabled( + const bool& ntpEnabled, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) +{ + std::string timeSyncMethod; + if (ntpEnabled) { - std::string timeSyncMethod; - if (ntpEnabled) - { - timeSyncMethod = - "xyz.openbmc_project.Time.Synchronization.Method.NTP"; - } - else - { - timeSyncMethod = - "xyz.openbmc_project.Time.Synchronization.Method.Manual"; - } - - crow::connections::systemBus->async_method_call( - [asyncResp](const boost::system::error_code errorCode) { - if (errorCode) - { - messages::internalError(asyncResp->res); - } - }, - "xyz.openbmc_project.Settings", - "/xyz/openbmc_project/time/sync_method", - "org.freedesktop.DBus.Properties", "Set", - "xyz.openbmc_project.Time.Synchronization", "TimeSyncMethod", - std::variant<std::string>{timeSyncMethod}); + timeSyncMethod = "xyz.openbmc_project.Time.Synchronization.Method.NTP"; } - - void handleNTPServersPatch( - const std::vector<std::string>& ntpServers, - const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) + else { - crow::connections::systemBus->async_method_call( - [asyncResp](const boost::system::error_code ec) { - if (ec) - { - messages::internalError(asyncResp->res); - return; - } - }, - "xyz.openbmc_project.Network", "/xyz/openbmc_project/network/eth0", - "org.freedesktop.DBus.Properties", "Set", - "xyz.openbmc_project.Network.EthernetInterface", "NTPServers", - std::variant<std::vector<std::string>>{ntpServers}); + timeSyncMethod = + "xyz.openbmc_project.Time.Synchronization.Method.Manual"; } - void handleIpmiProtocolEnabled( - const bool ipmiProtocolEnabled, - const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) - { - crow::connections::systemBus->async_method_call( - [ipmiProtocolEnabled, - asyncResp](const boost::system::error_code ec, - const crow::openbmc_mapper::GetSubTreeType& subtree) { - if (ec) - { - messages::internalError(asyncResp->res); - return; - } - - constexpr char const* netipmidBasePath = - "/xyz/openbmc_project/control/service/" - "phosphor_2dipmi_2dnet_40"; - - for (const auto& entry : subtree) - { - if (boost::algorithm::starts_with(entry.first, - netipmidBasePath)) - { - crow::connections::systemBus->async_method_call( - [asyncResp](const boost::system::error_code ec2) { - if (ec2) - { - messages::internalError(asyncResp->res); - return; - } - }, - entry.second.begin()->first, entry.first, - "org.freedesktop.DBus.Properties", "Set", - "xyz.openbmc_project.Control.Service.Attributes", - "Running", std::variant<bool>{ipmiProtocolEnabled}); - - crow::connections::systemBus->async_method_call( - [asyncResp](const boost::system::error_code ec2) { - if (ec2) - { - messages::internalError(asyncResp->res); - return; - } - }, - entry.second.begin()->first, entry.first, - "org.freedesktop.DBus.Properties", "Set", - "xyz.openbmc_project.Control.Service.Attributes", - "Enabled", std::variant<bool>{ipmiProtocolEnabled}); - } - } - }, - "xyz.openbmc_project.ObjectMapper", - "/xyz/openbmc_project/object_mapper", - "xyz.openbmc_project.ObjectMapper", "GetSubTree", - "/xyz/openbmc_project/control/service", 0, - std::array<const char*, 1>{ - "xyz.openbmc_project.Control.Service.Attributes"}); - } - - void doPatch(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, - const crow::Request& req, - const std::vector<std::string>&) override - { - - std::optional<std::string> newHostName; - std::optional<nlohmann::json> ntp; - std::optional<nlohmann::json> ipmi; - - if (!json_util::readJson(req, asyncResp->res, "NTP", ntp, "HostName", - newHostName, "IPMI", ipmi)) - { - return; - } - - asyncResp->res.result(boost::beast::http::status::no_content); - if (newHostName) - { -#ifdef BMCWEB_ALLOW_DEPRECATED_HOSTNAME_PATCH - handleHostnamePatch(*newHostName, asyncResp); -#else - messages::propertyNotWritable(asyncResp->res, "HostName"); -#endif - } + crow::connections::systemBus->async_method_call( + [asyncResp](const boost::system::error_code errorCode) { + if (errorCode) + { + messages::internalError(asyncResp->res); + } + }, + "xyz.openbmc_project.Settings", "/xyz/openbmc_project/time/sync_method", + "org.freedesktop.DBus.Properties", "Set", + "xyz.openbmc_project.Time.Synchronization", "TimeSyncMethod", + std::variant<std::string>{timeSyncMethod}); +} - if (ntp) - { - std::optional<std::vector<std::string>> ntpServers; - std::optional<bool> ntpEnabled; - if (!json_util::readJson(*ntp, asyncResp->res, "NTPServers", - ntpServers, "ProtocolEnabled", ntpEnabled)) +void handleNTPServersPatch(const std::vector<std::string>& ntpServers, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) +{ + crow::connections::systemBus->async_method_call( + [asyncResp](const boost::system::error_code ec) { + if (ec) { + messages::internalError(asyncResp->res); return; } + }, + "xyz.openbmc_project.Network", "/xyz/openbmc_project/network/eth0", + "org.freedesktop.DBus.Properties", "Set", + "xyz.openbmc_project.Network.EthernetInterface", "NTPServers", + std::variant<std::vector<std::string>>{ntpServers}); +} - if (ntpEnabled) +void handleIpmiProtocolEnabled( + const bool ipmiProtocolEnabled, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) +{ + crow::connections::systemBus->async_method_call( + [ipmiProtocolEnabled, + asyncResp](const boost::system::error_code ec, + const crow::openbmc_mapper::GetSubTreeType& subtree) { + if (ec) { - handleNTPProtocolEnabled(*ntpEnabled, asyncResp); + messages::internalError(asyncResp->res); + return; } - if (ntpServers) + constexpr char const* netipmidBasePath = + "/xyz/openbmc_project/control/service/" + "phosphor_2dipmi_2dnet_40"; + + for (const auto& entry : subtree) { - std::sort((*ntpServers).begin(), (*ntpServers).end()); - (*ntpServers) - .erase( - std::unique((*ntpServers).begin(), (*ntpServers).end()), - (*ntpServers).end()); - handleNTPServersPatch(*ntpServers, asyncResp); + if (boost::algorithm::starts_with(entry.first, + netipmidBasePath)) + { + crow::connections::systemBus->async_method_call( + [asyncResp](const boost::system::error_code ec2) { + if (ec2) + { + messages::internalError(asyncResp->res); + return; + } + }, + entry.second.begin()->first, entry.first, + "org.freedesktop.DBus.Properties", "Set", + "xyz.openbmc_project.Control.Service.Attributes", + "Running", std::variant<bool>{ipmiProtocolEnabled}); + + crow::connections::systemBus->async_method_call( + [asyncResp](const boost::system::error_code ec2) { + if (ec2) + { + messages::internalError(asyncResp->res); + return; + } + }, + entry.second.begin()->first, entry.first, + "org.freedesktop.DBus.Properties", "Set", + "xyz.openbmc_project.Control.Service.Attributes", + "Enabled", std::variant<bool>{ipmiProtocolEnabled}); + } } - } + }, + "xyz.openbmc_project.ObjectMapper", + "/xyz/openbmc_project/object_mapper", + "xyz.openbmc_project.ObjectMapper", "GetSubTree", + "/xyz/openbmc_project/control/service", 0, + std::array<const char*, 1>{ + "xyz.openbmc_project.Control.Service.Attributes"}); +} - if (ipmi) - { - std::optional<bool> ipmiProtocolEnabled; - if (!json_util::readJson(*ipmi, asyncResp->res, "ProtocolEnabled", - ipmiProtocolEnabled)) +std::string getHostName() +{ + std::string hostName; + + std::array<char, HOST_NAME_MAX> hostNameCStr; + if (gethostname(hostNameCStr.data(), hostNameCStr.size()) == 0) + { + hostName = hostNameCStr.data(); + } + return hostName; +} + +void getNTPProtocolEnabled(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) +{ + crow::connections::systemBus->async_method_call( + [asyncResp](const boost::system::error_code errorCode, + const std::variant<std::string>& timeSyncMethod) { + if (errorCode) { return; } - if (ipmiProtocolEnabled) + const std::string* s = std::get_if<std::string>(&timeSyncMethod); + + if (*s == "xyz.openbmc_project.Time.Synchronization.Method.NTP") { - handleIpmiProtocolEnabled(*ipmiProtocolEnabled, asyncResp); + asyncResp->res.jsonValue["NTP"]["ProtocolEnabled"] = true; } - } - } -}; + else if (*s == "xyz.openbmc_project.Time.Synchronization." + "Method.Manual") + { + asyncResp->res.jsonValue["NTP"]["ProtocolEnabled"] = false; + } + }, + "xyz.openbmc_project.Settings", "/xyz/openbmc_project/time/sync_method", + "org.freedesktop.DBus.Properties", "Get", + "xyz.openbmc_project.Time.Synchronization", "TimeSyncMethod"); +} + +inline void requestRoutesNetworkProtocol(App& app) +{ + BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/NetworkProtocol/") + .privileges({"ConfigureManager"}) + .methods(boost::beast::http::verb::patch)( + [](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { + std::optional<std::string> newHostName; + std::optional<nlohmann::json> ntp; + std::optional<nlohmann::json> ipmi; + + if (!json_util::readJson(req, asyncResp->res, "NTP", ntp, + "HostName", newHostName, "IPMI", ipmi)) + { + return; + } + + asyncResp->res.result(boost::beast::http::status::no_content); + if (newHostName) + { +#ifdef BMCWEB_ALLOW_DEPRECATED_HOSTNAME_PATCH + handleHostnamePatch(*newHostName, asyncResp); +#else + messages::propertyNotWritable(asyncResp->res, "HostName"); +#endif + } + + if (ntp) + { + std::optional<std::vector<std::string>> ntpServers; + std::optional<bool> ntpEnabled; + if (!json_util::readJson(*ntp, asyncResp->res, "NTPServers", + ntpServers, "ProtocolEnabled", + ntpEnabled)) + { + return; + } + + if (ntpEnabled) + { + handleNTPProtocolEnabled(*ntpEnabled, asyncResp); + } + + if (ntpServers) + { + std::sort((*ntpServers).begin(), (*ntpServers).end()); + (*ntpServers) + .erase(std::unique((*ntpServers).begin(), + (*ntpServers).end()), + (*ntpServers).end()); + handleNTPServersPatch(*ntpServers, asyncResp); + } + } + + if (ipmi) + { + std::optional<bool> ipmiProtocolEnabled; + if (!json_util::readJson(*ipmi, asyncResp->res, + "ProtocolEnabled", + ipmiProtocolEnabled)) + { + return; + } + + if (ipmiProtocolEnabled) + { + handleIpmiProtocolEnabled(*ipmiProtocolEnabled, + asyncResp); + } + } + }); + + BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/NetworkProtocol/") + .privileges({"Login"}) + .methods(boost::beast::http::verb::get)( + [](const crow::Request&, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { + getNetworkData(asyncResp); + }); +} } // namespace redfish |