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 53*d27c31e9SJagpal Singh Gill inline std::string getBMCUpdateServiceName() 54*d27c31e9SJagpal Singh Gill { 55*d27c31e9SJagpal Singh Gill if constexpr (BMCWEB_REDFISH_UPDATESERVICE_USE_DBUS) 56*d27c31e9SJagpal Singh Gill { 57*d27c31e9SJagpal Singh Gill return "xyz.openbmc_project.Software.Manager"; 58*d27c31e9SJagpal Singh Gill } 59*d27c31e9SJagpal Singh Gill return "xyz.openbmc_project.Software.BMC.Updater"; 60*d27c31e9SJagpal Singh Gill } 61*d27c31e9SJagpal Singh Gill 62*d27c31e9SJagpal Singh Gill inline std::string getBMCUpdateServicePath() 63*d27c31e9SJagpal Singh Gill { 64*d27c31e9SJagpal Singh Gill if constexpr (BMCWEB_REDFISH_UPDATESERVICE_USE_DBUS) 65*d27c31e9SJagpal Singh Gill { 66*d27c31e9SJagpal Singh Gill return "/xyz/openbmc_project/software/bmc"; 67*d27c31e9SJagpal Singh Gill } 68*d27c31e9SJagpal Singh Gill return "/xyz/openbmc_project/software"; 69*d27c31e9SJagpal Singh Gill } 70*d27c31e9SJagpal Singh Gill 71ed5befbdSJennifer Lee /** 722a5c4407SGunnar Mills * Function reboots the BMC. 732a5c4407SGunnar Mills * 742a5c4407SGunnar Mills * @param[in] asyncResp - Shared pointer for completing asynchronous calls 75ed5befbdSJennifer Lee */ 768d1b46d7Szhanghch05 inline void 778d1b46d7Szhanghch05 doBMCGracefulRestart(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 78ed5befbdSJennifer Lee { 79ed5befbdSJennifer Lee const char* processName = "xyz.openbmc_project.State.BMC"; 80ed5befbdSJennifer Lee const char* objectPath = "/xyz/openbmc_project/state/bmc0"; 81ed5befbdSJennifer Lee const char* interfaceName = "xyz.openbmc_project.State.BMC"; 82ed5befbdSJennifer Lee const std::string& propertyValue = 83ed5befbdSJennifer Lee "xyz.openbmc_project.State.BMC.Transition.Reboot"; 84ed5befbdSJennifer Lee const char* destProperty = "RequestedBMCTransition"; 85ed5befbdSJennifer Lee 86ed5befbdSJennifer Lee // Create the D-Bus variant for D-Bus call. 879ae226faSGeorge Liu sdbusplus::asio::setProperty( 889ae226faSGeorge Liu *crow::connections::systemBus, processName, objectPath, interfaceName, 899ae226faSGeorge Liu destProperty, propertyValue, 905e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 91ed5befbdSJennifer Lee // Use "Set" method to set the property value. 92ed5befbdSJennifer Lee if (ec) 93ed5befbdSJennifer Lee { 9462598e31SEd Tanous BMCWEB_LOG_DEBUG("[Set] Bad D-Bus request error: {}", ec); 95ed5befbdSJennifer Lee messages::internalError(asyncResp->res); 96ed5befbdSJennifer Lee return; 97ed5befbdSJennifer Lee } 98ed5befbdSJennifer Lee 99ed5befbdSJennifer Lee messages::success(asyncResp->res); 1009ae226faSGeorge Liu }); 101ed5befbdSJennifer Lee } 1022a5c4407SGunnar Mills 1038d1b46d7Szhanghch05 inline void 1048d1b46d7Szhanghch05 doBMCForceRestart(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 105f92af389SJayaprakash Mutyala { 106f92af389SJayaprakash Mutyala const char* processName = "xyz.openbmc_project.State.BMC"; 107f92af389SJayaprakash Mutyala const char* objectPath = "/xyz/openbmc_project/state/bmc0"; 108f92af389SJayaprakash Mutyala const char* interfaceName = "xyz.openbmc_project.State.BMC"; 109f92af389SJayaprakash Mutyala const std::string& propertyValue = 110f92af389SJayaprakash Mutyala "xyz.openbmc_project.State.BMC.Transition.HardReboot"; 111f92af389SJayaprakash Mutyala const char* destProperty = "RequestedBMCTransition"; 112f92af389SJayaprakash Mutyala 113f92af389SJayaprakash Mutyala // Create the D-Bus variant for D-Bus call. 1149ae226faSGeorge Liu sdbusplus::asio::setProperty( 1159ae226faSGeorge Liu *crow::connections::systemBus, processName, objectPath, interfaceName, 1169ae226faSGeorge Liu destProperty, propertyValue, 1175e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 118f92af389SJayaprakash Mutyala // Use "Set" method to set the property value. 119f92af389SJayaprakash Mutyala if (ec) 120f92af389SJayaprakash Mutyala { 12162598e31SEd Tanous BMCWEB_LOG_DEBUG("[Set] Bad D-Bus request error: {}", ec); 122f92af389SJayaprakash Mutyala messages::internalError(asyncResp->res); 123f92af389SJayaprakash Mutyala return; 124f92af389SJayaprakash Mutyala } 125f92af389SJayaprakash Mutyala 126f92af389SJayaprakash Mutyala messages::success(asyncResp->res); 1279ae226faSGeorge Liu }); 128f92af389SJayaprakash Mutyala } 129f92af389SJayaprakash Mutyala 1302a5c4407SGunnar Mills /** 1312a5c4407SGunnar Mills * ManagerResetAction class supports the POST method for the Reset (reboot) 1322a5c4407SGunnar Mills * action. 1332a5c4407SGunnar Mills */ 1347e860f15SJohn Edward Broadbent inline void requestRoutesManagerResetAction(App& app) 1352a5c4407SGunnar Mills { 1362a5c4407SGunnar Mills /** 1372a5c4407SGunnar Mills * Function handles POST method request. 1382a5c4407SGunnar Mills * Analyzes POST body before sending Reset (Reboot) request data to D-Bus. 139f92af389SJayaprakash Mutyala * OpenBMC supports ResetType "GracefulRestart" and "ForceRestart". 1402a5c4407SGunnar Mills */ 1417e860f15SJohn Edward Broadbent 142253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/Actions/Manager.Reset/") 143ed398213SEd Tanous .privileges(redfish::privileges::postManager) 1447e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 14545ca1b86SEd Tanous [&app](const crow::Request& req, 146253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 147253f11b8SEd Tanous const std::string& managerId) { 1483ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 14945ca1b86SEd Tanous { 15045ca1b86SEd Tanous return; 15145ca1b86SEd Tanous } 152253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 153253f11b8SEd Tanous { 154bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "Manager", 155bd79bce8SPatrick Williams managerId); 156253f11b8SEd Tanous return; 157253f11b8SEd Tanous } 158253f11b8SEd Tanous 15962598e31SEd Tanous BMCWEB_LOG_DEBUG("Post Manager Reset."); 1602a5c4407SGunnar Mills 1612a5c4407SGunnar Mills std::string resetType; 1622a5c4407SGunnar Mills 16315ed6780SWilly Tu if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", 1647e860f15SJohn Edward Broadbent resetType)) 1652a5c4407SGunnar Mills { 1662a5c4407SGunnar Mills return; 1672a5c4407SGunnar Mills } 1682a5c4407SGunnar Mills 169f92af389SJayaprakash Mutyala if (resetType == "GracefulRestart") 170f92af389SJayaprakash Mutyala { 17162598e31SEd Tanous BMCWEB_LOG_DEBUG("Proceeding with {}", resetType); 172f92af389SJayaprakash Mutyala doBMCGracefulRestart(asyncResp); 173f92af389SJayaprakash Mutyala return; 174f92af389SJayaprakash Mutyala } 1753174e4dfSEd Tanous if (resetType == "ForceRestart") 176f92af389SJayaprakash Mutyala { 17762598e31SEd Tanous BMCWEB_LOG_DEBUG("Proceeding with {}", resetType); 178f92af389SJayaprakash Mutyala doBMCForceRestart(asyncResp); 179f92af389SJayaprakash Mutyala return; 180f92af389SJayaprakash Mutyala } 181bd79bce8SPatrick Williams BMCWEB_LOG_DEBUG("Invalid property value for ResetType: {}", 182bd79bce8SPatrick Williams resetType); 1832a5c4407SGunnar Mills messages::actionParameterNotSupported(asyncResp->res, resetType, 1842a5c4407SGunnar Mills "ResetType"); 1852a5c4407SGunnar Mills 1862a5c4407SGunnar Mills return; 1877e860f15SJohn Edward Broadbent }); 1882a5c4407SGunnar Mills } 189ed5befbdSJennifer Lee 1903e40fc74SGunnar Mills /** 1913e40fc74SGunnar Mills * ManagerResetToDefaultsAction class supports POST method for factory reset 1923e40fc74SGunnar Mills * action. 1933e40fc74SGunnar Mills */ 1947e860f15SJohn Edward Broadbent inline void requestRoutesManagerResetToDefaultsAction(App& app) 1953e40fc74SGunnar Mills { 1963e40fc74SGunnar Mills /** 1973e40fc74SGunnar Mills * Function handles ResetToDefaults POST method request. 1983e40fc74SGunnar Mills * 1993e40fc74SGunnar Mills * Analyzes POST body message and factory resets BMC by calling 2003e40fc74SGunnar Mills * BMC code updater factory reset followed by a BMC reboot. 2013e40fc74SGunnar Mills * 2023e40fc74SGunnar Mills * BMC code updater factory reset wipes the whole BMC read-write 2033e40fc74SGunnar Mills * filesystem which includes things like the network settings. 2043e40fc74SGunnar Mills * 2053e40fc74SGunnar Mills * OpenBMC only supports ResetToDefaultsType "ResetAll". 2063e40fc74SGunnar Mills */ 2077e860f15SJohn Edward Broadbent 2087e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 209253f11b8SEd Tanous "/redfish/v1/Managers/<str>/Actions/Manager.ResetToDefaults/") 210ed398213SEd Tanous .privileges(redfish::privileges::postManager) 211bd79bce8SPatrick Williams .methods( 212bd79bce8SPatrick Williams boost::beast::http::verb:: 213bd79bce8SPatrick Williams post)([&app]( 214bd79bce8SPatrick Williams const crow::Request& req, 215253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 216253f11b8SEd Tanous const std::string& managerId) { 2173ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 21845ca1b86SEd Tanous { 21945ca1b86SEd Tanous return; 22045ca1b86SEd Tanous } 221253f11b8SEd Tanous 222253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 223253f11b8SEd Tanous { 224bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "Manager", 225bd79bce8SPatrick Williams managerId); 226253f11b8SEd Tanous return; 227253f11b8SEd Tanous } 228253f11b8SEd Tanous 22962598e31SEd Tanous BMCWEB_LOG_DEBUG("Post ResetToDefaults."); 2303e40fc74SGunnar Mills 2319970e93fSKonstantin Aladyshev std::optional<std::string> resetType; 2329970e93fSKonstantin Aladyshev std::optional<std::string> resetToDefaultsType; 2333e40fc74SGunnar Mills 234afc474aeSMyung Bae if (!json_util::readJsonAction( // 235afc474aeSMyung Bae req, asyncResp->res, // 236afc474aeSMyung Bae "ResetToDefaultsType", resetToDefaultsType, // 237afc474aeSMyung Bae "ResetType", resetType // 238afc474aeSMyung Bae )) 2393e40fc74SGunnar Mills { 2409970e93fSKonstantin Aladyshev BMCWEB_LOG_DEBUG("Missing property ResetType."); 2413e40fc74SGunnar Mills 242bd79bce8SPatrick Williams messages::actionParameterMissing( 243bd79bce8SPatrick Williams asyncResp->res, "ResetToDefaults", "ResetType"); 2443e40fc74SGunnar Mills return; 2453e40fc74SGunnar Mills } 2463e40fc74SGunnar Mills 2479970e93fSKonstantin Aladyshev if (resetToDefaultsType && !resetType) 2489970e93fSKonstantin Aladyshev { 2499970e93fSKonstantin Aladyshev BMCWEB_LOG_WARNING( 2509970e93fSKonstantin Aladyshev "Using deprecated ResetToDefaultsType, should be ResetType." 2519970e93fSKonstantin Aladyshev "Support for the ResetToDefaultsType will be dropped in 2Q24"); 2529970e93fSKonstantin Aladyshev resetType = resetToDefaultsType; 2539970e93fSKonstantin Aladyshev } 2549970e93fSKonstantin Aladyshev 2553e40fc74SGunnar Mills if (resetType != "ResetAll") 2563e40fc74SGunnar Mills { 2579970e93fSKonstantin Aladyshev BMCWEB_LOG_DEBUG("Invalid property value for ResetType: {}", 2589970e93fSKonstantin Aladyshev *resetType); 259bd79bce8SPatrick Williams messages::actionParameterNotSupported(asyncResp->res, 260bd79bce8SPatrick Williams *resetType, "ResetType"); 2613e40fc74SGunnar Mills return; 2623e40fc74SGunnar Mills } 2633e40fc74SGunnar Mills 2643e40fc74SGunnar Mills crow::connections::systemBus->async_method_call( 2655e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 2663e40fc74SGunnar Mills if (ec) 2673e40fc74SGunnar Mills { 26862598e31SEd Tanous BMCWEB_LOG_DEBUG("Failed to ResetToDefaults: {}", ec); 2693e40fc74SGunnar Mills messages::internalError(asyncResp->res); 2703e40fc74SGunnar Mills return; 2713e40fc74SGunnar Mills } 2723e40fc74SGunnar Mills // Factory Reset doesn't actually happen until a reboot 2733e40fc74SGunnar Mills // Can't erase what the BMC is running on 2743e40fc74SGunnar Mills doBMCGracefulRestart(asyncResp); 2753e40fc74SGunnar Mills }, 276*d27c31e9SJagpal Singh Gill getBMCUpdateServiceName(), getBMCUpdateServicePath(), 2773e40fc74SGunnar Mills "xyz.openbmc_project.Common.FactoryReset", "Reset"); 2787e860f15SJohn Edward Broadbent }); 2793e40fc74SGunnar Mills } 2803e40fc74SGunnar Mills 2811cb1a9e6SAppaRao Puli /** 2821cb1a9e6SAppaRao Puli * ManagerResetActionInfo derived class for delivering Manager 2831cb1a9e6SAppaRao Puli * ResetType AllowableValues using ResetInfo schema. 2841cb1a9e6SAppaRao Puli */ 2857e860f15SJohn Edward Broadbent inline void requestRoutesManagerResetActionInfo(App& app) 2861cb1a9e6SAppaRao Puli { 2871cb1a9e6SAppaRao Puli /** 2881cb1a9e6SAppaRao Puli * Functions triggers appropriate requests on DBus 2891cb1a9e6SAppaRao Puli */ 2907e860f15SJohn Edward Broadbent 291253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/ResetActionInfo/") 292ed398213SEd Tanous .privileges(redfish::privileges::getActionInfo) 2937e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 29445ca1b86SEd Tanous [&app](const crow::Request& req, 295253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 296253f11b8SEd Tanous const std::string& managerId) { 2973ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 29845ca1b86SEd Tanous { 29945ca1b86SEd Tanous return; 30045ca1b86SEd Tanous } 3011476687dSEd Tanous 302253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 303253f11b8SEd Tanous { 304bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "Manager", 305bd79bce8SPatrick Williams managerId); 306253f11b8SEd Tanous return; 307253f11b8SEd Tanous } 308253f11b8SEd Tanous 3091476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 3101476687dSEd Tanous "#ActionInfo.v1_1_2.ActionInfo"; 311bd79bce8SPatrick Williams asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 312bd79bce8SPatrick Williams "/redfish/v1/Managers/{}/ResetActionInfo", 313253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 3141476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "Reset Action Info"; 3151476687dSEd Tanous asyncResp->res.jsonValue["Id"] = "ResetActionInfo"; 3161476687dSEd Tanous nlohmann::json::object_t parameter; 3171476687dSEd Tanous parameter["Name"] = "ResetType"; 3181476687dSEd Tanous parameter["Required"] = true; 319539d8c6bSEd Tanous parameter["DataType"] = action_info::ParameterTypes::String; 3201476687dSEd Tanous 3211476687dSEd Tanous nlohmann::json::array_t allowableValues; 322ad539545SPatrick Williams allowableValues.emplace_back("GracefulRestart"); 323ad539545SPatrick Williams allowableValues.emplace_back("ForceRestart"); 3241476687dSEd Tanous parameter["AllowableValues"] = std::move(allowableValues); 3251476687dSEd Tanous 3261476687dSEd Tanous nlohmann::json::array_t parameters; 327ad539545SPatrick Williams parameters.emplace_back(std::move(parameter)); 3281476687dSEd Tanous 3291476687dSEd Tanous asyncResp->res.jsonValue["Parameters"] = std::move(parameters); 3307e860f15SJohn Edward Broadbent }); 3311cb1a9e6SAppaRao Puli } 3321cb1a9e6SAppaRao Puli 3335b4aa86bSJames Feist static constexpr const char* objectManagerIface = 3345b4aa86bSJames Feist "org.freedesktop.DBus.ObjectManager"; 3355b4aa86bSJames Feist static constexpr const char* pidConfigurationIface = 3365b4aa86bSJames Feist "xyz.openbmc_project.Configuration.Pid"; 3375b4aa86bSJames Feist static constexpr const char* pidZoneConfigurationIface = 3385b4aa86bSJames Feist "xyz.openbmc_project.Configuration.Pid.Zone"; 339b7a08d04SJames Feist static constexpr const char* stepwiseConfigurationIface = 340b7a08d04SJames Feist "xyz.openbmc_project.Configuration.Stepwise"; 34173df0db0SJames Feist static constexpr const char* thermalModeIface = 34273df0db0SJames Feist "xyz.openbmc_project.Control.ThermalMode"; 3439c310685SBorawski.Lukasz 3448d1b46d7Szhanghch05 inline void 3458d1b46d7Szhanghch05 asyncPopulatePid(const std::string& connection, const std::string& path, 34673df0db0SJames Feist const std::string& currentProfile, 34773df0db0SJames Feist const std::vector<std::string>& supportedProfiles, 3488d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 3495b4aa86bSJames Feist { 3505eb468daSGeorge Liu sdbusplus::message::object_path objPath(path); 3515eb468daSGeorge Liu dbus::utility::getManagedObjects( 3525eb468daSGeorge Liu connection, objPath, 35373df0db0SJames Feist [asyncResp, currentProfile, supportedProfiles]( 3545e7e2dc5SEd Tanous const boost::system::error_code& ec, 3555b4aa86bSJames Feist const dbus::utility::ManagedObjectType& managedObj) { 3565b4aa86bSJames Feist if (ec) 3575b4aa86bSJames Feist { 35862598e31SEd Tanous BMCWEB_LOG_ERROR("{}", ec); 359f12894f8SJason M. Bills messages::internalError(asyncResp->res); 3605b4aa86bSJames Feist return; 3615b4aa86bSJames Feist } 3625b4aa86bSJames Feist nlohmann::json& configRoot = 3635b4aa86bSJames Feist asyncResp->res.jsonValue["Oem"]["OpenBmc"]["Fan"]; 3645b4aa86bSJames Feist nlohmann::json& fans = configRoot["FanControllers"]; 365bd79bce8SPatrick Williams fans["@odata.type"] = 366bd79bce8SPatrick Williams "#OpenBMCManager.v1_0_0.Manager.FanControllers"; 367253f11b8SEd Tanous fans["@odata.id"] = boost::urls::format( 368253f11b8SEd Tanous "/redfish/v1/Managers/{}#/Oem/OpenBmc/Fan/FanControllers", 369253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 3705b4aa86bSJames Feist 3715b4aa86bSJames Feist nlohmann::json& pids = configRoot["PidControllers"]; 372bd79bce8SPatrick Williams pids["@odata.type"] = 373bd79bce8SPatrick Williams "#OpenBMCManager.v1_0_0.Manager.PidControllers"; 374253f11b8SEd Tanous pids["@odata.id"] = boost::urls::format( 375253f11b8SEd Tanous "/redfish/v1/Managers/{}#/Oem/OpenBmc/Fan/PidControllers", 376253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 3775b4aa86bSJames Feist 378b7a08d04SJames Feist nlohmann::json& stepwise = configRoot["StepwiseControllers"]; 379fc1cdd14SEd Tanous stepwise["@odata.type"] = 380fc1cdd14SEd Tanous "#OpenBMCManager.v1_0_0.Manager.StepwiseControllers"; 381253f11b8SEd Tanous stepwise["@odata.id"] = boost::urls::format( 382253f11b8SEd Tanous "/redfish/v1/Managers/{}#/Oem/OpenBmc/Fan/StepwiseControllers", 383253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 384b7a08d04SJames Feist 3855b4aa86bSJames Feist nlohmann::json& zones = configRoot["FanZones"]; 386253f11b8SEd Tanous zones["@odata.id"] = boost::urls::format( 387253f11b8SEd Tanous "/redfish/v1/Managers/{}#/Oem/OpenBmc/Fan/FanZones", 388253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 389fc1cdd14SEd Tanous zones["@odata.type"] = "#OpenBMCManager.v1_0_0.Manager.FanZones"; 390253f11b8SEd Tanous configRoot["@odata.id"] = 391253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}#/Oem/OpenBmc/Fan", 392253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 393fc1cdd14SEd Tanous configRoot["@odata.type"] = "#OpenBMCManager.v1_0_0.Manager.Fan"; 39473df0db0SJames Feist configRoot["Profile@Redfish.AllowableValues"] = supportedProfiles; 39573df0db0SJames Feist 39673df0db0SJames Feist if (!currentProfile.empty()) 39773df0db0SJames Feist { 39873df0db0SJames Feist configRoot["Profile"] = currentProfile; 39973df0db0SJames Feist } 400bf2ddedeSCarson Labrado BMCWEB_LOG_DEBUG("profile = {} !", currentProfile); 4015b4aa86bSJames Feist 4025b4aa86bSJames Feist for (const auto& pathPair : managedObj) 4035b4aa86bSJames Feist { 4045b4aa86bSJames Feist for (const auto& intfPair : pathPair.second) 4055b4aa86bSJames Feist { 4065b4aa86bSJames Feist if (intfPair.first != pidConfigurationIface && 407b7a08d04SJames Feist intfPair.first != pidZoneConfigurationIface && 408b7a08d04SJames Feist intfPair.first != stepwiseConfigurationIface) 4095b4aa86bSJames Feist { 4105b4aa86bSJames Feist continue; 4115b4aa86bSJames Feist } 41273df0db0SJames Feist 413711ac7a9SEd Tanous std::string name; 414711ac7a9SEd Tanous 415711ac7a9SEd Tanous for (const std::pair<std::string, 416bd79bce8SPatrick Williams dbus::utility::DbusVariantType>& 417bd79bce8SPatrick Williams propPair : intfPair.second) 418711ac7a9SEd Tanous { 419711ac7a9SEd Tanous if (propPair.first == "Name") 420711ac7a9SEd Tanous { 4215b4aa86bSJames Feist const std::string* namePtr = 422711ac7a9SEd Tanous std::get_if<std::string>(&propPair.second); 4235b4aa86bSJames Feist if (namePtr == nullptr) 4245b4aa86bSJames Feist { 42562598e31SEd Tanous BMCWEB_LOG_ERROR("Pid Name Field illegal"); 426b7a08d04SJames Feist messages::internalError(asyncResp->res); 4275b4aa86bSJames Feist return; 4285b4aa86bSJames Feist } 429db697703SWilly Tu name = *namePtr; 4305b4aa86bSJames Feist dbus::utility::escapePathForDbus(name); 431711ac7a9SEd Tanous } 432711ac7a9SEd Tanous else if (propPair.first == "Profiles") 43373df0db0SJames Feist { 43473df0db0SJames Feist const std::vector<std::string>* profiles = 43573df0db0SJames Feist std::get_if<std::vector<std::string>>( 436711ac7a9SEd Tanous &propPair.second); 43773df0db0SJames Feist if (profiles == nullptr) 43873df0db0SJames Feist { 43962598e31SEd Tanous BMCWEB_LOG_ERROR("Pid Profiles Field illegal"); 44073df0db0SJames Feist messages::internalError(asyncResp->res); 44173df0db0SJames Feist return; 44273df0db0SJames Feist } 44373df0db0SJames Feist if (std::find(profiles->begin(), profiles->end(), 44473df0db0SJames Feist currentProfile) == profiles->end()) 44573df0db0SJames Feist { 44662598e31SEd Tanous BMCWEB_LOG_INFO( 447bd79bce8SPatrick Williams "{} not supported in current profile", 448bd79bce8SPatrick Williams name); 44973df0db0SJames Feist continue; 45073df0db0SJames Feist } 45173df0db0SJames Feist } 452711ac7a9SEd Tanous } 453b7a08d04SJames Feist nlohmann::json* config = nullptr; 454c33a90ecSJames Feist const std::string* classPtr = nullptr; 455711ac7a9SEd Tanous 456711ac7a9SEd Tanous for (const std::pair<std::string, 457bd79bce8SPatrick Williams dbus::utility::DbusVariantType>& 458bd79bce8SPatrick Williams propPair : intfPair.second) 459c33a90ecSJames Feist { 460727dc83fSLei YU if (propPair.first == "Class") 461711ac7a9SEd Tanous { 462bd79bce8SPatrick Williams classPtr = 463bd79bce8SPatrick Williams std::get_if<std::string>(&propPair.second); 464711ac7a9SEd Tanous } 465c33a90ecSJames Feist } 466c33a90ecSJames Feist 467253f11b8SEd Tanous boost::urls::url url( 468253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}", 469253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME)); 4705b4aa86bSJames Feist if (intfPair.first == pidZoneConfigurationIface) 4715b4aa86bSJames Feist { 4725b4aa86bSJames Feist std::string chassis; 473bd79bce8SPatrick Williams if (!dbus::utility::getNthStringFromPath( 474bd79bce8SPatrick Williams pathPair.first.str, 5, chassis)) 4755b4aa86bSJames Feist { 4765b4aa86bSJames Feist chassis = "#IllegalValue"; 4775b4aa86bSJames Feist } 4785b4aa86bSJames Feist nlohmann::json& zone = zones[name]; 479bd79bce8SPatrick Williams zone["Chassis"]["@odata.id"] = boost::urls::format( 480bd79bce8SPatrick Williams "/redfish/v1/Chassis/{}", chassis); 481eddfc437SWilly Tu url.set_fragment( 482eddfc437SWilly Tu ("/Oem/OpenBmc/Fan/FanZones"_json_pointer / name) 483eddfc437SWilly Tu .to_string()); 484eddfc437SWilly Tu zone["@odata.id"] = std::move(url); 485fc1cdd14SEd Tanous zone["@odata.type"] = 486fc1cdd14SEd Tanous "#OpenBMCManager.v1_0_0.Manager.FanZone"; 487b7a08d04SJames Feist config = &zone; 4885b4aa86bSJames Feist } 4895b4aa86bSJames Feist 490b7a08d04SJames Feist else if (intfPair.first == stepwiseConfigurationIface) 4915b4aa86bSJames Feist { 492c33a90ecSJames Feist if (classPtr == nullptr) 493c33a90ecSJames Feist { 49462598e31SEd Tanous BMCWEB_LOG_ERROR("Pid Class Field illegal"); 495c33a90ecSJames Feist messages::internalError(asyncResp->res); 496c33a90ecSJames Feist return; 497c33a90ecSJames Feist } 498c33a90ecSJames Feist 499b7a08d04SJames Feist nlohmann::json& controller = stepwise[name]; 500b7a08d04SJames Feist config = &controller; 501eddfc437SWilly Tu url.set_fragment( 502eddfc437SWilly Tu ("/Oem/OpenBmc/Fan/StepwiseControllers"_json_pointer / 503eddfc437SWilly Tu name) 504eddfc437SWilly Tu .to_string()); 505eddfc437SWilly Tu controller["@odata.id"] = std::move(url); 506b7a08d04SJames Feist controller["@odata.type"] = 507fc1cdd14SEd Tanous "#OpenBMCManager.v1_0_0.Manager.StepwiseController"; 508b7a08d04SJames Feist 509c33a90ecSJames Feist controller["Direction"] = *classPtr; 5105b4aa86bSJames Feist } 5115b4aa86bSJames Feist 5125b4aa86bSJames Feist // pid and fans are off the same configuration 513b7a08d04SJames Feist else if (intfPair.first == pidConfigurationIface) 5145b4aa86bSJames Feist { 5155b4aa86bSJames Feist if (classPtr == nullptr) 5165b4aa86bSJames Feist { 51762598e31SEd Tanous BMCWEB_LOG_ERROR("Pid Class Field illegal"); 518a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 5195b4aa86bSJames Feist return; 5205b4aa86bSJames Feist } 5215b4aa86bSJames Feist bool isFan = *classPtr == "fan"; 522bd79bce8SPatrick Williams nlohmann::json& element = 523bd79bce8SPatrick Williams isFan ? fans[name] : pids[name]; 524b7a08d04SJames Feist config = &element; 5255b4aa86bSJames Feist if (isFan) 5265b4aa86bSJames Feist { 527eddfc437SWilly Tu url.set_fragment( 528eddfc437SWilly Tu ("/Oem/OpenBmc/Fan/FanControllers"_json_pointer / 529eddfc437SWilly Tu name) 530eddfc437SWilly Tu .to_string()); 531eddfc437SWilly Tu element["@odata.id"] = std::move(url); 532fc1cdd14SEd Tanous element["@odata.type"] = 533fc1cdd14SEd Tanous "#OpenBMCManager.v1_0_0.Manager.FanController"; 5345b4aa86bSJames Feist } 5355b4aa86bSJames Feist else 5365b4aa86bSJames Feist { 537eddfc437SWilly Tu url.set_fragment( 538eddfc437SWilly Tu ("/Oem/OpenBmc/Fan/PidControllers"_json_pointer / 539eddfc437SWilly Tu name) 540eddfc437SWilly Tu .to_string()); 541eddfc437SWilly Tu element["@odata.id"] = std::move(url); 542fc1cdd14SEd Tanous element["@odata.type"] = 543fc1cdd14SEd Tanous "#OpenBMCManager.v1_0_0.Manager.PidController"; 5445b4aa86bSJames Feist } 545b7a08d04SJames Feist } 546b7a08d04SJames Feist else 547b7a08d04SJames Feist { 54862598e31SEd Tanous BMCWEB_LOG_ERROR("Unexpected configuration"); 549b7a08d04SJames Feist messages::internalError(asyncResp->res); 550b7a08d04SJames Feist return; 551b7a08d04SJames Feist } 552b7a08d04SJames Feist 553b7a08d04SJames Feist // used for making maps out of 2 vectors 554b7a08d04SJames Feist const std::vector<double>* keys = nullptr; 555b7a08d04SJames Feist const std::vector<double>* values = nullptr; 556b7a08d04SJames Feist 557b7a08d04SJames Feist for (const auto& propertyPair : intfPair.second) 558b7a08d04SJames Feist { 559b7a08d04SJames Feist if (propertyPair.first == "Type" || 560b7a08d04SJames Feist propertyPair.first == "Class" || 561b7a08d04SJames Feist propertyPair.first == "Name") 562b7a08d04SJames Feist { 563b7a08d04SJames Feist continue; 564b7a08d04SJames Feist } 565b7a08d04SJames Feist 566b7a08d04SJames Feist // zones 567b7a08d04SJames Feist if (intfPair.first == pidZoneConfigurationIface) 568b7a08d04SJames Feist { 569b7a08d04SJames Feist const double* ptr = 570abf2add6SEd Tanous std::get_if<double>(&propertyPair.second); 571b7a08d04SJames Feist if (ptr == nullptr) 572b7a08d04SJames Feist { 57362598e31SEd Tanous BMCWEB_LOG_ERROR("Field Illegal {}", 57462598e31SEd Tanous propertyPair.first); 575b7a08d04SJames Feist messages::internalError(asyncResp->res); 576b7a08d04SJames Feist return; 577b7a08d04SJames Feist } 578b7a08d04SJames Feist (*config)[propertyPair.first] = *ptr; 579b7a08d04SJames Feist } 580b7a08d04SJames Feist 581b7a08d04SJames Feist if (intfPair.first == stepwiseConfigurationIface) 582b7a08d04SJames Feist { 583b7a08d04SJames Feist if (propertyPair.first == "Reading" || 584b7a08d04SJames Feist propertyPair.first == "Output") 585b7a08d04SJames Feist { 586b7a08d04SJames Feist const std::vector<double>* ptr = 587abf2add6SEd Tanous std::get_if<std::vector<double>>( 588b7a08d04SJames Feist &propertyPair.second); 589b7a08d04SJames Feist 590b7a08d04SJames Feist if (ptr == nullptr) 591b7a08d04SJames Feist { 59262598e31SEd Tanous BMCWEB_LOG_ERROR("Field Illegal {}", 59362598e31SEd Tanous propertyPair.first); 594b7a08d04SJames Feist messages::internalError(asyncResp->res); 595b7a08d04SJames Feist return; 596b7a08d04SJames Feist } 597b7a08d04SJames Feist 598b7a08d04SJames Feist if (propertyPair.first == "Reading") 599b7a08d04SJames Feist { 600b7a08d04SJames Feist keys = ptr; 601b7a08d04SJames Feist } 602b7a08d04SJames Feist else 603b7a08d04SJames Feist { 604b7a08d04SJames Feist values = ptr; 605b7a08d04SJames Feist } 606e662eae8SEd Tanous if (keys != nullptr && values != nullptr) 607b7a08d04SJames Feist { 608b7a08d04SJames Feist if (keys->size() != values->size()) 609b7a08d04SJames Feist { 61062598e31SEd Tanous BMCWEB_LOG_ERROR( 61162598e31SEd Tanous "Reading and Output size don't match "); 612b7a08d04SJames Feist messages::internalError(asyncResp->res); 613b7a08d04SJames Feist return; 614b7a08d04SJames Feist } 615b7a08d04SJames Feist nlohmann::json& steps = (*config)["Steps"]; 616b7a08d04SJames Feist steps = nlohmann::json::array(); 617b7a08d04SJames Feist for (size_t ii = 0; ii < keys->size(); ii++) 618b7a08d04SJames Feist { 6191476687dSEd Tanous nlohmann::json::object_t step; 6201476687dSEd Tanous step["Target"] = (*keys)[ii]; 6211476687dSEd Tanous step["Output"] = (*values)[ii]; 622b2ba3072SPatrick Williams steps.emplace_back(std::move(step)); 623b7a08d04SJames Feist } 624b7a08d04SJames Feist } 625b7a08d04SJames Feist } 626b7a08d04SJames Feist if (propertyPair.first == "NegativeHysteresis" || 627b7a08d04SJames Feist propertyPair.first == "PositiveHysteresis") 628b7a08d04SJames Feist { 629b7a08d04SJames Feist const double* ptr = 630abf2add6SEd Tanous std::get_if<double>(&propertyPair.second); 631b7a08d04SJames Feist if (ptr == nullptr) 632b7a08d04SJames Feist { 63362598e31SEd Tanous BMCWEB_LOG_ERROR("Field Illegal {}", 63462598e31SEd Tanous propertyPair.first); 635b7a08d04SJames Feist messages::internalError(asyncResp->res); 636b7a08d04SJames Feist return; 637b7a08d04SJames Feist } 638b7a08d04SJames Feist (*config)[propertyPair.first] = *ptr; 639b7a08d04SJames Feist } 640b7a08d04SJames Feist } 641b7a08d04SJames Feist 642b7a08d04SJames Feist // pid and fans are off the same configuration 643b7a08d04SJames Feist if (intfPair.first == pidConfigurationIface || 644b7a08d04SJames Feist intfPair.first == stepwiseConfigurationIface) 645b7a08d04SJames Feist { 6465b4aa86bSJames Feist if (propertyPair.first == "Zones") 6475b4aa86bSJames Feist { 6485b4aa86bSJames Feist const std::vector<std::string>* inputs = 649abf2add6SEd Tanous std::get_if<std::vector<std::string>>( 6501b6b96c5SEd Tanous &propertyPair.second); 6515b4aa86bSJames Feist 6525b4aa86bSJames Feist if (inputs == nullptr) 6535b4aa86bSJames Feist { 65462598e31SEd Tanous BMCWEB_LOG_ERROR("Zones Pid Field Illegal"); 655a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 6565b4aa86bSJames Feist return; 6575b4aa86bSJames Feist } 658b7a08d04SJames Feist auto& data = (*config)[propertyPair.first]; 6595b4aa86bSJames Feist data = nlohmann::json::array(); 6605b4aa86bSJames Feist for (std::string itemCopy : *inputs) 6615b4aa86bSJames Feist { 6625b4aa86bSJames Feist dbus::utility::escapePathForDbus(itemCopy); 6631476687dSEd Tanous nlohmann::json::object_t input; 664bd79bce8SPatrick Williams boost::urls::url managerUrl = 665bd79bce8SPatrick Williams boost::urls::format( 666253f11b8SEd Tanous "/redfish/v1/Managers/{}#{}", 667253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME, 668eddfc437SWilly Tu ("/Oem/OpenBmc/Fan/FanZones"_json_pointer / 669eddfc437SWilly Tu itemCopy) 670eddfc437SWilly Tu .to_string()); 671eddfc437SWilly Tu input["@odata.id"] = std::move(managerUrl); 672b2ba3072SPatrick Williams data.emplace_back(std::move(input)); 6735b4aa86bSJames Feist } 6745b4aa86bSJames Feist } 6755b4aa86bSJames Feist // todo(james): may never happen, but this 6765b4aa86bSJames Feist // assumes configuration data referenced in the 6775b4aa86bSJames Feist // PID config is provided by the same daemon, we 6785b4aa86bSJames Feist // could add another loop to cover all cases, 6795b4aa86bSJames Feist // but I'm okay kicking this can down the road a 6805b4aa86bSJames Feist // bit 6815b4aa86bSJames Feist 6825b4aa86bSJames Feist else if (propertyPair.first == "Inputs" || 6835b4aa86bSJames Feist propertyPair.first == "Outputs") 6845b4aa86bSJames Feist { 685b7a08d04SJames Feist auto& data = (*config)[propertyPair.first]; 6865b4aa86bSJames Feist const std::vector<std::string>* inputs = 687abf2add6SEd Tanous std::get_if<std::vector<std::string>>( 6881b6b96c5SEd Tanous &propertyPair.second); 6895b4aa86bSJames Feist 6905b4aa86bSJames Feist if (inputs == nullptr) 6915b4aa86bSJames Feist { 69262598e31SEd Tanous BMCWEB_LOG_ERROR("Field Illegal {}", 69362598e31SEd Tanous propertyPair.first); 694f12894f8SJason M. Bills messages::internalError(asyncResp->res); 6955b4aa86bSJames Feist return; 6965b4aa86bSJames Feist } 6975b4aa86bSJames Feist data = *inputs; 698b943aaefSJames Feist } 699b943aaefSJames Feist else if (propertyPair.first == "SetPointOffset") 700b943aaefSJames Feist { 701b943aaefSJames Feist const std::string* ptr = 702bd79bce8SPatrick Williams std::get_if<std::string>( 703bd79bce8SPatrick Williams &propertyPair.second); 704b943aaefSJames Feist 705b943aaefSJames Feist if (ptr == nullptr) 706b943aaefSJames Feist { 70762598e31SEd Tanous BMCWEB_LOG_ERROR("Field Illegal {}", 70862598e31SEd Tanous propertyPair.first); 709b943aaefSJames Feist messages::internalError(asyncResp->res); 710b943aaefSJames Feist return; 711b943aaefSJames Feist } 712b943aaefSJames Feist // translate from dbus to redfish 713b943aaefSJames Feist if (*ptr == "WarningHigh") 714b943aaefSJames Feist { 715b943aaefSJames Feist (*config)["SetPointOffset"] = 716b943aaefSJames Feist "UpperThresholdNonCritical"; 717b943aaefSJames Feist } 718b943aaefSJames Feist else if (*ptr == "WarningLow") 719b943aaefSJames Feist { 720b943aaefSJames Feist (*config)["SetPointOffset"] = 721b943aaefSJames Feist "LowerThresholdNonCritical"; 722b943aaefSJames Feist } 723b943aaefSJames Feist else if (*ptr == "CriticalHigh") 724b943aaefSJames Feist { 725b943aaefSJames Feist (*config)["SetPointOffset"] = 726b943aaefSJames Feist "UpperThresholdCritical"; 727b943aaefSJames Feist } 728b943aaefSJames Feist else if (*ptr == "CriticalLow") 729b943aaefSJames Feist { 730b943aaefSJames Feist (*config)["SetPointOffset"] = 731b943aaefSJames Feist "LowerThresholdCritical"; 732b943aaefSJames Feist } 733b943aaefSJames Feist else 734b943aaefSJames Feist { 73562598e31SEd Tanous BMCWEB_LOG_ERROR("Value Illegal {}", *ptr); 736b943aaefSJames Feist messages::internalError(asyncResp->res); 737b943aaefSJames Feist return; 738b943aaefSJames Feist } 739b943aaefSJames Feist } 740b943aaefSJames Feist // doubles 741bd79bce8SPatrick Williams else if (propertyPair.first == 742bd79bce8SPatrick Williams "FFGainCoefficient" || 7435b4aa86bSJames Feist propertyPair.first == "FFOffCoefficient" || 7445b4aa86bSJames Feist propertyPair.first == "ICoefficient" || 7455b4aa86bSJames Feist propertyPair.first == "ILimitMax" || 7465b4aa86bSJames Feist propertyPair.first == "ILimitMin" || 747bd79bce8SPatrick Williams propertyPair.first == 748bd79bce8SPatrick Williams "PositiveHysteresis" || 749bd79bce8SPatrick Williams propertyPair.first == 750bd79bce8SPatrick Williams "NegativeHysteresis" || 7515b4aa86bSJames Feist propertyPair.first == "OutLimitMax" || 7525b4aa86bSJames Feist propertyPair.first == "OutLimitMin" || 7535b4aa86bSJames Feist propertyPair.first == "PCoefficient" || 7547625cb81SJames Feist propertyPair.first == "SetPoint" || 7555b4aa86bSJames Feist propertyPair.first == "SlewNeg" || 7565b4aa86bSJames Feist propertyPair.first == "SlewPos") 7575b4aa86bSJames Feist { 7585b4aa86bSJames Feist const double* ptr = 759abf2add6SEd Tanous std::get_if<double>(&propertyPair.second); 7605b4aa86bSJames Feist if (ptr == nullptr) 7615b4aa86bSJames Feist { 76262598e31SEd Tanous BMCWEB_LOG_ERROR("Field Illegal {}", 76362598e31SEd Tanous propertyPair.first); 764f12894f8SJason M. Bills messages::internalError(asyncResp->res); 7655b4aa86bSJames Feist return; 7665b4aa86bSJames Feist } 767b7a08d04SJames Feist (*config)[propertyPair.first] = *ptr; 7685b4aa86bSJames Feist } 7695b4aa86bSJames Feist } 7705b4aa86bSJames Feist } 7715b4aa86bSJames Feist } 7725b4aa86bSJames Feist } 7735eb468daSGeorge Liu }); 7745b4aa86bSJames Feist } 775ca537928SJennifer Lee 77683ff9ab6SJames Feist enum class CreatePIDRet 77783ff9ab6SJames Feist { 77883ff9ab6SJames Feist fail, 77983ff9ab6SJames Feist del, 78083ff9ab6SJames Feist patch 78183ff9ab6SJames Feist }; 78283ff9ab6SJames Feist 7838d1b46d7Szhanghch05 inline bool 7848d1b46d7Szhanghch05 getZonesFromJsonReq(const std::shared_ptr<bmcweb::AsyncResp>& response, 7859e9b6049SEd Tanous std::vector<nlohmann::json::object_t>& config, 7865f2caaefSJames Feist std::vector<std::string>& zones) 7875f2caaefSJames Feist { 788b6baeaa4SJames Feist if (config.empty()) 789b6baeaa4SJames Feist { 79062598e31SEd Tanous BMCWEB_LOG_ERROR("Empty Zones"); 791f818b04dSEd Tanous messages::propertyValueFormatError(response->res, config, "Zones"); 792b6baeaa4SJames Feist return false; 793b6baeaa4SJames Feist } 7945f2caaefSJames Feist for (auto& odata : config) 7955f2caaefSJames Feist { 7965f2caaefSJames Feist std::string path; 7979e9b6049SEd Tanous if (!redfish::json_util::readJsonObject(odata, response->res, 7989e9b6049SEd Tanous "@odata.id", path)) 7995f2caaefSJames Feist { 8005f2caaefSJames Feist return false; 8015f2caaefSJames Feist } 8025f2caaefSJames Feist std::string input; 80361adbda3SJames Feist 80461adbda3SJames Feist // 8 below comes from 80561adbda3SJames Feist // /redfish/v1/Managers/bmc#/Oem/OpenBmc/Fan/FanZones/Left 80661adbda3SJames Feist // 0 1 2 3 4 5 6 7 8 80761adbda3SJames Feist if (!dbus::utility::getNthStringFromPath(path, 8, input)) 8085f2caaefSJames Feist { 80962598e31SEd Tanous BMCWEB_LOG_ERROR("Got invalid path {}", path); 81062598e31SEd Tanous BMCWEB_LOG_ERROR("Illegal Type Zones"); 811f818b04dSEd Tanous messages::propertyValueFormatError(response->res, odata, "Zones"); 8125f2caaefSJames Feist return false; 8135f2caaefSJames Feist } 814a170f275SEd Tanous std::replace(input.begin(), input.end(), '_', ' '); 8155f2caaefSJames Feist zones.emplace_back(std::move(input)); 8165f2caaefSJames Feist } 8175f2caaefSJames Feist return true; 8185f2caaefSJames Feist } 8195f2caaefSJames Feist 820711ac7a9SEd Tanous inline const dbus::utility::ManagedObjectType::value_type* 82173df0db0SJames Feist findChassis(const dbus::utility::ManagedObjectType& managedObj, 8229e9b6049SEd Tanous std::string_view value, std::string& chassis) 823b6baeaa4SJames Feist { 82462598e31SEd Tanous BMCWEB_LOG_DEBUG("Find Chassis: {}", value); 825b6baeaa4SJames Feist 8269e9b6049SEd Tanous std::string escaped(value); 8276ce82fabSYaswanth Reddy M std::replace(escaped.begin(), escaped.end(), ' ', '_'); 828b6baeaa4SJames Feist escaped = "/" + escaped; 8293544d2a7SEd Tanous auto it = std::ranges::find_if(managedObj, [&escaped](const auto& obj) { 83018f8f608SEd Tanous if (obj.first.str.ends_with(escaped)) 831b6baeaa4SJames Feist { 83262598e31SEd Tanous BMCWEB_LOG_DEBUG("Matched {}", obj.first.str); 833b6baeaa4SJames Feist return true; 834b6baeaa4SJames Feist } 835b6baeaa4SJames Feist return false; 836b6baeaa4SJames Feist }); 837b6baeaa4SJames Feist 838b6baeaa4SJames Feist if (it == managedObj.end()) 839b6baeaa4SJames Feist { 84073df0db0SJames Feist return nullptr; 841b6baeaa4SJames Feist } 842b6baeaa4SJames Feist // 5 comes from <chassis-name> being the 5th element 843b6baeaa4SJames Feist // /xyz/openbmc_project/inventory/system/chassis/<chassis-name> 84473df0db0SJames Feist if (dbus::utility::getNthStringFromPath(it->first.str, 5, chassis)) 84573df0db0SJames Feist { 84673df0db0SJames Feist return &(*it); 84773df0db0SJames Feist } 84873df0db0SJames Feist 84973df0db0SJames Feist return nullptr; 850b6baeaa4SJames Feist } 851b6baeaa4SJames Feist 85223a21a1cSEd Tanous inline CreatePIDRet createPidInterface( 8538d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& response, const std::string& type, 8549e9b6049SEd Tanous std::string_view name, nlohmann::json& jsonValue, const std::string& path, 85583ff9ab6SJames Feist const dbus::utility::ManagedObjectType& managedObj, bool createNewObject, 856b9d36b47SEd Tanous dbus::utility::DBusPropertiesMap& output, std::string& chassis, 857b9d36b47SEd Tanous const std::string& profile) 85883ff9ab6SJames Feist { 8595f2caaefSJames Feist // common deleter 8609e9b6049SEd Tanous if (jsonValue == nullptr) 8615f2caaefSJames Feist { 8625f2caaefSJames Feist std::string iface; 8635f2caaefSJames Feist if (type == "PidControllers" || type == "FanControllers") 8645f2caaefSJames Feist { 8655f2caaefSJames Feist iface = pidConfigurationIface; 8665f2caaefSJames Feist } 8675f2caaefSJames Feist else if (type == "FanZones") 8685f2caaefSJames Feist { 8695f2caaefSJames Feist iface = pidZoneConfigurationIface; 8705f2caaefSJames Feist } 8715f2caaefSJames Feist else if (type == "StepwiseControllers") 8725f2caaefSJames Feist { 8735f2caaefSJames Feist iface = stepwiseConfigurationIface; 8745f2caaefSJames Feist } 8755f2caaefSJames Feist else 8765f2caaefSJames Feist { 87762598e31SEd Tanous BMCWEB_LOG_ERROR("Illegal Type {}", type); 8785f2caaefSJames Feist messages::propertyUnknown(response->res, type); 8795f2caaefSJames Feist return CreatePIDRet::fail; 8805f2caaefSJames Feist } 8816ee7f774SJames Feist 88262598e31SEd Tanous BMCWEB_LOG_DEBUG("del {} {}", path, iface); 8835f2caaefSJames Feist // delete interface 8845f2caaefSJames Feist crow::connections::systemBus->async_method_call( 8855e7e2dc5SEd Tanous [response, path](const boost::system::error_code& ec) { 8865f2caaefSJames Feist if (ec) 8875f2caaefSJames Feist { 88862598e31SEd Tanous BMCWEB_LOG_ERROR("Error patching {}: {}", path, ec); 8895f2caaefSJames Feist messages::internalError(response->res); 890b6baeaa4SJames Feist return; 8915f2caaefSJames Feist } 892b6baeaa4SJames Feist messages::success(response->res); 8935f2caaefSJames Feist }, 8945f2caaefSJames Feist "xyz.openbmc_project.EntityManager", path, iface, "Delete"); 8955f2caaefSJames Feist return CreatePIDRet::del; 8965f2caaefSJames Feist } 8975f2caaefSJames Feist 898711ac7a9SEd Tanous const dbus::utility::ManagedObjectType::value_type* managedItem = nullptr; 899b6baeaa4SJames Feist if (!createNewObject) 900b6baeaa4SJames Feist { 901b6baeaa4SJames Feist // if we aren't creating a new object, we should be able to find it on 902b6baeaa4SJames Feist // d-bus 9039e9b6049SEd Tanous managedItem = findChassis(managedObj, name, chassis); 90473df0db0SJames Feist if (managedItem == nullptr) 905b6baeaa4SJames Feist { 90662598e31SEd Tanous BMCWEB_LOG_ERROR("Failed to get chassis from config patch"); 907ef4c65b7SEd Tanous messages::invalidObject( 908ef4c65b7SEd Tanous response->res, 909ef4c65b7SEd Tanous boost::urls::format("/redfish/v1/Chassis/{}", chassis)); 910b6baeaa4SJames Feist return CreatePIDRet::fail; 911b6baeaa4SJames Feist } 912b6baeaa4SJames Feist } 913b6baeaa4SJames Feist 91426f6976fSEd Tanous if (!profile.empty() && 91573df0db0SJames Feist (type == "PidControllers" || type == "FanControllers" || 91673df0db0SJames Feist type == "StepwiseControllers")) 91773df0db0SJames Feist { 91873df0db0SJames Feist if (managedItem == nullptr) 91973df0db0SJames Feist { 920b9d36b47SEd Tanous output.emplace_back("Profiles", std::vector<std::string>{profile}); 92173df0db0SJames Feist } 92273df0db0SJames Feist else 92373df0db0SJames Feist { 92473df0db0SJames Feist std::string interface; 92573df0db0SJames Feist if (type == "StepwiseControllers") 92673df0db0SJames Feist { 92773df0db0SJames Feist interface = stepwiseConfigurationIface; 92873df0db0SJames Feist } 92973df0db0SJames Feist else 93073df0db0SJames Feist { 93173df0db0SJames Feist interface = pidConfigurationIface; 93273df0db0SJames Feist } 933711ac7a9SEd Tanous bool ifaceFound = false; 934711ac7a9SEd Tanous for (const auto& iface : managedItem->second) 935711ac7a9SEd Tanous { 936711ac7a9SEd Tanous if (iface.first == interface) 937711ac7a9SEd Tanous { 938711ac7a9SEd Tanous ifaceFound = true; 939711ac7a9SEd Tanous for (const auto& prop : iface.second) 940711ac7a9SEd Tanous { 941711ac7a9SEd Tanous if (prop.first == "Profiles") 942711ac7a9SEd Tanous { 943711ac7a9SEd Tanous const std::vector<std::string>* curProfiles = 944711ac7a9SEd Tanous std::get_if<std::vector<std::string>>( 945711ac7a9SEd Tanous &(prop.second)); 946711ac7a9SEd Tanous if (curProfiles == nullptr) 947711ac7a9SEd Tanous { 94862598e31SEd Tanous BMCWEB_LOG_ERROR( 94962598e31SEd Tanous "Illegal profiles in managed object"); 950711ac7a9SEd Tanous messages::internalError(response->res); 951711ac7a9SEd Tanous return CreatePIDRet::fail; 952711ac7a9SEd Tanous } 953711ac7a9SEd Tanous if (std::find(curProfiles->begin(), 954bd79bce8SPatrick Williams curProfiles->end(), profile) == 955bd79bce8SPatrick Williams curProfiles->end()) 956711ac7a9SEd Tanous { 957711ac7a9SEd Tanous std::vector<std::string> newProfiles = 958711ac7a9SEd Tanous *curProfiles; 959711ac7a9SEd Tanous newProfiles.push_back(profile); 960b9d36b47SEd Tanous output.emplace_back("Profiles", newProfiles); 961711ac7a9SEd Tanous } 962711ac7a9SEd Tanous } 963711ac7a9SEd Tanous } 964711ac7a9SEd Tanous } 965711ac7a9SEd Tanous } 966711ac7a9SEd Tanous 967711ac7a9SEd Tanous if (!ifaceFound) 96873df0db0SJames Feist { 96962598e31SEd Tanous BMCWEB_LOG_ERROR("Failed to find interface in managed object"); 97073df0db0SJames Feist messages::internalError(response->res); 97173df0db0SJames Feist return CreatePIDRet::fail; 97273df0db0SJames Feist } 97373df0db0SJames Feist } 97473df0db0SJames Feist } 97573df0db0SJames Feist 97683ff9ab6SJames Feist if (type == "PidControllers" || type == "FanControllers") 97783ff9ab6SJames Feist { 97883ff9ab6SJames Feist if (createNewObject) 97983ff9ab6SJames Feist { 980b9d36b47SEd Tanous output.emplace_back("Class", 981b9d36b47SEd Tanous type == "PidControllers" ? "temp" : "fan"); 982b9d36b47SEd Tanous output.emplace_back("Type", "Pid"); 98383ff9ab6SJames Feist } 9845f2caaefSJames Feist 9859e9b6049SEd Tanous std::optional<std::vector<nlohmann::json::object_t>> zones; 9865f2caaefSJames Feist std::optional<std::vector<std::string>> inputs; 9875f2caaefSJames Feist std::optional<std::vector<std::string>> outputs; 9885f2caaefSJames Feist std::map<std::string, std::optional<double>> doubles; 989b943aaefSJames Feist std::optional<std::string> setpointOffset; 990afc474aeSMyung Bae if (!redfish::json_util::readJson( // 991afc474aeSMyung Bae jsonValue, response->res, // 992afc474aeSMyung Bae "FFGainCoefficient", doubles["FFGainCoefficient"], // 993afc474aeSMyung Bae "FFOffCoefficient", doubles["FFOffCoefficient"], // 994afc474aeSMyung Bae "ICoefficient", doubles["ICoefficient"], // 995afc474aeSMyung Bae "ILimitMax", doubles["ILimitMax"], // 996afc474aeSMyung Bae "ILimitMin", doubles["ILimitMin"], // 997afc474aeSMyung Bae "Inputs", inputs, // 998afc474aeSMyung Bae "NegativeHysteresis", doubles["NegativeHysteresis"], // 999afc474aeSMyung Bae "OutLimitMax", doubles["OutLimitMax"], // 1000afc474aeSMyung Bae "OutLimitMin", doubles["OutLimitMin"], // 1001afc474aeSMyung Bae "Outputs", outputs, // 1002afc474aeSMyung Bae "PCoefficient", doubles["PCoefficient"], // 1003afc474aeSMyung Bae "PositiveHysteresis", doubles["PositiveHysteresis"], // 1004afc474aeSMyung Bae "SetPoint", doubles["SetPoint"], // 1005afc474aeSMyung Bae "SetPointOffset", setpointOffset, // 1006afc474aeSMyung Bae "SlewNeg", doubles["SlewNeg"], // 1007afc474aeSMyung Bae "SlewPos", doubles["SlewPos"], // 1008afc474aeSMyung Bae "Zones", zones // 1009afc474aeSMyung Bae )) 101083ff9ab6SJames Feist { 10115f2caaefSJames Feist return CreatePIDRet::fail; 101283ff9ab6SJames Feist } 1013afc474aeSMyung Bae 10145f2caaefSJames Feist if (zones) 10155f2caaefSJames Feist { 10165f2caaefSJames Feist std::vector<std::string> zonesStr; 10175f2caaefSJames Feist if (!getZonesFromJsonReq(response, *zones, zonesStr)) 10185f2caaefSJames Feist { 101962598e31SEd Tanous BMCWEB_LOG_ERROR("Illegal Zones"); 10205f2caaefSJames Feist return CreatePIDRet::fail; 10215f2caaefSJames Feist } 1022b6baeaa4SJames Feist if (chassis.empty() && 1023e662eae8SEd Tanous findChassis(managedObj, zonesStr[0], chassis) == nullptr) 1024b6baeaa4SJames Feist { 102562598e31SEd Tanous BMCWEB_LOG_ERROR("Failed to get chassis from config patch"); 1026ace85d60SEd Tanous messages::invalidObject( 1027ef4c65b7SEd Tanous response->res, 1028ef4c65b7SEd Tanous boost::urls::format("/redfish/v1/Chassis/{}", chassis)); 1029b6baeaa4SJames Feist return CreatePIDRet::fail; 1030b6baeaa4SJames Feist } 1031b9d36b47SEd Tanous output.emplace_back("Zones", std::move(zonesStr)); 10325f2caaefSJames Feist } 1033afb9ee06SEd Tanous 1034afb9ee06SEd Tanous if (inputs) 10355f2caaefSJames Feist { 1036afb9ee06SEd Tanous for (std::string& value : *inputs) 103783ff9ab6SJames Feist { 1038a170f275SEd Tanous std::replace(value.begin(), value.end(), '_', ' '); 103983ff9ab6SJames Feist } 1040afb9ee06SEd Tanous output.emplace_back("Inputs", *inputs); 1041afb9ee06SEd Tanous } 1042afb9ee06SEd Tanous 1043afb9ee06SEd Tanous if (outputs) 10445f2caaefSJames Feist { 1045afb9ee06SEd Tanous for (std::string& value : *outputs) 10465f2caaefSJames Feist { 1047afb9ee06SEd Tanous std::replace(value.begin(), value.end(), '_', ' '); 10485f2caaefSJames Feist } 1049afb9ee06SEd Tanous output.emplace_back("Outputs", *outputs); 105083ff9ab6SJames Feist } 105183ff9ab6SJames Feist 1052b943aaefSJames Feist if (setpointOffset) 1053b943aaefSJames Feist { 1054b943aaefSJames Feist // translate between redfish and dbus names 1055b943aaefSJames Feist if (*setpointOffset == "UpperThresholdNonCritical") 1056b943aaefSJames Feist { 1057b9d36b47SEd Tanous output.emplace_back("SetPointOffset", "WarningLow"); 1058b943aaefSJames Feist } 1059b943aaefSJames Feist else if (*setpointOffset == "LowerThresholdNonCritical") 1060b943aaefSJames Feist { 1061b9d36b47SEd Tanous output.emplace_back("SetPointOffset", "WarningHigh"); 1062b943aaefSJames Feist } 1063b943aaefSJames Feist else if (*setpointOffset == "LowerThresholdCritical") 1064b943aaefSJames Feist { 1065b9d36b47SEd Tanous output.emplace_back("SetPointOffset", "CriticalLow"); 1066b943aaefSJames Feist } 1067b943aaefSJames Feist else if (*setpointOffset == "UpperThresholdCritical") 1068b943aaefSJames Feist { 1069b9d36b47SEd Tanous output.emplace_back("SetPointOffset", "CriticalHigh"); 1070b943aaefSJames Feist } 1071b943aaefSJames Feist else 1072b943aaefSJames Feist { 107362598e31SEd Tanous BMCWEB_LOG_ERROR("Invalid setpointoffset {}", *setpointOffset); 10749e9b6049SEd Tanous messages::propertyValueNotInList(response->res, name, 1075ace85d60SEd Tanous "SetPointOffset"); 1076b943aaefSJames Feist return CreatePIDRet::fail; 1077b943aaefSJames Feist } 1078b943aaefSJames Feist } 1079b943aaefSJames Feist 108083ff9ab6SJames Feist // doubles 10815f2caaefSJames Feist for (const auto& pairs : doubles) 108283ff9ab6SJames Feist { 10835f2caaefSJames Feist if (!pairs.second) 108483ff9ab6SJames Feist { 10855f2caaefSJames Feist continue; 108683ff9ab6SJames Feist } 108762598e31SEd Tanous BMCWEB_LOG_DEBUG("{} = {}", pairs.first, *pairs.second); 1088b9d36b47SEd Tanous output.emplace_back(pairs.first, *pairs.second); 10895f2caaefSJames Feist } 109083ff9ab6SJames Feist } 109183ff9ab6SJames Feist 109283ff9ab6SJames Feist else if (type == "FanZones") 109383ff9ab6SJames Feist { 1094b9d36b47SEd Tanous output.emplace_back("Type", "Pid.Zone"); 109583ff9ab6SJames Feist 10969e9b6049SEd Tanous std::optional<std::string> chassisId; 10975f2caaefSJames Feist std::optional<double> failSafePercent; 1098d3ec07f8SJames Feist std::optional<double> minThermalOutput; 1099afc474aeSMyung Bae if (!redfish::json_util::readJson( // 1100afc474aeSMyung Bae jsonValue, response->res, // 1101afc474aeSMyung Bae "Chassis/@odata.id", chassisId, // 1102afc474aeSMyung Bae "FailSafePercent", failSafePercent, // 1103afc474aeSMyung Bae "MinThermalOutput", minThermalOutput)) 110483ff9ab6SJames Feist { 110583ff9ab6SJames Feist return CreatePIDRet::fail; 110683ff9ab6SJames Feist } 11075f2caaefSJames Feist 11089e9b6049SEd Tanous if (chassisId) 110983ff9ab6SJames Feist { 1110717794d5SAppaRao Puli // /redfish/v1/chassis/chassis_name/ 11119e9b6049SEd Tanous if (!dbus::utility::getNthStringFromPath(*chassisId, 3, chassis)) 111283ff9ab6SJames Feist { 11139e9b6049SEd Tanous BMCWEB_LOG_ERROR("Got invalid path {}", *chassisId); 1114ace85d60SEd Tanous messages::invalidObject( 1115ef4c65b7SEd Tanous response->res, 11169e9b6049SEd Tanous boost::urls::format("/redfish/v1/Chassis/{}", *chassisId)); 111783ff9ab6SJames Feist return CreatePIDRet::fail; 111883ff9ab6SJames Feist } 111983ff9ab6SJames Feist } 1120d3ec07f8SJames Feist if (minThermalOutput) 112183ff9ab6SJames Feist { 1122b9d36b47SEd Tanous output.emplace_back("MinThermalOutput", *minThermalOutput); 11235f2caaefSJames Feist } 11245f2caaefSJames Feist if (failSafePercent) 112583ff9ab6SJames Feist { 1126b9d36b47SEd Tanous output.emplace_back("FailSafePercent", *failSafePercent); 11275f2caaefSJames Feist } 11285f2caaefSJames Feist } 11295f2caaefSJames Feist else if (type == "StepwiseControllers") 11305f2caaefSJames Feist { 1131b9d36b47SEd Tanous output.emplace_back("Type", "Stepwise"); 11325f2caaefSJames Feist 11339e9b6049SEd Tanous std::optional<std::vector<nlohmann::json::object_t>> zones; 11349e9b6049SEd Tanous std::optional<std::vector<nlohmann::json::object_t>> steps; 11355f2caaefSJames Feist std::optional<std::vector<std::string>> inputs; 11365f2caaefSJames Feist std::optional<double> positiveHysteresis; 11375f2caaefSJames Feist std::optional<double> negativeHysteresis; 1138c33a90ecSJames Feist std::optional<std::string> direction; // upper clipping curve vs lower 1139afc474aeSMyung Bae if (!redfish::json_util::readJson( // 1140afc474aeSMyung Bae jsonValue, response->res, // 1141afc474aeSMyung Bae "Direction", direction, // 1142afc474aeSMyung Bae "Inputs", inputs, // 1143afc474aeSMyung Bae "NegativeHysteresis", negativeHysteresis, // 1144afc474aeSMyung Bae "PositiveHysteresis", positiveHysteresis, // 1145afc474aeSMyung Bae "Steps", steps, // 1146afc474aeSMyung Bae "Zones", zones // 1147afc474aeSMyung Bae )) 11485f2caaefSJames Feist { 114983ff9ab6SJames Feist return CreatePIDRet::fail; 115083ff9ab6SJames Feist } 11515f2caaefSJames Feist 11525f2caaefSJames Feist if (zones) 115383ff9ab6SJames Feist { 1154b6baeaa4SJames Feist std::vector<std::string> zonesStrs; 1155b6baeaa4SJames Feist if (!getZonesFromJsonReq(response, *zones, zonesStrs)) 11565f2caaefSJames Feist { 115762598e31SEd Tanous BMCWEB_LOG_ERROR("Illegal Zones"); 115883ff9ab6SJames Feist return CreatePIDRet::fail; 115983ff9ab6SJames Feist } 1160b6baeaa4SJames Feist if (chassis.empty() && 1161e662eae8SEd Tanous findChassis(managedObj, zonesStrs[0], chassis) == nullptr) 1162b6baeaa4SJames Feist { 116362598e31SEd Tanous BMCWEB_LOG_ERROR("Failed to get chassis from config patch"); 1164ace85d60SEd Tanous messages::invalidObject( 1165ef4c65b7SEd Tanous response->res, 1166ef4c65b7SEd Tanous boost::urls::format("/redfish/v1/Chassis/{}", chassis)); 1167b6baeaa4SJames Feist return CreatePIDRet::fail; 1168b6baeaa4SJames Feist } 1169b9d36b47SEd Tanous output.emplace_back("Zones", std::move(zonesStrs)); 11705f2caaefSJames Feist } 11715f2caaefSJames Feist if (steps) 11725f2caaefSJames Feist { 11735f2caaefSJames Feist std::vector<double> readings; 11745f2caaefSJames Feist std::vector<double> outputs; 11755f2caaefSJames Feist for (auto& step : *steps) 11765f2caaefSJames Feist { 1177543f4400SEd Tanous double target = 0.0; 1178543f4400SEd Tanous double out = 0.0; 11795f2caaefSJames Feist 1180afc474aeSMyung Bae if (!redfish::json_util::readJsonObject( // 1181afc474aeSMyung Bae step, response->res, // 1182afc474aeSMyung Bae "Output", out, // 1183afc474aeSMyung Bae "Target", target // 1184afc474aeSMyung Bae )) 11855f2caaefSJames Feist { 11865f2caaefSJames Feist return CreatePIDRet::fail; 11875f2caaefSJames Feist } 11885f2caaefSJames Feist readings.emplace_back(target); 118923a21a1cSEd Tanous outputs.emplace_back(out); 11905f2caaefSJames Feist } 1191b9d36b47SEd Tanous output.emplace_back("Reading", std::move(readings)); 1192b9d36b47SEd Tanous output.emplace_back("Output", std::move(outputs)); 11935f2caaefSJames Feist } 11945f2caaefSJames Feist if (inputs) 11955f2caaefSJames Feist { 11965f2caaefSJames Feist for (std::string& value : *inputs) 11975f2caaefSJames Feist { 1198a170f275SEd Tanous std::replace(value.begin(), value.end(), '_', ' '); 11995f2caaefSJames Feist } 1200b9d36b47SEd Tanous output.emplace_back("Inputs", std::move(*inputs)); 12015f2caaefSJames Feist } 12025f2caaefSJames Feist if (negativeHysteresis) 12035f2caaefSJames Feist { 1204b9d36b47SEd Tanous output.emplace_back("NegativeHysteresis", *negativeHysteresis); 12055f2caaefSJames Feist } 12065f2caaefSJames Feist if (positiveHysteresis) 12075f2caaefSJames Feist { 1208b9d36b47SEd Tanous output.emplace_back("PositiveHysteresis", *positiveHysteresis); 120983ff9ab6SJames Feist } 1210c33a90ecSJames Feist if (direction) 1211c33a90ecSJames Feist { 1212c33a90ecSJames Feist constexpr const std::array<const char*, 2> allowedDirections = { 1213c33a90ecSJames Feist "Ceiling", "Floor"}; 12143544d2a7SEd Tanous if (std::ranges::find(allowedDirections, *direction) == 12153544d2a7SEd Tanous allowedDirections.end()) 1216c33a90ecSJames Feist { 1217c33a90ecSJames Feist messages::propertyValueTypeError(response->res, "Direction", 1218c33a90ecSJames Feist *direction); 1219c33a90ecSJames Feist return CreatePIDRet::fail; 1220c33a90ecSJames Feist } 1221b9d36b47SEd Tanous output.emplace_back("Class", *direction); 1222c33a90ecSJames Feist } 122383ff9ab6SJames Feist } 122483ff9ab6SJames Feist else 122583ff9ab6SJames Feist { 122662598e31SEd Tanous BMCWEB_LOG_ERROR("Illegal Type {}", type); 122735a62c7cSJason M. Bills messages::propertyUnknown(response->res, type); 122883ff9ab6SJames Feist return CreatePIDRet::fail; 122983ff9ab6SJames Feist } 123083ff9ab6SJames Feist return CreatePIDRet::patch; 123183ff9ab6SJames Feist } 123273df0db0SJames Feist struct GetPIDValues : std::enable_shared_from_this<GetPIDValues> 123373df0db0SJames Feist { 12346936afe4SEd Tanous struct CompletionValues 12356936afe4SEd Tanous { 12366936afe4SEd Tanous std::vector<std::string> supportedProfiles; 12376936afe4SEd Tanous std::string currentProfile; 12386936afe4SEd Tanous dbus::utility::MapperGetSubTreeResponse subtree; 12396936afe4SEd Tanous }; 124083ff9ab6SJames Feist 12414e23a444SEd Tanous explicit GetPIDValues( 12424e23a444SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncRespIn) : 124323a21a1cSEd Tanous asyncResp(asyncRespIn) 124473df0db0SJames Feist 12451214b7e7SGunnar Mills {} 12469c310685SBorawski.Lukasz 124773df0db0SJames Feist void run() 12485b4aa86bSJames Feist { 124973df0db0SJames Feist std::shared_ptr<GetPIDValues> self = shared_from_this(); 125073df0db0SJames Feist 125173df0db0SJames Feist // get all configurations 1252e99073f5SGeorge Liu constexpr std::array<std::string_view, 4> interfaces = { 1253e99073f5SGeorge Liu pidConfigurationIface, pidZoneConfigurationIface, 1254e99073f5SGeorge Liu objectManagerIface, stepwiseConfigurationIface}; 1255e99073f5SGeorge Liu dbus::utility::getSubTree( 1256e99073f5SGeorge Liu "/", 0, interfaces, 1257b9d36b47SEd Tanous [self]( 1258e99073f5SGeorge Liu const boost::system::error_code& ec, 1259b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreeResponse& subtreeLocal) { 12605b4aa86bSJames Feist if (ec) 12615b4aa86bSJames Feist { 126262598e31SEd Tanous BMCWEB_LOG_ERROR("{}", ec); 126373df0db0SJames Feist messages::internalError(self->asyncResp->res); 126473df0db0SJames Feist return; 126573df0db0SJames Feist } 12666936afe4SEd Tanous self->complete.subtree = subtreeLocal; 1267e99073f5SGeorge Liu }); 126873df0db0SJames Feist 126973df0db0SJames Feist // at the same time get the selected profile 1270e99073f5SGeorge Liu constexpr std::array<std::string_view, 1> thermalModeIfaces = { 1271e99073f5SGeorge Liu thermalModeIface}; 1272e99073f5SGeorge Liu dbus::utility::getSubTree( 1273e99073f5SGeorge Liu "/", 0, thermalModeIfaces, 1274b9d36b47SEd Tanous [self]( 1275e99073f5SGeorge Liu const boost::system::error_code& ec, 1276b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreeResponse& subtreeLocal) { 127723a21a1cSEd Tanous if (ec || subtreeLocal.empty()) 127873df0db0SJames Feist { 127973df0db0SJames Feist return; 128073df0db0SJames Feist } 128123a21a1cSEd Tanous if (subtreeLocal[0].second.size() != 1) 128273df0db0SJames Feist { 128373df0db0SJames Feist // invalid mapper response, should never happen 128462598e31SEd Tanous BMCWEB_LOG_ERROR("GetPIDValues: Mapper Error"); 128573df0db0SJames Feist messages::internalError(self->asyncResp->res); 12865b4aa86bSJames Feist return; 12875b4aa86bSJames Feist } 12885b4aa86bSJames Feist 128923a21a1cSEd Tanous const std::string& path = subtreeLocal[0].first; 129023a21a1cSEd Tanous const std::string& owner = subtreeLocal[0].second[0].first; 1291fac6e53bSKrzysztof Grobelny 1292fac6e53bSKrzysztof Grobelny sdbusplus::asio::getAllProperties( 1293bd79bce8SPatrick Williams *crow::connections::systemBus, owner, path, 1294bd79bce8SPatrick Williams thermalModeIface, 1295168e20c1SEd Tanous [path, owner, 12965e7e2dc5SEd Tanous self](const boost::system::error_code& ec2, 1297b9d36b47SEd Tanous const dbus::utility::DBusPropertiesMap& resp) { 129823a21a1cSEd Tanous if (ec2) 129973df0db0SJames Feist { 130062598e31SEd Tanous BMCWEB_LOG_ERROR( 1301bd79bce8SPatrick Williams "GetPIDValues: Can't get thermalModeIface {}", 1302bd79bce8SPatrick Williams path); 130373df0db0SJames Feist messages::internalError(self->asyncResp->res); 130473df0db0SJames Feist return; 130573df0db0SJames Feist } 1306fac6e53bSKrzysztof Grobelny 1307271584abSEd Tanous const std::string* current = nullptr; 1308271584abSEd Tanous const std::vector<std::string>* supported = nullptr; 1309fac6e53bSKrzysztof Grobelny 1310fac6e53bSKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 1311bd79bce8SPatrick Williams dbus_utils::UnpackErrorPrinter(), resp, "Current", 1312bd79bce8SPatrick Williams current, "Supported", supported); 1313fac6e53bSKrzysztof Grobelny 1314fac6e53bSKrzysztof Grobelny if (!success) 131573df0db0SJames Feist { 1316002d39b4SEd Tanous messages::internalError(self->asyncResp->res); 131773df0db0SJames Feist return; 131873df0db0SJames Feist } 1319fac6e53bSKrzysztof Grobelny 132073df0db0SJames Feist if (current == nullptr || supported == nullptr) 132173df0db0SJames Feist { 132262598e31SEd Tanous BMCWEB_LOG_ERROR( 1323bd79bce8SPatrick Williams "GetPIDValues: thermal mode iface invalid {}", 1324bd79bce8SPatrick Williams path); 132573df0db0SJames Feist messages::internalError(self->asyncResp->res); 132673df0db0SJames Feist return; 132773df0db0SJames Feist } 13286936afe4SEd Tanous self->complete.currentProfile = *current; 13296936afe4SEd Tanous self->complete.supportedProfiles = *supported; 1330fac6e53bSKrzysztof Grobelny }); 1331e99073f5SGeorge Liu }); 133273df0db0SJames Feist } 133373df0db0SJames Feist 13346936afe4SEd Tanous static void 13356936afe4SEd Tanous processingComplete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 13366936afe4SEd Tanous const CompletionValues& completion) 133773df0db0SJames Feist { 133873df0db0SJames Feist if (asyncResp->res.result() != boost::beast::http::status::ok) 133973df0db0SJames Feist { 134073df0db0SJames Feist return; 134173df0db0SJames Feist } 13425b4aa86bSJames Feist // create map of <connection, path to objMgr>> 13436936afe4SEd Tanous boost::container::flat_map< 13446936afe4SEd Tanous std::string, std::string, std::less<>, 13456936afe4SEd Tanous std::vector<std::pair<std::string, std::string>>> 13466936afe4SEd Tanous objectMgrPaths; 13476936afe4SEd Tanous boost::container::flat_set<std::string, std::less<>, 13486936afe4SEd Tanous std::vector<std::string>> 13496936afe4SEd Tanous calledConnections; 13506936afe4SEd Tanous for (const auto& pathGroup : completion.subtree) 13515b4aa86bSJames Feist { 13525b4aa86bSJames Feist for (const auto& connectionGroup : pathGroup.second) 13535b4aa86bSJames Feist { 13546bce33bcSJames Feist auto findConnection = 13556bce33bcSJames Feist calledConnections.find(connectionGroup.first); 13566bce33bcSJames Feist if (findConnection != calledConnections.end()) 13576bce33bcSJames Feist { 13586bce33bcSJames Feist break; 13596bce33bcSJames Feist } 136073df0db0SJames Feist for (const std::string& interface : connectionGroup.second) 13615b4aa86bSJames Feist { 13625b4aa86bSJames Feist if (interface == objectManagerIface) 13635b4aa86bSJames Feist { 136473df0db0SJames Feist objectMgrPaths[connectionGroup.first] = pathGroup.first; 13655b4aa86bSJames Feist } 13665b4aa86bSJames Feist // this list is alphabetical, so we 13675b4aa86bSJames Feist // should have found the objMgr by now 13685b4aa86bSJames Feist if (interface == pidConfigurationIface || 1369b7a08d04SJames Feist interface == pidZoneConfigurationIface || 1370b7a08d04SJames Feist interface == stepwiseConfigurationIface) 13715b4aa86bSJames Feist { 13725b4aa86bSJames Feist auto findObjMgr = 13735b4aa86bSJames Feist objectMgrPaths.find(connectionGroup.first); 13745b4aa86bSJames Feist if (findObjMgr == objectMgrPaths.end()) 13755b4aa86bSJames Feist { 137662598e31SEd Tanous BMCWEB_LOG_DEBUG("{}Has no Object Manager", 137762598e31SEd Tanous connectionGroup.first); 13785b4aa86bSJames Feist continue; 13795b4aa86bSJames Feist } 13806bce33bcSJames Feist 13816bce33bcSJames Feist calledConnections.insert(connectionGroup.first); 13826bce33bcSJames Feist 138373df0db0SJames Feist asyncPopulatePid(findObjMgr->first, findObjMgr->second, 13846936afe4SEd Tanous completion.currentProfile, 13856936afe4SEd Tanous completion.supportedProfiles, 138673df0db0SJames Feist asyncResp); 13875b4aa86bSJames Feist break; 13885b4aa86bSJames Feist } 13895b4aa86bSJames Feist } 13905b4aa86bSJames Feist } 13915b4aa86bSJames Feist } 139273df0db0SJames Feist } 139373df0db0SJames Feist 13946936afe4SEd Tanous ~GetPIDValues() 13956936afe4SEd Tanous { 13966936afe4SEd Tanous boost::asio::post(crow::connections::systemBus->get_io_context(), 13976936afe4SEd Tanous std::bind_front(&processingComplete, asyncResp, 13986936afe4SEd Tanous std::move(complete))); 13996936afe4SEd Tanous } 14006936afe4SEd Tanous 1401ecd6a3a2SEd Tanous GetPIDValues(const GetPIDValues&) = delete; 1402ecd6a3a2SEd Tanous GetPIDValues(GetPIDValues&&) = delete; 1403ecd6a3a2SEd Tanous GetPIDValues& operator=(const GetPIDValues&) = delete; 1404ecd6a3a2SEd Tanous GetPIDValues& operator=(GetPIDValues&&) = delete; 1405ecd6a3a2SEd Tanous 14068d1b46d7Szhanghch05 std::shared_ptr<bmcweb::AsyncResp> asyncResp; 14076936afe4SEd Tanous CompletionValues complete; 140873df0db0SJames Feist }; 140973df0db0SJames Feist 141073df0db0SJames Feist struct SetPIDValues : std::enable_shared_from_this<SetPIDValues> 141173df0db0SJames Feist { 14129e9b6049SEd Tanous SetPIDValues( 14139e9b6049SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncRespIn, 14149e9b6049SEd Tanous std::vector< 14159e9b6049SEd Tanous std::pair<std::string, std::optional<nlohmann::json::object_t>>>&& 14169e9b6049SEd Tanous configurationsIn, 14179e9b6049SEd Tanous std::optional<std::string>& profileIn) : 1418bd79bce8SPatrick Williams asyncResp(asyncRespIn), configuration(std::move(configurationsIn)), 14199e9b6049SEd Tanous profile(std::move(profileIn)) 14209e9b6049SEd Tanous {} 1421ecd6a3a2SEd Tanous 1422ecd6a3a2SEd Tanous SetPIDValues(const SetPIDValues&) = delete; 1423ecd6a3a2SEd Tanous SetPIDValues(SetPIDValues&&) = delete; 1424ecd6a3a2SEd Tanous SetPIDValues& operator=(const SetPIDValues&) = delete; 1425ecd6a3a2SEd Tanous SetPIDValues& operator=(SetPIDValues&&) = delete; 1426ecd6a3a2SEd Tanous 142773df0db0SJames Feist void run() 142873df0db0SJames Feist { 142973df0db0SJames Feist if (asyncResp->res.result() != boost::beast::http::status::ok) 143073df0db0SJames Feist { 143173df0db0SJames Feist return; 143273df0db0SJames Feist } 143373df0db0SJames Feist 143473df0db0SJames Feist std::shared_ptr<SetPIDValues> self = shared_from_this(); 143573df0db0SJames Feist 143673df0db0SJames Feist // todo(james): might make sense to do a mapper call here if this 143773df0db0SJames Feist // interface gets more traction 14385eb468daSGeorge Liu sdbusplus::message::object_path objPath( 14395eb468daSGeorge Liu "/xyz/openbmc_project/inventory"); 14405eb468daSGeorge Liu dbus::utility::getManagedObjects( 14415eb468daSGeorge Liu "xyz.openbmc_project.EntityManager", objPath, 14425e7e2dc5SEd Tanous [self](const boost::system::error_code& ec, 1443914e2d5dSEd Tanous const dbus::utility::ManagedObjectType& mObj) { 144473df0db0SJames Feist if (ec) 144573df0db0SJames Feist { 144662598e31SEd Tanous BMCWEB_LOG_ERROR("Error communicating to Entity Manager"); 144773df0db0SJames Feist messages::internalError(self->asyncResp->res); 144873df0db0SJames Feist return; 144973df0db0SJames Feist } 1450e69d9de2SJames Feist const std::array<const char*, 3> configurations = { 1451e69d9de2SJames Feist pidConfigurationIface, pidZoneConfigurationIface, 1452e69d9de2SJames Feist stepwiseConfigurationIface}; 1453e69d9de2SJames Feist 145414b0b8d5SJames Feist for (const auto& [path, object] : mObj) 1455e69d9de2SJames Feist { 145614b0b8d5SJames Feist for (const auto& [interface, _] : object) 1457e69d9de2SJames Feist { 14583544d2a7SEd Tanous if (std::ranges::find(configurations, interface) != 14593544d2a7SEd Tanous configurations.end()) 1460e69d9de2SJames Feist { 146114b0b8d5SJames Feist self->objectCount++; 1462e69d9de2SJames Feist break; 1463e69d9de2SJames Feist } 1464e69d9de2SJames Feist } 1465e69d9de2SJames Feist } 1466914e2d5dSEd Tanous self->managedObj = mObj; 14675eb468daSGeorge Liu }); 146873df0db0SJames Feist 146973df0db0SJames Feist // at the same time get the profile information 1470e99073f5SGeorge Liu constexpr std::array<std::string_view, 1> thermalModeIfaces = { 1471e99073f5SGeorge Liu thermalModeIface}; 1472e99073f5SGeorge Liu dbus::utility::getSubTree( 1473e99073f5SGeorge Liu "/", 0, thermalModeIfaces, 1474e99073f5SGeorge Liu [self](const boost::system::error_code& ec, 1475b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreeResponse& subtree) { 147673df0db0SJames Feist if (ec || subtree.empty()) 147773df0db0SJames Feist { 147873df0db0SJames Feist return; 147973df0db0SJames Feist } 148073df0db0SJames Feist if (subtree[0].second.empty()) 148173df0db0SJames Feist { 148273df0db0SJames Feist // invalid mapper response, should never happen 148362598e31SEd Tanous BMCWEB_LOG_ERROR("SetPIDValues: Mapper Error"); 148473df0db0SJames Feist messages::internalError(self->asyncResp->res); 148573df0db0SJames Feist return; 148673df0db0SJames Feist } 148773df0db0SJames Feist 148873df0db0SJames Feist const std::string& path = subtree[0].first; 148973df0db0SJames Feist const std::string& owner = subtree[0].second[0].first; 1490fac6e53bSKrzysztof Grobelny sdbusplus::asio::getAllProperties( 1491bd79bce8SPatrick Williams *crow::connections::systemBus, owner, path, 1492bd79bce8SPatrick Williams thermalModeIface, 1493bd79bce8SPatrick Williams [self, path, 1494bd79bce8SPatrick Williams owner](const boost::system::error_code& ec2, 1495b9d36b47SEd Tanous const dbus::utility::DBusPropertiesMap& r) { 1496cb13a392SEd Tanous if (ec2) 149773df0db0SJames Feist { 149862598e31SEd Tanous BMCWEB_LOG_ERROR( 1499bd79bce8SPatrick Williams "SetPIDValues: Can't get thermalModeIface {}", 1500bd79bce8SPatrick Williams path); 150173df0db0SJames Feist messages::internalError(self->asyncResp->res); 150273df0db0SJames Feist return; 150373df0db0SJames Feist } 1504271584abSEd Tanous const std::string* current = nullptr; 1505271584abSEd Tanous const std::vector<std::string>* supported = nullptr; 1506fac6e53bSKrzysztof Grobelny 1507fac6e53bSKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 1508bd79bce8SPatrick Williams dbus_utils::UnpackErrorPrinter(), r, "Current", 1509bd79bce8SPatrick Williams current, "Supported", supported); 1510fac6e53bSKrzysztof Grobelny 1511fac6e53bSKrzysztof Grobelny if (!success) 151273df0db0SJames Feist { 1513002d39b4SEd Tanous messages::internalError(self->asyncResp->res); 151473df0db0SJames Feist return; 151573df0db0SJames Feist } 1516fac6e53bSKrzysztof Grobelny 151773df0db0SJames Feist if (current == nullptr || supported == nullptr) 151873df0db0SJames Feist { 151962598e31SEd Tanous BMCWEB_LOG_ERROR( 1520bd79bce8SPatrick Williams "SetPIDValues: thermal mode iface invalid {}", 1521bd79bce8SPatrick Williams path); 152273df0db0SJames Feist messages::internalError(self->asyncResp->res); 152373df0db0SJames Feist return; 152473df0db0SJames Feist } 152573df0db0SJames Feist self->currentProfile = *current; 152673df0db0SJames Feist self->supportedProfiles = *supported; 152773df0db0SJames Feist self->profileConnection = owner; 152873df0db0SJames Feist self->profilePath = path; 1529fac6e53bSKrzysztof Grobelny }); 1530e99073f5SGeorge Liu }); 153173df0db0SJames Feist } 153224b2fe81SEd Tanous void pidSetDone() 153373df0db0SJames Feist { 153473df0db0SJames Feist if (asyncResp->res.result() != boost::beast::http::status::ok) 153573df0db0SJames Feist { 153673df0db0SJames Feist return; 15375b4aa86bSJames Feist } 15388d1b46d7Szhanghch05 std::shared_ptr<bmcweb::AsyncResp> response = asyncResp; 153973df0db0SJames Feist if (profile) 154073df0db0SJames Feist { 15413544d2a7SEd Tanous if (std::ranges::find(supportedProfiles, *profile) == 15423544d2a7SEd Tanous supportedProfiles.end()) 154373df0db0SJames Feist { 154473df0db0SJames Feist messages::actionParameterUnknown(response->res, "Profile", 154573df0db0SJames Feist *profile); 154673df0db0SJames Feist return; 154773df0db0SJames Feist } 154873df0db0SJames Feist currentProfile = *profile; 15499ae226faSGeorge Liu sdbusplus::asio::setProperty( 15509ae226faSGeorge Liu *crow::connections::systemBus, profileConnection, profilePath, 15519ae226faSGeorge Liu thermalModeIface, "Current", *profile, 15525e7e2dc5SEd Tanous [response](const boost::system::error_code& ec) { 155373df0db0SJames Feist if (ec) 155473df0db0SJames Feist { 155562598e31SEd Tanous BMCWEB_LOG_ERROR("Error patching profile{}", ec); 155673df0db0SJames Feist messages::internalError(response->res); 155773df0db0SJames Feist } 15589ae226faSGeorge Liu }); 155973df0db0SJames Feist } 156073df0db0SJames Feist 156173df0db0SJames Feist for (auto& containerPair : configuration) 156273df0db0SJames Feist { 156373df0db0SJames Feist auto& container = containerPair.second; 156473df0db0SJames Feist if (!container) 156573df0db0SJames Feist { 156673df0db0SJames Feist continue; 156773df0db0SJames Feist } 15686ee7f774SJames Feist 156902cad96eSEd Tanous const std::string& type = containerPair.first; 157073df0db0SJames Feist 15719e9b6049SEd Tanous for (auto& [name, value] : *container) 157273df0db0SJames Feist { 1573cddbf3dfSPotin Lai std::string dbusObjName = name; 1574cddbf3dfSPotin Lai std::replace(dbusObjName.begin(), dbusObjName.end(), ' ', '_'); 157562598e31SEd Tanous BMCWEB_LOG_DEBUG("looking for {}", name); 15766ee7f774SJames Feist 15773544d2a7SEd Tanous auto pathItr = std::ranges::find_if( 15783544d2a7SEd Tanous managedObj, [&dbusObjName](const auto& obj) { 157991f75cafSEd Tanous return obj.first.filename() == dbusObjName; 158073df0db0SJames Feist }); 1581b9d36b47SEd Tanous dbus::utility::DBusPropertiesMap output; 158273df0db0SJames Feist 158373df0db0SJames Feist output.reserve(16); // The pid interface length 158473df0db0SJames Feist 158573df0db0SJames Feist // determines if we're patching entity-manager or 158673df0db0SJames Feist // creating a new object 158773df0db0SJames Feist bool createNewObject = (pathItr == managedObj.end()); 158862598e31SEd Tanous BMCWEB_LOG_DEBUG("Found = {}", !createNewObject); 15896ee7f774SJames Feist 159073df0db0SJames Feist std::string iface; 1591ea2b670dSEd Tanous if (!createNewObject) 1592ea2b670dSEd Tanous { 15938be2b5b6SPotin Lai bool findInterface = false; 1594ea2b670dSEd Tanous for (const auto& interface : pathItr->second) 1595ea2b670dSEd Tanous { 1596ea2b670dSEd Tanous if (interface.first == pidConfigurationIface) 1597ea2b670dSEd Tanous { 1598ea2b670dSEd Tanous if (type == "PidControllers" || 1599ea2b670dSEd Tanous type == "FanControllers") 160073df0db0SJames Feist { 160173df0db0SJames Feist iface = pidConfigurationIface; 16028be2b5b6SPotin Lai findInterface = true; 16038be2b5b6SPotin Lai break; 160473df0db0SJames Feist } 160573df0db0SJames Feist } 1606ea2b670dSEd Tanous else if (interface.first == pidZoneConfigurationIface) 160773df0db0SJames Feist { 1608ea2b670dSEd Tanous if (type == "FanZones") 160973df0db0SJames Feist { 1610da39350aSPavanKumarIntel iface = pidZoneConfigurationIface; 16118be2b5b6SPotin Lai findInterface = true; 16128be2b5b6SPotin Lai break; 161373df0db0SJames Feist } 161473df0db0SJames Feist } 1615ea2b670dSEd Tanous else if (interface.first == stepwiseConfigurationIface) 1616ea2b670dSEd Tanous { 1617ea2b670dSEd Tanous if (type == "StepwiseControllers") 161873df0db0SJames Feist { 161973df0db0SJames Feist iface = stepwiseConfigurationIface; 16208be2b5b6SPotin Lai findInterface = true; 16218be2b5b6SPotin Lai break; 16228be2b5b6SPotin Lai } 16238be2b5b6SPotin Lai } 16248be2b5b6SPotin Lai } 16258be2b5b6SPotin Lai 16268be2b5b6SPotin Lai // create new object if interface not found 16278be2b5b6SPotin Lai if (!findInterface) 16288be2b5b6SPotin Lai { 162973df0db0SJames Feist createNewObject = true; 163073df0db0SJames Feist } 1631ea2b670dSEd Tanous } 16326ee7f774SJames Feist 16339e9b6049SEd Tanous if (createNewObject && value == nullptr) 16346ee7f774SJames Feist { 16354e0453b1SGunnar Mills // can't delete a non-existent object 16369e9b6049SEd Tanous messages::propertyValueNotInList(response->res, value, 1637e2616cc5SEd Tanous name); 16386ee7f774SJames Feist continue; 16396ee7f774SJames Feist } 16406ee7f774SJames Feist 16416ee7f774SJames Feist std::string path; 16426ee7f774SJames Feist if (pathItr != managedObj.end()) 16436ee7f774SJames Feist { 16446ee7f774SJames Feist path = pathItr->first.str; 16456ee7f774SJames Feist } 16466ee7f774SJames Feist 164762598e31SEd Tanous BMCWEB_LOG_DEBUG("Create new = {}", createNewObject); 1648e69d9de2SJames Feist 1649e69d9de2SJames Feist // arbitrary limit to avoid attacks 1650e69d9de2SJames Feist constexpr const size_t controllerLimit = 500; 165114b0b8d5SJames Feist if (createNewObject && objectCount >= controllerLimit) 1652e69d9de2SJames Feist { 1653e69d9de2SJames Feist messages::resourceExhaustion(response->res, type); 1654e69d9de2SJames Feist continue; 1655e69d9de2SJames Feist } 1656a170f275SEd Tanous std::string escaped = name; 1657a170f275SEd Tanous std::replace(escaped.begin(), escaped.end(), '_', ' '); 1658a170f275SEd Tanous output.emplace_back("Name", escaped); 165973df0db0SJames Feist 166073df0db0SJames Feist std::string chassis; 166173df0db0SJames Feist CreatePIDRet ret = createPidInterface( 16629e9b6049SEd Tanous response, type, name, value, path, managedObj, 16639e9b6049SEd Tanous createNewObject, output, chassis, currentProfile); 166473df0db0SJames Feist if (ret == CreatePIDRet::fail) 166573df0db0SJames Feist { 166673df0db0SJames Feist return; 166773df0db0SJames Feist } 16683174e4dfSEd Tanous if (ret == CreatePIDRet::del) 166973df0db0SJames Feist { 167073df0db0SJames Feist continue; 167173df0db0SJames Feist } 167273df0db0SJames Feist 167373df0db0SJames Feist if (!createNewObject) 167473df0db0SJames Feist { 167573df0db0SJames Feist for (const auto& property : output) 167673df0db0SJames Feist { 16777a696974SPotin Lai crow::connections::systemBus->async_method_call( 167873df0db0SJames Feist [response, 167973df0db0SJames Feist propertyName{std::string(property.first)}]( 16805e7e2dc5SEd Tanous const boost::system::error_code& ec) { 168173df0db0SJames Feist if (ec) 168273df0db0SJames Feist { 168362598e31SEd Tanous BMCWEB_LOG_ERROR("Error patching {}: {}", 168462598e31SEd Tanous propertyName, ec); 168573df0db0SJames Feist messages::internalError(response->res); 168673df0db0SJames Feist return; 168773df0db0SJames Feist } 168873df0db0SJames Feist messages::success(response->res); 16897a696974SPotin Lai }, 16907a696974SPotin Lai "xyz.openbmc_project.EntityManager", path, 16917a696974SPotin Lai "org.freedesktop.DBus.Properties", "Set", iface, 16927a696974SPotin Lai property.first, property.second); 169373df0db0SJames Feist } 169473df0db0SJames Feist } 169573df0db0SJames Feist else 169673df0db0SJames Feist { 169773df0db0SJames Feist if (chassis.empty()) 169873df0db0SJames Feist { 169962598e31SEd Tanous BMCWEB_LOG_ERROR("Failed to get chassis from config"); 1700ace85d60SEd Tanous messages::internalError(response->res); 170173df0db0SJames Feist return; 170273df0db0SJames Feist } 170373df0db0SJames Feist 170473df0db0SJames Feist bool foundChassis = false; 170573df0db0SJames Feist for (const auto& obj : managedObj) 170673df0db0SJames Feist { 170791f75cafSEd Tanous if (obj.first.filename() == chassis) 170873df0db0SJames Feist { 170973df0db0SJames Feist chassis = obj.first.str; 171073df0db0SJames Feist foundChassis = true; 171173df0db0SJames Feist break; 171273df0db0SJames Feist } 171373df0db0SJames Feist } 171473df0db0SJames Feist if (!foundChassis) 171573df0db0SJames Feist { 171662598e31SEd Tanous BMCWEB_LOG_ERROR("Failed to find chassis on dbus"); 171773df0db0SJames Feist messages::resourceMissingAtURI( 1718ace85d60SEd Tanous response->res, 1719ef4c65b7SEd Tanous boost::urls::format("/redfish/v1/Chassis/{}", 1720ef4c65b7SEd Tanous chassis)); 172173df0db0SJames Feist return; 172273df0db0SJames Feist } 172373df0db0SJames Feist 172473df0db0SJames Feist crow::connections::systemBus->async_method_call( 17255e7e2dc5SEd Tanous [response](const boost::system::error_code& ec) { 172673df0db0SJames Feist if (ec) 172773df0db0SJames Feist { 1728bd79bce8SPatrick Williams BMCWEB_LOG_ERROR("Error Adding Pid Object {}", 1729bd79bce8SPatrick Williams ec); 173073df0db0SJames Feist messages::internalError(response->res); 173173df0db0SJames Feist return; 173273df0db0SJames Feist } 173373df0db0SJames Feist messages::success(response->res); 173473df0db0SJames Feist }, 173573df0db0SJames Feist "xyz.openbmc_project.EntityManager", chassis, 173673df0db0SJames Feist "xyz.openbmc_project.AddObject", "AddObject", output); 173773df0db0SJames Feist } 173873df0db0SJames Feist } 173973df0db0SJames Feist } 174073df0db0SJames Feist } 174124b2fe81SEd Tanous 174224b2fe81SEd Tanous ~SetPIDValues() 174324b2fe81SEd Tanous { 174424b2fe81SEd Tanous try 174524b2fe81SEd Tanous { 174624b2fe81SEd Tanous pidSetDone(); 174724b2fe81SEd Tanous } 174824b2fe81SEd Tanous catch (...) 174924b2fe81SEd Tanous { 175062598e31SEd Tanous BMCWEB_LOG_CRITICAL("pidSetDone threw exception"); 175124b2fe81SEd Tanous } 175224b2fe81SEd Tanous } 175324b2fe81SEd Tanous 17548d1b46d7Szhanghch05 std::shared_ptr<bmcweb::AsyncResp> asyncResp; 17559e9b6049SEd Tanous std::vector<std::pair<std::string, std::optional<nlohmann::json::object_t>>> 175673df0db0SJames Feist configuration; 175773df0db0SJames Feist std::optional<std::string> profile; 175873df0db0SJames Feist dbus::utility::ManagedObjectType managedObj; 175973df0db0SJames Feist std::vector<std::string> supportedProfiles; 176073df0db0SJames Feist std::string currentProfile; 176173df0db0SJames Feist std::string profileConnection; 176273df0db0SJames Feist std::string profilePath; 176314b0b8d5SJames Feist size_t objectCount = 0; 176473df0db0SJames Feist }; 176573df0db0SJames Feist 1766071d8fdfSSunnySrivastava1984 /** 1767071d8fdfSSunnySrivastava1984 * @brief Retrieves BMC manager location data over DBus 1768071d8fdfSSunnySrivastava1984 * 1769ac106bf6SEd Tanous * @param[in] asyncResp Shared pointer for completing asynchronous calls 1770071d8fdfSSunnySrivastava1984 * @param[in] connectionName - service name 1771071d8fdfSSunnySrivastava1984 * @param[in] path - object path 1772071d8fdfSSunnySrivastava1984 * @return none 1773071d8fdfSSunnySrivastava1984 */ 1774ac106bf6SEd Tanous inline void getLocation(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1775071d8fdfSSunnySrivastava1984 const std::string& connectionName, 1776071d8fdfSSunnySrivastava1984 const std::string& path) 1777071d8fdfSSunnySrivastava1984 { 177862598e31SEd Tanous BMCWEB_LOG_DEBUG("Get BMC manager Location data."); 1779071d8fdfSSunnySrivastava1984 17801e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 17811e1e598dSJonathan Doman *crow::connections::systemBus, connectionName, path, 17821e1e598dSJonathan Doman "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode", 1783ac106bf6SEd Tanous [asyncResp](const boost::system::error_code& ec, 17841e1e598dSJonathan Doman const std::string& property) { 1785071d8fdfSSunnySrivastava1984 if (ec) 1786071d8fdfSSunnySrivastava1984 { 178762598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error for " 178862598e31SEd Tanous "Location"); 1789ac106bf6SEd Tanous messages::internalError(asyncResp->res); 1790071d8fdfSSunnySrivastava1984 return; 1791071d8fdfSSunnySrivastava1984 } 1792071d8fdfSSunnySrivastava1984 1793bd79bce8SPatrick Williams asyncResp->res 1794bd79bce8SPatrick Williams .jsonValue["Location"]["PartLocation"]["ServiceLabel"] = 17951e1e598dSJonathan Doman property; 17961e1e598dSJonathan Doman }); 1797071d8fdfSSunnySrivastava1984 } 17987e860f15SJohn Edward Broadbent // avoid name collision systems.hpp 17997e860f15SJohn Edward Broadbent inline void 1800ac106bf6SEd Tanous managerGetLastResetTime(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 18014bf2b033SGunnar Mills { 180262598e31SEd Tanous BMCWEB_LOG_DEBUG("Getting Manager Last Reset Time"); 18034bf2b033SGunnar Mills 18041e1e598dSJonathan Doman sdbusplus::asio::getProperty<uint64_t>( 18051e1e598dSJonathan Doman *crow::connections::systemBus, "xyz.openbmc_project.State.BMC", 18061e1e598dSJonathan Doman "/xyz/openbmc_project/state/bmc0", "xyz.openbmc_project.State.BMC", 18071e1e598dSJonathan Doman "LastRebootTime", 1808ac106bf6SEd Tanous [asyncResp](const boost::system::error_code& ec, 18091e1e598dSJonathan Doman const uint64_t lastResetTime) { 18104bf2b033SGunnar Mills if (ec) 18114bf2b033SGunnar Mills { 181262598e31SEd Tanous BMCWEB_LOG_DEBUG("D-BUS response error {}", ec); 18134bf2b033SGunnar Mills return; 18144bf2b033SGunnar Mills } 18154bf2b033SGunnar Mills 18164bf2b033SGunnar Mills // LastRebootTime is epoch time, in milliseconds 18174bf2b033SGunnar Mills // https://github.com/openbmc/phosphor-dbus-interfaces/blob/7f9a128eb9296e926422ddc312c148b625890bb6/xyz/openbmc_project/State/BMC.interface.yaml#L19 18181e1e598dSJonathan Doman uint64_t lastResetTimeStamp = lastResetTime / 1000; 18194bf2b033SGunnar Mills 18204bf2b033SGunnar Mills // Convert to ISO 8601 standard 1821ac106bf6SEd Tanous asyncResp->res.jsonValue["LastResetTime"] = 18222b82937eSEd Tanous redfish::time_utils::getDateTimeUint(lastResetTimeStamp); 18231e1e598dSJonathan Doman }); 18244bf2b033SGunnar Mills } 18254bf2b033SGunnar Mills 18264bfefa74SGunnar Mills /** 18274bfefa74SGunnar Mills * @brief Set the running firmware image 18284bfefa74SGunnar Mills * 1829ac106bf6SEd Tanous * @param[i,o] asyncResp - Async response object 18304bfefa74SGunnar Mills * @param[i] runningFirmwareTarget - Image to make the running image 18314bfefa74SGunnar Mills * 18324bfefa74SGunnar Mills * @return void 18334bfefa74SGunnar Mills */ 18347e860f15SJohn Edward Broadbent inline void 1835ac106bf6SEd Tanous setActiveFirmwareImage(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1836f23b7296SEd Tanous const std::string& runningFirmwareTarget) 18374bfefa74SGunnar Mills { 18384bfefa74SGunnar Mills // Get the Id from /redfish/v1/UpdateService/FirmwareInventory/<Id> 1839f23b7296SEd Tanous std::string::size_type idPos = runningFirmwareTarget.rfind('/'); 18404bfefa74SGunnar Mills if (idPos == std::string::npos) 18414bfefa74SGunnar Mills { 1842ac106bf6SEd Tanous messages::propertyValueNotInList(asyncResp->res, runningFirmwareTarget, 18434bfefa74SGunnar Mills "@odata.id"); 184462598e31SEd Tanous BMCWEB_LOG_DEBUG("Can't parse firmware ID!"); 18454bfefa74SGunnar Mills return; 18464bfefa74SGunnar Mills } 18474bfefa74SGunnar Mills idPos++; 18484bfefa74SGunnar Mills if (idPos >= runningFirmwareTarget.size()) 18494bfefa74SGunnar Mills { 1850ac106bf6SEd Tanous messages::propertyValueNotInList(asyncResp->res, runningFirmwareTarget, 18514bfefa74SGunnar Mills "@odata.id"); 185262598e31SEd Tanous BMCWEB_LOG_DEBUG("Invalid firmware ID."); 18534bfefa74SGunnar Mills return; 18544bfefa74SGunnar Mills } 18554bfefa74SGunnar Mills std::string firmwareId = runningFirmwareTarget.substr(idPos); 18564bfefa74SGunnar Mills 18574bfefa74SGunnar Mills // Make sure the image is valid before setting priority 18585eb468daSGeorge Liu sdbusplus::message::object_path objPath("/xyz/openbmc_project/software"); 18595eb468daSGeorge Liu dbus::utility::getManagedObjects( 1860*d27c31e9SJagpal Singh Gill getBMCUpdateServiceName(), objPath, 18615eb468daSGeorge Liu [asyncResp, firmwareId, runningFirmwareTarget]( 18625eb468daSGeorge Liu const boost::system::error_code& ec, 18635eb468daSGeorge Liu const dbus::utility::ManagedObjectType& subtree) { 18644bfefa74SGunnar Mills if (ec) 18654bfefa74SGunnar Mills { 186662598e31SEd Tanous BMCWEB_LOG_DEBUG("D-Bus response error getting objects."); 1867ac106bf6SEd Tanous messages::internalError(asyncResp->res); 18684bfefa74SGunnar Mills return; 18694bfefa74SGunnar Mills } 18704bfefa74SGunnar Mills 187126f6976fSEd Tanous if (subtree.empty()) 18724bfefa74SGunnar Mills { 187362598e31SEd Tanous BMCWEB_LOG_DEBUG("Can't find image!"); 1874ac106bf6SEd Tanous messages::internalError(asyncResp->res); 18754bfefa74SGunnar Mills return; 18764bfefa74SGunnar Mills } 18774bfefa74SGunnar Mills 18784bfefa74SGunnar Mills bool foundImage = false; 187902cad96eSEd Tanous for (const auto& object : subtree) 18804bfefa74SGunnar Mills { 18814bfefa74SGunnar Mills const std::string& path = 18824bfefa74SGunnar Mills static_cast<const std::string&>(object.first); 1883f23b7296SEd Tanous std::size_t idPos2 = path.rfind('/'); 18844bfefa74SGunnar Mills 18854bfefa74SGunnar Mills if (idPos2 == std::string::npos) 18864bfefa74SGunnar Mills { 18874bfefa74SGunnar Mills continue; 18884bfefa74SGunnar Mills } 18894bfefa74SGunnar Mills 18904bfefa74SGunnar Mills idPos2++; 18914bfefa74SGunnar Mills if (idPos2 >= path.size()) 18924bfefa74SGunnar Mills { 18934bfefa74SGunnar Mills continue; 18944bfefa74SGunnar Mills } 18954bfefa74SGunnar Mills 18964bfefa74SGunnar Mills if (path.substr(idPos2) == firmwareId) 18974bfefa74SGunnar Mills { 18984bfefa74SGunnar Mills foundImage = true; 18994bfefa74SGunnar Mills break; 19004bfefa74SGunnar Mills } 19014bfefa74SGunnar Mills } 19024bfefa74SGunnar Mills 19034bfefa74SGunnar Mills if (!foundImage) 19044bfefa74SGunnar Mills { 1905ac106bf6SEd Tanous messages::propertyValueNotInList( 1906ac106bf6SEd Tanous asyncResp->res, runningFirmwareTarget, "@odata.id"); 190762598e31SEd Tanous BMCWEB_LOG_DEBUG("Invalid firmware ID."); 19084bfefa74SGunnar Mills return; 19094bfefa74SGunnar Mills } 19104bfefa74SGunnar Mills 191162598e31SEd Tanous BMCWEB_LOG_DEBUG("Setting firmware version {} to priority 0.", 191262598e31SEd Tanous firmwareId); 19134bfefa74SGunnar Mills 19144bfefa74SGunnar Mills // Only support Immediate 19154bfefa74SGunnar Mills // An addition could be a Redfish Setting like 19164bfefa74SGunnar Mills // ActiveSoftwareImageApplyTime and support OnReset 19179ae226faSGeorge Liu sdbusplus::asio::setProperty( 1918*d27c31e9SJagpal Singh Gill *crow::connections::systemBus, getBMCUpdateServiceName(), 19199ae226faSGeorge Liu "/xyz/openbmc_project/software/" + firmwareId, 19209ae226faSGeorge Liu "xyz.openbmc_project.Software.RedundancyPriority", "Priority", 19219ae226faSGeorge Liu static_cast<uint8_t>(0), 1922ac106bf6SEd Tanous [asyncResp](const boost::system::error_code& ec2) { 19238a592810SEd Tanous if (ec2) 19244bfefa74SGunnar Mills { 192562598e31SEd Tanous BMCWEB_LOG_DEBUG("D-Bus response error setting."); 1926ac106bf6SEd Tanous messages::internalError(asyncResp->res); 19274bfefa74SGunnar Mills return; 19284bfefa74SGunnar Mills } 1929ac106bf6SEd Tanous doBMCGracefulRestart(asyncResp); 19309ae226faSGeorge Liu }); 19315eb468daSGeorge Liu }); 19324bfefa74SGunnar Mills } 19334bfefa74SGunnar Mills 1934bd79bce8SPatrick Williams inline void afterSetDateTime( 1935bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1936bd79bce8SPatrick Williams const boost::system::error_code& ec, const sdbusplus::message_t& msg) 1937c51afd54SEd Tanous { 1938c51afd54SEd Tanous if (ec) 1939c51afd54SEd Tanous { 1940c51afd54SEd Tanous BMCWEB_LOG_DEBUG("Failed to set elapsed time. DBUS response error {}", 1941c51afd54SEd Tanous ec); 1942c51afd54SEd Tanous const sd_bus_error* dbusError = msg.get_error(); 1943c51afd54SEd Tanous if (dbusError != nullptr) 1944c51afd54SEd Tanous { 1945c51afd54SEd Tanous std::string_view errorName(dbusError->name); 1946c51afd54SEd Tanous if (errorName == 1947c51afd54SEd Tanous "org.freedesktop.timedate1.AutomaticTimeSyncEnabled") 1948c51afd54SEd Tanous { 1949c51afd54SEd Tanous BMCWEB_LOG_DEBUG("Setting conflict"); 1950c51afd54SEd Tanous messages::propertyValueConflict( 1951c51afd54SEd Tanous asyncResp->res, "DateTime", 1952c51afd54SEd Tanous "Managers/NetworkProtocol/NTPProcotolEnabled"); 1953c51afd54SEd Tanous return; 1954c51afd54SEd Tanous } 1955c51afd54SEd Tanous } 1956c51afd54SEd Tanous messages::internalError(asyncResp->res); 1957c51afd54SEd Tanous return; 1958c51afd54SEd Tanous } 1959c51afd54SEd Tanous asyncResp->res.result(boost::beast::http::status::no_content); 1960c51afd54SEd Tanous } 1961c51afd54SEd Tanous 1962c51afd54SEd Tanous inline void setDateTime(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1963c51afd54SEd Tanous const std::string& datetime) 1964af5d6058SSantosh Puranik { 196562598e31SEd Tanous BMCWEB_LOG_DEBUG("Set date time: {}", datetime); 1966af5d6058SSantosh Puranik 1967c2e32007SEd Tanous std::optional<redfish::time_utils::usSinceEpoch> us = 1968c2e32007SEd Tanous redfish::time_utils::dateStringToEpoch(datetime); 1969c2e32007SEd Tanous if (!us) 1970af5d6058SSantosh Puranik { 1971ac106bf6SEd Tanous messages::propertyValueFormatError(asyncResp->res, datetime, 1972ac106bf6SEd Tanous "DateTime"); 1973c2e32007SEd Tanous return; 1974c2e32007SEd Tanous } 1975c51afd54SEd Tanous // Set the absolute datetime 1976c51afd54SEd Tanous bool relative = false; 1977c51afd54SEd Tanous bool interactive = false; 1978c51afd54SEd Tanous crow::connections::systemBus->async_method_call( 1979c51afd54SEd Tanous [asyncResp](const boost::system::error_code& ec, 1980c51afd54SEd Tanous const sdbusplus::message_t& msg) { 1981c51afd54SEd Tanous afterSetDateTime(asyncResp, ec, msg); 1982c51afd54SEd Tanous }, 1983c51afd54SEd Tanous "org.freedesktop.timedate1", "/org/freedesktop/timedate1", 1984c51afd54SEd Tanous "org.freedesktop.timedate1", "SetTime", us->count(), relative, 1985c51afd54SEd Tanous interactive); 198683ff9ab6SJames Feist } 19879c310685SBorawski.Lukasz 198875815e5cSEd Tanous inline void 198975815e5cSEd Tanous checkForQuiesced(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 199075815e5cSEd Tanous { 199175815e5cSEd Tanous sdbusplus::asio::getProperty<std::string>( 199275815e5cSEd Tanous *crow::connections::systemBus, "org.freedesktop.systemd1", 199375815e5cSEd Tanous "/org/freedesktop/systemd1/unit/obmc-bmc-service-quiesce@0.target", 199475815e5cSEd Tanous "org.freedesktop.systemd1.Unit", "ActiveState", 199575815e5cSEd Tanous [asyncResp](const boost::system::error_code& ec, 199675815e5cSEd Tanous const std::string& val) { 199775815e5cSEd Tanous if (!ec) 199875815e5cSEd Tanous { 199975815e5cSEd Tanous if (val == "active") 200075815e5cSEd Tanous { 2001539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["Health"] = 2002539d8c6bSEd Tanous resource::Health::Critical; 2003539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = 2004539d8c6bSEd Tanous resource::State::Quiesced; 200575815e5cSEd Tanous return; 200675815e5cSEd Tanous } 200775815e5cSEd Tanous } 2008539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK; 2009bd79bce8SPatrick Williams asyncResp->res.jsonValue["Status"]["State"] = 2010bd79bce8SPatrick Williams resource::State::Enabled; 201175815e5cSEd Tanous }); 201275815e5cSEd Tanous } 201375815e5cSEd Tanous 20147e860f15SJohn Edward Broadbent inline void requestRoutesManager(App& app) 20157e860f15SJohn Edward Broadbent { 20167e860f15SJohn Edward Broadbent std::string uuid = persistent_data::getConfig().systemUuid; 20179c310685SBorawski.Lukasz 2018253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/") 2019ed398213SEd Tanous .privileges(redfish::privileges::getManager) 2020bd79bce8SPatrick Williams .methods( 2021bd79bce8SPatrick Williams boost::beast::http::verb:: 2022bd79bce8SPatrick Williams get)([&app, 2023bd79bce8SPatrick Williams uuid](const crow::Request& req, 2024253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2025253f11b8SEd Tanous const std::string& managerId) { 20263ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 202745ca1b86SEd Tanous { 202845ca1b86SEd Tanous return; 202945ca1b86SEd Tanous } 2030253f11b8SEd Tanous 2031253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2032253f11b8SEd Tanous { 2033bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "Manager", 2034bd79bce8SPatrick Williams managerId); 2035253f11b8SEd Tanous return; 2036253f11b8SEd Tanous } 2037253f11b8SEd Tanous 2038253f11b8SEd Tanous asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 2039253f11b8SEd Tanous "/redfish/v1/Managers/{}", BMCWEB_REDFISH_MANAGER_URI_NAME); 2040bd79bce8SPatrick Williams asyncResp->res.jsonValue["@odata.type"] = 2041bd79bce8SPatrick Williams "#Manager.v1_14_0.Manager"; 2042253f11b8SEd Tanous asyncResp->res.jsonValue["Id"] = BMCWEB_REDFISH_MANAGER_URI_NAME; 20437e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Name"] = "OpenBmc Manager"; 20447e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Description"] = 20457e860f15SJohn Edward Broadbent "Baseboard Management Controller"; 2046539d8c6bSEd Tanous asyncResp->res.jsonValue["PowerState"] = resource::PowerState::On; 20471476687dSEd Tanous 2048539d8c6bSEd Tanous asyncResp->res.jsonValue["ManagerType"] = manager::ManagerType::BMC; 20497e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["UUID"] = systemd_utils::getUuid(); 20507e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["ServiceEntryPointUUID"] = uuid; 2051bd79bce8SPatrick Williams asyncResp->res.jsonValue["Model"] = 2052bd79bce8SPatrick Williams "OpenBmc"; // TODO(ed), get model 20537e860f15SJohn Edward Broadbent 20541476687dSEd Tanous asyncResp->res.jsonValue["LogServices"]["@odata.id"] = 2055253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}/LogServices", 2056253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 20571476687dSEd Tanous asyncResp->res.jsonValue["NetworkProtocol"]["@odata.id"] = 2058253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}/NetworkProtocol", 2059253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 20601476687dSEd Tanous asyncResp->res.jsonValue["EthernetInterfaces"]["@odata.id"] = 2061bd79bce8SPatrick Williams boost::urls::format( 2062bd79bce8SPatrick Williams "/redfish/v1/Managers/{}/EthernetInterfaces", 2063253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 20647e860f15SJohn Edward Broadbent 206525b54dbaSEd Tanous if constexpr (BMCWEB_VM_NBDPROXY) 206636c0f2a3SEd Tanous { 20671476687dSEd Tanous asyncResp->res.jsonValue["VirtualMedia"]["@odata.id"] = 2068253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}/VirtualMedia", 2069253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 207036c0f2a3SEd Tanous } 20717e860f15SJohn Edward Broadbent 20727e860f15SJohn Edward Broadbent // default oem data 20737e860f15SJohn Edward Broadbent nlohmann::json& oem = asyncResp->res.jsonValue["Oem"]; 20747e860f15SJohn Edward Broadbent nlohmann::json& oemOpenbmc = oem["OpenBmc"]; 2075bd79bce8SPatrick Williams oem["@odata.id"] = 2076bd79bce8SPatrick Williams boost::urls::format("/redfish/v1/Managers/{}#/Oem", 2077253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 2078fc1cdd14SEd Tanous oemOpenbmc["@odata.type"] = "#OpenBMCManager.v1_0_0.Manager"; 2079253f11b8SEd Tanous oemOpenbmc["@odata.id"] = 2080253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}#/Oem/OpenBmc", 2081253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 20821476687dSEd Tanous 20831476687dSEd Tanous nlohmann::json::object_t certificates; 2084253f11b8SEd Tanous certificates["@odata.id"] = boost::urls::format( 2085253f11b8SEd Tanous "/redfish/v1/Managers/{}/Truststore/Certificates", 2086253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 20871476687dSEd Tanous oemOpenbmc["Certificates"] = std::move(certificates); 20887e860f15SJohn Edward Broadbent 20897e860f15SJohn Edward Broadbent // Manager.Reset (an action) can be many values, OpenBMC only 20907e860f15SJohn Edward Broadbent // supports BMC reboot. 20917e860f15SJohn Edward Broadbent nlohmann::json& managerReset = 20927e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Actions"]["#Manager.Reset"]; 2093bd79bce8SPatrick Williams managerReset["target"] = boost::urls::format( 2094bd79bce8SPatrick Williams "/redfish/v1/Managers/{}/Actions/Manager.Reset", 2095253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 20967e860f15SJohn Edward Broadbent managerReset["@Redfish.ActionInfo"] = 2097253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}/ResetActionInfo", 2098253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 20997e860f15SJohn Edward Broadbent 21007e860f15SJohn Edward Broadbent // ResetToDefaults (Factory Reset) has values like 21017e860f15SJohn Edward Broadbent // PreserveNetworkAndUsers and PreserveNetwork that aren't supported 21027e860f15SJohn Edward Broadbent // on OpenBMC 21037e860f15SJohn Edward Broadbent nlohmann::json& resetToDefaults = 21047e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Actions"]["#Manager.ResetToDefaults"]; 2105253f11b8SEd Tanous resetToDefaults["target"] = boost::urls::format( 2106253f11b8SEd Tanous "/redfish/v1/Managers/{}/Actions/Manager.ResetToDefaults", 2107253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 2108613dabeaSEd Tanous resetToDefaults["ResetType@Redfish.AllowableValues"] = 2109613dabeaSEd Tanous nlohmann::json::array_t({"ResetAll"}); 21107e860f15SJohn Edward Broadbent 21117c8c4058STejas Patil std::pair<std::string, std::string> redfishDateTimeOffset = 21122b82937eSEd Tanous redfish::time_utils::getDateTimeOffsetNow(); 21137c8c4058STejas Patil 21147c8c4058STejas Patil asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first; 21157c8c4058STejas Patil asyncResp->res.jsonValue["DateTimeLocalOffset"] = 21167c8c4058STejas Patil redfishDateTimeOffset.second; 21177e860f15SJohn Edward Broadbent 21180e8ac5e7SGunnar Mills // TODO (Gunnar): Remove these one day since moved to ComputerSystem 21190e8ac5e7SGunnar Mills // Still used by OCP profiles 21200e8ac5e7SGunnar Mills // https://github.com/opencomputeproject/OCP-Profiles/issues/23 21217e860f15SJohn Edward Broadbent // Fill in SerialConsole info 21227e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["SerialConsole"]["ServiceEnabled"] = true; 2123bd79bce8SPatrick Williams asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] = 2124bd79bce8SPatrick Williams 15; 2125613dabeaSEd Tanous asyncResp->res.jsonValue["SerialConsole"]["ConnectTypesSupported"] = 2126613dabeaSEd Tanous nlohmann::json::array_t({"IPMI", "SSH"}); 212725b54dbaSEd Tanous if constexpr (BMCWEB_KVM) 212825b54dbaSEd Tanous { 21297e860f15SJohn Edward Broadbent // Fill in GraphicalConsole info 213025b54dbaSEd Tanous asyncResp->res.jsonValue["GraphicalConsole"]["ServiceEnabled"] = 213125b54dbaSEd Tanous true; 213225b54dbaSEd Tanous asyncResp->res 213325b54dbaSEd Tanous .jsonValue["GraphicalConsole"]["MaxConcurrentSessions"] = 4; 213425b54dbaSEd Tanous asyncResp->res 213525b54dbaSEd Tanous .jsonValue["GraphicalConsole"]["ConnectTypesSupported"] = 2136613dabeaSEd Tanous nlohmann::json::array_t({"KVMIP"}); 213725b54dbaSEd Tanous } 213825b54dbaSEd Tanous if constexpr (!BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 21397f3e84a1SEd Tanous { 2140bd79bce8SPatrick Williams asyncResp->res 2141bd79bce8SPatrick Williams .jsonValue["Links"]["ManagerForServers@odata.count"] = 1; 21421476687dSEd Tanous 21431476687dSEd Tanous nlohmann::json::array_t managerForServers; 21441476687dSEd Tanous nlohmann::json::object_t manager; 2145bd79bce8SPatrick Williams manager["@odata.id"] = std::format( 2146bd79bce8SPatrick Williams "/redfish/v1/Systems/{}", BMCWEB_REDFISH_SYSTEM_URI_NAME); 2147ad539545SPatrick Williams managerForServers.emplace_back(std::move(manager)); 21481476687dSEd Tanous 21491476687dSEd Tanous asyncResp->res.jsonValue["Links"]["ManagerForServers"] = 21501476687dSEd Tanous std::move(managerForServers); 21517f3e84a1SEd Tanous } 21527e860f15SJohn Edward Broadbent 2153eee0013eSWilly Tu sw_util::populateSoftwareInformation(asyncResp, sw_util::bmcPurpose, 21547e860f15SJohn Edward Broadbent "FirmwareVersion", true); 21557e860f15SJohn Edward Broadbent 21567e860f15SJohn Edward Broadbent managerGetLastResetTime(asyncResp); 21577e860f15SJohn Edward Broadbent 2158a51fc2d2SSui Chen // ManagerDiagnosticData is added for all BMCs. 2159a51fc2d2SSui Chen nlohmann::json& managerDiagnosticData = 2160a51fc2d2SSui Chen asyncResp->res.jsonValue["ManagerDiagnosticData"]; 2161bd79bce8SPatrick Williams managerDiagnosticData["@odata.id"] = boost::urls::format( 2162bd79bce8SPatrick Williams "/redfish/v1/Managers/{}/ManagerDiagnosticData", 2163253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 2164a51fc2d2SSui Chen 216525b54dbaSEd Tanous if constexpr (BMCWEB_REDFISH_OEM_MANAGER_FAN_DATA) 216625b54dbaSEd Tanous { 21677e860f15SJohn Edward Broadbent auto pids = std::make_shared<GetPIDValues>(asyncResp); 21687e860f15SJohn Edward Broadbent pids->run(); 216925b54dbaSEd Tanous } 21707e860f15SJohn Edward Broadbent 2171bd79bce8SPatrick Williams getMainChassisId(asyncResp, [](const std::string& chassisId, 2172bd79bce8SPatrick Williams const std::shared_ptr< 2173bd79bce8SPatrick Williams bmcweb::AsyncResp>& aRsp) { 2174bd79bce8SPatrick Williams aRsp->res.jsonValue["Links"]["ManagerForChassis@odata.count"] = 2175bd79bce8SPatrick Williams 1; 21761476687dSEd Tanous nlohmann::json::array_t managerForChassis; 21778a592810SEd Tanous nlohmann::json::object_t managerObj; 2178ef4c65b7SEd Tanous boost::urls::url chassiUrl = 2179ef4c65b7SEd Tanous boost::urls::format("/redfish/v1/Chassis/{}", chassisId); 2180eddfc437SWilly Tu managerObj["@odata.id"] = chassiUrl; 2181ad539545SPatrick Williams managerForChassis.emplace_back(std::move(managerObj)); 21821476687dSEd Tanous aRsp->res.jsonValue["Links"]["ManagerForChassis"] = 21831476687dSEd Tanous std::move(managerForChassis); 21841476687dSEd Tanous aRsp->res.jsonValue["Links"]["ManagerInChassis"]["@odata.id"] = 2185eddfc437SWilly Tu chassiUrl; 21867e860f15SJohn Edward Broadbent }); 21877e860f15SJohn Edward Broadbent 21881e1e598dSJonathan Doman sdbusplus::asio::getProperty<double>( 21891e1e598dSJonathan Doman *crow::connections::systemBus, "org.freedesktop.systemd1", 2190002d39b4SEd Tanous "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", 2191002d39b4SEd Tanous "Progress", 219275815e5cSEd Tanous [asyncResp](const boost::system::error_code& ec, double val) { 21937e860f15SJohn Edward Broadbent if (ec) 21941abe55efSEd Tanous { 219562598e31SEd Tanous BMCWEB_LOG_ERROR("Error while getting progress"); 21967e860f15SJohn Edward Broadbent messages::internalError(asyncResp->res); 21977e860f15SJohn Edward Broadbent return; 21987e860f15SJohn Edward Broadbent } 21991e1e598dSJonathan Doman if (val < 1.0) 22007e860f15SJohn Edward Broadbent { 2201539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["Health"] = 2202539d8c6bSEd Tanous resource::Health::OK; 2203539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = 2204539d8c6bSEd Tanous resource::State::Starting; 220575815e5cSEd Tanous return; 22067e860f15SJohn Edward Broadbent } 220775815e5cSEd Tanous checkForQuiesced(asyncResp); 22081e1e598dSJonathan Doman }); 22099c310685SBorawski.Lukasz 2210e99073f5SGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 2211e99073f5SGeorge Liu "xyz.openbmc_project.Inventory.Item.Bmc"}; 2212e99073f5SGeorge Liu dbus::utility::getSubTree( 2213e99073f5SGeorge Liu "/xyz/openbmc_project/inventory", 0, interfaces, 22147e860f15SJohn Edward Broadbent [asyncResp]( 2215e99073f5SGeorge Liu const boost::system::error_code& ec, 2216b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreeResponse& subtree) { 22177e860f15SJohn Edward Broadbent if (ec) 22181abe55efSEd Tanous { 2219bd79bce8SPatrick Williams BMCWEB_LOG_DEBUG( 2220bd79bce8SPatrick Williams "D-Bus response error on GetSubTree {}", ec); 22217e860f15SJohn Edward Broadbent return; 22227e860f15SJohn Edward Broadbent } 222326f6976fSEd Tanous if (subtree.empty()) 22247e860f15SJohn Edward Broadbent { 222562598e31SEd Tanous BMCWEB_LOG_DEBUG("Can't find bmc D-Bus object!"); 22267e860f15SJohn Edward Broadbent return; 22277e860f15SJohn Edward Broadbent } 22287e860f15SJohn Edward Broadbent // Assume only 1 bmc D-Bus object 22297e860f15SJohn Edward Broadbent // Throw an error if there is more than 1 22307e860f15SJohn Edward Broadbent if (subtree.size() > 1) 22317e860f15SJohn Edward Broadbent { 223262598e31SEd Tanous BMCWEB_LOG_DEBUG("Found more than 1 bmc D-Bus object!"); 22337e860f15SJohn Edward Broadbent messages::internalError(asyncResp->res); 22347e860f15SJohn Edward Broadbent return; 22357e860f15SJohn Edward Broadbent } 22367e860f15SJohn Edward Broadbent 2237bd79bce8SPatrick Williams if (subtree[0].first.empty() || 2238bd79bce8SPatrick Williams subtree[0].second.size() != 1) 22397e860f15SJohn Edward Broadbent { 224062598e31SEd Tanous BMCWEB_LOG_DEBUG("Error getting bmc D-Bus object!"); 22417e860f15SJohn Edward Broadbent messages::internalError(asyncResp->res); 22427e860f15SJohn Edward Broadbent return; 22437e860f15SJohn Edward Broadbent } 22447e860f15SJohn Edward Broadbent 22457e860f15SJohn Edward Broadbent const std::string& path = subtree[0].first; 2246bd79bce8SPatrick Williams const std::string& connectionName = 2247bd79bce8SPatrick Williams subtree[0].second[0].first; 22487e860f15SJohn Edward Broadbent 2249bd79bce8SPatrick Williams for (const auto& interfaceName : 2250bd79bce8SPatrick Williams subtree[0].second[0].second) 22517e860f15SJohn Edward Broadbent { 22527e860f15SJohn Edward Broadbent if (interfaceName == 22537e860f15SJohn Edward Broadbent "xyz.openbmc_project.Inventory.Decorator.Asset") 22547e860f15SJohn Edward Broadbent { 2255fac6e53bSKrzysztof Grobelny sdbusplus::asio::getAllProperties( 2256bd79bce8SPatrick Williams *crow::connections::systemBus, connectionName, 2257bd79bce8SPatrick Williams path, 2258fac6e53bSKrzysztof Grobelny "xyz.openbmc_project.Inventory.Decorator.Asset", 2259bd79bce8SPatrick Williams [asyncResp]( 2260bd79bce8SPatrick Williams const boost::system::error_code& ec2, 2261b9d36b47SEd Tanous const dbus::utility::DBusPropertiesMap& 22627e860f15SJohn Edward Broadbent propertiesList) { 22638a592810SEd Tanous if (ec2) 22647e860f15SJohn Edward Broadbent { 2265bd79bce8SPatrick Williams BMCWEB_LOG_DEBUG( 2266bd79bce8SPatrick Williams "Can't get bmc asset!"); 22677e860f15SJohn Edward Broadbent return; 22687e860f15SJohn Edward Broadbent } 22697e860f15SJohn Edward Broadbent 2270fac6e53bSKrzysztof Grobelny const std::string* partNumber = nullptr; 2271fac6e53bSKrzysztof Grobelny const std::string* serialNumber = nullptr; 2272fac6e53bSKrzysztof Grobelny const std::string* manufacturer = nullptr; 2273fac6e53bSKrzysztof Grobelny const std::string* model = nullptr; 2274bd79bce8SPatrick Williams const std::string* sparePartNumber = 2275bd79bce8SPatrick Williams nullptr; 2276fac6e53bSKrzysztof Grobelny 2277bd79bce8SPatrick Williams const bool success = 2278bd79bce8SPatrick Williams sdbusplus::unpackPropertiesNoThrow( 2279bd79bce8SPatrick Williams dbus_utils::UnpackErrorPrinter(), 2280bd79bce8SPatrick Williams propertiesList, "PartNumber", 2281bd79bce8SPatrick Williams partNumber, "SerialNumber", 2282bd79bce8SPatrick Williams serialNumber, "Manufacturer", 2283bd79bce8SPatrick Williams manufacturer, "Model", model, 2284bd79bce8SPatrick Williams "SparePartNumber", sparePartNumber); 2285fac6e53bSKrzysztof Grobelny 2286fac6e53bSKrzysztof Grobelny if (!success) 22877e860f15SJohn Edward Broadbent { 2288002d39b4SEd Tanous messages::internalError(asyncResp->res); 22897e860f15SJohn Edward Broadbent return; 22907e860f15SJohn Edward Broadbent } 2291fac6e53bSKrzysztof Grobelny 2292fac6e53bSKrzysztof Grobelny if (partNumber != nullptr) 2293fac6e53bSKrzysztof Grobelny { 2294fac6e53bSKrzysztof Grobelny asyncResp->res.jsonValue["PartNumber"] = 2295fac6e53bSKrzysztof Grobelny *partNumber; 22967e860f15SJohn Edward Broadbent } 2297fac6e53bSKrzysztof Grobelny 2298fac6e53bSKrzysztof Grobelny if (serialNumber != nullptr) 2299fac6e53bSKrzysztof Grobelny { 2300bd79bce8SPatrick Williams asyncResp->res 2301bd79bce8SPatrick Williams .jsonValue["SerialNumber"] = 2302fac6e53bSKrzysztof Grobelny *serialNumber; 23037e860f15SJohn Edward Broadbent } 2304fac6e53bSKrzysztof Grobelny 2305fac6e53bSKrzysztof Grobelny if (manufacturer != nullptr) 2306fac6e53bSKrzysztof Grobelny { 2307bd79bce8SPatrick Williams asyncResp->res 2308bd79bce8SPatrick Williams .jsonValue["Manufacturer"] = 2309fac6e53bSKrzysztof Grobelny *manufacturer; 2310fac6e53bSKrzysztof Grobelny } 2311fac6e53bSKrzysztof Grobelny 2312fac6e53bSKrzysztof Grobelny if (model != nullptr) 2313fac6e53bSKrzysztof Grobelny { 2314bd79bce8SPatrick Williams asyncResp->res.jsonValue["Model"] = 2315bd79bce8SPatrick Williams *model; 2316fac6e53bSKrzysztof Grobelny } 2317fac6e53bSKrzysztof Grobelny 2318fac6e53bSKrzysztof Grobelny if (sparePartNumber != nullptr) 2319fac6e53bSKrzysztof Grobelny { 2320bd79bce8SPatrick Williams asyncResp->res 2321bd79bce8SPatrick Williams .jsonValue["SparePartNumber"] = 2322fac6e53bSKrzysztof Grobelny *sparePartNumber; 2323fac6e53bSKrzysztof Grobelny } 2324fac6e53bSKrzysztof Grobelny }); 23257e860f15SJohn Edward Broadbent } 2326bd79bce8SPatrick Williams else if ( 2327bd79bce8SPatrick Williams interfaceName == 23280fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.LocationCode") 23297e860f15SJohn Edward Broadbent { 23307e860f15SJohn Edward Broadbent getLocation(asyncResp, connectionName, path); 23317e860f15SJohn Edward Broadbent } 23327e860f15SJohn Edward Broadbent } 2333e99073f5SGeorge Liu }); 23347e860f15SJohn Edward Broadbent }); 23357e860f15SJohn Edward Broadbent 2336253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/") 2337ed398213SEd Tanous .privileges(redfish::privileges::patchManager) 233845ca1b86SEd Tanous .methods(boost::beast::http::verb::patch)( 233945ca1b86SEd Tanous [&app](const crow::Request& req, 2340253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2341253f11b8SEd Tanous const std::string& managerId) { 23423ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 234345ca1b86SEd Tanous { 234445ca1b86SEd Tanous return; 234545ca1b86SEd Tanous } 2346253f11b8SEd Tanous 2347253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2348253f11b8SEd Tanous { 2349bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "Manager", 2350bd79bce8SPatrick Williams managerId); 2351253f11b8SEd Tanous return; 2352253f11b8SEd Tanous } 2353253f11b8SEd Tanous 23549e9b6049SEd Tanous std::optional<std::string> activeSoftwareImageOdataId; 23557e860f15SJohn Edward Broadbent std::optional<std::string> datetime; 23569e9b6049SEd Tanous std::optional<nlohmann::json::object_t> pidControllers; 23579e9b6049SEd Tanous std::optional<nlohmann::json::object_t> fanControllers; 23589e9b6049SEd Tanous std::optional<nlohmann::json::object_t> fanZones; 23599e9b6049SEd Tanous std::optional<nlohmann::json::object_t> stepwiseControllers; 23609e9b6049SEd Tanous std::optional<std::string> profile; 23617e860f15SJohn Edward Broadbent 2362afc474aeSMyung Bae if (!json_util::readJsonPatch( // 2363afc474aeSMyung Bae req, asyncResp->res, // 2364afc474aeSMyung Bae "DateTime", datetime, // 2365afc474aeSMyung Bae "Links/ActiveSoftwareImage/@odata.id", 2366afc474aeSMyung Bae activeSoftwareImageOdataId, // 2367afc474aeSMyung Bae "Oem/OpenBmc/Fan/FanControllers", fanControllers, // 2368afc474aeSMyung Bae "Oem/OpenBmc/Fan/FanZones", fanZones, // 2369afc474aeSMyung Bae "Oem/OpenBmc/Fan/PidControllers", pidControllers, // 2370afc474aeSMyung Bae "Oem/OpenBmc/Fan/Profile", profile, // 2371afc474aeSMyung Bae "Oem/OpenBmc/Fan/StepwiseControllers", 2372afc474aeSMyung Bae stepwiseControllers // 23739e9b6049SEd Tanous )) 23747e860f15SJohn Edward Broadbent { 23757e860f15SJohn Edward Broadbent return; 23767e860f15SJohn Edward Broadbent } 23777e860f15SJohn Edward Broadbent 23789e9b6049SEd Tanous if (pidControllers || fanControllers || fanZones || 23799e9b6049SEd Tanous stepwiseControllers || profile) 23807e860f15SJohn Edward Broadbent { 238125b54dbaSEd Tanous if constexpr (BMCWEB_REDFISH_OEM_MANAGER_FAN_DATA) 238225b54dbaSEd Tanous { 2383bd79bce8SPatrick Williams std::vector< 2384bd79bce8SPatrick Williams std::pair<std::string, 238525b54dbaSEd Tanous std::optional<nlohmann::json::object_t>>> 23869e9b6049SEd Tanous configuration; 23879e9b6049SEd Tanous if (pidControllers) 23887e860f15SJohn Edward Broadbent { 2389bd79bce8SPatrick Williams configuration.emplace_back( 2390bd79bce8SPatrick Williams "PidControllers", std::move(pidControllers)); 23917e860f15SJohn Edward Broadbent } 23929e9b6049SEd Tanous if (fanControllers) 23937e860f15SJohn Edward Broadbent { 2394bd79bce8SPatrick Williams configuration.emplace_back( 2395bd79bce8SPatrick Williams "FanControllers", std::move(fanControllers)); 23967e860f15SJohn Edward Broadbent } 23979e9b6049SEd Tanous if (fanZones) 23987e860f15SJohn Edward Broadbent { 2399bd79bce8SPatrick Williams configuration.emplace_back("FanZones", 2400bd79bce8SPatrick Williams std::move(fanZones)); 24019e9b6049SEd Tanous } 24029e9b6049SEd Tanous if (stepwiseControllers) 24039e9b6049SEd Tanous { 2404bd79bce8SPatrick Williams configuration.emplace_back( 2405bd79bce8SPatrick Williams "StepwiseControllers", 24069e9b6049SEd Tanous std::move(stepwiseControllers)); 24079e9b6049SEd Tanous } 24089e9b6049SEd Tanous auto pid = std::make_shared<SetPIDValues>( 24099e9b6049SEd Tanous asyncResp, std::move(configuration), profile); 24107e860f15SJohn Edward Broadbent pid->run(); 241125b54dbaSEd Tanous } 241225b54dbaSEd Tanous else 241325b54dbaSEd Tanous { 241454dce7f5SGunnar Mills messages::propertyUnknown(asyncResp->res, "Oem"); 241554dce7f5SGunnar Mills return; 241625b54dbaSEd Tanous } 24177e860f15SJohn Edward Broadbent } 24189e9b6049SEd Tanous 24199e9b6049SEd Tanous if (activeSoftwareImageOdataId) 24207e860f15SJohn Edward Broadbent { 2421bd79bce8SPatrick Williams setActiveFirmwareImage(asyncResp, 2422bd79bce8SPatrick Williams *activeSoftwareImageOdataId); 24237e860f15SJohn Edward Broadbent } 24247e860f15SJohn Edward Broadbent 24257e860f15SJohn Edward Broadbent if (datetime) 24267e860f15SJohn Edward Broadbent { 2427c51afd54SEd Tanous setDateTime(asyncResp, *datetime); 24287e860f15SJohn Edward Broadbent } 24297e860f15SJohn Edward Broadbent }); 24307e860f15SJohn Edward Broadbent } 24317e860f15SJohn Edward Broadbent 24327e860f15SJohn Edward Broadbent inline void requestRoutesManagerCollection(App& app) 24337e860f15SJohn Edward Broadbent { 24347e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Managers/") 2435ed398213SEd Tanous .privileges(redfish::privileges::getManagerCollection) 24367e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 243745ca1b86SEd Tanous [&app](const crow::Request& req, 24387e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 24393ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 244045ca1b86SEd Tanous { 244145ca1b86SEd Tanous return; 244245ca1b86SEd Tanous } 244383ff9ab6SJames Feist // Collections don't include the static data added by SubRoute 244483ff9ab6SJames Feist // because it has a duplicate entry for members 24458d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Managers"; 24468d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 24478d1b46d7Szhanghch05 "#ManagerCollection.ManagerCollection"; 24488d1b46d7Szhanghch05 asyncResp->res.jsonValue["Name"] = "Manager Collection"; 24498d1b46d7Szhanghch05 asyncResp->res.jsonValue["Members@odata.count"] = 1; 24501476687dSEd Tanous nlohmann::json::array_t members; 24511476687dSEd Tanous nlohmann::json& bmc = members.emplace_back(); 2452bd79bce8SPatrick Williams bmc["@odata.id"] = boost::urls::format( 2453bd79bce8SPatrick Williams "/redfish/v1/Managers/{}", BMCWEB_REDFISH_MANAGER_URI_NAME); 24541476687dSEd Tanous asyncResp->res.jsonValue["Members"] = std::move(members); 24557e860f15SJohn Edward Broadbent }); 24569c310685SBorawski.Lukasz } 24579c310685SBorawski.Lukasz } // namespace redfish 2458