19c310685SBorawski.Lukasz /* 26be832e2SEd Tanous Copyright (c) 2018 Intel Corporation 36be832e2SEd Tanous 46be832e2SEd Tanous Licensed under the Apache License, Version 2.0 (the "License"); 56be832e2SEd Tanous you may not use this file except in compliance with the License. 66be832e2SEd Tanous You may obtain a copy of the License at 76be832e2SEd Tanous 86be832e2SEd Tanous http://www.apache.org/licenses/LICENSE-2.0 96be832e2SEd Tanous 106be832e2SEd Tanous Unless required by applicable law or agreed to in writing, software 116be832e2SEd Tanous distributed under the License is distributed on an "AS IS" BASIS, 126be832e2SEd Tanous WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136be832e2SEd Tanous See the License for the specific language governing permissions and 146be832e2SEd Tanous limitations under the License. 159c310685SBorawski.Lukasz */ 169c310685SBorawski.Lukasz #pragma once 179c310685SBorawski.Lukasz 1813451e39SWilly Tu #include "bmcweb_config.h" 1913451e39SWilly Tu 20a51fc2d2SSui Chen #include "app.hpp" 21a51fc2d2SSui Chen #include "dbus_utility.hpp" 22539d8c6bSEd Tanous #include "generated/enums/action_info.hpp" 23539d8c6bSEd Tanous #include "generated/enums/manager.hpp" 24539d8c6bSEd Tanous #include "generated/enums/resource.hpp" 25a51fc2d2SSui Chen #include "query.hpp" 26c5d03ff4SJennifer Lee #include "redfish_util.hpp" 27a51fc2d2SSui Chen #include "registries/privilege_registry.hpp" 28fac6e53bSKrzysztof Grobelny #include "utils/dbus_utils.hpp" 293ccb3adbSEd Tanous #include "utils/json_utils.hpp" 30a51fc2d2SSui Chen #include "utils/sw_utils.hpp" 31a51fc2d2SSui Chen #include "utils/systemd_utils.hpp" 322b82937eSEd Tanous #include "utils/time_utils.hpp" 339c310685SBorawski.Lukasz 34e99073f5SGeorge Liu #include <boost/system/error_code.hpp> 35ef4c65b7SEd Tanous #include <boost/url/format.hpp> 36fac6e53bSKrzysztof Grobelny #include <sdbusplus/asio/property.hpp> 37fac6e53bSKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp> 381214b7e7SGunnar Mills 39a170f275SEd Tanous #include <algorithm> 40e99073f5SGeorge Liu #include <array> 414bfefa74SGunnar Mills #include <cstdint> 421214b7e7SGunnar Mills #include <memory> 439970e93fSKonstantin Aladyshev #include <optional> 443544d2a7SEd Tanous #include <ranges> 451214b7e7SGunnar Mills #include <sstream> 469970e93fSKonstantin Aladyshev #include <string> 47e99073f5SGeorge Liu #include <string_view> 48abf2add6SEd Tanous #include <variant> 495b4aa86bSJames Feist 501abe55efSEd Tanous namespace redfish 511abe55efSEd Tanous { 52ed5befbdSJennifer Lee 53ed5befbdSJennifer Lee /** 542a5c4407SGunnar Mills * Function reboots the BMC. 552a5c4407SGunnar Mills * 562a5c4407SGunnar Mills * @param[in] asyncResp - Shared pointer for completing asynchronous calls 57ed5befbdSJennifer Lee */ 588d1b46d7Szhanghch05 inline void 598d1b46d7Szhanghch05 doBMCGracefulRestart(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 60ed5befbdSJennifer Lee { 61ed5befbdSJennifer Lee const char* processName = "xyz.openbmc_project.State.BMC"; 62ed5befbdSJennifer Lee const char* objectPath = "/xyz/openbmc_project/state/bmc0"; 63ed5befbdSJennifer Lee const char* interfaceName = "xyz.openbmc_project.State.BMC"; 64ed5befbdSJennifer Lee const std::string& propertyValue = 65ed5befbdSJennifer Lee "xyz.openbmc_project.State.BMC.Transition.Reboot"; 66ed5befbdSJennifer Lee const char* destProperty = "RequestedBMCTransition"; 67ed5befbdSJennifer Lee 68ed5befbdSJennifer Lee // Create the D-Bus variant for D-Bus call. 699ae226faSGeorge Liu sdbusplus::asio::setProperty( 709ae226faSGeorge Liu *crow::connections::systemBus, processName, objectPath, interfaceName, 719ae226faSGeorge Liu destProperty, propertyValue, 725e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 73ed5befbdSJennifer Lee // Use "Set" method to set the property value. 74ed5befbdSJennifer Lee if (ec) 75ed5befbdSJennifer Lee { 7662598e31SEd Tanous BMCWEB_LOG_DEBUG("[Set] Bad D-Bus request error: {}", ec); 77ed5befbdSJennifer Lee messages::internalError(asyncResp->res); 78ed5befbdSJennifer Lee return; 79ed5befbdSJennifer Lee } 80ed5befbdSJennifer Lee 81ed5befbdSJennifer Lee messages::success(asyncResp->res); 829ae226faSGeorge Liu }); 83ed5befbdSJennifer Lee } 842a5c4407SGunnar Mills 858d1b46d7Szhanghch05 inline void 868d1b46d7Szhanghch05 doBMCForceRestart(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 87f92af389SJayaprakash Mutyala { 88f92af389SJayaprakash Mutyala const char* processName = "xyz.openbmc_project.State.BMC"; 89f92af389SJayaprakash Mutyala const char* objectPath = "/xyz/openbmc_project/state/bmc0"; 90f92af389SJayaprakash Mutyala const char* interfaceName = "xyz.openbmc_project.State.BMC"; 91f92af389SJayaprakash Mutyala const std::string& propertyValue = 92f92af389SJayaprakash Mutyala "xyz.openbmc_project.State.BMC.Transition.HardReboot"; 93f92af389SJayaprakash Mutyala const char* destProperty = "RequestedBMCTransition"; 94f92af389SJayaprakash Mutyala 95f92af389SJayaprakash Mutyala // Create the D-Bus variant for D-Bus call. 969ae226faSGeorge Liu sdbusplus::asio::setProperty( 979ae226faSGeorge Liu *crow::connections::systemBus, processName, objectPath, interfaceName, 989ae226faSGeorge Liu destProperty, propertyValue, 995e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 100f92af389SJayaprakash Mutyala // Use "Set" method to set the property value. 101f92af389SJayaprakash Mutyala if (ec) 102f92af389SJayaprakash Mutyala { 10362598e31SEd Tanous BMCWEB_LOG_DEBUG("[Set] Bad D-Bus request error: {}", ec); 104f92af389SJayaprakash Mutyala messages::internalError(asyncResp->res); 105f92af389SJayaprakash Mutyala return; 106f92af389SJayaprakash Mutyala } 107f92af389SJayaprakash Mutyala 108f92af389SJayaprakash Mutyala messages::success(asyncResp->res); 1099ae226faSGeorge Liu }); 110f92af389SJayaprakash Mutyala } 111f92af389SJayaprakash Mutyala 1122a5c4407SGunnar Mills /** 1132a5c4407SGunnar Mills * ManagerResetAction class supports the POST method for the Reset (reboot) 1142a5c4407SGunnar Mills * action. 1152a5c4407SGunnar Mills */ 1167e860f15SJohn Edward Broadbent inline void requestRoutesManagerResetAction(App& app) 1172a5c4407SGunnar Mills { 1182a5c4407SGunnar Mills /** 1192a5c4407SGunnar Mills * Function handles POST method request. 1202a5c4407SGunnar Mills * Analyzes POST body before sending Reset (Reboot) request data to D-Bus. 121f92af389SJayaprakash Mutyala * OpenBMC supports ResetType "GracefulRestart" and "ForceRestart". 1222a5c4407SGunnar Mills */ 1237e860f15SJohn Edward Broadbent 124253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/Actions/Manager.Reset/") 125ed398213SEd Tanous .privileges(redfish::privileges::postManager) 1267e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 12745ca1b86SEd Tanous [&app](const crow::Request& req, 128253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 129253f11b8SEd Tanous const std::string& managerId) { 1303ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 13145ca1b86SEd Tanous { 13245ca1b86SEd Tanous return; 13345ca1b86SEd Tanous } 134253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 135253f11b8SEd Tanous { 136bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "Manager", 137bd79bce8SPatrick Williams managerId); 138253f11b8SEd Tanous return; 139253f11b8SEd Tanous } 140253f11b8SEd Tanous 14162598e31SEd Tanous BMCWEB_LOG_DEBUG("Post Manager Reset."); 1422a5c4407SGunnar Mills 1432a5c4407SGunnar Mills std::string resetType; 1442a5c4407SGunnar Mills 14515ed6780SWilly Tu if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", 1467e860f15SJohn Edward Broadbent resetType)) 1472a5c4407SGunnar Mills { 1482a5c4407SGunnar Mills return; 1492a5c4407SGunnar Mills } 1502a5c4407SGunnar Mills 151f92af389SJayaprakash Mutyala if (resetType == "GracefulRestart") 152f92af389SJayaprakash Mutyala { 15362598e31SEd Tanous BMCWEB_LOG_DEBUG("Proceeding with {}", resetType); 154f92af389SJayaprakash Mutyala doBMCGracefulRestart(asyncResp); 155f92af389SJayaprakash Mutyala return; 156f92af389SJayaprakash Mutyala } 1573174e4dfSEd Tanous if (resetType == "ForceRestart") 158f92af389SJayaprakash Mutyala { 15962598e31SEd Tanous BMCWEB_LOG_DEBUG("Proceeding with {}", resetType); 160f92af389SJayaprakash Mutyala doBMCForceRestart(asyncResp); 161f92af389SJayaprakash Mutyala return; 162f92af389SJayaprakash Mutyala } 163bd79bce8SPatrick Williams BMCWEB_LOG_DEBUG("Invalid property value for ResetType: {}", 164bd79bce8SPatrick Williams resetType); 1652a5c4407SGunnar Mills messages::actionParameterNotSupported(asyncResp->res, resetType, 1662a5c4407SGunnar Mills "ResetType"); 1672a5c4407SGunnar Mills 1682a5c4407SGunnar Mills return; 1697e860f15SJohn Edward Broadbent }); 1702a5c4407SGunnar Mills } 171ed5befbdSJennifer Lee 1723e40fc74SGunnar Mills /** 1733e40fc74SGunnar Mills * ManagerResetToDefaultsAction class supports POST method for factory reset 1743e40fc74SGunnar Mills * action. 1753e40fc74SGunnar Mills */ 1767e860f15SJohn Edward Broadbent inline void requestRoutesManagerResetToDefaultsAction(App& app) 1773e40fc74SGunnar Mills { 1783e40fc74SGunnar Mills /** 1793e40fc74SGunnar Mills * Function handles ResetToDefaults POST method request. 1803e40fc74SGunnar Mills * 1813e40fc74SGunnar Mills * Analyzes POST body message and factory resets BMC by calling 1823e40fc74SGunnar Mills * BMC code updater factory reset followed by a BMC reboot. 1833e40fc74SGunnar Mills * 1843e40fc74SGunnar Mills * BMC code updater factory reset wipes the whole BMC read-write 1853e40fc74SGunnar Mills * filesystem which includes things like the network settings. 1863e40fc74SGunnar Mills * 1873e40fc74SGunnar Mills * OpenBMC only supports ResetToDefaultsType "ResetAll". 1883e40fc74SGunnar Mills */ 1897e860f15SJohn Edward Broadbent 1907e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 191253f11b8SEd Tanous "/redfish/v1/Managers/<str>/Actions/Manager.ResetToDefaults/") 192ed398213SEd Tanous .privileges(redfish::privileges::postManager) 193bd79bce8SPatrick Williams .methods( 194bd79bce8SPatrick Williams boost::beast::http::verb:: 195bd79bce8SPatrick Williams post)([&app]( 196bd79bce8SPatrick Williams const crow::Request& req, 197253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 198253f11b8SEd Tanous const std::string& managerId) { 1993ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 20045ca1b86SEd Tanous { 20145ca1b86SEd Tanous return; 20245ca1b86SEd Tanous } 203253f11b8SEd Tanous 204253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 205253f11b8SEd Tanous { 206bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "Manager", 207bd79bce8SPatrick Williams managerId); 208253f11b8SEd Tanous return; 209253f11b8SEd Tanous } 210253f11b8SEd Tanous 21162598e31SEd Tanous BMCWEB_LOG_DEBUG("Post ResetToDefaults."); 2123e40fc74SGunnar Mills 2139970e93fSKonstantin Aladyshev std::optional<std::string> resetType; 2149970e93fSKonstantin Aladyshev std::optional<std::string> resetToDefaultsType; 2153e40fc74SGunnar Mills 216*afc474aeSMyung Bae if (!json_util::readJsonAction( // 217*afc474aeSMyung Bae req, asyncResp->res, // 218*afc474aeSMyung Bae "ResetToDefaultsType", resetToDefaultsType, // 219*afc474aeSMyung Bae "ResetType", resetType // 220*afc474aeSMyung Bae )) 2213e40fc74SGunnar Mills { 2229970e93fSKonstantin Aladyshev BMCWEB_LOG_DEBUG("Missing property ResetType."); 2233e40fc74SGunnar Mills 224bd79bce8SPatrick Williams messages::actionParameterMissing( 225bd79bce8SPatrick Williams asyncResp->res, "ResetToDefaults", "ResetType"); 2263e40fc74SGunnar Mills return; 2273e40fc74SGunnar Mills } 2283e40fc74SGunnar Mills 2299970e93fSKonstantin Aladyshev if (resetToDefaultsType && !resetType) 2309970e93fSKonstantin Aladyshev { 2319970e93fSKonstantin Aladyshev BMCWEB_LOG_WARNING( 2329970e93fSKonstantin Aladyshev "Using deprecated ResetToDefaultsType, should be ResetType." 2339970e93fSKonstantin Aladyshev "Support for the ResetToDefaultsType will be dropped in 2Q24"); 2349970e93fSKonstantin Aladyshev resetType = resetToDefaultsType; 2359970e93fSKonstantin Aladyshev } 2369970e93fSKonstantin Aladyshev 2373e40fc74SGunnar Mills if (resetType != "ResetAll") 2383e40fc74SGunnar Mills { 2399970e93fSKonstantin Aladyshev BMCWEB_LOG_DEBUG("Invalid property value for ResetType: {}", 2409970e93fSKonstantin Aladyshev *resetType); 241bd79bce8SPatrick Williams messages::actionParameterNotSupported(asyncResp->res, 242bd79bce8SPatrick Williams *resetType, "ResetType"); 2433e40fc74SGunnar Mills return; 2443e40fc74SGunnar Mills } 2453e40fc74SGunnar Mills 2463e40fc74SGunnar Mills crow::connections::systemBus->async_method_call( 2475e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 2483e40fc74SGunnar Mills if (ec) 2493e40fc74SGunnar Mills { 25062598e31SEd Tanous BMCWEB_LOG_DEBUG("Failed to ResetToDefaults: {}", ec); 2513e40fc74SGunnar Mills messages::internalError(asyncResp->res); 2523e40fc74SGunnar Mills return; 2533e40fc74SGunnar Mills } 2543e40fc74SGunnar Mills // Factory Reset doesn't actually happen until a reboot 2553e40fc74SGunnar Mills // Can't erase what the BMC is running on 2563e40fc74SGunnar Mills doBMCGracefulRestart(asyncResp); 2573e40fc74SGunnar Mills }, 2583e40fc74SGunnar Mills "xyz.openbmc_project.Software.BMC.Updater", 2593e40fc74SGunnar Mills "/xyz/openbmc_project/software", 2603e40fc74SGunnar Mills "xyz.openbmc_project.Common.FactoryReset", "Reset"); 2617e860f15SJohn Edward Broadbent }); 2623e40fc74SGunnar Mills } 2633e40fc74SGunnar Mills 2641cb1a9e6SAppaRao Puli /** 2651cb1a9e6SAppaRao Puli * ManagerResetActionInfo derived class for delivering Manager 2661cb1a9e6SAppaRao Puli * ResetType AllowableValues using ResetInfo schema. 2671cb1a9e6SAppaRao Puli */ 2687e860f15SJohn Edward Broadbent inline void requestRoutesManagerResetActionInfo(App& app) 2691cb1a9e6SAppaRao Puli { 2701cb1a9e6SAppaRao Puli /** 2711cb1a9e6SAppaRao Puli * Functions triggers appropriate requests on DBus 2721cb1a9e6SAppaRao Puli */ 2737e860f15SJohn Edward Broadbent 274253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/ResetActionInfo/") 275ed398213SEd Tanous .privileges(redfish::privileges::getActionInfo) 2767e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 27745ca1b86SEd Tanous [&app](const crow::Request& req, 278253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 279253f11b8SEd Tanous const std::string& managerId) { 2803ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 28145ca1b86SEd Tanous { 28245ca1b86SEd Tanous return; 28345ca1b86SEd Tanous } 2841476687dSEd Tanous 285253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 286253f11b8SEd Tanous { 287bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "Manager", 288bd79bce8SPatrick Williams managerId); 289253f11b8SEd Tanous return; 290253f11b8SEd Tanous } 291253f11b8SEd Tanous 2921476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 2931476687dSEd Tanous "#ActionInfo.v1_1_2.ActionInfo"; 294bd79bce8SPatrick Williams asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 295bd79bce8SPatrick Williams "/redfish/v1/Managers/{}/ResetActionInfo", 296253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 2971476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "Reset Action Info"; 2981476687dSEd Tanous asyncResp->res.jsonValue["Id"] = "ResetActionInfo"; 2991476687dSEd Tanous nlohmann::json::object_t parameter; 3001476687dSEd Tanous parameter["Name"] = "ResetType"; 3011476687dSEd Tanous parameter["Required"] = true; 302539d8c6bSEd Tanous parameter["DataType"] = action_info::ParameterTypes::String; 3031476687dSEd Tanous 3041476687dSEd Tanous nlohmann::json::array_t allowableValues; 305ad539545SPatrick Williams allowableValues.emplace_back("GracefulRestart"); 306ad539545SPatrick Williams allowableValues.emplace_back("ForceRestart"); 3071476687dSEd Tanous parameter["AllowableValues"] = std::move(allowableValues); 3081476687dSEd Tanous 3091476687dSEd Tanous nlohmann::json::array_t parameters; 310ad539545SPatrick Williams parameters.emplace_back(std::move(parameter)); 3111476687dSEd Tanous 3121476687dSEd Tanous asyncResp->res.jsonValue["Parameters"] = std::move(parameters); 3137e860f15SJohn Edward Broadbent }); 3141cb1a9e6SAppaRao Puli } 3151cb1a9e6SAppaRao Puli 3165b4aa86bSJames Feist static constexpr const char* objectManagerIface = 3175b4aa86bSJames Feist "org.freedesktop.DBus.ObjectManager"; 3185b4aa86bSJames Feist static constexpr const char* pidConfigurationIface = 3195b4aa86bSJames Feist "xyz.openbmc_project.Configuration.Pid"; 3205b4aa86bSJames Feist static constexpr const char* pidZoneConfigurationIface = 3215b4aa86bSJames Feist "xyz.openbmc_project.Configuration.Pid.Zone"; 322b7a08d04SJames Feist static constexpr const char* stepwiseConfigurationIface = 323b7a08d04SJames Feist "xyz.openbmc_project.Configuration.Stepwise"; 32473df0db0SJames Feist static constexpr const char* thermalModeIface = 32573df0db0SJames Feist "xyz.openbmc_project.Control.ThermalMode"; 3269c310685SBorawski.Lukasz 3278d1b46d7Szhanghch05 inline void 3288d1b46d7Szhanghch05 asyncPopulatePid(const std::string& connection, const std::string& path, 32973df0db0SJames Feist const std::string& currentProfile, 33073df0db0SJames Feist const std::vector<std::string>& supportedProfiles, 3318d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 3325b4aa86bSJames Feist { 3335eb468daSGeorge Liu sdbusplus::message::object_path objPath(path); 3345eb468daSGeorge Liu dbus::utility::getManagedObjects( 3355eb468daSGeorge Liu connection, objPath, 33673df0db0SJames Feist [asyncResp, currentProfile, supportedProfiles]( 3375e7e2dc5SEd Tanous const boost::system::error_code& ec, 3385b4aa86bSJames Feist const dbus::utility::ManagedObjectType& managedObj) { 3395b4aa86bSJames Feist if (ec) 3405b4aa86bSJames Feist { 34162598e31SEd Tanous BMCWEB_LOG_ERROR("{}", ec); 342f12894f8SJason M. Bills messages::internalError(asyncResp->res); 3435b4aa86bSJames Feist return; 3445b4aa86bSJames Feist } 3455b4aa86bSJames Feist nlohmann::json& configRoot = 3465b4aa86bSJames Feist asyncResp->res.jsonValue["Oem"]["OpenBmc"]["Fan"]; 3475b4aa86bSJames Feist nlohmann::json& fans = configRoot["FanControllers"]; 348bd79bce8SPatrick Williams fans["@odata.type"] = 349bd79bce8SPatrick Williams "#OpenBMCManager.v1_0_0.Manager.FanControllers"; 350253f11b8SEd Tanous fans["@odata.id"] = boost::urls::format( 351253f11b8SEd Tanous "/redfish/v1/Managers/{}#/Oem/OpenBmc/Fan/FanControllers", 352253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 3535b4aa86bSJames Feist 3545b4aa86bSJames Feist nlohmann::json& pids = configRoot["PidControllers"]; 355bd79bce8SPatrick Williams pids["@odata.type"] = 356bd79bce8SPatrick Williams "#OpenBMCManager.v1_0_0.Manager.PidControllers"; 357253f11b8SEd Tanous pids["@odata.id"] = boost::urls::format( 358253f11b8SEd Tanous "/redfish/v1/Managers/{}#/Oem/OpenBmc/Fan/PidControllers", 359253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 3605b4aa86bSJames Feist 361b7a08d04SJames Feist nlohmann::json& stepwise = configRoot["StepwiseControllers"]; 362fc1cdd14SEd Tanous stepwise["@odata.type"] = 363fc1cdd14SEd Tanous "#OpenBMCManager.v1_0_0.Manager.StepwiseControllers"; 364253f11b8SEd Tanous stepwise["@odata.id"] = boost::urls::format( 365253f11b8SEd Tanous "/redfish/v1/Managers/{}#/Oem/OpenBmc/Fan/StepwiseControllers", 366253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 367b7a08d04SJames Feist 3685b4aa86bSJames Feist nlohmann::json& zones = configRoot["FanZones"]; 369253f11b8SEd Tanous zones["@odata.id"] = boost::urls::format( 370253f11b8SEd Tanous "/redfish/v1/Managers/{}#/Oem/OpenBmc/Fan/FanZones", 371253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 372fc1cdd14SEd Tanous zones["@odata.type"] = "#OpenBMCManager.v1_0_0.Manager.FanZones"; 373253f11b8SEd Tanous configRoot["@odata.id"] = 374253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}#/Oem/OpenBmc/Fan", 375253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 376fc1cdd14SEd Tanous configRoot["@odata.type"] = "#OpenBMCManager.v1_0_0.Manager.Fan"; 37773df0db0SJames Feist configRoot["Profile@Redfish.AllowableValues"] = supportedProfiles; 37873df0db0SJames Feist 37973df0db0SJames Feist if (!currentProfile.empty()) 38073df0db0SJames Feist { 38173df0db0SJames Feist configRoot["Profile"] = currentProfile; 38273df0db0SJames Feist } 383bf2ddedeSCarson Labrado BMCWEB_LOG_DEBUG("profile = {} !", currentProfile); 3845b4aa86bSJames Feist 3855b4aa86bSJames Feist for (const auto& pathPair : managedObj) 3865b4aa86bSJames Feist { 3875b4aa86bSJames Feist for (const auto& intfPair : pathPair.second) 3885b4aa86bSJames Feist { 3895b4aa86bSJames Feist if (intfPair.first != pidConfigurationIface && 390b7a08d04SJames Feist intfPair.first != pidZoneConfigurationIface && 391b7a08d04SJames Feist intfPair.first != stepwiseConfigurationIface) 3925b4aa86bSJames Feist { 3935b4aa86bSJames Feist continue; 3945b4aa86bSJames Feist } 39573df0db0SJames Feist 396711ac7a9SEd Tanous std::string name; 397711ac7a9SEd Tanous 398711ac7a9SEd Tanous for (const std::pair<std::string, 399bd79bce8SPatrick Williams dbus::utility::DbusVariantType>& 400bd79bce8SPatrick Williams propPair : intfPair.second) 401711ac7a9SEd Tanous { 402711ac7a9SEd Tanous if (propPair.first == "Name") 403711ac7a9SEd Tanous { 4045b4aa86bSJames Feist const std::string* namePtr = 405711ac7a9SEd Tanous std::get_if<std::string>(&propPair.second); 4065b4aa86bSJames Feist if (namePtr == nullptr) 4075b4aa86bSJames Feist { 40862598e31SEd Tanous BMCWEB_LOG_ERROR("Pid Name Field illegal"); 409b7a08d04SJames Feist messages::internalError(asyncResp->res); 4105b4aa86bSJames Feist return; 4115b4aa86bSJames Feist } 412db697703SWilly Tu name = *namePtr; 4135b4aa86bSJames Feist dbus::utility::escapePathForDbus(name); 414711ac7a9SEd Tanous } 415711ac7a9SEd Tanous else if (propPair.first == "Profiles") 41673df0db0SJames Feist { 41773df0db0SJames Feist const std::vector<std::string>* profiles = 41873df0db0SJames Feist std::get_if<std::vector<std::string>>( 419711ac7a9SEd Tanous &propPair.second); 42073df0db0SJames Feist if (profiles == nullptr) 42173df0db0SJames Feist { 42262598e31SEd Tanous BMCWEB_LOG_ERROR("Pid Profiles Field illegal"); 42373df0db0SJames Feist messages::internalError(asyncResp->res); 42473df0db0SJames Feist return; 42573df0db0SJames Feist } 42673df0db0SJames Feist if (std::find(profiles->begin(), profiles->end(), 42773df0db0SJames Feist currentProfile) == profiles->end()) 42873df0db0SJames Feist { 42962598e31SEd Tanous BMCWEB_LOG_INFO( 430bd79bce8SPatrick Williams "{} not supported in current profile", 431bd79bce8SPatrick Williams name); 43273df0db0SJames Feist continue; 43373df0db0SJames Feist } 43473df0db0SJames Feist } 435711ac7a9SEd Tanous } 436b7a08d04SJames Feist nlohmann::json* config = nullptr; 437c33a90ecSJames Feist const std::string* classPtr = nullptr; 438711ac7a9SEd Tanous 439711ac7a9SEd Tanous for (const std::pair<std::string, 440bd79bce8SPatrick Williams dbus::utility::DbusVariantType>& 441bd79bce8SPatrick Williams propPair : intfPair.second) 442c33a90ecSJames Feist { 443727dc83fSLei YU if (propPair.first == "Class") 444711ac7a9SEd Tanous { 445bd79bce8SPatrick Williams classPtr = 446bd79bce8SPatrick Williams std::get_if<std::string>(&propPair.second); 447711ac7a9SEd Tanous } 448c33a90ecSJames Feist } 449c33a90ecSJames Feist 450253f11b8SEd Tanous boost::urls::url url( 451253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}", 452253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME)); 4535b4aa86bSJames Feist if (intfPair.first == pidZoneConfigurationIface) 4545b4aa86bSJames Feist { 4555b4aa86bSJames Feist std::string chassis; 456bd79bce8SPatrick Williams if (!dbus::utility::getNthStringFromPath( 457bd79bce8SPatrick Williams pathPair.first.str, 5, chassis)) 4585b4aa86bSJames Feist { 4595b4aa86bSJames Feist chassis = "#IllegalValue"; 4605b4aa86bSJames Feist } 4615b4aa86bSJames Feist nlohmann::json& zone = zones[name]; 462bd79bce8SPatrick Williams zone["Chassis"]["@odata.id"] = boost::urls::format( 463bd79bce8SPatrick Williams "/redfish/v1/Chassis/{}", chassis); 464eddfc437SWilly Tu url.set_fragment( 465eddfc437SWilly Tu ("/Oem/OpenBmc/Fan/FanZones"_json_pointer / name) 466eddfc437SWilly Tu .to_string()); 467eddfc437SWilly Tu zone["@odata.id"] = std::move(url); 468fc1cdd14SEd Tanous zone["@odata.type"] = 469fc1cdd14SEd Tanous "#OpenBMCManager.v1_0_0.Manager.FanZone"; 470b7a08d04SJames Feist config = &zone; 4715b4aa86bSJames Feist } 4725b4aa86bSJames Feist 473b7a08d04SJames Feist else if (intfPair.first == stepwiseConfigurationIface) 4745b4aa86bSJames Feist { 475c33a90ecSJames Feist if (classPtr == nullptr) 476c33a90ecSJames Feist { 47762598e31SEd Tanous BMCWEB_LOG_ERROR("Pid Class Field illegal"); 478c33a90ecSJames Feist messages::internalError(asyncResp->res); 479c33a90ecSJames Feist return; 480c33a90ecSJames Feist } 481c33a90ecSJames Feist 482b7a08d04SJames Feist nlohmann::json& controller = stepwise[name]; 483b7a08d04SJames Feist config = &controller; 484eddfc437SWilly Tu url.set_fragment( 485eddfc437SWilly Tu ("/Oem/OpenBmc/Fan/StepwiseControllers"_json_pointer / 486eddfc437SWilly Tu name) 487eddfc437SWilly Tu .to_string()); 488eddfc437SWilly Tu controller["@odata.id"] = std::move(url); 489b7a08d04SJames Feist controller["@odata.type"] = 490fc1cdd14SEd Tanous "#OpenBMCManager.v1_0_0.Manager.StepwiseController"; 491b7a08d04SJames Feist 492c33a90ecSJames Feist controller["Direction"] = *classPtr; 4935b4aa86bSJames Feist } 4945b4aa86bSJames Feist 4955b4aa86bSJames Feist // pid and fans are off the same configuration 496b7a08d04SJames Feist else if (intfPair.first == pidConfigurationIface) 4975b4aa86bSJames Feist { 4985b4aa86bSJames Feist if (classPtr == nullptr) 4995b4aa86bSJames Feist { 50062598e31SEd Tanous BMCWEB_LOG_ERROR("Pid Class Field illegal"); 501a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 5025b4aa86bSJames Feist return; 5035b4aa86bSJames Feist } 5045b4aa86bSJames Feist bool isFan = *classPtr == "fan"; 505bd79bce8SPatrick Williams nlohmann::json& element = 506bd79bce8SPatrick Williams isFan ? fans[name] : pids[name]; 507b7a08d04SJames Feist config = &element; 5085b4aa86bSJames Feist if (isFan) 5095b4aa86bSJames Feist { 510eddfc437SWilly Tu url.set_fragment( 511eddfc437SWilly Tu ("/Oem/OpenBmc/Fan/FanControllers"_json_pointer / 512eddfc437SWilly Tu name) 513eddfc437SWilly Tu .to_string()); 514eddfc437SWilly Tu element["@odata.id"] = std::move(url); 515fc1cdd14SEd Tanous element["@odata.type"] = 516fc1cdd14SEd Tanous "#OpenBMCManager.v1_0_0.Manager.FanController"; 5175b4aa86bSJames Feist } 5185b4aa86bSJames Feist else 5195b4aa86bSJames Feist { 520eddfc437SWilly Tu url.set_fragment( 521eddfc437SWilly Tu ("/Oem/OpenBmc/Fan/PidControllers"_json_pointer / 522eddfc437SWilly Tu name) 523eddfc437SWilly Tu .to_string()); 524eddfc437SWilly Tu element["@odata.id"] = std::move(url); 525fc1cdd14SEd Tanous element["@odata.type"] = 526fc1cdd14SEd Tanous "#OpenBMCManager.v1_0_0.Manager.PidController"; 5275b4aa86bSJames Feist } 528b7a08d04SJames Feist } 529b7a08d04SJames Feist else 530b7a08d04SJames Feist { 53162598e31SEd Tanous BMCWEB_LOG_ERROR("Unexpected configuration"); 532b7a08d04SJames Feist messages::internalError(asyncResp->res); 533b7a08d04SJames Feist return; 534b7a08d04SJames Feist } 535b7a08d04SJames Feist 536b7a08d04SJames Feist // used for making maps out of 2 vectors 537b7a08d04SJames Feist const std::vector<double>* keys = nullptr; 538b7a08d04SJames Feist const std::vector<double>* values = nullptr; 539b7a08d04SJames Feist 540b7a08d04SJames Feist for (const auto& propertyPair : intfPair.second) 541b7a08d04SJames Feist { 542b7a08d04SJames Feist if (propertyPair.first == "Type" || 543b7a08d04SJames Feist propertyPair.first == "Class" || 544b7a08d04SJames Feist propertyPair.first == "Name") 545b7a08d04SJames Feist { 546b7a08d04SJames Feist continue; 547b7a08d04SJames Feist } 548b7a08d04SJames Feist 549b7a08d04SJames Feist // zones 550b7a08d04SJames Feist if (intfPair.first == pidZoneConfigurationIface) 551b7a08d04SJames Feist { 552b7a08d04SJames Feist const double* ptr = 553abf2add6SEd Tanous std::get_if<double>(&propertyPair.second); 554b7a08d04SJames Feist if (ptr == nullptr) 555b7a08d04SJames Feist { 55662598e31SEd Tanous BMCWEB_LOG_ERROR("Field Illegal {}", 55762598e31SEd Tanous propertyPair.first); 558b7a08d04SJames Feist messages::internalError(asyncResp->res); 559b7a08d04SJames Feist return; 560b7a08d04SJames Feist } 561b7a08d04SJames Feist (*config)[propertyPair.first] = *ptr; 562b7a08d04SJames Feist } 563b7a08d04SJames Feist 564b7a08d04SJames Feist if (intfPair.first == stepwiseConfigurationIface) 565b7a08d04SJames Feist { 566b7a08d04SJames Feist if (propertyPair.first == "Reading" || 567b7a08d04SJames Feist propertyPair.first == "Output") 568b7a08d04SJames Feist { 569b7a08d04SJames Feist const std::vector<double>* ptr = 570abf2add6SEd Tanous std::get_if<std::vector<double>>( 571b7a08d04SJames Feist &propertyPair.second); 572b7a08d04SJames Feist 573b7a08d04SJames Feist if (ptr == nullptr) 574b7a08d04SJames Feist { 57562598e31SEd Tanous BMCWEB_LOG_ERROR("Field Illegal {}", 57662598e31SEd Tanous propertyPair.first); 577b7a08d04SJames Feist messages::internalError(asyncResp->res); 578b7a08d04SJames Feist return; 579b7a08d04SJames Feist } 580b7a08d04SJames Feist 581b7a08d04SJames Feist if (propertyPair.first == "Reading") 582b7a08d04SJames Feist { 583b7a08d04SJames Feist keys = ptr; 584b7a08d04SJames Feist } 585b7a08d04SJames Feist else 586b7a08d04SJames Feist { 587b7a08d04SJames Feist values = ptr; 588b7a08d04SJames Feist } 589e662eae8SEd Tanous if (keys != nullptr && values != nullptr) 590b7a08d04SJames Feist { 591b7a08d04SJames Feist if (keys->size() != values->size()) 592b7a08d04SJames Feist { 59362598e31SEd Tanous BMCWEB_LOG_ERROR( 59462598e31SEd Tanous "Reading and Output size don't match "); 595b7a08d04SJames Feist messages::internalError(asyncResp->res); 596b7a08d04SJames Feist return; 597b7a08d04SJames Feist } 598b7a08d04SJames Feist nlohmann::json& steps = (*config)["Steps"]; 599b7a08d04SJames Feist steps = nlohmann::json::array(); 600b7a08d04SJames Feist for (size_t ii = 0; ii < keys->size(); ii++) 601b7a08d04SJames Feist { 6021476687dSEd Tanous nlohmann::json::object_t step; 6031476687dSEd Tanous step["Target"] = (*keys)[ii]; 6041476687dSEd Tanous step["Output"] = (*values)[ii]; 605b2ba3072SPatrick Williams steps.emplace_back(std::move(step)); 606b7a08d04SJames Feist } 607b7a08d04SJames Feist } 608b7a08d04SJames Feist } 609b7a08d04SJames Feist if (propertyPair.first == "NegativeHysteresis" || 610b7a08d04SJames Feist propertyPair.first == "PositiveHysteresis") 611b7a08d04SJames Feist { 612b7a08d04SJames Feist const double* ptr = 613abf2add6SEd Tanous std::get_if<double>(&propertyPair.second); 614b7a08d04SJames Feist if (ptr == nullptr) 615b7a08d04SJames Feist { 61662598e31SEd Tanous BMCWEB_LOG_ERROR("Field Illegal {}", 61762598e31SEd Tanous propertyPair.first); 618b7a08d04SJames Feist messages::internalError(asyncResp->res); 619b7a08d04SJames Feist return; 620b7a08d04SJames Feist } 621b7a08d04SJames Feist (*config)[propertyPair.first] = *ptr; 622b7a08d04SJames Feist } 623b7a08d04SJames Feist } 624b7a08d04SJames Feist 625b7a08d04SJames Feist // pid and fans are off the same configuration 626b7a08d04SJames Feist if (intfPair.first == pidConfigurationIface || 627b7a08d04SJames Feist intfPair.first == stepwiseConfigurationIface) 628b7a08d04SJames Feist { 6295b4aa86bSJames Feist if (propertyPair.first == "Zones") 6305b4aa86bSJames Feist { 6315b4aa86bSJames Feist const std::vector<std::string>* inputs = 632abf2add6SEd Tanous std::get_if<std::vector<std::string>>( 6331b6b96c5SEd Tanous &propertyPair.second); 6345b4aa86bSJames Feist 6355b4aa86bSJames Feist if (inputs == nullptr) 6365b4aa86bSJames Feist { 63762598e31SEd Tanous BMCWEB_LOG_ERROR("Zones Pid Field Illegal"); 638a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 6395b4aa86bSJames Feist return; 6405b4aa86bSJames Feist } 641b7a08d04SJames Feist auto& data = (*config)[propertyPair.first]; 6425b4aa86bSJames Feist data = nlohmann::json::array(); 6435b4aa86bSJames Feist for (std::string itemCopy : *inputs) 6445b4aa86bSJames Feist { 6455b4aa86bSJames Feist dbus::utility::escapePathForDbus(itemCopy); 6461476687dSEd Tanous nlohmann::json::object_t input; 647bd79bce8SPatrick Williams boost::urls::url managerUrl = 648bd79bce8SPatrick Williams boost::urls::format( 649253f11b8SEd Tanous "/redfish/v1/Managers/{}#{}", 650253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME, 651eddfc437SWilly Tu ("/Oem/OpenBmc/Fan/FanZones"_json_pointer / 652eddfc437SWilly Tu itemCopy) 653eddfc437SWilly Tu .to_string()); 654eddfc437SWilly Tu input["@odata.id"] = std::move(managerUrl); 655b2ba3072SPatrick Williams data.emplace_back(std::move(input)); 6565b4aa86bSJames Feist } 6575b4aa86bSJames Feist } 6585b4aa86bSJames Feist // todo(james): may never happen, but this 6595b4aa86bSJames Feist // assumes configuration data referenced in the 6605b4aa86bSJames Feist // PID config is provided by the same daemon, we 6615b4aa86bSJames Feist // could add another loop to cover all cases, 6625b4aa86bSJames Feist // but I'm okay kicking this can down the road a 6635b4aa86bSJames Feist // bit 6645b4aa86bSJames Feist 6655b4aa86bSJames Feist else if (propertyPair.first == "Inputs" || 6665b4aa86bSJames Feist propertyPair.first == "Outputs") 6675b4aa86bSJames Feist { 668b7a08d04SJames Feist auto& data = (*config)[propertyPair.first]; 6695b4aa86bSJames Feist const std::vector<std::string>* inputs = 670abf2add6SEd Tanous std::get_if<std::vector<std::string>>( 6711b6b96c5SEd Tanous &propertyPair.second); 6725b4aa86bSJames Feist 6735b4aa86bSJames Feist if (inputs == nullptr) 6745b4aa86bSJames Feist { 67562598e31SEd Tanous BMCWEB_LOG_ERROR("Field Illegal {}", 67662598e31SEd Tanous propertyPair.first); 677f12894f8SJason M. Bills messages::internalError(asyncResp->res); 6785b4aa86bSJames Feist return; 6795b4aa86bSJames Feist } 6805b4aa86bSJames Feist data = *inputs; 681b943aaefSJames Feist } 682b943aaefSJames Feist else if (propertyPair.first == "SetPointOffset") 683b943aaefSJames Feist { 684b943aaefSJames Feist const std::string* ptr = 685bd79bce8SPatrick Williams std::get_if<std::string>( 686bd79bce8SPatrick Williams &propertyPair.second); 687b943aaefSJames Feist 688b943aaefSJames Feist if (ptr == nullptr) 689b943aaefSJames Feist { 69062598e31SEd Tanous BMCWEB_LOG_ERROR("Field Illegal {}", 69162598e31SEd Tanous propertyPair.first); 692b943aaefSJames Feist messages::internalError(asyncResp->res); 693b943aaefSJames Feist return; 694b943aaefSJames Feist } 695b943aaefSJames Feist // translate from dbus to redfish 696b943aaefSJames Feist if (*ptr == "WarningHigh") 697b943aaefSJames Feist { 698b943aaefSJames Feist (*config)["SetPointOffset"] = 699b943aaefSJames Feist "UpperThresholdNonCritical"; 700b943aaefSJames Feist } 701b943aaefSJames Feist else if (*ptr == "WarningLow") 702b943aaefSJames Feist { 703b943aaefSJames Feist (*config)["SetPointOffset"] = 704b943aaefSJames Feist "LowerThresholdNonCritical"; 705b943aaefSJames Feist } 706b943aaefSJames Feist else if (*ptr == "CriticalHigh") 707b943aaefSJames Feist { 708b943aaefSJames Feist (*config)["SetPointOffset"] = 709b943aaefSJames Feist "UpperThresholdCritical"; 710b943aaefSJames Feist } 711b943aaefSJames Feist else if (*ptr == "CriticalLow") 712b943aaefSJames Feist { 713b943aaefSJames Feist (*config)["SetPointOffset"] = 714b943aaefSJames Feist "LowerThresholdCritical"; 715b943aaefSJames Feist } 716b943aaefSJames Feist else 717b943aaefSJames Feist { 71862598e31SEd Tanous BMCWEB_LOG_ERROR("Value Illegal {}", *ptr); 719b943aaefSJames Feist messages::internalError(asyncResp->res); 720b943aaefSJames Feist return; 721b943aaefSJames Feist } 722b943aaefSJames Feist } 723b943aaefSJames Feist // doubles 724bd79bce8SPatrick Williams else if (propertyPair.first == 725bd79bce8SPatrick Williams "FFGainCoefficient" || 7265b4aa86bSJames Feist propertyPair.first == "FFOffCoefficient" || 7275b4aa86bSJames Feist propertyPair.first == "ICoefficient" || 7285b4aa86bSJames Feist propertyPair.first == "ILimitMax" || 7295b4aa86bSJames Feist propertyPair.first == "ILimitMin" || 730bd79bce8SPatrick Williams propertyPair.first == 731bd79bce8SPatrick Williams "PositiveHysteresis" || 732bd79bce8SPatrick Williams propertyPair.first == 733bd79bce8SPatrick Williams "NegativeHysteresis" || 7345b4aa86bSJames Feist propertyPair.first == "OutLimitMax" || 7355b4aa86bSJames Feist propertyPair.first == "OutLimitMin" || 7365b4aa86bSJames Feist propertyPair.first == "PCoefficient" || 7377625cb81SJames Feist propertyPair.first == "SetPoint" || 7385b4aa86bSJames Feist propertyPair.first == "SlewNeg" || 7395b4aa86bSJames Feist propertyPair.first == "SlewPos") 7405b4aa86bSJames Feist { 7415b4aa86bSJames Feist const double* ptr = 742abf2add6SEd Tanous std::get_if<double>(&propertyPair.second); 7435b4aa86bSJames Feist if (ptr == nullptr) 7445b4aa86bSJames Feist { 74562598e31SEd Tanous BMCWEB_LOG_ERROR("Field Illegal {}", 74662598e31SEd Tanous propertyPair.first); 747f12894f8SJason M. Bills messages::internalError(asyncResp->res); 7485b4aa86bSJames Feist return; 7495b4aa86bSJames Feist } 750b7a08d04SJames Feist (*config)[propertyPair.first] = *ptr; 7515b4aa86bSJames Feist } 7525b4aa86bSJames Feist } 7535b4aa86bSJames Feist } 7545b4aa86bSJames Feist } 7555b4aa86bSJames Feist } 7565eb468daSGeorge Liu }); 7575b4aa86bSJames Feist } 758ca537928SJennifer Lee 75983ff9ab6SJames Feist enum class CreatePIDRet 76083ff9ab6SJames Feist { 76183ff9ab6SJames Feist fail, 76283ff9ab6SJames Feist del, 76383ff9ab6SJames Feist patch 76483ff9ab6SJames Feist }; 76583ff9ab6SJames Feist 7668d1b46d7Szhanghch05 inline bool 7678d1b46d7Szhanghch05 getZonesFromJsonReq(const std::shared_ptr<bmcweb::AsyncResp>& response, 7689e9b6049SEd Tanous std::vector<nlohmann::json::object_t>& config, 7695f2caaefSJames Feist std::vector<std::string>& zones) 7705f2caaefSJames Feist { 771b6baeaa4SJames Feist if (config.empty()) 772b6baeaa4SJames Feist { 77362598e31SEd Tanous BMCWEB_LOG_ERROR("Empty Zones"); 774f818b04dSEd Tanous messages::propertyValueFormatError(response->res, config, "Zones"); 775b6baeaa4SJames Feist return false; 776b6baeaa4SJames Feist } 7775f2caaefSJames Feist for (auto& odata : config) 7785f2caaefSJames Feist { 7795f2caaefSJames Feist std::string path; 7809e9b6049SEd Tanous if (!redfish::json_util::readJsonObject(odata, response->res, 7819e9b6049SEd Tanous "@odata.id", path)) 7825f2caaefSJames Feist { 7835f2caaefSJames Feist return false; 7845f2caaefSJames Feist } 7855f2caaefSJames Feist std::string input; 78661adbda3SJames Feist 78761adbda3SJames Feist // 8 below comes from 78861adbda3SJames Feist // /redfish/v1/Managers/bmc#/Oem/OpenBmc/Fan/FanZones/Left 78961adbda3SJames Feist // 0 1 2 3 4 5 6 7 8 79061adbda3SJames Feist if (!dbus::utility::getNthStringFromPath(path, 8, input)) 7915f2caaefSJames Feist { 79262598e31SEd Tanous BMCWEB_LOG_ERROR("Got invalid path {}", path); 79362598e31SEd Tanous BMCWEB_LOG_ERROR("Illegal Type Zones"); 794f818b04dSEd Tanous messages::propertyValueFormatError(response->res, odata, "Zones"); 7955f2caaefSJames Feist return false; 7965f2caaefSJames Feist } 797a170f275SEd Tanous std::replace(input.begin(), input.end(), '_', ' '); 7985f2caaefSJames Feist zones.emplace_back(std::move(input)); 7995f2caaefSJames Feist } 8005f2caaefSJames Feist return true; 8015f2caaefSJames Feist } 8025f2caaefSJames Feist 803711ac7a9SEd Tanous inline const dbus::utility::ManagedObjectType::value_type* 80473df0db0SJames Feist findChassis(const dbus::utility::ManagedObjectType& managedObj, 8059e9b6049SEd Tanous std::string_view value, std::string& chassis) 806b6baeaa4SJames Feist { 80762598e31SEd Tanous BMCWEB_LOG_DEBUG("Find Chassis: {}", value); 808b6baeaa4SJames Feist 8099e9b6049SEd Tanous std::string escaped(value); 8106ce82fabSYaswanth Reddy M std::replace(escaped.begin(), escaped.end(), ' ', '_'); 811b6baeaa4SJames Feist escaped = "/" + escaped; 8123544d2a7SEd Tanous auto it = std::ranges::find_if(managedObj, [&escaped](const auto& obj) { 81318f8f608SEd Tanous if (obj.first.str.ends_with(escaped)) 814b6baeaa4SJames Feist { 81562598e31SEd Tanous BMCWEB_LOG_DEBUG("Matched {}", obj.first.str); 816b6baeaa4SJames Feist return true; 817b6baeaa4SJames Feist } 818b6baeaa4SJames Feist return false; 819b6baeaa4SJames Feist }); 820b6baeaa4SJames Feist 821b6baeaa4SJames Feist if (it == managedObj.end()) 822b6baeaa4SJames Feist { 82373df0db0SJames Feist return nullptr; 824b6baeaa4SJames Feist } 825b6baeaa4SJames Feist // 5 comes from <chassis-name> being the 5th element 826b6baeaa4SJames Feist // /xyz/openbmc_project/inventory/system/chassis/<chassis-name> 82773df0db0SJames Feist if (dbus::utility::getNthStringFromPath(it->first.str, 5, chassis)) 82873df0db0SJames Feist { 82973df0db0SJames Feist return &(*it); 83073df0db0SJames Feist } 83173df0db0SJames Feist 83273df0db0SJames Feist return nullptr; 833b6baeaa4SJames Feist } 834b6baeaa4SJames Feist 83523a21a1cSEd Tanous inline CreatePIDRet createPidInterface( 8368d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& response, const std::string& type, 8379e9b6049SEd Tanous std::string_view name, nlohmann::json& jsonValue, const std::string& path, 83883ff9ab6SJames Feist const dbus::utility::ManagedObjectType& managedObj, bool createNewObject, 839b9d36b47SEd Tanous dbus::utility::DBusPropertiesMap& output, std::string& chassis, 840b9d36b47SEd Tanous const std::string& profile) 84183ff9ab6SJames Feist { 8425f2caaefSJames Feist // common deleter 8439e9b6049SEd Tanous if (jsonValue == nullptr) 8445f2caaefSJames Feist { 8455f2caaefSJames Feist std::string iface; 8465f2caaefSJames Feist if (type == "PidControllers" || type == "FanControllers") 8475f2caaefSJames Feist { 8485f2caaefSJames Feist iface = pidConfigurationIface; 8495f2caaefSJames Feist } 8505f2caaefSJames Feist else if (type == "FanZones") 8515f2caaefSJames Feist { 8525f2caaefSJames Feist iface = pidZoneConfigurationIface; 8535f2caaefSJames Feist } 8545f2caaefSJames Feist else if (type == "StepwiseControllers") 8555f2caaefSJames Feist { 8565f2caaefSJames Feist iface = stepwiseConfigurationIface; 8575f2caaefSJames Feist } 8585f2caaefSJames Feist else 8595f2caaefSJames Feist { 86062598e31SEd Tanous BMCWEB_LOG_ERROR("Illegal Type {}", type); 8615f2caaefSJames Feist messages::propertyUnknown(response->res, type); 8625f2caaefSJames Feist return CreatePIDRet::fail; 8635f2caaefSJames Feist } 8646ee7f774SJames Feist 86562598e31SEd Tanous BMCWEB_LOG_DEBUG("del {} {}", path, iface); 8665f2caaefSJames Feist // delete interface 8675f2caaefSJames Feist crow::connections::systemBus->async_method_call( 8685e7e2dc5SEd Tanous [response, path](const boost::system::error_code& ec) { 8695f2caaefSJames Feist if (ec) 8705f2caaefSJames Feist { 87162598e31SEd Tanous BMCWEB_LOG_ERROR("Error patching {}: {}", path, ec); 8725f2caaefSJames Feist messages::internalError(response->res); 873b6baeaa4SJames Feist return; 8745f2caaefSJames Feist } 875b6baeaa4SJames Feist messages::success(response->res); 8765f2caaefSJames Feist }, 8775f2caaefSJames Feist "xyz.openbmc_project.EntityManager", path, iface, "Delete"); 8785f2caaefSJames Feist return CreatePIDRet::del; 8795f2caaefSJames Feist } 8805f2caaefSJames Feist 881711ac7a9SEd Tanous const dbus::utility::ManagedObjectType::value_type* managedItem = nullptr; 882b6baeaa4SJames Feist if (!createNewObject) 883b6baeaa4SJames Feist { 884b6baeaa4SJames Feist // if we aren't creating a new object, we should be able to find it on 885b6baeaa4SJames Feist // d-bus 8869e9b6049SEd Tanous managedItem = findChassis(managedObj, name, chassis); 88773df0db0SJames Feist if (managedItem == nullptr) 888b6baeaa4SJames Feist { 88962598e31SEd Tanous BMCWEB_LOG_ERROR("Failed to get chassis from config patch"); 890ef4c65b7SEd Tanous messages::invalidObject( 891ef4c65b7SEd Tanous response->res, 892ef4c65b7SEd Tanous boost::urls::format("/redfish/v1/Chassis/{}", chassis)); 893b6baeaa4SJames Feist return CreatePIDRet::fail; 894b6baeaa4SJames Feist } 895b6baeaa4SJames Feist } 896b6baeaa4SJames Feist 89726f6976fSEd Tanous if (!profile.empty() && 89873df0db0SJames Feist (type == "PidControllers" || type == "FanControllers" || 89973df0db0SJames Feist type == "StepwiseControllers")) 90073df0db0SJames Feist { 90173df0db0SJames Feist if (managedItem == nullptr) 90273df0db0SJames Feist { 903b9d36b47SEd Tanous output.emplace_back("Profiles", std::vector<std::string>{profile}); 90473df0db0SJames Feist } 90573df0db0SJames Feist else 90673df0db0SJames Feist { 90773df0db0SJames Feist std::string interface; 90873df0db0SJames Feist if (type == "StepwiseControllers") 90973df0db0SJames Feist { 91073df0db0SJames Feist interface = stepwiseConfigurationIface; 91173df0db0SJames Feist } 91273df0db0SJames Feist else 91373df0db0SJames Feist { 91473df0db0SJames Feist interface = pidConfigurationIface; 91573df0db0SJames Feist } 916711ac7a9SEd Tanous bool ifaceFound = false; 917711ac7a9SEd Tanous for (const auto& iface : managedItem->second) 918711ac7a9SEd Tanous { 919711ac7a9SEd Tanous if (iface.first == interface) 920711ac7a9SEd Tanous { 921711ac7a9SEd Tanous ifaceFound = true; 922711ac7a9SEd Tanous for (const auto& prop : iface.second) 923711ac7a9SEd Tanous { 924711ac7a9SEd Tanous if (prop.first == "Profiles") 925711ac7a9SEd Tanous { 926711ac7a9SEd Tanous const std::vector<std::string>* curProfiles = 927711ac7a9SEd Tanous std::get_if<std::vector<std::string>>( 928711ac7a9SEd Tanous &(prop.second)); 929711ac7a9SEd Tanous if (curProfiles == nullptr) 930711ac7a9SEd Tanous { 93162598e31SEd Tanous BMCWEB_LOG_ERROR( 93262598e31SEd Tanous "Illegal profiles in managed object"); 933711ac7a9SEd Tanous messages::internalError(response->res); 934711ac7a9SEd Tanous return CreatePIDRet::fail; 935711ac7a9SEd Tanous } 936711ac7a9SEd Tanous if (std::find(curProfiles->begin(), 937bd79bce8SPatrick Williams curProfiles->end(), profile) == 938bd79bce8SPatrick Williams curProfiles->end()) 939711ac7a9SEd Tanous { 940711ac7a9SEd Tanous std::vector<std::string> newProfiles = 941711ac7a9SEd Tanous *curProfiles; 942711ac7a9SEd Tanous newProfiles.push_back(profile); 943b9d36b47SEd Tanous output.emplace_back("Profiles", newProfiles); 944711ac7a9SEd Tanous } 945711ac7a9SEd Tanous } 946711ac7a9SEd Tanous } 947711ac7a9SEd Tanous } 948711ac7a9SEd Tanous } 949711ac7a9SEd Tanous 950711ac7a9SEd Tanous if (!ifaceFound) 95173df0db0SJames Feist { 95262598e31SEd Tanous BMCWEB_LOG_ERROR("Failed to find interface in managed object"); 95373df0db0SJames Feist messages::internalError(response->res); 95473df0db0SJames Feist return CreatePIDRet::fail; 95573df0db0SJames Feist } 95673df0db0SJames Feist } 95773df0db0SJames Feist } 95873df0db0SJames Feist 95983ff9ab6SJames Feist if (type == "PidControllers" || type == "FanControllers") 96083ff9ab6SJames Feist { 96183ff9ab6SJames Feist if (createNewObject) 96283ff9ab6SJames Feist { 963b9d36b47SEd Tanous output.emplace_back("Class", 964b9d36b47SEd Tanous type == "PidControllers" ? "temp" : "fan"); 965b9d36b47SEd Tanous output.emplace_back("Type", "Pid"); 96683ff9ab6SJames Feist } 9675f2caaefSJames Feist 9689e9b6049SEd Tanous std::optional<std::vector<nlohmann::json::object_t>> zones; 9695f2caaefSJames Feist std::optional<std::vector<std::string>> inputs; 9705f2caaefSJames Feist std::optional<std::vector<std::string>> outputs; 9715f2caaefSJames Feist std::map<std::string, std::optional<double>> doubles; 972b943aaefSJames Feist std::optional<std::string> setpointOffset; 973*afc474aeSMyung Bae if (!redfish::json_util::readJson( // 974*afc474aeSMyung Bae jsonValue, response->res, // 975*afc474aeSMyung Bae "FFGainCoefficient", doubles["FFGainCoefficient"], // 976*afc474aeSMyung Bae "FFOffCoefficient", doubles["FFOffCoefficient"], // 977*afc474aeSMyung Bae "ICoefficient", doubles["ICoefficient"], // 978*afc474aeSMyung Bae "ILimitMax", doubles["ILimitMax"], // 979*afc474aeSMyung Bae "ILimitMin", doubles["ILimitMin"], // 980*afc474aeSMyung Bae "Inputs", inputs, // 981*afc474aeSMyung Bae "NegativeHysteresis", doubles["NegativeHysteresis"], // 982*afc474aeSMyung Bae "OutLimitMax", doubles["OutLimitMax"], // 983*afc474aeSMyung Bae "OutLimitMin", doubles["OutLimitMin"], // 984*afc474aeSMyung Bae "Outputs", outputs, // 985*afc474aeSMyung Bae "PCoefficient", doubles["PCoefficient"], // 986*afc474aeSMyung Bae "PositiveHysteresis", doubles["PositiveHysteresis"], // 987*afc474aeSMyung Bae "SetPoint", doubles["SetPoint"], // 988*afc474aeSMyung Bae "SetPointOffset", setpointOffset, // 989*afc474aeSMyung Bae "SlewNeg", doubles["SlewNeg"], // 990*afc474aeSMyung Bae "SlewPos", doubles["SlewPos"], // 991*afc474aeSMyung Bae "Zones", zones // 992*afc474aeSMyung Bae )) 99383ff9ab6SJames Feist { 9945f2caaefSJames Feist return CreatePIDRet::fail; 99583ff9ab6SJames Feist } 996*afc474aeSMyung Bae 9975f2caaefSJames Feist if (zones) 9985f2caaefSJames Feist { 9995f2caaefSJames Feist std::vector<std::string> zonesStr; 10005f2caaefSJames Feist if (!getZonesFromJsonReq(response, *zones, zonesStr)) 10015f2caaefSJames Feist { 100262598e31SEd Tanous BMCWEB_LOG_ERROR("Illegal Zones"); 10035f2caaefSJames Feist return CreatePIDRet::fail; 10045f2caaefSJames Feist } 1005b6baeaa4SJames Feist if (chassis.empty() && 1006e662eae8SEd Tanous findChassis(managedObj, zonesStr[0], chassis) == nullptr) 1007b6baeaa4SJames Feist { 100862598e31SEd Tanous BMCWEB_LOG_ERROR("Failed to get chassis from config patch"); 1009ace85d60SEd Tanous messages::invalidObject( 1010ef4c65b7SEd Tanous response->res, 1011ef4c65b7SEd Tanous boost::urls::format("/redfish/v1/Chassis/{}", chassis)); 1012b6baeaa4SJames Feist return CreatePIDRet::fail; 1013b6baeaa4SJames Feist } 1014b9d36b47SEd Tanous output.emplace_back("Zones", std::move(zonesStr)); 10155f2caaefSJames Feist } 1016afb9ee06SEd Tanous 1017afb9ee06SEd Tanous if (inputs) 10185f2caaefSJames Feist { 1019afb9ee06SEd Tanous for (std::string& value : *inputs) 102083ff9ab6SJames Feist { 1021a170f275SEd Tanous std::replace(value.begin(), value.end(), '_', ' '); 102283ff9ab6SJames Feist } 1023afb9ee06SEd Tanous output.emplace_back("Inputs", *inputs); 1024afb9ee06SEd Tanous } 1025afb9ee06SEd Tanous 1026afb9ee06SEd Tanous if (outputs) 10275f2caaefSJames Feist { 1028afb9ee06SEd Tanous for (std::string& value : *outputs) 10295f2caaefSJames Feist { 1030afb9ee06SEd Tanous std::replace(value.begin(), value.end(), '_', ' '); 10315f2caaefSJames Feist } 1032afb9ee06SEd Tanous output.emplace_back("Outputs", *outputs); 103383ff9ab6SJames Feist } 103483ff9ab6SJames Feist 1035b943aaefSJames Feist if (setpointOffset) 1036b943aaefSJames Feist { 1037b943aaefSJames Feist // translate between redfish and dbus names 1038b943aaefSJames Feist if (*setpointOffset == "UpperThresholdNonCritical") 1039b943aaefSJames Feist { 1040b9d36b47SEd Tanous output.emplace_back("SetPointOffset", "WarningLow"); 1041b943aaefSJames Feist } 1042b943aaefSJames Feist else if (*setpointOffset == "LowerThresholdNonCritical") 1043b943aaefSJames Feist { 1044b9d36b47SEd Tanous output.emplace_back("SetPointOffset", "WarningHigh"); 1045b943aaefSJames Feist } 1046b943aaefSJames Feist else if (*setpointOffset == "LowerThresholdCritical") 1047b943aaefSJames Feist { 1048b9d36b47SEd Tanous output.emplace_back("SetPointOffset", "CriticalLow"); 1049b943aaefSJames Feist } 1050b943aaefSJames Feist else if (*setpointOffset == "UpperThresholdCritical") 1051b943aaefSJames Feist { 1052b9d36b47SEd Tanous output.emplace_back("SetPointOffset", "CriticalHigh"); 1053b943aaefSJames Feist } 1054b943aaefSJames Feist else 1055b943aaefSJames Feist { 105662598e31SEd Tanous BMCWEB_LOG_ERROR("Invalid setpointoffset {}", *setpointOffset); 10579e9b6049SEd Tanous messages::propertyValueNotInList(response->res, name, 1058ace85d60SEd Tanous "SetPointOffset"); 1059b943aaefSJames Feist return CreatePIDRet::fail; 1060b943aaefSJames Feist } 1061b943aaefSJames Feist } 1062b943aaefSJames Feist 106383ff9ab6SJames Feist // doubles 10645f2caaefSJames Feist for (const auto& pairs : doubles) 106583ff9ab6SJames Feist { 10665f2caaefSJames Feist if (!pairs.second) 106783ff9ab6SJames Feist { 10685f2caaefSJames Feist continue; 106983ff9ab6SJames Feist } 107062598e31SEd Tanous BMCWEB_LOG_DEBUG("{} = {}", pairs.first, *pairs.second); 1071b9d36b47SEd Tanous output.emplace_back(pairs.first, *pairs.second); 10725f2caaefSJames Feist } 107383ff9ab6SJames Feist } 107483ff9ab6SJames Feist 107583ff9ab6SJames Feist else if (type == "FanZones") 107683ff9ab6SJames Feist { 1077b9d36b47SEd Tanous output.emplace_back("Type", "Pid.Zone"); 107883ff9ab6SJames Feist 10799e9b6049SEd Tanous std::optional<std::string> chassisId; 10805f2caaefSJames Feist std::optional<double> failSafePercent; 1081d3ec07f8SJames Feist std::optional<double> minThermalOutput; 1082*afc474aeSMyung Bae if (!redfish::json_util::readJson( // 1083*afc474aeSMyung Bae jsonValue, response->res, // 1084*afc474aeSMyung Bae "Chassis/@odata.id", chassisId, // 1085*afc474aeSMyung Bae "FailSafePercent", failSafePercent, // 1086*afc474aeSMyung Bae "MinThermalOutput", minThermalOutput)) 108783ff9ab6SJames Feist { 108883ff9ab6SJames Feist return CreatePIDRet::fail; 108983ff9ab6SJames Feist } 10905f2caaefSJames Feist 10919e9b6049SEd Tanous if (chassisId) 109283ff9ab6SJames Feist { 1093717794d5SAppaRao Puli // /redfish/v1/chassis/chassis_name/ 10949e9b6049SEd Tanous if (!dbus::utility::getNthStringFromPath(*chassisId, 3, chassis)) 109583ff9ab6SJames Feist { 10969e9b6049SEd Tanous BMCWEB_LOG_ERROR("Got invalid path {}", *chassisId); 1097ace85d60SEd Tanous messages::invalidObject( 1098ef4c65b7SEd Tanous response->res, 10999e9b6049SEd Tanous boost::urls::format("/redfish/v1/Chassis/{}", *chassisId)); 110083ff9ab6SJames Feist return CreatePIDRet::fail; 110183ff9ab6SJames Feist } 110283ff9ab6SJames Feist } 1103d3ec07f8SJames Feist if (minThermalOutput) 110483ff9ab6SJames Feist { 1105b9d36b47SEd Tanous output.emplace_back("MinThermalOutput", *minThermalOutput); 11065f2caaefSJames Feist } 11075f2caaefSJames Feist if (failSafePercent) 110883ff9ab6SJames Feist { 1109b9d36b47SEd Tanous output.emplace_back("FailSafePercent", *failSafePercent); 11105f2caaefSJames Feist } 11115f2caaefSJames Feist } 11125f2caaefSJames Feist else if (type == "StepwiseControllers") 11135f2caaefSJames Feist { 1114b9d36b47SEd Tanous output.emplace_back("Type", "Stepwise"); 11155f2caaefSJames Feist 11169e9b6049SEd Tanous std::optional<std::vector<nlohmann::json::object_t>> zones; 11179e9b6049SEd Tanous std::optional<std::vector<nlohmann::json::object_t>> steps; 11185f2caaefSJames Feist std::optional<std::vector<std::string>> inputs; 11195f2caaefSJames Feist std::optional<double> positiveHysteresis; 11205f2caaefSJames Feist std::optional<double> negativeHysteresis; 1121c33a90ecSJames Feist std::optional<std::string> direction; // upper clipping curve vs lower 1122*afc474aeSMyung Bae if (!redfish::json_util::readJson( // 1123*afc474aeSMyung Bae jsonValue, response->res, // 1124*afc474aeSMyung Bae "Direction", direction, // 1125*afc474aeSMyung Bae "Inputs", inputs, // 1126*afc474aeSMyung Bae "NegativeHysteresis", negativeHysteresis, // 1127*afc474aeSMyung Bae "PositiveHysteresis", positiveHysteresis, // 1128*afc474aeSMyung Bae "Steps", steps, // 1129*afc474aeSMyung Bae "Zones", zones // 1130*afc474aeSMyung Bae )) 11315f2caaefSJames Feist { 113283ff9ab6SJames Feist return CreatePIDRet::fail; 113383ff9ab6SJames Feist } 11345f2caaefSJames Feist 11355f2caaefSJames Feist if (zones) 113683ff9ab6SJames Feist { 1137b6baeaa4SJames Feist std::vector<std::string> zonesStrs; 1138b6baeaa4SJames Feist if (!getZonesFromJsonReq(response, *zones, zonesStrs)) 11395f2caaefSJames Feist { 114062598e31SEd Tanous BMCWEB_LOG_ERROR("Illegal Zones"); 114183ff9ab6SJames Feist return CreatePIDRet::fail; 114283ff9ab6SJames Feist } 1143b6baeaa4SJames Feist if (chassis.empty() && 1144e662eae8SEd Tanous findChassis(managedObj, zonesStrs[0], chassis) == nullptr) 1145b6baeaa4SJames Feist { 114662598e31SEd Tanous BMCWEB_LOG_ERROR("Failed to get chassis from config patch"); 1147ace85d60SEd Tanous messages::invalidObject( 1148ef4c65b7SEd Tanous response->res, 1149ef4c65b7SEd Tanous boost::urls::format("/redfish/v1/Chassis/{}", chassis)); 1150b6baeaa4SJames Feist return CreatePIDRet::fail; 1151b6baeaa4SJames Feist } 1152b9d36b47SEd Tanous output.emplace_back("Zones", std::move(zonesStrs)); 11535f2caaefSJames Feist } 11545f2caaefSJames Feist if (steps) 11555f2caaefSJames Feist { 11565f2caaefSJames Feist std::vector<double> readings; 11575f2caaefSJames Feist std::vector<double> outputs; 11585f2caaefSJames Feist for (auto& step : *steps) 11595f2caaefSJames Feist { 1160543f4400SEd Tanous double target = 0.0; 1161543f4400SEd Tanous double out = 0.0; 11625f2caaefSJames Feist 1163*afc474aeSMyung Bae if (!redfish::json_util::readJsonObject( // 1164*afc474aeSMyung Bae step, response->res, // 1165*afc474aeSMyung Bae "Output", out, // 1166*afc474aeSMyung Bae "Target", target // 1167*afc474aeSMyung Bae )) 11685f2caaefSJames Feist { 11695f2caaefSJames Feist return CreatePIDRet::fail; 11705f2caaefSJames Feist } 11715f2caaefSJames Feist readings.emplace_back(target); 117223a21a1cSEd Tanous outputs.emplace_back(out); 11735f2caaefSJames Feist } 1174b9d36b47SEd Tanous output.emplace_back("Reading", std::move(readings)); 1175b9d36b47SEd Tanous output.emplace_back("Output", std::move(outputs)); 11765f2caaefSJames Feist } 11775f2caaefSJames Feist if (inputs) 11785f2caaefSJames Feist { 11795f2caaefSJames Feist for (std::string& value : *inputs) 11805f2caaefSJames Feist { 1181a170f275SEd Tanous std::replace(value.begin(), value.end(), '_', ' '); 11825f2caaefSJames Feist } 1183b9d36b47SEd Tanous output.emplace_back("Inputs", std::move(*inputs)); 11845f2caaefSJames Feist } 11855f2caaefSJames Feist if (negativeHysteresis) 11865f2caaefSJames Feist { 1187b9d36b47SEd Tanous output.emplace_back("NegativeHysteresis", *negativeHysteresis); 11885f2caaefSJames Feist } 11895f2caaefSJames Feist if (positiveHysteresis) 11905f2caaefSJames Feist { 1191b9d36b47SEd Tanous output.emplace_back("PositiveHysteresis", *positiveHysteresis); 119283ff9ab6SJames Feist } 1193c33a90ecSJames Feist if (direction) 1194c33a90ecSJames Feist { 1195c33a90ecSJames Feist constexpr const std::array<const char*, 2> allowedDirections = { 1196c33a90ecSJames Feist "Ceiling", "Floor"}; 11973544d2a7SEd Tanous if (std::ranges::find(allowedDirections, *direction) == 11983544d2a7SEd Tanous allowedDirections.end()) 1199c33a90ecSJames Feist { 1200c33a90ecSJames Feist messages::propertyValueTypeError(response->res, "Direction", 1201c33a90ecSJames Feist *direction); 1202c33a90ecSJames Feist return CreatePIDRet::fail; 1203c33a90ecSJames Feist } 1204b9d36b47SEd Tanous output.emplace_back("Class", *direction); 1205c33a90ecSJames Feist } 120683ff9ab6SJames Feist } 120783ff9ab6SJames Feist else 120883ff9ab6SJames Feist { 120962598e31SEd Tanous BMCWEB_LOG_ERROR("Illegal Type {}", type); 121035a62c7cSJason M. Bills messages::propertyUnknown(response->res, type); 121183ff9ab6SJames Feist return CreatePIDRet::fail; 121283ff9ab6SJames Feist } 121383ff9ab6SJames Feist return CreatePIDRet::patch; 121483ff9ab6SJames Feist } 121573df0db0SJames Feist struct GetPIDValues : std::enable_shared_from_this<GetPIDValues> 121673df0db0SJames Feist { 12176936afe4SEd Tanous struct CompletionValues 12186936afe4SEd Tanous { 12196936afe4SEd Tanous std::vector<std::string> supportedProfiles; 12206936afe4SEd Tanous std::string currentProfile; 12216936afe4SEd Tanous dbus::utility::MapperGetSubTreeResponse subtree; 12226936afe4SEd Tanous }; 122383ff9ab6SJames Feist 12244e23a444SEd Tanous explicit GetPIDValues( 12254e23a444SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncRespIn) : 122623a21a1cSEd Tanous asyncResp(asyncRespIn) 122773df0db0SJames Feist 12281214b7e7SGunnar Mills {} 12299c310685SBorawski.Lukasz 123073df0db0SJames Feist void run() 12315b4aa86bSJames Feist { 123273df0db0SJames Feist std::shared_ptr<GetPIDValues> self = shared_from_this(); 123373df0db0SJames Feist 123473df0db0SJames Feist // get all configurations 1235e99073f5SGeorge Liu constexpr std::array<std::string_view, 4> interfaces = { 1236e99073f5SGeorge Liu pidConfigurationIface, pidZoneConfigurationIface, 1237e99073f5SGeorge Liu objectManagerIface, stepwiseConfigurationIface}; 1238e99073f5SGeorge Liu dbus::utility::getSubTree( 1239e99073f5SGeorge Liu "/", 0, interfaces, 1240b9d36b47SEd Tanous [self]( 1241e99073f5SGeorge Liu const boost::system::error_code& ec, 1242b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreeResponse& subtreeLocal) { 12435b4aa86bSJames Feist if (ec) 12445b4aa86bSJames Feist { 124562598e31SEd Tanous BMCWEB_LOG_ERROR("{}", ec); 124673df0db0SJames Feist messages::internalError(self->asyncResp->res); 124773df0db0SJames Feist return; 124873df0db0SJames Feist } 12496936afe4SEd Tanous self->complete.subtree = subtreeLocal; 1250e99073f5SGeorge Liu }); 125173df0db0SJames Feist 125273df0db0SJames Feist // at the same time get the selected profile 1253e99073f5SGeorge Liu constexpr std::array<std::string_view, 1> thermalModeIfaces = { 1254e99073f5SGeorge Liu thermalModeIface}; 1255e99073f5SGeorge Liu dbus::utility::getSubTree( 1256e99073f5SGeorge Liu "/", 0, thermalModeIfaces, 1257b9d36b47SEd Tanous [self]( 1258e99073f5SGeorge Liu const boost::system::error_code& ec, 1259b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreeResponse& subtreeLocal) { 126023a21a1cSEd Tanous if (ec || subtreeLocal.empty()) 126173df0db0SJames Feist { 126273df0db0SJames Feist return; 126373df0db0SJames Feist } 126423a21a1cSEd Tanous if (subtreeLocal[0].second.size() != 1) 126573df0db0SJames Feist { 126673df0db0SJames Feist // invalid mapper response, should never happen 126762598e31SEd Tanous BMCWEB_LOG_ERROR("GetPIDValues: Mapper Error"); 126873df0db0SJames Feist messages::internalError(self->asyncResp->res); 12695b4aa86bSJames Feist return; 12705b4aa86bSJames Feist } 12715b4aa86bSJames Feist 127223a21a1cSEd Tanous const std::string& path = subtreeLocal[0].first; 127323a21a1cSEd Tanous const std::string& owner = subtreeLocal[0].second[0].first; 1274fac6e53bSKrzysztof Grobelny 1275fac6e53bSKrzysztof Grobelny sdbusplus::asio::getAllProperties( 1276bd79bce8SPatrick Williams *crow::connections::systemBus, owner, path, 1277bd79bce8SPatrick Williams thermalModeIface, 1278168e20c1SEd Tanous [path, owner, 12795e7e2dc5SEd Tanous self](const boost::system::error_code& ec2, 1280b9d36b47SEd Tanous const dbus::utility::DBusPropertiesMap& resp) { 128123a21a1cSEd Tanous if (ec2) 128273df0db0SJames Feist { 128362598e31SEd Tanous BMCWEB_LOG_ERROR( 1284bd79bce8SPatrick Williams "GetPIDValues: Can't get thermalModeIface {}", 1285bd79bce8SPatrick Williams path); 128673df0db0SJames Feist messages::internalError(self->asyncResp->res); 128773df0db0SJames Feist return; 128873df0db0SJames Feist } 1289fac6e53bSKrzysztof Grobelny 1290271584abSEd Tanous const std::string* current = nullptr; 1291271584abSEd Tanous const std::vector<std::string>* supported = nullptr; 1292fac6e53bSKrzysztof Grobelny 1293fac6e53bSKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 1294bd79bce8SPatrick Williams dbus_utils::UnpackErrorPrinter(), resp, "Current", 1295bd79bce8SPatrick Williams current, "Supported", supported); 1296fac6e53bSKrzysztof Grobelny 1297fac6e53bSKrzysztof Grobelny if (!success) 129873df0db0SJames Feist { 1299002d39b4SEd Tanous messages::internalError(self->asyncResp->res); 130073df0db0SJames Feist return; 130173df0db0SJames Feist } 1302fac6e53bSKrzysztof Grobelny 130373df0db0SJames Feist if (current == nullptr || supported == nullptr) 130473df0db0SJames Feist { 130562598e31SEd Tanous BMCWEB_LOG_ERROR( 1306bd79bce8SPatrick Williams "GetPIDValues: thermal mode iface invalid {}", 1307bd79bce8SPatrick Williams path); 130873df0db0SJames Feist messages::internalError(self->asyncResp->res); 130973df0db0SJames Feist return; 131073df0db0SJames Feist } 13116936afe4SEd Tanous self->complete.currentProfile = *current; 13126936afe4SEd Tanous self->complete.supportedProfiles = *supported; 1313fac6e53bSKrzysztof Grobelny }); 1314e99073f5SGeorge Liu }); 131573df0db0SJames Feist } 131673df0db0SJames Feist 13176936afe4SEd Tanous static void 13186936afe4SEd Tanous processingComplete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 13196936afe4SEd Tanous const CompletionValues& completion) 132073df0db0SJames Feist { 132173df0db0SJames Feist if (asyncResp->res.result() != boost::beast::http::status::ok) 132273df0db0SJames Feist { 132373df0db0SJames Feist return; 132473df0db0SJames Feist } 13255b4aa86bSJames Feist // create map of <connection, path to objMgr>> 13266936afe4SEd Tanous boost::container::flat_map< 13276936afe4SEd Tanous std::string, std::string, std::less<>, 13286936afe4SEd Tanous std::vector<std::pair<std::string, std::string>>> 13296936afe4SEd Tanous objectMgrPaths; 13306936afe4SEd Tanous boost::container::flat_set<std::string, std::less<>, 13316936afe4SEd Tanous std::vector<std::string>> 13326936afe4SEd Tanous calledConnections; 13336936afe4SEd Tanous for (const auto& pathGroup : completion.subtree) 13345b4aa86bSJames Feist { 13355b4aa86bSJames Feist for (const auto& connectionGroup : pathGroup.second) 13365b4aa86bSJames Feist { 13376bce33bcSJames Feist auto findConnection = 13386bce33bcSJames Feist calledConnections.find(connectionGroup.first); 13396bce33bcSJames Feist if (findConnection != calledConnections.end()) 13406bce33bcSJames Feist { 13416bce33bcSJames Feist break; 13426bce33bcSJames Feist } 134373df0db0SJames Feist for (const std::string& interface : connectionGroup.second) 13445b4aa86bSJames Feist { 13455b4aa86bSJames Feist if (interface == objectManagerIface) 13465b4aa86bSJames Feist { 134773df0db0SJames Feist objectMgrPaths[connectionGroup.first] = pathGroup.first; 13485b4aa86bSJames Feist } 13495b4aa86bSJames Feist // this list is alphabetical, so we 13505b4aa86bSJames Feist // should have found the objMgr by now 13515b4aa86bSJames Feist if (interface == pidConfigurationIface || 1352b7a08d04SJames Feist interface == pidZoneConfigurationIface || 1353b7a08d04SJames Feist interface == stepwiseConfigurationIface) 13545b4aa86bSJames Feist { 13555b4aa86bSJames Feist auto findObjMgr = 13565b4aa86bSJames Feist objectMgrPaths.find(connectionGroup.first); 13575b4aa86bSJames Feist if (findObjMgr == objectMgrPaths.end()) 13585b4aa86bSJames Feist { 135962598e31SEd Tanous BMCWEB_LOG_DEBUG("{}Has no Object Manager", 136062598e31SEd Tanous connectionGroup.first); 13615b4aa86bSJames Feist continue; 13625b4aa86bSJames Feist } 13636bce33bcSJames Feist 13646bce33bcSJames Feist calledConnections.insert(connectionGroup.first); 13656bce33bcSJames Feist 136673df0db0SJames Feist asyncPopulatePid(findObjMgr->first, findObjMgr->second, 13676936afe4SEd Tanous completion.currentProfile, 13686936afe4SEd Tanous completion.supportedProfiles, 136973df0db0SJames Feist asyncResp); 13705b4aa86bSJames Feist break; 13715b4aa86bSJames Feist } 13725b4aa86bSJames Feist } 13735b4aa86bSJames Feist } 13745b4aa86bSJames Feist } 137573df0db0SJames Feist } 137673df0db0SJames Feist 13776936afe4SEd Tanous ~GetPIDValues() 13786936afe4SEd Tanous { 13796936afe4SEd Tanous boost::asio::post(crow::connections::systemBus->get_io_context(), 13806936afe4SEd Tanous std::bind_front(&processingComplete, asyncResp, 13816936afe4SEd Tanous std::move(complete))); 13826936afe4SEd Tanous } 13836936afe4SEd Tanous 1384ecd6a3a2SEd Tanous GetPIDValues(const GetPIDValues&) = delete; 1385ecd6a3a2SEd Tanous GetPIDValues(GetPIDValues&&) = delete; 1386ecd6a3a2SEd Tanous GetPIDValues& operator=(const GetPIDValues&) = delete; 1387ecd6a3a2SEd Tanous GetPIDValues& operator=(GetPIDValues&&) = delete; 1388ecd6a3a2SEd Tanous 13898d1b46d7Szhanghch05 std::shared_ptr<bmcweb::AsyncResp> asyncResp; 13906936afe4SEd Tanous CompletionValues complete; 139173df0db0SJames Feist }; 139273df0db0SJames Feist 139373df0db0SJames Feist struct SetPIDValues : std::enable_shared_from_this<SetPIDValues> 139473df0db0SJames Feist { 13959e9b6049SEd Tanous SetPIDValues( 13969e9b6049SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncRespIn, 13979e9b6049SEd Tanous std::vector< 13989e9b6049SEd Tanous std::pair<std::string, std::optional<nlohmann::json::object_t>>>&& 13999e9b6049SEd Tanous configurationsIn, 14009e9b6049SEd Tanous std::optional<std::string>& profileIn) : 1401bd79bce8SPatrick Williams asyncResp(asyncRespIn), configuration(std::move(configurationsIn)), 14029e9b6049SEd Tanous profile(std::move(profileIn)) 14039e9b6049SEd Tanous {} 1404ecd6a3a2SEd Tanous 1405ecd6a3a2SEd Tanous SetPIDValues(const SetPIDValues&) = delete; 1406ecd6a3a2SEd Tanous SetPIDValues(SetPIDValues&&) = delete; 1407ecd6a3a2SEd Tanous SetPIDValues& operator=(const SetPIDValues&) = delete; 1408ecd6a3a2SEd Tanous SetPIDValues& operator=(SetPIDValues&&) = delete; 1409ecd6a3a2SEd Tanous 141073df0db0SJames Feist void run() 141173df0db0SJames Feist { 141273df0db0SJames Feist if (asyncResp->res.result() != boost::beast::http::status::ok) 141373df0db0SJames Feist { 141473df0db0SJames Feist return; 141573df0db0SJames Feist } 141673df0db0SJames Feist 141773df0db0SJames Feist std::shared_ptr<SetPIDValues> self = shared_from_this(); 141873df0db0SJames Feist 141973df0db0SJames Feist // todo(james): might make sense to do a mapper call here if this 142073df0db0SJames Feist // interface gets more traction 14215eb468daSGeorge Liu sdbusplus::message::object_path objPath( 14225eb468daSGeorge Liu "/xyz/openbmc_project/inventory"); 14235eb468daSGeorge Liu dbus::utility::getManagedObjects( 14245eb468daSGeorge Liu "xyz.openbmc_project.EntityManager", objPath, 14255e7e2dc5SEd Tanous [self](const boost::system::error_code& ec, 1426914e2d5dSEd Tanous const dbus::utility::ManagedObjectType& mObj) { 142773df0db0SJames Feist if (ec) 142873df0db0SJames Feist { 142962598e31SEd Tanous BMCWEB_LOG_ERROR("Error communicating to Entity Manager"); 143073df0db0SJames Feist messages::internalError(self->asyncResp->res); 143173df0db0SJames Feist return; 143273df0db0SJames Feist } 1433e69d9de2SJames Feist const std::array<const char*, 3> configurations = { 1434e69d9de2SJames Feist pidConfigurationIface, pidZoneConfigurationIface, 1435e69d9de2SJames Feist stepwiseConfigurationIface}; 1436e69d9de2SJames Feist 143714b0b8d5SJames Feist for (const auto& [path, object] : mObj) 1438e69d9de2SJames Feist { 143914b0b8d5SJames Feist for (const auto& [interface, _] : object) 1440e69d9de2SJames Feist { 14413544d2a7SEd Tanous if (std::ranges::find(configurations, interface) != 14423544d2a7SEd Tanous configurations.end()) 1443e69d9de2SJames Feist { 144414b0b8d5SJames Feist self->objectCount++; 1445e69d9de2SJames Feist break; 1446e69d9de2SJames Feist } 1447e69d9de2SJames Feist } 1448e69d9de2SJames Feist } 1449914e2d5dSEd Tanous self->managedObj = mObj; 14505eb468daSGeorge Liu }); 145173df0db0SJames Feist 145273df0db0SJames Feist // at the same time get the profile information 1453e99073f5SGeorge Liu constexpr std::array<std::string_view, 1> thermalModeIfaces = { 1454e99073f5SGeorge Liu thermalModeIface}; 1455e99073f5SGeorge Liu dbus::utility::getSubTree( 1456e99073f5SGeorge Liu "/", 0, thermalModeIfaces, 1457e99073f5SGeorge Liu [self](const boost::system::error_code& ec, 1458b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreeResponse& subtree) { 145973df0db0SJames Feist if (ec || subtree.empty()) 146073df0db0SJames Feist { 146173df0db0SJames Feist return; 146273df0db0SJames Feist } 146373df0db0SJames Feist if (subtree[0].second.empty()) 146473df0db0SJames Feist { 146573df0db0SJames Feist // invalid mapper response, should never happen 146662598e31SEd Tanous BMCWEB_LOG_ERROR("SetPIDValues: Mapper Error"); 146773df0db0SJames Feist messages::internalError(self->asyncResp->res); 146873df0db0SJames Feist return; 146973df0db0SJames Feist } 147073df0db0SJames Feist 147173df0db0SJames Feist const std::string& path = subtree[0].first; 147273df0db0SJames Feist const std::string& owner = subtree[0].second[0].first; 1473fac6e53bSKrzysztof Grobelny sdbusplus::asio::getAllProperties( 1474bd79bce8SPatrick Williams *crow::connections::systemBus, owner, path, 1475bd79bce8SPatrick Williams thermalModeIface, 1476bd79bce8SPatrick Williams [self, path, 1477bd79bce8SPatrick Williams owner](const boost::system::error_code& ec2, 1478b9d36b47SEd Tanous const dbus::utility::DBusPropertiesMap& r) { 1479cb13a392SEd Tanous if (ec2) 148073df0db0SJames Feist { 148162598e31SEd Tanous BMCWEB_LOG_ERROR( 1482bd79bce8SPatrick Williams "SetPIDValues: Can't get thermalModeIface {}", 1483bd79bce8SPatrick Williams path); 148473df0db0SJames Feist messages::internalError(self->asyncResp->res); 148573df0db0SJames Feist return; 148673df0db0SJames Feist } 1487271584abSEd Tanous const std::string* current = nullptr; 1488271584abSEd Tanous const std::vector<std::string>* supported = nullptr; 1489fac6e53bSKrzysztof Grobelny 1490fac6e53bSKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 1491bd79bce8SPatrick Williams dbus_utils::UnpackErrorPrinter(), r, "Current", 1492bd79bce8SPatrick Williams current, "Supported", supported); 1493fac6e53bSKrzysztof Grobelny 1494fac6e53bSKrzysztof Grobelny if (!success) 149573df0db0SJames Feist { 1496002d39b4SEd Tanous messages::internalError(self->asyncResp->res); 149773df0db0SJames Feist return; 149873df0db0SJames Feist } 1499fac6e53bSKrzysztof Grobelny 150073df0db0SJames Feist if (current == nullptr || supported == nullptr) 150173df0db0SJames Feist { 150262598e31SEd Tanous BMCWEB_LOG_ERROR( 1503bd79bce8SPatrick Williams "SetPIDValues: thermal mode iface invalid {}", 1504bd79bce8SPatrick Williams path); 150573df0db0SJames Feist messages::internalError(self->asyncResp->res); 150673df0db0SJames Feist return; 150773df0db0SJames Feist } 150873df0db0SJames Feist self->currentProfile = *current; 150973df0db0SJames Feist self->supportedProfiles = *supported; 151073df0db0SJames Feist self->profileConnection = owner; 151173df0db0SJames Feist self->profilePath = path; 1512fac6e53bSKrzysztof Grobelny }); 1513e99073f5SGeorge Liu }); 151473df0db0SJames Feist } 151524b2fe81SEd Tanous void pidSetDone() 151673df0db0SJames Feist { 151773df0db0SJames Feist if (asyncResp->res.result() != boost::beast::http::status::ok) 151873df0db0SJames Feist { 151973df0db0SJames Feist return; 15205b4aa86bSJames Feist } 15218d1b46d7Szhanghch05 std::shared_ptr<bmcweb::AsyncResp> response = asyncResp; 152273df0db0SJames Feist if (profile) 152373df0db0SJames Feist { 15243544d2a7SEd Tanous if (std::ranges::find(supportedProfiles, *profile) == 15253544d2a7SEd Tanous supportedProfiles.end()) 152673df0db0SJames Feist { 152773df0db0SJames Feist messages::actionParameterUnknown(response->res, "Profile", 152873df0db0SJames Feist *profile); 152973df0db0SJames Feist return; 153073df0db0SJames Feist } 153173df0db0SJames Feist currentProfile = *profile; 15329ae226faSGeorge Liu sdbusplus::asio::setProperty( 15339ae226faSGeorge Liu *crow::connections::systemBus, profileConnection, profilePath, 15349ae226faSGeorge Liu thermalModeIface, "Current", *profile, 15355e7e2dc5SEd Tanous [response](const boost::system::error_code& ec) { 153673df0db0SJames Feist if (ec) 153773df0db0SJames Feist { 153862598e31SEd Tanous BMCWEB_LOG_ERROR("Error patching profile{}", ec); 153973df0db0SJames Feist messages::internalError(response->res); 154073df0db0SJames Feist } 15419ae226faSGeorge Liu }); 154273df0db0SJames Feist } 154373df0db0SJames Feist 154473df0db0SJames Feist for (auto& containerPair : configuration) 154573df0db0SJames Feist { 154673df0db0SJames Feist auto& container = containerPair.second; 154773df0db0SJames Feist if (!container) 154873df0db0SJames Feist { 154973df0db0SJames Feist continue; 155073df0db0SJames Feist } 15516ee7f774SJames Feist 155202cad96eSEd Tanous const std::string& type = containerPair.first; 155373df0db0SJames Feist 15549e9b6049SEd Tanous for (auto& [name, value] : *container) 155573df0db0SJames Feist { 1556cddbf3dfSPotin Lai std::string dbusObjName = name; 1557cddbf3dfSPotin Lai std::replace(dbusObjName.begin(), dbusObjName.end(), ' ', '_'); 155862598e31SEd Tanous BMCWEB_LOG_DEBUG("looking for {}", name); 15596ee7f774SJames Feist 15603544d2a7SEd Tanous auto pathItr = std::ranges::find_if( 15613544d2a7SEd Tanous managedObj, [&dbusObjName](const auto& obj) { 156291f75cafSEd Tanous return obj.first.filename() == dbusObjName; 156373df0db0SJames Feist }); 1564b9d36b47SEd Tanous dbus::utility::DBusPropertiesMap output; 156573df0db0SJames Feist 156673df0db0SJames Feist output.reserve(16); // The pid interface length 156773df0db0SJames Feist 156873df0db0SJames Feist // determines if we're patching entity-manager or 156973df0db0SJames Feist // creating a new object 157073df0db0SJames Feist bool createNewObject = (pathItr == managedObj.end()); 157162598e31SEd Tanous BMCWEB_LOG_DEBUG("Found = {}", !createNewObject); 15726ee7f774SJames Feist 157373df0db0SJames Feist std::string iface; 1574ea2b670dSEd Tanous if (!createNewObject) 1575ea2b670dSEd Tanous { 15768be2b5b6SPotin Lai bool findInterface = false; 1577ea2b670dSEd Tanous for (const auto& interface : pathItr->second) 1578ea2b670dSEd Tanous { 1579ea2b670dSEd Tanous if (interface.first == pidConfigurationIface) 1580ea2b670dSEd Tanous { 1581ea2b670dSEd Tanous if (type == "PidControllers" || 1582ea2b670dSEd Tanous type == "FanControllers") 158373df0db0SJames Feist { 158473df0db0SJames Feist iface = pidConfigurationIface; 15858be2b5b6SPotin Lai findInterface = true; 15868be2b5b6SPotin Lai break; 158773df0db0SJames Feist } 158873df0db0SJames Feist } 1589ea2b670dSEd Tanous else if (interface.first == pidZoneConfigurationIface) 159073df0db0SJames Feist { 1591ea2b670dSEd Tanous if (type == "FanZones") 159273df0db0SJames Feist { 1593da39350aSPavanKumarIntel iface = pidZoneConfigurationIface; 15948be2b5b6SPotin Lai findInterface = true; 15958be2b5b6SPotin Lai break; 159673df0db0SJames Feist } 159773df0db0SJames Feist } 1598ea2b670dSEd Tanous else if (interface.first == stepwiseConfigurationIface) 1599ea2b670dSEd Tanous { 1600ea2b670dSEd Tanous if (type == "StepwiseControllers") 160173df0db0SJames Feist { 160273df0db0SJames Feist iface = stepwiseConfigurationIface; 16038be2b5b6SPotin Lai findInterface = true; 16048be2b5b6SPotin Lai break; 16058be2b5b6SPotin Lai } 16068be2b5b6SPotin Lai } 16078be2b5b6SPotin Lai } 16088be2b5b6SPotin Lai 16098be2b5b6SPotin Lai // create new object if interface not found 16108be2b5b6SPotin Lai if (!findInterface) 16118be2b5b6SPotin Lai { 161273df0db0SJames Feist createNewObject = true; 161373df0db0SJames Feist } 1614ea2b670dSEd Tanous } 16156ee7f774SJames Feist 16169e9b6049SEd Tanous if (createNewObject && value == nullptr) 16176ee7f774SJames Feist { 16184e0453b1SGunnar Mills // can't delete a non-existent object 16199e9b6049SEd Tanous messages::propertyValueNotInList(response->res, value, 1620e2616cc5SEd Tanous name); 16216ee7f774SJames Feist continue; 16226ee7f774SJames Feist } 16236ee7f774SJames Feist 16246ee7f774SJames Feist std::string path; 16256ee7f774SJames Feist if (pathItr != managedObj.end()) 16266ee7f774SJames Feist { 16276ee7f774SJames Feist path = pathItr->first.str; 16286ee7f774SJames Feist } 16296ee7f774SJames Feist 163062598e31SEd Tanous BMCWEB_LOG_DEBUG("Create new = {}", createNewObject); 1631e69d9de2SJames Feist 1632e69d9de2SJames Feist // arbitrary limit to avoid attacks 1633e69d9de2SJames Feist constexpr const size_t controllerLimit = 500; 163414b0b8d5SJames Feist if (createNewObject && objectCount >= controllerLimit) 1635e69d9de2SJames Feist { 1636e69d9de2SJames Feist messages::resourceExhaustion(response->res, type); 1637e69d9de2SJames Feist continue; 1638e69d9de2SJames Feist } 1639a170f275SEd Tanous std::string escaped = name; 1640a170f275SEd Tanous std::replace(escaped.begin(), escaped.end(), '_', ' '); 1641a170f275SEd Tanous output.emplace_back("Name", escaped); 164273df0db0SJames Feist 164373df0db0SJames Feist std::string chassis; 164473df0db0SJames Feist CreatePIDRet ret = createPidInterface( 16459e9b6049SEd Tanous response, type, name, value, path, managedObj, 16469e9b6049SEd Tanous createNewObject, output, chassis, currentProfile); 164773df0db0SJames Feist if (ret == CreatePIDRet::fail) 164873df0db0SJames Feist { 164973df0db0SJames Feist return; 165073df0db0SJames Feist } 16513174e4dfSEd Tanous if (ret == CreatePIDRet::del) 165273df0db0SJames Feist { 165373df0db0SJames Feist continue; 165473df0db0SJames Feist } 165573df0db0SJames Feist 165673df0db0SJames Feist if (!createNewObject) 165773df0db0SJames Feist { 165873df0db0SJames Feist for (const auto& property : output) 165973df0db0SJames Feist { 16607a696974SPotin Lai crow::connections::systemBus->async_method_call( 166173df0db0SJames Feist [response, 166273df0db0SJames Feist propertyName{std::string(property.first)}]( 16635e7e2dc5SEd Tanous const boost::system::error_code& ec) { 166473df0db0SJames Feist if (ec) 166573df0db0SJames Feist { 166662598e31SEd Tanous BMCWEB_LOG_ERROR("Error patching {}: {}", 166762598e31SEd Tanous propertyName, ec); 166873df0db0SJames Feist messages::internalError(response->res); 166973df0db0SJames Feist return; 167073df0db0SJames Feist } 167173df0db0SJames Feist messages::success(response->res); 16727a696974SPotin Lai }, 16737a696974SPotin Lai "xyz.openbmc_project.EntityManager", path, 16747a696974SPotin Lai "org.freedesktop.DBus.Properties", "Set", iface, 16757a696974SPotin Lai property.first, property.second); 167673df0db0SJames Feist } 167773df0db0SJames Feist } 167873df0db0SJames Feist else 167973df0db0SJames Feist { 168073df0db0SJames Feist if (chassis.empty()) 168173df0db0SJames Feist { 168262598e31SEd Tanous BMCWEB_LOG_ERROR("Failed to get chassis from config"); 1683ace85d60SEd Tanous messages::internalError(response->res); 168473df0db0SJames Feist return; 168573df0db0SJames Feist } 168673df0db0SJames Feist 168773df0db0SJames Feist bool foundChassis = false; 168873df0db0SJames Feist for (const auto& obj : managedObj) 168973df0db0SJames Feist { 169091f75cafSEd Tanous if (obj.first.filename() == chassis) 169173df0db0SJames Feist { 169273df0db0SJames Feist chassis = obj.first.str; 169373df0db0SJames Feist foundChassis = true; 169473df0db0SJames Feist break; 169573df0db0SJames Feist } 169673df0db0SJames Feist } 169773df0db0SJames Feist if (!foundChassis) 169873df0db0SJames Feist { 169962598e31SEd Tanous BMCWEB_LOG_ERROR("Failed to find chassis on dbus"); 170073df0db0SJames Feist messages::resourceMissingAtURI( 1701ace85d60SEd Tanous response->res, 1702ef4c65b7SEd Tanous boost::urls::format("/redfish/v1/Chassis/{}", 1703ef4c65b7SEd Tanous chassis)); 170473df0db0SJames Feist return; 170573df0db0SJames Feist } 170673df0db0SJames Feist 170773df0db0SJames Feist crow::connections::systemBus->async_method_call( 17085e7e2dc5SEd Tanous [response](const boost::system::error_code& ec) { 170973df0db0SJames Feist if (ec) 171073df0db0SJames Feist { 1711bd79bce8SPatrick Williams BMCWEB_LOG_ERROR("Error Adding Pid Object {}", 1712bd79bce8SPatrick Williams ec); 171373df0db0SJames Feist messages::internalError(response->res); 171473df0db0SJames Feist return; 171573df0db0SJames Feist } 171673df0db0SJames Feist messages::success(response->res); 171773df0db0SJames Feist }, 171873df0db0SJames Feist "xyz.openbmc_project.EntityManager", chassis, 171973df0db0SJames Feist "xyz.openbmc_project.AddObject", "AddObject", output); 172073df0db0SJames Feist } 172173df0db0SJames Feist } 172273df0db0SJames Feist } 172373df0db0SJames Feist } 172424b2fe81SEd Tanous 172524b2fe81SEd Tanous ~SetPIDValues() 172624b2fe81SEd Tanous { 172724b2fe81SEd Tanous try 172824b2fe81SEd Tanous { 172924b2fe81SEd Tanous pidSetDone(); 173024b2fe81SEd Tanous } 173124b2fe81SEd Tanous catch (...) 173224b2fe81SEd Tanous { 173362598e31SEd Tanous BMCWEB_LOG_CRITICAL("pidSetDone threw exception"); 173424b2fe81SEd Tanous } 173524b2fe81SEd Tanous } 173624b2fe81SEd Tanous 17378d1b46d7Szhanghch05 std::shared_ptr<bmcweb::AsyncResp> asyncResp; 17389e9b6049SEd Tanous std::vector<std::pair<std::string, std::optional<nlohmann::json::object_t>>> 173973df0db0SJames Feist configuration; 174073df0db0SJames Feist std::optional<std::string> profile; 174173df0db0SJames Feist dbus::utility::ManagedObjectType managedObj; 174273df0db0SJames Feist std::vector<std::string> supportedProfiles; 174373df0db0SJames Feist std::string currentProfile; 174473df0db0SJames Feist std::string profileConnection; 174573df0db0SJames Feist std::string profilePath; 174614b0b8d5SJames Feist size_t objectCount = 0; 174773df0db0SJames Feist }; 174873df0db0SJames Feist 1749071d8fdfSSunnySrivastava1984 /** 1750071d8fdfSSunnySrivastava1984 * @brief Retrieves BMC manager location data over DBus 1751071d8fdfSSunnySrivastava1984 * 1752ac106bf6SEd Tanous * @param[in] asyncResp Shared pointer for completing asynchronous calls 1753071d8fdfSSunnySrivastava1984 * @param[in] connectionName - service name 1754071d8fdfSSunnySrivastava1984 * @param[in] path - object path 1755071d8fdfSSunnySrivastava1984 * @return none 1756071d8fdfSSunnySrivastava1984 */ 1757ac106bf6SEd Tanous inline void getLocation(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1758071d8fdfSSunnySrivastava1984 const std::string& connectionName, 1759071d8fdfSSunnySrivastava1984 const std::string& path) 1760071d8fdfSSunnySrivastava1984 { 176162598e31SEd Tanous BMCWEB_LOG_DEBUG("Get BMC manager Location data."); 1762071d8fdfSSunnySrivastava1984 17631e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 17641e1e598dSJonathan Doman *crow::connections::systemBus, connectionName, path, 17651e1e598dSJonathan Doman "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode", 1766ac106bf6SEd Tanous [asyncResp](const boost::system::error_code& ec, 17671e1e598dSJonathan Doman const std::string& property) { 1768071d8fdfSSunnySrivastava1984 if (ec) 1769071d8fdfSSunnySrivastava1984 { 177062598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error for " 177162598e31SEd Tanous "Location"); 1772ac106bf6SEd Tanous messages::internalError(asyncResp->res); 1773071d8fdfSSunnySrivastava1984 return; 1774071d8fdfSSunnySrivastava1984 } 1775071d8fdfSSunnySrivastava1984 1776bd79bce8SPatrick Williams asyncResp->res 1777bd79bce8SPatrick Williams .jsonValue["Location"]["PartLocation"]["ServiceLabel"] = 17781e1e598dSJonathan Doman property; 17791e1e598dSJonathan Doman }); 1780071d8fdfSSunnySrivastava1984 } 17817e860f15SJohn Edward Broadbent // avoid name collision systems.hpp 17827e860f15SJohn Edward Broadbent inline void 1783ac106bf6SEd Tanous managerGetLastResetTime(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 17844bf2b033SGunnar Mills { 178562598e31SEd Tanous BMCWEB_LOG_DEBUG("Getting Manager Last Reset Time"); 17864bf2b033SGunnar Mills 17871e1e598dSJonathan Doman sdbusplus::asio::getProperty<uint64_t>( 17881e1e598dSJonathan Doman *crow::connections::systemBus, "xyz.openbmc_project.State.BMC", 17891e1e598dSJonathan Doman "/xyz/openbmc_project/state/bmc0", "xyz.openbmc_project.State.BMC", 17901e1e598dSJonathan Doman "LastRebootTime", 1791ac106bf6SEd Tanous [asyncResp](const boost::system::error_code& ec, 17921e1e598dSJonathan Doman const uint64_t lastResetTime) { 17934bf2b033SGunnar Mills if (ec) 17944bf2b033SGunnar Mills { 179562598e31SEd Tanous BMCWEB_LOG_DEBUG("D-BUS response error {}", ec); 17964bf2b033SGunnar Mills return; 17974bf2b033SGunnar Mills } 17984bf2b033SGunnar Mills 17994bf2b033SGunnar Mills // LastRebootTime is epoch time, in milliseconds 18004bf2b033SGunnar Mills // https://github.com/openbmc/phosphor-dbus-interfaces/blob/7f9a128eb9296e926422ddc312c148b625890bb6/xyz/openbmc_project/State/BMC.interface.yaml#L19 18011e1e598dSJonathan Doman uint64_t lastResetTimeStamp = lastResetTime / 1000; 18024bf2b033SGunnar Mills 18034bf2b033SGunnar Mills // Convert to ISO 8601 standard 1804ac106bf6SEd Tanous asyncResp->res.jsonValue["LastResetTime"] = 18052b82937eSEd Tanous redfish::time_utils::getDateTimeUint(lastResetTimeStamp); 18061e1e598dSJonathan Doman }); 18074bf2b033SGunnar Mills } 18084bf2b033SGunnar Mills 18094bfefa74SGunnar Mills /** 18104bfefa74SGunnar Mills * @brief Set the running firmware image 18114bfefa74SGunnar Mills * 1812ac106bf6SEd Tanous * @param[i,o] asyncResp - Async response object 18134bfefa74SGunnar Mills * @param[i] runningFirmwareTarget - Image to make the running image 18144bfefa74SGunnar Mills * 18154bfefa74SGunnar Mills * @return void 18164bfefa74SGunnar Mills */ 18177e860f15SJohn Edward Broadbent inline void 1818ac106bf6SEd Tanous setActiveFirmwareImage(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1819f23b7296SEd Tanous const std::string& runningFirmwareTarget) 18204bfefa74SGunnar Mills { 18214bfefa74SGunnar Mills // Get the Id from /redfish/v1/UpdateService/FirmwareInventory/<Id> 1822f23b7296SEd Tanous std::string::size_type idPos = runningFirmwareTarget.rfind('/'); 18234bfefa74SGunnar Mills if (idPos == std::string::npos) 18244bfefa74SGunnar Mills { 1825ac106bf6SEd Tanous messages::propertyValueNotInList(asyncResp->res, runningFirmwareTarget, 18264bfefa74SGunnar Mills "@odata.id"); 182762598e31SEd Tanous BMCWEB_LOG_DEBUG("Can't parse firmware ID!"); 18284bfefa74SGunnar Mills return; 18294bfefa74SGunnar Mills } 18304bfefa74SGunnar Mills idPos++; 18314bfefa74SGunnar Mills if (idPos >= runningFirmwareTarget.size()) 18324bfefa74SGunnar Mills { 1833ac106bf6SEd Tanous messages::propertyValueNotInList(asyncResp->res, runningFirmwareTarget, 18344bfefa74SGunnar Mills "@odata.id"); 183562598e31SEd Tanous BMCWEB_LOG_DEBUG("Invalid firmware ID."); 18364bfefa74SGunnar Mills return; 18374bfefa74SGunnar Mills } 18384bfefa74SGunnar Mills std::string firmwareId = runningFirmwareTarget.substr(idPos); 18394bfefa74SGunnar Mills 18404bfefa74SGunnar Mills // Make sure the image is valid before setting priority 18415eb468daSGeorge Liu sdbusplus::message::object_path objPath("/xyz/openbmc_project/software"); 18425eb468daSGeorge Liu dbus::utility::getManagedObjects( 18435eb468daSGeorge Liu "xyz.openbmc_project.Software.BMC.Updater", objPath, 18445eb468daSGeorge Liu [asyncResp, firmwareId, runningFirmwareTarget]( 18455eb468daSGeorge Liu const boost::system::error_code& ec, 18465eb468daSGeorge Liu const dbus::utility::ManagedObjectType& subtree) { 18474bfefa74SGunnar Mills if (ec) 18484bfefa74SGunnar Mills { 184962598e31SEd Tanous BMCWEB_LOG_DEBUG("D-Bus response error getting objects."); 1850ac106bf6SEd Tanous messages::internalError(asyncResp->res); 18514bfefa74SGunnar Mills return; 18524bfefa74SGunnar Mills } 18534bfefa74SGunnar Mills 185426f6976fSEd Tanous if (subtree.empty()) 18554bfefa74SGunnar Mills { 185662598e31SEd Tanous BMCWEB_LOG_DEBUG("Can't find image!"); 1857ac106bf6SEd Tanous messages::internalError(asyncResp->res); 18584bfefa74SGunnar Mills return; 18594bfefa74SGunnar Mills } 18604bfefa74SGunnar Mills 18614bfefa74SGunnar Mills bool foundImage = false; 186202cad96eSEd Tanous for (const auto& object : subtree) 18634bfefa74SGunnar Mills { 18644bfefa74SGunnar Mills const std::string& path = 18654bfefa74SGunnar Mills static_cast<const std::string&>(object.first); 1866f23b7296SEd Tanous std::size_t idPos2 = path.rfind('/'); 18674bfefa74SGunnar Mills 18684bfefa74SGunnar Mills if (idPos2 == std::string::npos) 18694bfefa74SGunnar Mills { 18704bfefa74SGunnar Mills continue; 18714bfefa74SGunnar Mills } 18724bfefa74SGunnar Mills 18734bfefa74SGunnar Mills idPos2++; 18744bfefa74SGunnar Mills if (idPos2 >= path.size()) 18754bfefa74SGunnar Mills { 18764bfefa74SGunnar Mills continue; 18774bfefa74SGunnar Mills } 18784bfefa74SGunnar Mills 18794bfefa74SGunnar Mills if (path.substr(idPos2) == firmwareId) 18804bfefa74SGunnar Mills { 18814bfefa74SGunnar Mills foundImage = true; 18824bfefa74SGunnar Mills break; 18834bfefa74SGunnar Mills } 18844bfefa74SGunnar Mills } 18854bfefa74SGunnar Mills 18864bfefa74SGunnar Mills if (!foundImage) 18874bfefa74SGunnar Mills { 1888ac106bf6SEd Tanous messages::propertyValueNotInList( 1889ac106bf6SEd Tanous asyncResp->res, runningFirmwareTarget, "@odata.id"); 189062598e31SEd Tanous BMCWEB_LOG_DEBUG("Invalid firmware ID."); 18914bfefa74SGunnar Mills return; 18924bfefa74SGunnar Mills } 18934bfefa74SGunnar Mills 189462598e31SEd Tanous BMCWEB_LOG_DEBUG("Setting firmware version {} to priority 0.", 189562598e31SEd Tanous firmwareId); 18964bfefa74SGunnar Mills 18974bfefa74SGunnar Mills // Only support Immediate 18984bfefa74SGunnar Mills // An addition could be a Redfish Setting like 18994bfefa74SGunnar Mills // ActiveSoftwareImageApplyTime and support OnReset 19009ae226faSGeorge Liu sdbusplus::asio::setProperty( 19019ae226faSGeorge Liu *crow::connections::systemBus, 19029ae226faSGeorge Liu "xyz.openbmc_project.Software.BMC.Updater", 19039ae226faSGeorge Liu "/xyz/openbmc_project/software/" + firmwareId, 19049ae226faSGeorge Liu "xyz.openbmc_project.Software.RedundancyPriority", "Priority", 19059ae226faSGeorge Liu static_cast<uint8_t>(0), 1906ac106bf6SEd Tanous [asyncResp](const boost::system::error_code& ec2) { 19078a592810SEd Tanous if (ec2) 19084bfefa74SGunnar Mills { 190962598e31SEd Tanous BMCWEB_LOG_DEBUG("D-Bus response error setting."); 1910ac106bf6SEd Tanous messages::internalError(asyncResp->res); 19114bfefa74SGunnar Mills return; 19124bfefa74SGunnar Mills } 1913ac106bf6SEd Tanous doBMCGracefulRestart(asyncResp); 19149ae226faSGeorge Liu }); 19155eb468daSGeorge Liu }); 19164bfefa74SGunnar Mills } 19174bfefa74SGunnar Mills 1918bd79bce8SPatrick Williams inline void afterSetDateTime( 1919bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1920bd79bce8SPatrick Williams const boost::system::error_code& ec, const sdbusplus::message_t& msg) 1921c51afd54SEd Tanous { 1922c51afd54SEd Tanous if (ec) 1923c51afd54SEd Tanous { 1924c51afd54SEd Tanous BMCWEB_LOG_DEBUG("Failed to set elapsed time. DBUS response error {}", 1925c51afd54SEd Tanous ec); 1926c51afd54SEd Tanous const sd_bus_error* dbusError = msg.get_error(); 1927c51afd54SEd Tanous if (dbusError != nullptr) 1928c51afd54SEd Tanous { 1929c51afd54SEd Tanous std::string_view errorName(dbusError->name); 1930c51afd54SEd Tanous if (errorName == 1931c51afd54SEd Tanous "org.freedesktop.timedate1.AutomaticTimeSyncEnabled") 1932c51afd54SEd Tanous { 1933c51afd54SEd Tanous BMCWEB_LOG_DEBUG("Setting conflict"); 1934c51afd54SEd Tanous messages::propertyValueConflict( 1935c51afd54SEd Tanous asyncResp->res, "DateTime", 1936c51afd54SEd Tanous "Managers/NetworkProtocol/NTPProcotolEnabled"); 1937c51afd54SEd Tanous return; 1938c51afd54SEd Tanous } 1939c51afd54SEd Tanous } 1940c51afd54SEd Tanous messages::internalError(asyncResp->res); 1941c51afd54SEd Tanous return; 1942c51afd54SEd Tanous } 1943c51afd54SEd Tanous asyncResp->res.result(boost::beast::http::status::no_content); 1944c51afd54SEd Tanous } 1945c51afd54SEd Tanous 1946c51afd54SEd Tanous inline void setDateTime(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1947c51afd54SEd Tanous const std::string& datetime) 1948af5d6058SSantosh Puranik { 194962598e31SEd Tanous BMCWEB_LOG_DEBUG("Set date time: {}", datetime); 1950af5d6058SSantosh Puranik 1951c2e32007SEd Tanous std::optional<redfish::time_utils::usSinceEpoch> us = 1952c2e32007SEd Tanous redfish::time_utils::dateStringToEpoch(datetime); 1953c2e32007SEd Tanous if (!us) 1954af5d6058SSantosh Puranik { 1955ac106bf6SEd Tanous messages::propertyValueFormatError(asyncResp->res, datetime, 1956ac106bf6SEd Tanous "DateTime"); 1957c2e32007SEd Tanous return; 1958c2e32007SEd Tanous } 1959c51afd54SEd Tanous // Set the absolute datetime 1960c51afd54SEd Tanous bool relative = false; 1961c51afd54SEd Tanous bool interactive = false; 1962c51afd54SEd Tanous crow::connections::systemBus->async_method_call( 1963c51afd54SEd Tanous [asyncResp](const boost::system::error_code& ec, 1964c51afd54SEd Tanous const sdbusplus::message_t& msg) { 1965c51afd54SEd Tanous afterSetDateTime(asyncResp, ec, msg); 1966c51afd54SEd Tanous }, 1967c51afd54SEd Tanous "org.freedesktop.timedate1", "/org/freedesktop/timedate1", 1968c51afd54SEd Tanous "org.freedesktop.timedate1", "SetTime", us->count(), relative, 1969c51afd54SEd Tanous interactive); 197083ff9ab6SJames Feist } 19719c310685SBorawski.Lukasz 197275815e5cSEd Tanous inline void 197375815e5cSEd Tanous checkForQuiesced(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 197475815e5cSEd Tanous { 197575815e5cSEd Tanous sdbusplus::asio::getProperty<std::string>( 197675815e5cSEd Tanous *crow::connections::systemBus, "org.freedesktop.systemd1", 197775815e5cSEd Tanous "/org/freedesktop/systemd1/unit/obmc-bmc-service-quiesce@0.target", 197875815e5cSEd Tanous "org.freedesktop.systemd1.Unit", "ActiveState", 197975815e5cSEd Tanous [asyncResp](const boost::system::error_code& ec, 198075815e5cSEd Tanous const std::string& val) { 198175815e5cSEd Tanous if (!ec) 198275815e5cSEd Tanous { 198375815e5cSEd Tanous if (val == "active") 198475815e5cSEd Tanous { 1985539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["Health"] = 1986539d8c6bSEd Tanous resource::Health::Critical; 1987539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = 1988539d8c6bSEd Tanous resource::State::Quiesced; 198975815e5cSEd Tanous return; 199075815e5cSEd Tanous } 199175815e5cSEd Tanous } 1992539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK; 1993bd79bce8SPatrick Williams asyncResp->res.jsonValue["Status"]["State"] = 1994bd79bce8SPatrick Williams resource::State::Enabled; 199575815e5cSEd Tanous }); 199675815e5cSEd Tanous } 199775815e5cSEd Tanous 19987e860f15SJohn Edward Broadbent inline void requestRoutesManager(App& app) 19997e860f15SJohn Edward Broadbent { 20007e860f15SJohn Edward Broadbent std::string uuid = persistent_data::getConfig().systemUuid; 20019c310685SBorawski.Lukasz 2002253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/") 2003ed398213SEd Tanous .privileges(redfish::privileges::getManager) 2004bd79bce8SPatrick Williams .methods( 2005bd79bce8SPatrick Williams boost::beast::http::verb:: 2006bd79bce8SPatrick Williams get)([&app, 2007bd79bce8SPatrick Williams uuid](const crow::Request& req, 2008253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2009253f11b8SEd Tanous const std::string& managerId) { 20103ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 201145ca1b86SEd Tanous { 201245ca1b86SEd Tanous return; 201345ca1b86SEd Tanous } 2014253f11b8SEd Tanous 2015253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2016253f11b8SEd Tanous { 2017bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "Manager", 2018bd79bce8SPatrick Williams managerId); 2019253f11b8SEd Tanous return; 2020253f11b8SEd Tanous } 2021253f11b8SEd Tanous 2022253f11b8SEd Tanous asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 2023253f11b8SEd Tanous "/redfish/v1/Managers/{}", BMCWEB_REDFISH_MANAGER_URI_NAME); 2024bd79bce8SPatrick Williams asyncResp->res.jsonValue["@odata.type"] = 2025bd79bce8SPatrick Williams "#Manager.v1_14_0.Manager"; 2026253f11b8SEd Tanous asyncResp->res.jsonValue["Id"] = BMCWEB_REDFISH_MANAGER_URI_NAME; 20277e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Name"] = "OpenBmc Manager"; 20287e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Description"] = 20297e860f15SJohn Edward Broadbent "Baseboard Management Controller"; 2030539d8c6bSEd Tanous asyncResp->res.jsonValue["PowerState"] = resource::PowerState::On; 20311476687dSEd Tanous 2032539d8c6bSEd Tanous asyncResp->res.jsonValue["ManagerType"] = manager::ManagerType::BMC; 20337e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["UUID"] = systemd_utils::getUuid(); 20347e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["ServiceEntryPointUUID"] = uuid; 2035bd79bce8SPatrick Williams asyncResp->res.jsonValue["Model"] = 2036bd79bce8SPatrick Williams "OpenBmc"; // TODO(ed), get model 20377e860f15SJohn Edward Broadbent 20381476687dSEd Tanous asyncResp->res.jsonValue["LogServices"]["@odata.id"] = 2039253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}/LogServices", 2040253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 20411476687dSEd Tanous asyncResp->res.jsonValue["NetworkProtocol"]["@odata.id"] = 2042253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}/NetworkProtocol", 2043253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 20441476687dSEd Tanous asyncResp->res.jsonValue["EthernetInterfaces"]["@odata.id"] = 2045bd79bce8SPatrick Williams boost::urls::format( 2046bd79bce8SPatrick Williams "/redfish/v1/Managers/{}/EthernetInterfaces", 2047253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 20487e860f15SJohn Edward Broadbent 204925b54dbaSEd Tanous if constexpr (BMCWEB_VM_NBDPROXY) 205036c0f2a3SEd Tanous { 20511476687dSEd Tanous asyncResp->res.jsonValue["VirtualMedia"]["@odata.id"] = 2052253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}/VirtualMedia", 2053253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 205436c0f2a3SEd Tanous } 20557e860f15SJohn Edward Broadbent 20567e860f15SJohn Edward Broadbent // default oem data 20577e860f15SJohn Edward Broadbent nlohmann::json& oem = asyncResp->res.jsonValue["Oem"]; 20587e860f15SJohn Edward Broadbent nlohmann::json& oemOpenbmc = oem["OpenBmc"]; 2059bd79bce8SPatrick Williams oem["@odata.id"] = 2060bd79bce8SPatrick Williams boost::urls::format("/redfish/v1/Managers/{}#/Oem", 2061253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 2062fc1cdd14SEd Tanous oemOpenbmc["@odata.type"] = "#OpenBMCManager.v1_0_0.Manager"; 2063253f11b8SEd Tanous oemOpenbmc["@odata.id"] = 2064253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}#/Oem/OpenBmc", 2065253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 20661476687dSEd Tanous 20671476687dSEd Tanous nlohmann::json::object_t certificates; 2068253f11b8SEd Tanous certificates["@odata.id"] = boost::urls::format( 2069253f11b8SEd Tanous "/redfish/v1/Managers/{}/Truststore/Certificates", 2070253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 20711476687dSEd Tanous oemOpenbmc["Certificates"] = std::move(certificates); 20727e860f15SJohn Edward Broadbent 20737e860f15SJohn Edward Broadbent // Manager.Reset (an action) can be many values, OpenBMC only 20747e860f15SJohn Edward Broadbent // supports BMC reboot. 20757e860f15SJohn Edward Broadbent nlohmann::json& managerReset = 20767e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Actions"]["#Manager.Reset"]; 2077bd79bce8SPatrick Williams managerReset["target"] = boost::urls::format( 2078bd79bce8SPatrick Williams "/redfish/v1/Managers/{}/Actions/Manager.Reset", 2079253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 20807e860f15SJohn Edward Broadbent managerReset["@Redfish.ActionInfo"] = 2081253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}/ResetActionInfo", 2082253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 20837e860f15SJohn Edward Broadbent 20847e860f15SJohn Edward Broadbent // ResetToDefaults (Factory Reset) has values like 20857e860f15SJohn Edward Broadbent // PreserveNetworkAndUsers and PreserveNetwork that aren't supported 20867e860f15SJohn Edward Broadbent // on OpenBMC 20877e860f15SJohn Edward Broadbent nlohmann::json& resetToDefaults = 20887e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Actions"]["#Manager.ResetToDefaults"]; 2089253f11b8SEd Tanous resetToDefaults["target"] = boost::urls::format( 2090253f11b8SEd Tanous "/redfish/v1/Managers/{}/Actions/Manager.ResetToDefaults", 2091253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 2092613dabeaSEd Tanous resetToDefaults["ResetType@Redfish.AllowableValues"] = 2093613dabeaSEd Tanous nlohmann::json::array_t({"ResetAll"}); 20947e860f15SJohn Edward Broadbent 20957c8c4058STejas Patil std::pair<std::string, std::string> redfishDateTimeOffset = 20962b82937eSEd Tanous redfish::time_utils::getDateTimeOffsetNow(); 20977c8c4058STejas Patil 20987c8c4058STejas Patil asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first; 20997c8c4058STejas Patil asyncResp->res.jsonValue["DateTimeLocalOffset"] = 21007c8c4058STejas Patil redfishDateTimeOffset.second; 21017e860f15SJohn Edward Broadbent 21020e8ac5e7SGunnar Mills // TODO (Gunnar): Remove these one day since moved to ComputerSystem 21030e8ac5e7SGunnar Mills // Still used by OCP profiles 21040e8ac5e7SGunnar Mills // https://github.com/opencomputeproject/OCP-Profiles/issues/23 21057e860f15SJohn Edward Broadbent // Fill in SerialConsole info 21067e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["SerialConsole"]["ServiceEnabled"] = true; 2107bd79bce8SPatrick Williams asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] = 2108bd79bce8SPatrick Williams 15; 2109613dabeaSEd Tanous asyncResp->res.jsonValue["SerialConsole"]["ConnectTypesSupported"] = 2110613dabeaSEd Tanous nlohmann::json::array_t({"IPMI", "SSH"}); 211125b54dbaSEd Tanous if constexpr (BMCWEB_KVM) 211225b54dbaSEd Tanous { 21137e860f15SJohn Edward Broadbent // Fill in GraphicalConsole info 211425b54dbaSEd Tanous asyncResp->res.jsonValue["GraphicalConsole"]["ServiceEnabled"] = 211525b54dbaSEd Tanous true; 211625b54dbaSEd Tanous asyncResp->res 211725b54dbaSEd Tanous .jsonValue["GraphicalConsole"]["MaxConcurrentSessions"] = 4; 211825b54dbaSEd Tanous asyncResp->res 211925b54dbaSEd Tanous .jsonValue["GraphicalConsole"]["ConnectTypesSupported"] = 2120613dabeaSEd Tanous nlohmann::json::array_t({"KVMIP"}); 212125b54dbaSEd Tanous } 212225b54dbaSEd Tanous if constexpr (!BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 21237f3e84a1SEd Tanous { 2124bd79bce8SPatrick Williams asyncResp->res 2125bd79bce8SPatrick Williams .jsonValue["Links"]["ManagerForServers@odata.count"] = 1; 21261476687dSEd Tanous 21271476687dSEd Tanous nlohmann::json::array_t managerForServers; 21281476687dSEd Tanous nlohmann::json::object_t manager; 2129bd79bce8SPatrick Williams manager["@odata.id"] = std::format( 2130bd79bce8SPatrick Williams "/redfish/v1/Systems/{}", BMCWEB_REDFISH_SYSTEM_URI_NAME); 2131ad539545SPatrick Williams managerForServers.emplace_back(std::move(manager)); 21321476687dSEd Tanous 21331476687dSEd Tanous asyncResp->res.jsonValue["Links"]["ManagerForServers"] = 21341476687dSEd Tanous std::move(managerForServers); 21357f3e84a1SEd Tanous } 21367e860f15SJohn Edward Broadbent 2137eee0013eSWilly Tu sw_util::populateSoftwareInformation(asyncResp, sw_util::bmcPurpose, 21387e860f15SJohn Edward Broadbent "FirmwareVersion", true); 21397e860f15SJohn Edward Broadbent 21407e860f15SJohn Edward Broadbent managerGetLastResetTime(asyncResp); 21417e860f15SJohn Edward Broadbent 2142a51fc2d2SSui Chen // ManagerDiagnosticData is added for all BMCs. 2143a51fc2d2SSui Chen nlohmann::json& managerDiagnosticData = 2144a51fc2d2SSui Chen asyncResp->res.jsonValue["ManagerDiagnosticData"]; 2145bd79bce8SPatrick Williams managerDiagnosticData["@odata.id"] = boost::urls::format( 2146bd79bce8SPatrick Williams "/redfish/v1/Managers/{}/ManagerDiagnosticData", 2147253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 2148a51fc2d2SSui Chen 214925b54dbaSEd Tanous if constexpr (BMCWEB_REDFISH_OEM_MANAGER_FAN_DATA) 215025b54dbaSEd Tanous { 21517e860f15SJohn Edward Broadbent auto pids = std::make_shared<GetPIDValues>(asyncResp); 21527e860f15SJohn Edward Broadbent pids->run(); 215325b54dbaSEd Tanous } 21547e860f15SJohn Edward Broadbent 2155bd79bce8SPatrick Williams getMainChassisId(asyncResp, [](const std::string& chassisId, 2156bd79bce8SPatrick Williams const std::shared_ptr< 2157bd79bce8SPatrick Williams bmcweb::AsyncResp>& aRsp) { 2158bd79bce8SPatrick Williams aRsp->res.jsonValue["Links"]["ManagerForChassis@odata.count"] = 2159bd79bce8SPatrick Williams 1; 21601476687dSEd Tanous nlohmann::json::array_t managerForChassis; 21618a592810SEd Tanous nlohmann::json::object_t managerObj; 2162ef4c65b7SEd Tanous boost::urls::url chassiUrl = 2163ef4c65b7SEd Tanous boost::urls::format("/redfish/v1/Chassis/{}", chassisId); 2164eddfc437SWilly Tu managerObj["@odata.id"] = chassiUrl; 2165ad539545SPatrick Williams managerForChassis.emplace_back(std::move(managerObj)); 21661476687dSEd Tanous aRsp->res.jsonValue["Links"]["ManagerForChassis"] = 21671476687dSEd Tanous std::move(managerForChassis); 21681476687dSEd Tanous aRsp->res.jsonValue["Links"]["ManagerInChassis"]["@odata.id"] = 2169eddfc437SWilly Tu chassiUrl; 21707e860f15SJohn Edward Broadbent }); 21717e860f15SJohn Edward Broadbent 21721e1e598dSJonathan Doman sdbusplus::asio::getProperty<double>( 21731e1e598dSJonathan Doman *crow::connections::systemBus, "org.freedesktop.systemd1", 2174002d39b4SEd Tanous "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", 2175002d39b4SEd Tanous "Progress", 217675815e5cSEd Tanous [asyncResp](const boost::system::error_code& ec, double val) { 21777e860f15SJohn Edward Broadbent if (ec) 21781abe55efSEd Tanous { 217962598e31SEd Tanous BMCWEB_LOG_ERROR("Error while getting progress"); 21807e860f15SJohn Edward Broadbent messages::internalError(asyncResp->res); 21817e860f15SJohn Edward Broadbent return; 21827e860f15SJohn Edward Broadbent } 21831e1e598dSJonathan Doman if (val < 1.0) 21847e860f15SJohn Edward Broadbent { 2185539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["Health"] = 2186539d8c6bSEd Tanous resource::Health::OK; 2187539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = 2188539d8c6bSEd Tanous resource::State::Starting; 218975815e5cSEd Tanous return; 21907e860f15SJohn Edward Broadbent } 219175815e5cSEd Tanous checkForQuiesced(asyncResp); 21921e1e598dSJonathan Doman }); 21939c310685SBorawski.Lukasz 2194e99073f5SGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 2195e99073f5SGeorge Liu "xyz.openbmc_project.Inventory.Item.Bmc"}; 2196e99073f5SGeorge Liu dbus::utility::getSubTree( 2197e99073f5SGeorge Liu "/xyz/openbmc_project/inventory", 0, interfaces, 21987e860f15SJohn Edward Broadbent [asyncResp]( 2199e99073f5SGeorge Liu const boost::system::error_code& ec, 2200b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreeResponse& subtree) { 22017e860f15SJohn Edward Broadbent if (ec) 22021abe55efSEd Tanous { 2203bd79bce8SPatrick Williams BMCWEB_LOG_DEBUG( 2204bd79bce8SPatrick Williams "D-Bus response error on GetSubTree {}", ec); 22057e860f15SJohn Edward Broadbent return; 22067e860f15SJohn Edward Broadbent } 220726f6976fSEd Tanous if (subtree.empty()) 22087e860f15SJohn Edward Broadbent { 220962598e31SEd Tanous BMCWEB_LOG_DEBUG("Can't find bmc D-Bus object!"); 22107e860f15SJohn Edward Broadbent return; 22117e860f15SJohn Edward Broadbent } 22127e860f15SJohn Edward Broadbent // Assume only 1 bmc D-Bus object 22137e860f15SJohn Edward Broadbent // Throw an error if there is more than 1 22147e860f15SJohn Edward Broadbent if (subtree.size() > 1) 22157e860f15SJohn Edward Broadbent { 221662598e31SEd Tanous BMCWEB_LOG_DEBUG("Found more than 1 bmc D-Bus object!"); 22177e860f15SJohn Edward Broadbent messages::internalError(asyncResp->res); 22187e860f15SJohn Edward Broadbent return; 22197e860f15SJohn Edward Broadbent } 22207e860f15SJohn Edward Broadbent 2221bd79bce8SPatrick Williams if (subtree[0].first.empty() || 2222bd79bce8SPatrick Williams subtree[0].second.size() != 1) 22237e860f15SJohn Edward Broadbent { 222462598e31SEd Tanous BMCWEB_LOG_DEBUG("Error getting bmc D-Bus object!"); 22257e860f15SJohn Edward Broadbent messages::internalError(asyncResp->res); 22267e860f15SJohn Edward Broadbent return; 22277e860f15SJohn Edward Broadbent } 22287e860f15SJohn Edward Broadbent 22297e860f15SJohn Edward Broadbent const std::string& path = subtree[0].first; 2230bd79bce8SPatrick Williams const std::string& connectionName = 2231bd79bce8SPatrick Williams subtree[0].second[0].first; 22327e860f15SJohn Edward Broadbent 2233bd79bce8SPatrick Williams for (const auto& interfaceName : 2234bd79bce8SPatrick Williams subtree[0].second[0].second) 22357e860f15SJohn Edward Broadbent { 22367e860f15SJohn Edward Broadbent if (interfaceName == 22377e860f15SJohn Edward Broadbent "xyz.openbmc_project.Inventory.Decorator.Asset") 22387e860f15SJohn Edward Broadbent { 2239fac6e53bSKrzysztof Grobelny sdbusplus::asio::getAllProperties( 2240bd79bce8SPatrick Williams *crow::connections::systemBus, connectionName, 2241bd79bce8SPatrick Williams path, 2242fac6e53bSKrzysztof Grobelny "xyz.openbmc_project.Inventory.Decorator.Asset", 2243bd79bce8SPatrick Williams [asyncResp]( 2244bd79bce8SPatrick Williams const boost::system::error_code& ec2, 2245b9d36b47SEd Tanous const dbus::utility::DBusPropertiesMap& 22467e860f15SJohn Edward Broadbent propertiesList) { 22478a592810SEd Tanous if (ec2) 22487e860f15SJohn Edward Broadbent { 2249bd79bce8SPatrick Williams BMCWEB_LOG_DEBUG( 2250bd79bce8SPatrick Williams "Can't get bmc asset!"); 22517e860f15SJohn Edward Broadbent return; 22527e860f15SJohn Edward Broadbent } 22537e860f15SJohn Edward Broadbent 2254fac6e53bSKrzysztof Grobelny const std::string* partNumber = nullptr; 2255fac6e53bSKrzysztof Grobelny const std::string* serialNumber = nullptr; 2256fac6e53bSKrzysztof Grobelny const std::string* manufacturer = nullptr; 2257fac6e53bSKrzysztof Grobelny const std::string* model = nullptr; 2258bd79bce8SPatrick Williams const std::string* sparePartNumber = 2259bd79bce8SPatrick Williams nullptr; 2260fac6e53bSKrzysztof Grobelny 2261bd79bce8SPatrick Williams const bool success = 2262bd79bce8SPatrick Williams sdbusplus::unpackPropertiesNoThrow( 2263bd79bce8SPatrick Williams dbus_utils::UnpackErrorPrinter(), 2264bd79bce8SPatrick Williams propertiesList, "PartNumber", 2265bd79bce8SPatrick Williams partNumber, "SerialNumber", 2266bd79bce8SPatrick Williams serialNumber, "Manufacturer", 2267bd79bce8SPatrick Williams manufacturer, "Model", model, 2268bd79bce8SPatrick Williams "SparePartNumber", sparePartNumber); 2269fac6e53bSKrzysztof Grobelny 2270fac6e53bSKrzysztof Grobelny if (!success) 22717e860f15SJohn Edward Broadbent { 2272002d39b4SEd Tanous messages::internalError(asyncResp->res); 22737e860f15SJohn Edward Broadbent return; 22747e860f15SJohn Edward Broadbent } 2275fac6e53bSKrzysztof Grobelny 2276fac6e53bSKrzysztof Grobelny if (partNumber != nullptr) 2277fac6e53bSKrzysztof Grobelny { 2278fac6e53bSKrzysztof Grobelny asyncResp->res.jsonValue["PartNumber"] = 2279fac6e53bSKrzysztof Grobelny *partNumber; 22807e860f15SJohn Edward Broadbent } 2281fac6e53bSKrzysztof Grobelny 2282fac6e53bSKrzysztof Grobelny if (serialNumber != nullptr) 2283fac6e53bSKrzysztof Grobelny { 2284bd79bce8SPatrick Williams asyncResp->res 2285bd79bce8SPatrick Williams .jsonValue["SerialNumber"] = 2286fac6e53bSKrzysztof Grobelny *serialNumber; 22877e860f15SJohn Edward Broadbent } 2288fac6e53bSKrzysztof Grobelny 2289fac6e53bSKrzysztof Grobelny if (manufacturer != nullptr) 2290fac6e53bSKrzysztof Grobelny { 2291bd79bce8SPatrick Williams asyncResp->res 2292bd79bce8SPatrick Williams .jsonValue["Manufacturer"] = 2293fac6e53bSKrzysztof Grobelny *manufacturer; 2294fac6e53bSKrzysztof Grobelny } 2295fac6e53bSKrzysztof Grobelny 2296fac6e53bSKrzysztof Grobelny if (model != nullptr) 2297fac6e53bSKrzysztof Grobelny { 2298bd79bce8SPatrick Williams asyncResp->res.jsonValue["Model"] = 2299bd79bce8SPatrick Williams *model; 2300fac6e53bSKrzysztof Grobelny } 2301fac6e53bSKrzysztof Grobelny 2302fac6e53bSKrzysztof Grobelny if (sparePartNumber != nullptr) 2303fac6e53bSKrzysztof Grobelny { 2304bd79bce8SPatrick Williams asyncResp->res 2305bd79bce8SPatrick Williams .jsonValue["SparePartNumber"] = 2306fac6e53bSKrzysztof Grobelny *sparePartNumber; 2307fac6e53bSKrzysztof Grobelny } 2308fac6e53bSKrzysztof Grobelny }); 23097e860f15SJohn Edward Broadbent } 2310bd79bce8SPatrick Williams else if ( 2311bd79bce8SPatrick Williams interfaceName == 23120fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.LocationCode") 23137e860f15SJohn Edward Broadbent { 23147e860f15SJohn Edward Broadbent getLocation(asyncResp, connectionName, path); 23157e860f15SJohn Edward Broadbent } 23167e860f15SJohn Edward Broadbent } 2317e99073f5SGeorge Liu }); 23187e860f15SJohn Edward Broadbent }); 23197e860f15SJohn Edward Broadbent 2320253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/") 2321ed398213SEd Tanous .privileges(redfish::privileges::patchManager) 232245ca1b86SEd Tanous .methods(boost::beast::http::verb::patch)( 232345ca1b86SEd Tanous [&app](const crow::Request& req, 2324253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2325253f11b8SEd Tanous const std::string& managerId) { 23263ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 232745ca1b86SEd Tanous { 232845ca1b86SEd Tanous return; 232945ca1b86SEd Tanous } 2330253f11b8SEd Tanous 2331253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2332253f11b8SEd Tanous { 2333bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "Manager", 2334bd79bce8SPatrick Williams managerId); 2335253f11b8SEd Tanous return; 2336253f11b8SEd Tanous } 2337253f11b8SEd Tanous 23389e9b6049SEd Tanous std::optional<std::string> activeSoftwareImageOdataId; 23397e860f15SJohn Edward Broadbent std::optional<std::string> datetime; 23409e9b6049SEd Tanous std::optional<nlohmann::json::object_t> pidControllers; 23419e9b6049SEd Tanous std::optional<nlohmann::json::object_t> fanControllers; 23429e9b6049SEd Tanous std::optional<nlohmann::json::object_t> fanZones; 23439e9b6049SEd Tanous std::optional<nlohmann::json::object_t> stepwiseControllers; 23449e9b6049SEd Tanous std::optional<std::string> profile; 23457e860f15SJohn Edward Broadbent 2346*afc474aeSMyung Bae if (!json_util::readJsonPatch( // 2347*afc474aeSMyung Bae req, asyncResp->res, // 2348*afc474aeSMyung Bae "DateTime", datetime, // 2349*afc474aeSMyung Bae "Links/ActiveSoftwareImage/@odata.id", 2350*afc474aeSMyung Bae activeSoftwareImageOdataId, // 2351*afc474aeSMyung Bae "Oem/OpenBmc/Fan/FanControllers", fanControllers, // 2352*afc474aeSMyung Bae "Oem/OpenBmc/Fan/FanZones", fanZones, // 2353*afc474aeSMyung Bae "Oem/OpenBmc/Fan/PidControllers", pidControllers, // 2354*afc474aeSMyung Bae "Oem/OpenBmc/Fan/Profile", profile, // 2355*afc474aeSMyung Bae "Oem/OpenBmc/Fan/StepwiseControllers", 2356*afc474aeSMyung Bae stepwiseControllers // 23579e9b6049SEd Tanous )) 23587e860f15SJohn Edward Broadbent { 23597e860f15SJohn Edward Broadbent return; 23607e860f15SJohn Edward Broadbent } 23617e860f15SJohn Edward Broadbent 23629e9b6049SEd Tanous if (pidControllers || fanControllers || fanZones || 23639e9b6049SEd Tanous stepwiseControllers || profile) 23647e860f15SJohn Edward Broadbent { 236525b54dbaSEd Tanous if constexpr (BMCWEB_REDFISH_OEM_MANAGER_FAN_DATA) 236625b54dbaSEd Tanous { 2367bd79bce8SPatrick Williams std::vector< 2368bd79bce8SPatrick Williams std::pair<std::string, 236925b54dbaSEd Tanous std::optional<nlohmann::json::object_t>>> 23709e9b6049SEd Tanous configuration; 23719e9b6049SEd Tanous if (pidControllers) 23727e860f15SJohn Edward Broadbent { 2373bd79bce8SPatrick Williams configuration.emplace_back( 2374bd79bce8SPatrick Williams "PidControllers", std::move(pidControllers)); 23757e860f15SJohn Edward Broadbent } 23769e9b6049SEd Tanous if (fanControllers) 23777e860f15SJohn Edward Broadbent { 2378bd79bce8SPatrick Williams configuration.emplace_back( 2379bd79bce8SPatrick Williams "FanControllers", std::move(fanControllers)); 23807e860f15SJohn Edward Broadbent } 23819e9b6049SEd Tanous if (fanZones) 23827e860f15SJohn Edward Broadbent { 2383bd79bce8SPatrick Williams configuration.emplace_back("FanZones", 2384bd79bce8SPatrick Williams std::move(fanZones)); 23859e9b6049SEd Tanous } 23869e9b6049SEd Tanous if (stepwiseControllers) 23879e9b6049SEd Tanous { 2388bd79bce8SPatrick Williams configuration.emplace_back( 2389bd79bce8SPatrick Williams "StepwiseControllers", 23909e9b6049SEd Tanous std::move(stepwiseControllers)); 23919e9b6049SEd Tanous } 23929e9b6049SEd Tanous auto pid = std::make_shared<SetPIDValues>( 23939e9b6049SEd Tanous asyncResp, std::move(configuration), profile); 23947e860f15SJohn Edward Broadbent pid->run(); 239525b54dbaSEd Tanous } 239625b54dbaSEd Tanous else 239725b54dbaSEd Tanous { 239854dce7f5SGunnar Mills messages::propertyUnknown(asyncResp->res, "Oem"); 239954dce7f5SGunnar Mills return; 240025b54dbaSEd Tanous } 24017e860f15SJohn Edward Broadbent } 24029e9b6049SEd Tanous 24039e9b6049SEd Tanous if (activeSoftwareImageOdataId) 24047e860f15SJohn Edward Broadbent { 2405bd79bce8SPatrick Williams setActiveFirmwareImage(asyncResp, 2406bd79bce8SPatrick Williams *activeSoftwareImageOdataId); 24077e860f15SJohn Edward Broadbent } 24087e860f15SJohn Edward Broadbent 24097e860f15SJohn Edward Broadbent if (datetime) 24107e860f15SJohn Edward Broadbent { 2411c51afd54SEd Tanous setDateTime(asyncResp, *datetime); 24127e860f15SJohn Edward Broadbent } 24137e860f15SJohn Edward Broadbent }); 24147e860f15SJohn Edward Broadbent } 24157e860f15SJohn Edward Broadbent 24167e860f15SJohn Edward Broadbent inline void requestRoutesManagerCollection(App& app) 24177e860f15SJohn Edward Broadbent { 24187e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Managers/") 2419ed398213SEd Tanous .privileges(redfish::privileges::getManagerCollection) 24207e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 242145ca1b86SEd Tanous [&app](const crow::Request& req, 24227e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 24233ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 242445ca1b86SEd Tanous { 242545ca1b86SEd Tanous return; 242645ca1b86SEd Tanous } 242783ff9ab6SJames Feist // Collections don't include the static data added by SubRoute 242883ff9ab6SJames Feist // because it has a duplicate entry for members 24298d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Managers"; 24308d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 24318d1b46d7Szhanghch05 "#ManagerCollection.ManagerCollection"; 24328d1b46d7Szhanghch05 asyncResp->res.jsonValue["Name"] = "Manager Collection"; 24338d1b46d7Szhanghch05 asyncResp->res.jsonValue["Members@odata.count"] = 1; 24341476687dSEd Tanous nlohmann::json::array_t members; 24351476687dSEd Tanous nlohmann::json& bmc = members.emplace_back(); 2436bd79bce8SPatrick Williams bmc["@odata.id"] = boost::urls::format( 2437bd79bce8SPatrick Williams "/redfish/v1/Managers/{}", BMCWEB_REDFISH_MANAGER_URI_NAME); 24381476687dSEd Tanous asyncResp->res.jsonValue["Members"] = std::move(members); 24397e860f15SJohn Edward Broadbent }); 24409c310685SBorawski.Lukasz } 24419c310685SBorawski.Lukasz } // namespace redfish 2442