140e9b92eSEd Tanous // SPDX-License-Identifier: Apache-2.0 240e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright OpenBMC Authors 340e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright 2018 Intel Corporation 49c310685SBorawski.Lukasz #pragma once 59c310685SBorawski.Lukasz 613451e39SWilly Tu #include "bmcweb_config.h" 713451e39SWilly Tu 8a51fc2d2SSui Chen #include "app.hpp" 9d7857201SEd Tanous #include "async_resp.hpp" 10d7857201SEd Tanous #include "dbus_singleton.hpp" 11a51fc2d2SSui Chen #include "dbus_utility.hpp" 12d7857201SEd Tanous #include "error_messages.hpp" 13539d8c6bSEd Tanous #include "generated/enums/action_info.hpp" 14539d8c6bSEd Tanous #include "generated/enums/manager.hpp" 15539d8c6bSEd Tanous #include "generated/enums/resource.hpp" 16d7857201SEd Tanous #include "http_request.hpp" 1779f3b6a1SGeorge Liu #include "led.hpp" 18d7857201SEd Tanous #include "logging.hpp" 19d7857201SEd Tanous #include "persistent_data.hpp" 20a51fc2d2SSui Chen #include "query.hpp" 21c1a75ebcSrohitpai #include "redfish.hpp" 22c5d03ff4SJennifer Lee #include "redfish_util.hpp" 23a51fc2d2SSui Chen #include "registries/privilege_registry.hpp" 24fac6e53bSKrzysztof Grobelny #include "utils/dbus_utils.hpp" 253ccb3adbSEd Tanous #include "utils/json_utils.hpp" 26e30d3345SCorey Ethington #include "utils/manager_utils.hpp" 27a51fc2d2SSui Chen #include "utils/sw_utils.hpp" 28a51fc2d2SSui Chen #include "utils/systemd_utils.hpp" 292b82937eSEd Tanous #include "utils/time_utils.hpp" 309c310685SBorawski.Lukasz 31d7857201SEd Tanous #include <systemd/sd-bus.h> 32d7857201SEd Tanous 33d7857201SEd Tanous #include <boost/beast/http/status.hpp> 34d7857201SEd Tanous #include <boost/beast/http/verb.hpp> 35e99073f5SGeorge Liu #include <boost/system/error_code.hpp> 36ef4c65b7SEd Tanous #include <boost/url/format.hpp> 37d7857201SEd Tanous #include <boost/url/url.hpp> 38d7857201SEd Tanous #include <nlohmann/json.hpp> 39fac6e53bSKrzysztof Grobelny #include <sdbusplus/asio/property.hpp> 40d7857201SEd Tanous #include <sdbusplus/message.hpp> 41d7857201SEd Tanous #include <sdbusplus/message/native_types.hpp> 42fac6e53bSKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp> 431214b7e7SGunnar Mills 44e99073f5SGeorge Liu #include <array> 45d7857201SEd Tanous #include <cstddef> 464bfefa74SGunnar Mills #include <cstdint> 47d7857201SEd Tanous #include <format> 48d7857201SEd Tanous #include <functional> 49d7857201SEd Tanous #include <map> 501214b7e7SGunnar Mills #include <memory> 519970e93fSKonstantin Aladyshev #include <optional> 523544d2a7SEd Tanous #include <ranges> 539970e93fSKonstantin Aladyshev #include <string> 54e99073f5SGeorge Liu #include <string_view> 55d7857201SEd Tanous #include <utility> 56d7857201SEd Tanous #include <vector> 575b4aa86bSJames Feist 581abe55efSEd Tanous namespace redfish 591abe55efSEd Tanous { 60ed5befbdSJennifer Lee 6179f3b6a1SGeorge Liu inline void handleSetLocationIndicatorActive( 6279f3b6a1SGeorge Liu const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 6379f3b6a1SGeorge Liu bool locationIndicatorActive, const std::string& managerId, 6479f3b6a1SGeorge Liu const boost::system::error_code& ec, 6579f3b6a1SGeorge Liu const dbus::utility::MapperGetSubTreePathsResponse& subtreePaths) 6679f3b6a1SGeorge Liu { 6779f3b6a1SGeorge Liu if (ec) 6879f3b6a1SGeorge Liu { 6979f3b6a1SGeorge Liu if (ec == boost::system::errc::io_error) 7079f3b6a1SGeorge Liu { 7179f3b6a1SGeorge Liu // Not found 7279f3b6a1SGeorge Liu BMCWEB_LOG_WARNING("Manager {} not found", managerId); 7379f3b6a1SGeorge Liu messages::resourceNotFound(asyncResp->res, "Manager", managerId); 7479f3b6a1SGeorge Liu return; 7579f3b6a1SGeorge Liu } 7679f3b6a1SGeorge Liu BMCWEB_LOG_ERROR("D-Bus response error {}", ec.value()); 7779f3b6a1SGeorge Liu messages::internalError(asyncResp->res); 7879f3b6a1SGeorge Liu return; 7979f3b6a1SGeorge Liu } 8079f3b6a1SGeorge Liu if (subtreePaths.empty()) 8179f3b6a1SGeorge Liu { 8279f3b6a1SGeorge Liu BMCWEB_LOG_WARNING("Manager {} not found", managerId); 8379f3b6a1SGeorge Liu messages::resourceNotFound(asyncResp->res, "Manager", managerId); 8479f3b6a1SGeorge Liu return; 8579f3b6a1SGeorge Liu } 8679f3b6a1SGeorge Liu // Assume only 1 bmc D-Bus object 8779f3b6a1SGeorge Liu // Throw an error if there is more than 1 8879f3b6a1SGeorge Liu if (subtreePaths.size() != 1) 8979f3b6a1SGeorge Liu { 9079f3b6a1SGeorge Liu BMCWEB_LOG_ERROR("Found {} Bmc D-Bus paths", subtreePaths.size()); 9179f3b6a1SGeorge Liu messages::internalError(asyncResp->res); 9279f3b6a1SGeorge Liu return; 9379f3b6a1SGeorge Liu } 9479f3b6a1SGeorge Liu 9579f3b6a1SGeorge Liu setLocationIndicatorActive(asyncResp, subtreePaths[0], 9679f3b6a1SGeorge Liu locationIndicatorActive); 9779f3b6a1SGeorge Liu } 9879f3b6a1SGeorge Liu 9979f3b6a1SGeorge Liu /** 10079f3b6a1SGeorge Liu * Set the locationIndicatorActive. 10179f3b6a1SGeorge Liu * 10279f3b6a1SGeorge Liu * @param[in,out] asyncResp Async HTTP response. 10379f3b6a1SGeorge Liu * @param[in] locationIndicatorActive Value of the property 10479f3b6a1SGeorge Liu */ 10579f3b6a1SGeorge Liu inline void setLocationIndicatorActiveState( 10679f3b6a1SGeorge Liu const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 10779f3b6a1SGeorge Liu bool locationIndicatorActive, const std::string& managerId) 10879f3b6a1SGeorge Liu { 10979f3b6a1SGeorge Liu // GetSubTree on all interfaces which provide info about a Manager 11079f3b6a1SGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 11179f3b6a1SGeorge Liu "xyz.openbmc_project.Inventory.Item.Bmc"}; 11279f3b6a1SGeorge Liu dbus::utility::getSubTreePaths( 11379f3b6a1SGeorge Liu "/xyz/openbmc_project/inventory", 0, interfaces, 11479f3b6a1SGeorge Liu std::bind_front(handleSetLocationIndicatorActive, asyncResp, 11579f3b6a1SGeorge Liu locationIndicatorActive, managerId)); 11679f3b6a1SGeorge Liu } 11779f3b6a1SGeorge Liu 118d27c31e9SJagpal Singh Gill inline std::string getBMCUpdateServiceName() 119d27c31e9SJagpal Singh Gill { 120d27c31e9SJagpal Singh Gill if constexpr (BMCWEB_REDFISH_UPDATESERVICE_USE_DBUS) 121d27c31e9SJagpal Singh Gill { 122d27c31e9SJagpal Singh Gill return "xyz.openbmc_project.Software.Manager"; 123d27c31e9SJagpal Singh Gill } 124d27c31e9SJagpal Singh Gill return "xyz.openbmc_project.Software.BMC.Updater"; 125d27c31e9SJagpal Singh Gill } 126d27c31e9SJagpal Singh Gill 127d27c31e9SJagpal Singh Gill inline std::string getBMCUpdateServicePath() 128d27c31e9SJagpal Singh Gill { 129d27c31e9SJagpal Singh Gill if constexpr (BMCWEB_REDFISH_UPDATESERVICE_USE_DBUS) 130d27c31e9SJagpal Singh Gill { 131d27c31e9SJagpal Singh Gill return "/xyz/openbmc_project/software/bmc"; 132d27c31e9SJagpal Singh Gill } 133d27c31e9SJagpal Singh Gill return "/xyz/openbmc_project/software"; 134d27c31e9SJagpal Singh Gill } 135d27c31e9SJagpal Singh Gill 136ed5befbdSJennifer Lee /** 1372a5c4407SGunnar Mills * Function reboots the BMC. 1382a5c4407SGunnar Mills * 1392a5c4407SGunnar Mills * @param[in] asyncResp - Shared pointer for completing asynchronous calls 140ed5befbdSJennifer Lee */ 141504af5a0SPatrick Williams inline void doBMCGracefulRestart( 142504af5a0SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 143ed5befbdSJennifer Lee { 144ed5befbdSJennifer Lee const char* processName = "xyz.openbmc_project.State.BMC"; 145ed5befbdSJennifer Lee const char* objectPath = "/xyz/openbmc_project/state/bmc0"; 146ed5befbdSJennifer Lee const char* interfaceName = "xyz.openbmc_project.State.BMC"; 147ed5befbdSJennifer Lee const std::string& propertyValue = 148ed5befbdSJennifer Lee "xyz.openbmc_project.State.BMC.Transition.Reboot"; 149ed5befbdSJennifer Lee const char* destProperty = "RequestedBMCTransition"; 150ed5befbdSJennifer Lee 151ed5befbdSJennifer Lee // Create the D-Bus variant for D-Bus call. 1529ae226faSGeorge Liu sdbusplus::asio::setProperty( 1539ae226faSGeorge Liu *crow::connections::systemBus, processName, objectPath, interfaceName, 1549ae226faSGeorge Liu destProperty, propertyValue, 1555e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 156ed5befbdSJennifer Lee // Use "Set" method to set the property value. 157ed5befbdSJennifer Lee if (ec) 158ed5befbdSJennifer Lee { 15962598e31SEd Tanous BMCWEB_LOG_DEBUG("[Set] Bad D-Bus request error: {}", ec); 160ed5befbdSJennifer Lee messages::internalError(asyncResp->res); 161ed5befbdSJennifer Lee return; 162ed5befbdSJennifer Lee } 163ed5befbdSJennifer Lee 164ed5befbdSJennifer Lee messages::success(asyncResp->res); 1659ae226faSGeorge Liu }); 166ed5befbdSJennifer Lee } 1672a5c4407SGunnar Mills 168504af5a0SPatrick Williams inline void doBMCForceRestart( 169504af5a0SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 170f92af389SJayaprakash Mutyala { 171f92af389SJayaprakash Mutyala const char* processName = "xyz.openbmc_project.State.BMC"; 172f92af389SJayaprakash Mutyala const char* objectPath = "/xyz/openbmc_project/state/bmc0"; 173f92af389SJayaprakash Mutyala const char* interfaceName = "xyz.openbmc_project.State.BMC"; 174f92af389SJayaprakash Mutyala const std::string& propertyValue = 175f92af389SJayaprakash Mutyala "xyz.openbmc_project.State.BMC.Transition.HardReboot"; 176f92af389SJayaprakash Mutyala const char* destProperty = "RequestedBMCTransition"; 177f92af389SJayaprakash Mutyala 178f92af389SJayaprakash Mutyala // Create the D-Bus variant for D-Bus call. 1799ae226faSGeorge Liu sdbusplus::asio::setProperty( 1809ae226faSGeorge Liu *crow::connections::systemBus, processName, objectPath, interfaceName, 1819ae226faSGeorge Liu destProperty, propertyValue, 1825e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 183f92af389SJayaprakash Mutyala // Use "Set" method to set the property value. 184f92af389SJayaprakash Mutyala if (ec) 185f92af389SJayaprakash Mutyala { 18662598e31SEd Tanous BMCWEB_LOG_DEBUG("[Set] Bad D-Bus request error: {}", ec); 187f92af389SJayaprakash Mutyala messages::internalError(asyncResp->res); 188f92af389SJayaprakash Mutyala return; 189f92af389SJayaprakash Mutyala } 190f92af389SJayaprakash Mutyala 191f92af389SJayaprakash Mutyala messages::success(asyncResp->res); 1929ae226faSGeorge Liu }); 193f92af389SJayaprakash Mutyala } 194f92af389SJayaprakash Mutyala 1952a5c4407SGunnar Mills /** 1962a5c4407SGunnar Mills * ManagerResetAction class supports the POST method for the Reset (reboot) 1972a5c4407SGunnar Mills * action. 1982a5c4407SGunnar Mills */ 1997e860f15SJohn Edward Broadbent inline void requestRoutesManagerResetAction(App& app) 2002a5c4407SGunnar Mills { 2012a5c4407SGunnar Mills /** 2022a5c4407SGunnar Mills * Function handles POST method request. 2032a5c4407SGunnar Mills * Analyzes POST body before sending Reset (Reboot) request data to D-Bus. 204f92af389SJayaprakash Mutyala * OpenBMC supports ResetType "GracefulRestart" and "ForceRestart". 2052a5c4407SGunnar Mills */ 2067e860f15SJohn Edward Broadbent 207253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/Actions/Manager.Reset/") 208ed398213SEd Tanous .privileges(redfish::privileges::postManager) 2097e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 21045ca1b86SEd Tanous [&app](const crow::Request& req, 211253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 212253f11b8SEd Tanous const std::string& managerId) { 2133ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 21445ca1b86SEd Tanous { 21545ca1b86SEd Tanous return; 21645ca1b86SEd Tanous } 217253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 218253f11b8SEd Tanous { 219bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "Manager", 220bd79bce8SPatrick Williams managerId); 221253f11b8SEd Tanous return; 222253f11b8SEd Tanous } 223253f11b8SEd Tanous 22462598e31SEd Tanous BMCWEB_LOG_DEBUG("Post Manager Reset."); 2252a5c4407SGunnar Mills 2262a5c4407SGunnar Mills std::string resetType; 2272a5c4407SGunnar Mills 22815ed6780SWilly Tu if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", 2297e860f15SJohn Edward Broadbent resetType)) 2302a5c4407SGunnar Mills { 2312a5c4407SGunnar Mills return; 2322a5c4407SGunnar Mills } 2332a5c4407SGunnar Mills 234f92af389SJayaprakash Mutyala if (resetType == "GracefulRestart") 235f92af389SJayaprakash Mutyala { 23662598e31SEd Tanous BMCWEB_LOG_DEBUG("Proceeding with {}", resetType); 237f92af389SJayaprakash Mutyala doBMCGracefulRestart(asyncResp); 238f92af389SJayaprakash Mutyala return; 239f92af389SJayaprakash Mutyala } 2403174e4dfSEd Tanous if (resetType == "ForceRestart") 241f92af389SJayaprakash Mutyala { 24262598e31SEd Tanous BMCWEB_LOG_DEBUG("Proceeding with {}", resetType); 243f92af389SJayaprakash Mutyala doBMCForceRestart(asyncResp); 244f92af389SJayaprakash Mutyala return; 245f92af389SJayaprakash Mutyala } 246bd79bce8SPatrick Williams BMCWEB_LOG_DEBUG("Invalid property value for ResetType: {}", 247bd79bce8SPatrick Williams resetType); 2482a5c4407SGunnar Mills messages::actionParameterNotSupported(asyncResp->res, resetType, 2492a5c4407SGunnar Mills "ResetType"); 2502a5c4407SGunnar Mills 2512a5c4407SGunnar Mills return; 2527e860f15SJohn Edward Broadbent }); 2532a5c4407SGunnar Mills } 254ed5befbdSJennifer Lee 2553e40fc74SGunnar Mills /** 2563e40fc74SGunnar Mills * ManagerResetToDefaultsAction class supports POST method for factory reset 2573e40fc74SGunnar Mills * action. 2583e40fc74SGunnar Mills */ 2597e860f15SJohn Edward Broadbent inline void requestRoutesManagerResetToDefaultsAction(App& app) 2603e40fc74SGunnar Mills { 2613e40fc74SGunnar Mills /** 2623e40fc74SGunnar Mills * Function handles ResetToDefaults POST method request. 2633e40fc74SGunnar Mills * 2643e40fc74SGunnar Mills * Analyzes POST body message and factory resets BMC by calling 2653e40fc74SGunnar Mills * BMC code updater factory reset followed by a BMC reboot. 2663e40fc74SGunnar Mills * 2673e40fc74SGunnar Mills * BMC code updater factory reset wipes the whole BMC read-write 2683e40fc74SGunnar Mills * filesystem which includes things like the network settings. 2693e40fc74SGunnar Mills * 27018bf4bf6SGunnar Mills * OpenBMC only supports ResetType "ResetAll". 2713e40fc74SGunnar Mills */ 2727e860f15SJohn Edward Broadbent 2737e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 274253f11b8SEd Tanous "/redfish/v1/Managers/<str>/Actions/Manager.ResetToDefaults/") 275ed398213SEd Tanous .privileges(redfish::privileges::postManager) 27618bf4bf6SGunnar Mills .methods(boost::beast::http::verb::post)( 27718bf4bf6SGunnar Mills [&app](const crow::Request& req, 278253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 279253f11b8SEd Tanous const std::string& managerId) { 2803ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 28145ca1b86SEd Tanous { 28245ca1b86SEd Tanous return; 28345ca1b86SEd Tanous } 284253f11b8SEd Tanous 285253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 286253f11b8SEd Tanous { 287bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "Manager", 288bd79bce8SPatrick Williams managerId); 289253f11b8SEd Tanous return; 290253f11b8SEd Tanous } 291253f11b8SEd Tanous 29262598e31SEd Tanous BMCWEB_LOG_DEBUG("Post ResetToDefaults."); 2933e40fc74SGunnar Mills 2949970e93fSKonstantin Aladyshev std::optional<std::string> resetType; 2953e40fc74SGunnar Mills 296afc474aeSMyung Bae if (!json_util::readJsonAction( // 297afc474aeSMyung Bae req, asyncResp->res, // 298afc474aeSMyung Bae "ResetType", resetType // 299afc474aeSMyung Bae )) 3003e40fc74SGunnar Mills { 3019970e93fSKonstantin Aladyshev BMCWEB_LOG_DEBUG("Missing property ResetType."); 3023e40fc74SGunnar Mills 303bd79bce8SPatrick Williams messages::actionParameterMissing( 304bd79bce8SPatrick Williams asyncResp->res, "ResetToDefaults", "ResetType"); 3053e40fc74SGunnar Mills return; 3063e40fc74SGunnar Mills } 3073e40fc74SGunnar Mills 3083e40fc74SGunnar Mills if (resetType != "ResetAll") 3093e40fc74SGunnar Mills { 3109970e93fSKonstantin Aladyshev BMCWEB_LOG_DEBUG("Invalid property value for ResetType: {}", 3119970e93fSKonstantin Aladyshev *resetType); 31218bf4bf6SGunnar Mills messages::actionParameterNotSupported( 31318bf4bf6SGunnar Mills asyncResp->res, *resetType, "ResetType"); 3143e40fc74SGunnar Mills return; 3153e40fc74SGunnar Mills } 3163e40fc74SGunnar Mills 3173e40fc74SGunnar Mills crow::connections::systemBus->async_method_call( 3185e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 3193e40fc74SGunnar Mills if (ec) 3203e40fc74SGunnar Mills { 32118bf4bf6SGunnar Mills BMCWEB_LOG_DEBUG("Failed to ResetToDefaults: {}", 32218bf4bf6SGunnar Mills ec); 3233e40fc74SGunnar Mills messages::internalError(asyncResp->res); 3243e40fc74SGunnar Mills return; 3253e40fc74SGunnar Mills } 3263e40fc74SGunnar Mills // Factory Reset doesn't actually happen until a reboot 3273e40fc74SGunnar Mills // Can't erase what the BMC is running on 3283e40fc74SGunnar Mills doBMCGracefulRestart(asyncResp); 3293e40fc74SGunnar Mills }, 330d27c31e9SJagpal Singh Gill getBMCUpdateServiceName(), getBMCUpdateServicePath(), 3313e40fc74SGunnar Mills "xyz.openbmc_project.Common.FactoryReset", "Reset"); 3327e860f15SJohn Edward Broadbent }); 3333e40fc74SGunnar Mills } 3343e40fc74SGunnar Mills 3351cb1a9e6SAppaRao Puli /** 3361cb1a9e6SAppaRao Puli * ManagerResetActionInfo derived class for delivering Manager 3371cb1a9e6SAppaRao Puli * ResetType AllowableValues using ResetInfo schema. 3381cb1a9e6SAppaRao Puli */ 3397e860f15SJohn Edward Broadbent inline void requestRoutesManagerResetActionInfo(App& app) 3401cb1a9e6SAppaRao Puli { 3411cb1a9e6SAppaRao Puli /** 3421cb1a9e6SAppaRao Puli * Functions triggers appropriate requests on DBus 3431cb1a9e6SAppaRao Puli */ 3447e860f15SJohn Edward Broadbent 345253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/ResetActionInfo/") 346ed398213SEd Tanous .privileges(redfish::privileges::getActionInfo) 3477e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 34845ca1b86SEd Tanous [&app](const crow::Request& req, 349253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 350253f11b8SEd Tanous const std::string& managerId) { 3513ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 35245ca1b86SEd Tanous { 35345ca1b86SEd Tanous return; 35445ca1b86SEd Tanous } 3551476687dSEd Tanous 356253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 357253f11b8SEd Tanous { 358bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "Manager", 359bd79bce8SPatrick Williams managerId); 360253f11b8SEd Tanous return; 361253f11b8SEd Tanous } 362253f11b8SEd Tanous 3631476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 3641476687dSEd Tanous "#ActionInfo.v1_1_2.ActionInfo"; 365bd79bce8SPatrick Williams asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 366bd79bce8SPatrick Williams "/redfish/v1/Managers/{}/ResetActionInfo", 367253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 3681476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "Reset Action Info"; 3691476687dSEd Tanous asyncResp->res.jsonValue["Id"] = "ResetActionInfo"; 3701476687dSEd Tanous nlohmann::json::object_t parameter; 3711476687dSEd Tanous parameter["Name"] = "ResetType"; 3721476687dSEd Tanous parameter["Required"] = true; 373539d8c6bSEd Tanous parameter["DataType"] = action_info::ParameterTypes::String; 3741476687dSEd Tanous 3751476687dSEd Tanous nlohmann::json::array_t allowableValues; 376ad539545SPatrick Williams allowableValues.emplace_back("GracefulRestart"); 377ad539545SPatrick Williams allowableValues.emplace_back("ForceRestart"); 3781476687dSEd Tanous parameter["AllowableValues"] = std::move(allowableValues); 3791476687dSEd Tanous 3801476687dSEd Tanous nlohmann::json::array_t parameters; 381ad539545SPatrick Williams parameters.emplace_back(std::move(parameter)); 3821476687dSEd Tanous 3831476687dSEd Tanous asyncResp->res.jsonValue["Parameters"] = std::move(parameters); 3847e860f15SJohn Edward Broadbent }); 3851cb1a9e6SAppaRao Puli } 3861cb1a9e6SAppaRao Puli 387071d8fdfSSunnySrivastava1984 /** 388071d8fdfSSunnySrivastava1984 * @brief Retrieves BMC manager location data over DBus 389071d8fdfSSunnySrivastava1984 * 390ac106bf6SEd Tanous * @param[in] asyncResp Shared pointer for completing asynchronous calls 391071d8fdfSSunnySrivastava1984 * @param[in] connectionName - service name 392071d8fdfSSunnySrivastava1984 * @param[in] path - object path 393071d8fdfSSunnySrivastava1984 * @return none 394071d8fdfSSunnySrivastava1984 */ 395ac106bf6SEd Tanous inline void getLocation(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 396071d8fdfSSunnySrivastava1984 const std::string& connectionName, 397071d8fdfSSunnySrivastava1984 const std::string& path) 398071d8fdfSSunnySrivastava1984 { 39962598e31SEd Tanous BMCWEB_LOG_DEBUG("Get BMC manager Location data."); 400071d8fdfSSunnySrivastava1984 401deae6a78SEd Tanous dbus::utility::getProperty<std::string>( 402deae6a78SEd Tanous connectionName, path, 4031e1e598dSJonathan Doman "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode", 404ac106bf6SEd Tanous [asyncResp](const boost::system::error_code& ec, 4051e1e598dSJonathan Doman const std::string& property) { 406071d8fdfSSunnySrivastava1984 if (ec) 407071d8fdfSSunnySrivastava1984 { 40862598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error for " 40962598e31SEd Tanous "Location"); 410ac106bf6SEd Tanous messages::internalError(asyncResp->res); 411071d8fdfSSunnySrivastava1984 return; 412071d8fdfSSunnySrivastava1984 } 413071d8fdfSSunnySrivastava1984 414bd79bce8SPatrick Williams asyncResp->res 415bd79bce8SPatrick Williams .jsonValue["Location"]["PartLocation"]["ServiceLabel"] = 4161e1e598dSJonathan Doman property; 4171e1e598dSJonathan Doman }); 418071d8fdfSSunnySrivastava1984 } 4197e860f15SJohn Edward Broadbent // avoid name collision systems.hpp 420504af5a0SPatrick Williams inline void managerGetLastResetTime( 421504af5a0SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 4224bf2b033SGunnar Mills { 42362598e31SEd Tanous BMCWEB_LOG_DEBUG("Getting Manager Last Reset Time"); 4244bf2b033SGunnar Mills 425deae6a78SEd Tanous dbus::utility::getProperty<uint64_t>( 426deae6a78SEd Tanous "xyz.openbmc_project.State.BMC", "/xyz/openbmc_project/state/bmc0", 427deae6a78SEd Tanous "xyz.openbmc_project.State.BMC", "LastRebootTime", 428ac106bf6SEd Tanous [asyncResp](const boost::system::error_code& ec, 4291e1e598dSJonathan Doman const uint64_t lastResetTime) { 4304bf2b033SGunnar Mills if (ec) 4314bf2b033SGunnar Mills { 43262598e31SEd Tanous BMCWEB_LOG_DEBUG("D-BUS response error {}", ec); 4334bf2b033SGunnar Mills return; 4344bf2b033SGunnar Mills } 4354bf2b033SGunnar Mills 4364bf2b033SGunnar Mills // LastRebootTime is epoch time, in milliseconds 4374bf2b033SGunnar Mills // https://github.com/openbmc/phosphor-dbus-interfaces/blob/7f9a128eb9296e926422ddc312c148b625890bb6/xyz/openbmc_project/State/BMC.interface.yaml#L19 4381e1e598dSJonathan Doman uint64_t lastResetTimeStamp = lastResetTime / 1000; 4394bf2b033SGunnar Mills 4404bf2b033SGunnar Mills // Convert to ISO 8601 standard 441ac106bf6SEd Tanous asyncResp->res.jsonValue["LastResetTime"] = 4422b82937eSEd Tanous redfish::time_utils::getDateTimeUint(lastResetTimeStamp); 4431e1e598dSJonathan Doman }); 4444bf2b033SGunnar Mills } 4454bf2b033SGunnar Mills 4464bfefa74SGunnar Mills /** 4474bfefa74SGunnar Mills * @brief Set the running firmware image 4484bfefa74SGunnar Mills * 449ac106bf6SEd Tanous * @param[i,o] asyncResp - Async response object 4504bfefa74SGunnar Mills * @param[i] runningFirmwareTarget - Image to make the running image 4514bfefa74SGunnar Mills * 4524bfefa74SGunnar Mills * @return void 4534bfefa74SGunnar Mills */ 454504af5a0SPatrick Williams inline void setActiveFirmwareImage( 455504af5a0SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 456f23b7296SEd Tanous const std::string& runningFirmwareTarget) 4574bfefa74SGunnar Mills { 4584bfefa74SGunnar Mills // Get the Id from /redfish/v1/UpdateService/FirmwareInventory/<Id> 459f23b7296SEd Tanous std::string::size_type idPos = runningFirmwareTarget.rfind('/'); 4604bfefa74SGunnar Mills if (idPos == std::string::npos) 4614bfefa74SGunnar Mills { 462ac106bf6SEd Tanous messages::propertyValueNotInList(asyncResp->res, runningFirmwareTarget, 4634bfefa74SGunnar Mills "@odata.id"); 46462598e31SEd Tanous BMCWEB_LOG_DEBUG("Can't parse firmware ID!"); 4654bfefa74SGunnar Mills return; 4664bfefa74SGunnar Mills } 4674bfefa74SGunnar Mills idPos++; 4684bfefa74SGunnar Mills if (idPos >= runningFirmwareTarget.size()) 4694bfefa74SGunnar Mills { 470ac106bf6SEd Tanous messages::propertyValueNotInList(asyncResp->res, runningFirmwareTarget, 4714bfefa74SGunnar Mills "@odata.id"); 47262598e31SEd Tanous BMCWEB_LOG_DEBUG("Invalid firmware ID."); 4734bfefa74SGunnar Mills return; 4744bfefa74SGunnar Mills } 4754bfefa74SGunnar Mills std::string firmwareId = runningFirmwareTarget.substr(idPos); 4764bfefa74SGunnar Mills 4774bfefa74SGunnar Mills // Make sure the image is valid before setting priority 4785eb468daSGeorge Liu sdbusplus::message::object_path objPath("/xyz/openbmc_project/software"); 4795eb468daSGeorge Liu dbus::utility::getManagedObjects( 480d27c31e9SJagpal Singh Gill getBMCUpdateServiceName(), objPath, 4815eb468daSGeorge Liu [asyncResp, firmwareId, runningFirmwareTarget]( 4825eb468daSGeorge Liu const boost::system::error_code& ec, 4835eb468daSGeorge Liu const dbus::utility::ManagedObjectType& subtree) { 4844bfefa74SGunnar Mills if (ec) 4854bfefa74SGunnar Mills { 48662598e31SEd Tanous BMCWEB_LOG_DEBUG("D-Bus response error getting objects."); 487ac106bf6SEd Tanous messages::internalError(asyncResp->res); 4884bfefa74SGunnar Mills return; 4894bfefa74SGunnar Mills } 4904bfefa74SGunnar Mills 49126f6976fSEd Tanous if (subtree.empty()) 4924bfefa74SGunnar Mills { 49362598e31SEd Tanous BMCWEB_LOG_DEBUG("Can't find image!"); 494ac106bf6SEd Tanous messages::internalError(asyncResp->res); 4954bfefa74SGunnar Mills return; 4964bfefa74SGunnar Mills } 4974bfefa74SGunnar Mills 4984bfefa74SGunnar Mills bool foundImage = false; 49902cad96eSEd Tanous for (const auto& object : subtree) 5004bfefa74SGunnar Mills { 5014bfefa74SGunnar Mills const std::string& path = 5024bfefa74SGunnar Mills static_cast<const std::string&>(object.first); 503f23b7296SEd Tanous std::size_t idPos2 = path.rfind('/'); 5044bfefa74SGunnar Mills 5054bfefa74SGunnar Mills if (idPos2 == std::string::npos) 5064bfefa74SGunnar Mills { 5074bfefa74SGunnar Mills continue; 5084bfefa74SGunnar Mills } 5094bfefa74SGunnar Mills 5104bfefa74SGunnar Mills idPos2++; 5114bfefa74SGunnar Mills if (idPos2 >= path.size()) 5124bfefa74SGunnar Mills { 5134bfefa74SGunnar Mills continue; 5144bfefa74SGunnar Mills } 5154bfefa74SGunnar Mills 5164bfefa74SGunnar Mills if (path.substr(idPos2) == firmwareId) 5174bfefa74SGunnar Mills { 5184bfefa74SGunnar Mills foundImage = true; 5194bfefa74SGunnar Mills break; 5204bfefa74SGunnar Mills } 5214bfefa74SGunnar Mills } 5224bfefa74SGunnar Mills 5234bfefa74SGunnar Mills if (!foundImage) 5244bfefa74SGunnar Mills { 525ac106bf6SEd Tanous messages::propertyValueNotInList( 526ac106bf6SEd Tanous asyncResp->res, runningFirmwareTarget, "@odata.id"); 52762598e31SEd Tanous BMCWEB_LOG_DEBUG("Invalid firmware ID."); 5284bfefa74SGunnar Mills return; 5294bfefa74SGunnar Mills } 5304bfefa74SGunnar Mills 53162598e31SEd Tanous BMCWEB_LOG_DEBUG("Setting firmware version {} to priority 0.", 53262598e31SEd Tanous firmwareId); 5334bfefa74SGunnar Mills 5344bfefa74SGunnar Mills // Only support Immediate 5354bfefa74SGunnar Mills // An addition could be a Redfish Setting like 5364bfefa74SGunnar Mills // ActiveSoftwareImageApplyTime and support OnReset 5379ae226faSGeorge Liu sdbusplus::asio::setProperty( 538d27c31e9SJagpal Singh Gill *crow::connections::systemBus, getBMCUpdateServiceName(), 5399ae226faSGeorge Liu "/xyz/openbmc_project/software/" + firmwareId, 5409ae226faSGeorge Liu "xyz.openbmc_project.Software.RedundancyPriority", "Priority", 5419ae226faSGeorge Liu static_cast<uint8_t>(0), 542ac106bf6SEd Tanous [asyncResp](const boost::system::error_code& ec2) { 5438a592810SEd Tanous if (ec2) 5444bfefa74SGunnar Mills { 54562598e31SEd Tanous BMCWEB_LOG_DEBUG("D-Bus response error setting."); 546ac106bf6SEd Tanous messages::internalError(asyncResp->res); 5474bfefa74SGunnar Mills return; 5484bfefa74SGunnar Mills } 549ac106bf6SEd Tanous doBMCGracefulRestart(asyncResp); 5509ae226faSGeorge Liu }); 5515eb468daSGeorge Liu }); 5524bfefa74SGunnar Mills } 5534bfefa74SGunnar Mills 554bd79bce8SPatrick Williams inline void afterSetDateTime( 555bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 556bd79bce8SPatrick Williams const boost::system::error_code& ec, const sdbusplus::message_t& msg) 557c51afd54SEd Tanous { 558c51afd54SEd Tanous if (ec) 559c51afd54SEd Tanous { 560c51afd54SEd Tanous BMCWEB_LOG_DEBUG("Failed to set elapsed time. DBUS response error {}", 561c51afd54SEd Tanous ec); 562c51afd54SEd Tanous const sd_bus_error* dbusError = msg.get_error(); 563c51afd54SEd Tanous if (dbusError != nullptr) 564c51afd54SEd Tanous { 565c51afd54SEd Tanous std::string_view errorName(dbusError->name); 566c51afd54SEd Tanous if (errorName == 567c51afd54SEd Tanous "org.freedesktop.timedate1.AutomaticTimeSyncEnabled") 568c51afd54SEd Tanous { 569c51afd54SEd Tanous BMCWEB_LOG_DEBUG("Setting conflict"); 570c51afd54SEd Tanous messages::propertyValueConflict( 571c51afd54SEd Tanous asyncResp->res, "DateTime", 572c51afd54SEd Tanous "Managers/NetworkProtocol/NTPProcotolEnabled"); 573c51afd54SEd Tanous return; 574c51afd54SEd Tanous } 575c51afd54SEd Tanous } 576c51afd54SEd Tanous messages::internalError(asyncResp->res); 577c51afd54SEd Tanous return; 578c51afd54SEd Tanous } 579c51afd54SEd Tanous asyncResp->res.result(boost::beast::http::status::no_content); 580c51afd54SEd Tanous } 581c51afd54SEd Tanous 582c51afd54SEd Tanous inline void setDateTime(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 583c51afd54SEd Tanous const std::string& datetime) 584af5d6058SSantosh Puranik { 58562598e31SEd Tanous BMCWEB_LOG_DEBUG("Set date time: {}", datetime); 586af5d6058SSantosh Puranik 587c2e32007SEd Tanous std::optional<redfish::time_utils::usSinceEpoch> us = 588c2e32007SEd Tanous redfish::time_utils::dateStringToEpoch(datetime); 589c2e32007SEd Tanous if (!us) 590af5d6058SSantosh Puranik { 591ac106bf6SEd Tanous messages::propertyValueFormatError(asyncResp->res, datetime, 592ac106bf6SEd Tanous "DateTime"); 593c2e32007SEd Tanous return; 594c2e32007SEd Tanous } 595c51afd54SEd Tanous // Set the absolute datetime 596c51afd54SEd Tanous bool relative = false; 597c51afd54SEd Tanous bool interactive = false; 598c51afd54SEd Tanous crow::connections::systemBus->async_method_call( 599c51afd54SEd Tanous [asyncResp](const boost::system::error_code& ec, 600c51afd54SEd Tanous const sdbusplus::message_t& msg) { 601c51afd54SEd Tanous afterSetDateTime(asyncResp, ec, msg); 602c51afd54SEd Tanous }, 603c51afd54SEd Tanous "org.freedesktop.timedate1", "/org/freedesktop/timedate1", 604c51afd54SEd Tanous "org.freedesktop.timedate1", "SetTime", us->count(), relative, 605c51afd54SEd Tanous interactive); 60683ff9ab6SJames Feist } 6079c310685SBorawski.Lukasz 608504af5a0SPatrick Williams inline void checkForQuiesced( 609504af5a0SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 61075815e5cSEd Tanous { 611deae6a78SEd Tanous dbus::utility::getProperty<std::string>( 612deae6a78SEd Tanous "org.freedesktop.systemd1", 61375815e5cSEd Tanous "/org/freedesktop/systemd1/unit/obmc-bmc-service-quiesce@0.target", 61475815e5cSEd Tanous "org.freedesktop.systemd1.Unit", "ActiveState", 61575815e5cSEd Tanous [asyncResp](const boost::system::error_code& ec, 61675815e5cSEd Tanous const std::string& val) { 61775815e5cSEd Tanous if (!ec) 61875815e5cSEd Tanous { 61975815e5cSEd Tanous if (val == "active") 62075815e5cSEd Tanous { 621539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["Health"] = 622539d8c6bSEd Tanous resource::Health::Critical; 623539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = 624539d8c6bSEd Tanous resource::State::Quiesced; 62575815e5cSEd Tanous return; 62675815e5cSEd Tanous } 62775815e5cSEd Tanous } 628539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK; 629bd79bce8SPatrick Williams asyncResp->res.jsonValue["Status"]["State"] = 630bd79bce8SPatrick Williams resource::State::Enabled; 63175815e5cSEd Tanous }); 63275815e5cSEd Tanous } 63375815e5cSEd Tanous 634e2cdf06fSJanet Adkins inline void getPhysicalAssets( 635e2cdf06fSJanet Adkins const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 636e2cdf06fSJanet Adkins const boost::system::error_code& ec, 637e2cdf06fSJanet Adkins const dbus::utility::DBusPropertiesMap& propertiesList) 638e2cdf06fSJanet Adkins { 639e2cdf06fSJanet Adkins if (ec) 640e2cdf06fSJanet Adkins { 641e2cdf06fSJanet Adkins BMCWEB_LOG_DEBUG("Can't get bmc asset!"); 642e2cdf06fSJanet Adkins return; 643e2cdf06fSJanet Adkins } 644e2cdf06fSJanet Adkins 645e2cdf06fSJanet Adkins const std::string* partNumber = nullptr; 646e2cdf06fSJanet Adkins const std::string* serialNumber = nullptr; 647e2cdf06fSJanet Adkins const std::string* manufacturer = nullptr; 648e2cdf06fSJanet Adkins const std::string* model = nullptr; 649e2cdf06fSJanet Adkins const std::string* sparePartNumber = nullptr; 650e2cdf06fSJanet Adkins 651e2cdf06fSJanet Adkins const bool success = sdbusplus::unpackPropertiesNoThrow( 652e2cdf06fSJanet Adkins dbus_utils::UnpackErrorPrinter(), propertiesList, "PartNumber", 653e2cdf06fSJanet Adkins partNumber, "SerialNumber", serialNumber, "Manufacturer", manufacturer, 654e2cdf06fSJanet Adkins "Model", model, "SparePartNumber", sparePartNumber); 655e2cdf06fSJanet Adkins 656e2cdf06fSJanet Adkins if (!success) 657e2cdf06fSJanet Adkins { 658e2cdf06fSJanet Adkins messages::internalError(asyncResp->res); 659e2cdf06fSJanet Adkins return; 660e2cdf06fSJanet Adkins } 661e2cdf06fSJanet Adkins 662e2cdf06fSJanet Adkins if (partNumber != nullptr) 663e2cdf06fSJanet Adkins { 664e2cdf06fSJanet Adkins asyncResp->res.jsonValue["PartNumber"] = *partNumber; 665e2cdf06fSJanet Adkins } 666e2cdf06fSJanet Adkins 667e2cdf06fSJanet Adkins if (serialNumber != nullptr) 668e2cdf06fSJanet Adkins { 669e2cdf06fSJanet Adkins asyncResp->res.jsonValue["SerialNumber"] = *serialNumber; 670e2cdf06fSJanet Adkins } 671e2cdf06fSJanet Adkins 672e2cdf06fSJanet Adkins if (manufacturer != nullptr) 673e2cdf06fSJanet Adkins { 674e2cdf06fSJanet Adkins asyncResp->res.jsonValue["Manufacturer"] = *manufacturer; 675e2cdf06fSJanet Adkins } 676e2cdf06fSJanet Adkins 677e2cdf06fSJanet Adkins if (model != nullptr) 678e2cdf06fSJanet Adkins { 679e2cdf06fSJanet Adkins asyncResp->res.jsonValue["Model"] = *model; 680e2cdf06fSJanet Adkins } 681e2cdf06fSJanet Adkins 682e2cdf06fSJanet Adkins if (sparePartNumber != nullptr) 683e2cdf06fSJanet Adkins { 684e2cdf06fSJanet Adkins asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber; 685e2cdf06fSJanet Adkins } 686e2cdf06fSJanet Adkins } 687e2cdf06fSJanet Adkins 688e2cdf06fSJanet Adkins inline void getManagerData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 689e2cdf06fSJanet Adkins const std::string& managerPath, 690e2cdf06fSJanet Adkins const dbus::utility::MapperServiceMap& serviceMap) 691e2cdf06fSJanet Adkins { 692e2cdf06fSJanet Adkins if (managerPath.empty() || serviceMap.size() != 1) 693e2cdf06fSJanet Adkins { 694e2cdf06fSJanet Adkins BMCWEB_LOG_DEBUG("Error getting bmc D-Bus object!"); 695e2cdf06fSJanet Adkins messages::internalError(asyncResp->res); 696e2cdf06fSJanet Adkins return; 697e2cdf06fSJanet Adkins } 698e2cdf06fSJanet Adkins 699e2cdf06fSJanet Adkins for (const auto& [connectionName, interfaces] : serviceMap) 700e2cdf06fSJanet Adkins { 701e2cdf06fSJanet Adkins for (const auto& interfaceName : interfaces) 702e2cdf06fSJanet Adkins { 703e2cdf06fSJanet Adkins if (interfaceName == 704e2cdf06fSJanet Adkins "xyz.openbmc_project.Inventory.Decorator.Asset") 705e2cdf06fSJanet Adkins { 706e2cdf06fSJanet Adkins dbus::utility::getAllProperties( 707e2cdf06fSJanet Adkins *crow::connections::systemBus, connectionName, managerPath, 708e2cdf06fSJanet Adkins "xyz.openbmc_project.Inventory.Decorator.Asset", 709e2cdf06fSJanet Adkins std::bind_front(getPhysicalAssets, asyncResp)); 710e2cdf06fSJanet Adkins } 711e2cdf06fSJanet Adkins else if (interfaceName == 712e2cdf06fSJanet Adkins "xyz.openbmc_project.Inventory.Decorator.LocationCode") 713e2cdf06fSJanet Adkins { 714e2cdf06fSJanet Adkins getLocation(asyncResp, connectionName, managerPath); 715e2cdf06fSJanet Adkins } 71679f3b6a1SGeorge Liu else if (interfaceName == 71779f3b6a1SGeorge Liu "xyz.openbmc_project.Association.Definitions") 71879f3b6a1SGeorge Liu { 71979f3b6a1SGeorge Liu getLocationIndicatorActive(asyncResp, managerPath); 72079f3b6a1SGeorge Liu } 721e2cdf06fSJanet Adkins } 722e2cdf06fSJanet Adkins } 723e2cdf06fSJanet Adkins } 724e2cdf06fSJanet Adkins 725e2cdf06fSJanet Adkins inline void afterGetManagerObject( 726e2cdf06fSJanet Adkins const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 727e2cdf06fSJanet Adkins const boost::system::error_code& ec, 728e2cdf06fSJanet Adkins const dbus::utility::MapperGetSubTreeResponse& subtree, 729e2cdf06fSJanet Adkins const std::function< 730e2cdf06fSJanet Adkins void(const std::string& managerPath, 731e2cdf06fSJanet Adkins const dbus::utility::MapperServiceMap& serviceMap)>& callback) 732e2cdf06fSJanet Adkins { 733e2cdf06fSJanet Adkins if (ec) 734e2cdf06fSJanet Adkins { 735e2cdf06fSJanet Adkins BMCWEB_LOG_DEBUG("D-Bus response error on GetSubTree {}", ec); 736e2cdf06fSJanet Adkins return; 737e2cdf06fSJanet Adkins } 738e2cdf06fSJanet Adkins if (subtree.empty()) 739e2cdf06fSJanet Adkins { 740e2cdf06fSJanet Adkins BMCWEB_LOG_DEBUG("Can't find bmc D-Bus object!"); 741e2cdf06fSJanet Adkins return; 742e2cdf06fSJanet Adkins } 743e2cdf06fSJanet Adkins // Assume only 1 bmc D-Bus object 744e2cdf06fSJanet Adkins // Throw an error if there is more than 1 745e2cdf06fSJanet Adkins if (subtree.size() > 1) 746e2cdf06fSJanet Adkins { 747e2cdf06fSJanet Adkins BMCWEB_LOG_ERROR("Found more than 1 bmc D-Bus object!"); 748e2cdf06fSJanet Adkins messages::internalError(asyncResp->res); 749e2cdf06fSJanet Adkins return; 750e2cdf06fSJanet Adkins } 751e2cdf06fSJanet Adkins 752e2cdf06fSJanet Adkins callback(subtree[0].first, subtree[0].second); 753e2cdf06fSJanet Adkins } 754e2cdf06fSJanet Adkins 755e2cdf06fSJanet Adkins inline void getManagerObject( 756e2cdf06fSJanet Adkins const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 757e2cdf06fSJanet Adkins const std::string& /* managerId */, 758e2cdf06fSJanet Adkins std::function<void(const std::string& managerPath, 759e2cdf06fSJanet Adkins const dbus::utility::MapperServiceMap& serviceMap)>&& 760e2cdf06fSJanet Adkins callback) 761e2cdf06fSJanet Adkins { 762e2cdf06fSJanet Adkins constexpr std::array<std::string_view, 1> interfaces = { 763e2cdf06fSJanet Adkins "xyz.openbmc_project.Inventory.Item.Bmc"}; 764e2cdf06fSJanet Adkins dbus::utility::getSubTree( 765e2cdf06fSJanet Adkins "/xyz/openbmc_project/inventory", 0, interfaces, 766e2cdf06fSJanet Adkins [asyncResp, callback{std::move(callback)}]( 767e2cdf06fSJanet Adkins const boost::system::error_code& ec, 768e2cdf06fSJanet Adkins const dbus::utility::MapperGetSubTreeResponse& subtree) { 769e2cdf06fSJanet Adkins afterGetManagerObject(asyncResp, ec, subtree, callback); 770e2cdf06fSJanet Adkins }); 771e2cdf06fSJanet Adkins } 772e2cdf06fSJanet Adkins 773*96153bdeSMyung Bae inline void handleManagerGet( 774*96153bdeSMyung Bae App& app, const crow::Request& req, 775253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 776*96153bdeSMyung Bae const std::string& managerId) 777*96153bdeSMyung Bae { 7783ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 77945ca1b86SEd Tanous { 78045ca1b86SEd Tanous return; 78145ca1b86SEd Tanous } 782253f11b8SEd Tanous 783253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 784253f11b8SEd Tanous { 785*96153bdeSMyung Bae messages::resourceNotFound(asyncResp->res, "Manager", managerId); 786253f11b8SEd Tanous return; 787253f11b8SEd Tanous } 788253f11b8SEd Tanous 789*96153bdeSMyung Bae std::string uuid = persistent_data::getConfig().systemUuid; 790*96153bdeSMyung Bae 791253f11b8SEd Tanous asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 792253f11b8SEd Tanous "/redfish/v1/Managers/{}", BMCWEB_REDFISH_MANAGER_URI_NAME); 793*96153bdeSMyung Bae asyncResp->res.jsonValue["@odata.type"] = "#Manager.v1_15_0.Manager"; 794253f11b8SEd Tanous asyncResp->res.jsonValue["Id"] = BMCWEB_REDFISH_MANAGER_URI_NAME; 7957e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Name"] = "OpenBmc Manager"; 796*96153bdeSMyung Bae asyncResp->res.jsonValue["Description"] = "Baseboard Management Controller"; 797539d8c6bSEd Tanous asyncResp->res.jsonValue["PowerState"] = resource::PowerState::On; 7981476687dSEd Tanous 799539d8c6bSEd Tanous asyncResp->res.jsonValue["ManagerType"] = manager::ManagerType::BMC; 8007e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["UUID"] = systemd_utils::getUuid(); 8017e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["ServiceEntryPointUUID"] = uuid; 802*96153bdeSMyung Bae asyncResp->res.jsonValue["Model"] = "OpenBmc"; // TODO(ed), get model 8037e860f15SJohn Edward Broadbent 804*96153bdeSMyung Bae asyncResp->res.jsonValue["LogServices"]["@odata.id"] = boost::urls::format( 805*96153bdeSMyung Bae "/redfish/v1/Managers/{}/LogServices", BMCWEB_REDFISH_MANAGER_URI_NAME); 8061476687dSEd Tanous asyncResp->res.jsonValue["NetworkProtocol"]["@odata.id"] = 807253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}/NetworkProtocol", 808253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 8091476687dSEd Tanous asyncResp->res.jsonValue["EthernetInterfaces"]["@odata.id"] = 810*96153bdeSMyung Bae boost::urls::format("/redfish/v1/Managers/{}/EthernetInterfaces", 811253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 8127e860f15SJohn Edward Broadbent 813e30d3345SCorey Ethington manager_utils::getServiceIdentification(asyncResp, false); 814e30d3345SCorey Ethington 81525b54dbaSEd Tanous if constexpr (BMCWEB_VM_NBDPROXY) 81636c0f2a3SEd Tanous { 8171476687dSEd Tanous asyncResp->res.jsonValue["VirtualMedia"]["@odata.id"] = 818253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}/VirtualMedia", 819253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 82036c0f2a3SEd Tanous } 8217e860f15SJohn Edward Broadbent 8227e860f15SJohn Edward Broadbent // Manager.Reset (an action) can be many values, OpenBMC only 8237e860f15SJohn Edward Broadbent // supports BMC reboot. 8247e860f15SJohn Edward Broadbent nlohmann::json& managerReset = 8257e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Actions"]["#Manager.Reset"]; 826*96153bdeSMyung Bae managerReset["target"] = 827*96153bdeSMyung Bae boost::urls::format("/redfish/v1/Managers/{}/Actions/Manager.Reset", 828253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 8297e860f15SJohn Edward Broadbent managerReset["@Redfish.ActionInfo"] = 830253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}/ResetActionInfo", 831253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 8327e860f15SJohn Edward Broadbent 8337e860f15SJohn Edward Broadbent // ResetToDefaults (Factory Reset) has values like 8347e860f15SJohn Edward Broadbent // PreserveNetworkAndUsers and PreserveNetwork that aren't supported 8357e860f15SJohn Edward Broadbent // on OpenBMC 8367e860f15SJohn Edward Broadbent nlohmann::json& resetToDefaults = 8377e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Actions"]["#Manager.ResetToDefaults"]; 838253f11b8SEd Tanous resetToDefaults["target"] = boost::urls::format( 839253f11b8SEd Tanous "/redfish/v1/Managers/{}/Actions/Manager.ResetToDefaults", 840253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 841613dabeaSEd Tanous resetToDefaults["ResetType@Redfish.AllowableValues"] = 842613dabeaSEd Tanous nlohmann::json::array_t({"ResetAll"}); 8437e860f15SJohn Edward Broadbent 8447c8c4058STejas Patil std::pair<std::string, std::string> redfishDateTimeOffset = 8452b82937eSEd Tanous redfish::time_utils::getDateTimeOffsetNow(); 8467c8c4058STejas Patil 8477c8c4058STejas Patil asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first; 8487c8c4058STejas Patil asyncResp->res.jsonValue["DateTimeLocalOffset"] = 8497c8c4058STejas Patil redfishDateTimeOffset.second; 8507e860f15SJohn Edward Broadbent 85125b54dbaSEd Tanous if constexpr (BMCWEB_KVM) 85225b54dbaSEd Tanous { 8537e860f15SJohn Edward Broadbent // Fill in GraphicalConsole info 854*96153bdeSMyung Bae asyncResp->res.jsonValue["GraphicalConsole"]["ServiceEnabled"] = true; 855*96153bdeSMyung Bae asyncResp->res.jsonValue["GraphicalConsole"]["MaxConcurrentSessions"] = 856*96153bdeSMyung Bae 4; 857*96153bdeSMyung Bae asyncResp->res.jsonValue["GraphicalConsole"]["ConnectTypesSupported"] = 858613dabeaSEd Tanous nlohmann::json::array_t({"KVMIP"}); 85925b54dbaSEd Tanous } 86025b54dbaSEd Tanous if constexpr (!BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 8617f3e84a1SEd Tanous { 862*96153bdeSMyung Bae asyncResp->res.jsonValue["Links"]["ManagerForServers@odata.count"] = 1; 8631476687dSEd Tanous 8641476687dSEd Tanous nlohmann::json::array_t managerForServers; 8651476687dSEd Tanous nlohmann::json::object_t manager; 866*96153bdeSMyung Bae manager["@odata.id"] = std::format("/redfish/v1/Systems/{}", 867*96153bdeSMyung Bae BMCWEB_REDFISH_SYSTEM_URI_NAME); 868ad539545SPatrick Williams managerForServers.emplace_back(std::move(manager)); 8691476687dSEd Tanous 8701476687dSEd Tanous asyncResp->res.jsonValue["Links"]["ManagerForServers"] = 8711476687dSEd Tanous std::move(managerForServers); 8727f3e84a1SEd Tanous } 8737e860f15SJohn Edward Broadbent 874eee0013eSWilly Tu sw_util::populateSoftwareInformation(asyncResp, sw_util::bmcPurpose, 8757e860f15SJohn Edward Broadbent "FirmwareVersion", true); 8767e860f15SJohn Edward Broadbent 8777e860f15SJohn Edward Broadbent managerGetLastResetTime(asyncResp); 8787e860f15SJohn Edward Broadbent 879a51fc2d2SSui Chen // ManagerDiagnosticData is added for all BMCs. 880a51fc2d2SSui Chen nlohmann::json& managerDiagnosticData = 881a51fc2d2SSui Chen asyncResp->res.jsonValue["ManagerDiagnosticData"]; 882*96153bdeSMyung Bae managerDiagnosticData["@odata.id"] = 883*96153bdeSMyung Bae boost::urls::format("/redfish/v1/Managers/{}/ManagerDiagnosticData", 884253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 885a51fc2d2SSui Chen 886*96153bdeSMyung Bae getMainChassisId( 887*96153bdeSMyung Bae asyncResp, [](const std::string& chassisId, 888*96153bdeSMyung Bae const std::shared_ptr<bmcweb::AsyncResp>& aRsp) { 889*96153bdeSMyung Bae aRsp->res.jsonValue["Links"]["ManagerForChassis@odata.count"] = 1; 8901476687dSEd Tanous nlohmann::json::array_t managerForChassis; 8918a592810SEd Tanous nlohmann::json::object_t managerObj; 892ef4c65b7SEd Tanous boost::urls::url chassiUrl = 893ef4c65b7SEd Tanous boost::urls::format("/redfish/v1/Chassis/{}", chassisId); 894eddfc437SWilly Tu managerObj["@odata.id"] = chassiUrl; 895ad539545SPatrick Williams managerForChassis.emplace_back(std::move(managerObj)); 8961476687dSEd Tanous aRsp->res.jsonValue["Links"]["ManagerForChassis"] = 8971476687dSEd Tanous std::move(managerForChassis); 8981476687dSEd Tanous aRsp->res.jsonValue["Links"]["ManagerInChassis"]["@odata.id"] = 899eddfc437SWilly Tu chassiUrl; 9007e860f15SJohn Edward Broadbent }); 9017e860f15SJohn Edward Broadbent 902deae6a78SEd Tanous dbus::utility::getProperty<double>( 903deae6a78SEd Tanous "org.freedesktop.systemd1", "/org/freedesktop/systemd1", 904deae6a78SEd Tanous "org.freedesktop.systemd1.Manager", "Progress", 90575815e5cSEd Tanous [asyncResp](const boost::system::error_code& ec, double val) { 9067e860f15SJohn Edward Broadbent if (ec) 9071abe55efSEd Tanous { 90862598e31SEd Tanous BMCWEB_LOG_ERROR("Error while getting progress"); 9097e860f15SJohn Edward Broadbent messages::internalError(asyncResp->res); 9107e860f15SJohn Edward Broadbent return; 9117e860f15SJohn Edward Broadbent } 9121e1e598dSJonathan Doman if (val < 1.0) 9137e860f15SJohn Edward Broadbent { 914539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["Health"] = 915539d8c6bSEd Tanous resource::Health::OK; 916539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = 917539d8c6bSEd Tanous resource::State::Starting; 91875815e5cSEd Tanous return; 9197e860f15SJohn Edward Broadbent } 92075815e5cSEd Tanous checkForQuiesced(asyncResp); 9211e1e598dSJonathan Doman }); 9229c310685SBorawski.Lukasz 923e2cdf06fSJanet Adkins getManagerObject(asyncResp, managerId, 924e2cdf06fSJanet Adkins std::bind_front(getManagerData, asyncResp)); 925c1a75ebcSrohitpai 926c1a75ebcSrohitpai RedfishService::getInstance(app).handleSubRoute(req, asyncResp); 927*96153bdeSMyung Bae } 9287e860f15SJohn Edward Broadbent 929*96153bdeSMyung Bae inline void handleManagerPatch( 930*96153bdeSMyung Bae App& app, const crow::Request& req, 931253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 932*96153bdeSMyung Bae const std::string& managerId) 933*96153bdeSMyung Bae { 9343ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 93545ca1b86SEd Tanous { 93645ca1b86SEd Tanous return; 93745ca1b86SEd Tanous } 938253f11b8SEd Tanous 939253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 940253f11b8SEd Tanous { 941*96153bdeSMyung Bae messages::resourceNotFound(asyncResp->res, "Manager", managerId); 942253f11b8SEd Tanous return; 943253f11b8SEd Tanous } 944253f11b8SEd Tanous 9459e9b6049SEd Tanous std::optional<std::string> activeSoftwareImageOdataId; 9467e860f15SJohn Edward Broadbent std::optional<std::string> datetime; 94779f3b6a1SGeorge Liu std::optional<bool> locationIndicatorActive; 9489e9b6049SEd Tanous std::optional<nlohmann::json::object_t> pidControllers; 9499e9b6049SEd Tanous std::optional<nlohmann::json::object_t> fanControllers; 9509e9b6049SEd Tanous std::optional<nlohmann::json::object_t> fanZones; 9519e9b6049SEd Tanous std::optional<nlohmann::json::object_t> stepwiseControllers; 9529e9b6049SEd Tanous std::optional<std::string> profile; 953e30d3345SCorey Ethington std::optional<std::string> serviceIdentification; 9547e860f15SJohn Edward Broadbent 955afc474aeSMyung Bae if (!json_util::readJsonPatch( // 956afc474aeSMyung Bae req, asyncResp->res, // 957afc474aeSMyung Bae "DateTime", datetime, // 958afc474aeSMyung Bae "Links/ActiveSoftwareImage/@odata.id", 959afc474aeSMyung Bae activeSoftwareImageOdataId, // 96079f3b6a1SGeorge Liu "LocationIndicatorActive", 96179f3b6a1SGeorge Liu locationIndicatorActive, // 962afc474aeSMyung Bae "Oem/OpenBmc/Fan/FanControllers", fanControllers, // 963afc474aeSMyung Bae "Oem/OpenBmc/Fan/FanZones", fanZones, // 964afc474aeSMyung Bae "Oem/OpenBmc/Fan/PidControllers", pidControllers, // 965afc474aeSMyung Bae "Oem/OpenBmc/Fan/Profile", profile, // 966afc474aeSMyung Bae "Oem/OpenBmc/Fan/StepwiseControllers", 967e30d3345SCorey Ethington stepwiseControllers, // 968e30d3345SCorey Ethington "ServiceIdentification", serviceIdentification // 9699e9b6049SEd Tanous )) 9707e860f15SJohn Edward Broadbent { 9717e860f15SJohn Edward Broadbent return; 9727e860f15SJohn Edward Broadbent } 9737e860f15SJohn Edward Broadbent 9749e9b6049SEd Tanous if (activeSoftwareImageOdataId) 9757e860f15SJohn Edward Broadbent { 976*96153bdeSMyung Bae setActiveFirmwareImage(asyncResp, *activeSoftwareImageOdataId); 9777e860f15SJohn Edward Broadbent } 9787e860f15SJohn Edward Broadbent 9797e860f15SJohn Edward Broadbent if (datetime) 9807e860f15SJohn Edward Broadbent { 981c51afd54SEd Tanous setDateTime(asyncResp, *datetime); 9827e860f15SJohn Edward Broadbent } 98384aad24dSrohitpai 98479f3b6a1SGeorge Liu if (locationIndicatorActive) 98579f3b6a1SGeorge Liu { 986*96153bdeSMyung Bae setLocationIndicatorActiveState(asyncResp, *locationIndicatorActive, 987*96153bdeSMyung Bae managerId); 98879f3b6a1SGeorge Liu } 98979f3b6a1SGeorge Liu 990e30d3345SCorey Ethington if (serviceIdentification) 991e30d3345SCorey Ethington { 992*96153bdeSMyung Bae manager_utils::setServiceIdentification(asyncResp, 993*96153bdeSMyung Bae serviceIdentification.value()); 994e30d3345SCorey Ethington } 995e30d3345SCorey Ethington 99684aad24dSrohitpai RedfishService::getInstance(app).handleSubRoute(req, asyncResp); 9977e860f15SJohn Edward Broadbent } 9987e860f15SJohn Edward Broadbent 999*96153bdeSMyung Bae inline void handleManagerCollectionGet( 1000*96153bdeSMyung Bae crow::App& app, const crow::Request& req, 1001*96153bdeSMyung Bae const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 10027e860f15SJohn Edward Broadbent { 10033ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 100445ca1b86SEd Tanous { 100545ca1b86SEd Tanous return; 100645ca1b86SEd Tanous } 100783ff9ab6SJames Feist // Collections don't include the static data added by SubRoute 100883ff9ab6SJames Feist // because it has a duplicate entry for members 10098d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Managers"; 10108d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 10118d1b46d7Szhanghch05 "#ManagerCollection.ManagerCollection"; 10128d1b46d7Szhanghch05 asyncResp->res.jsonValue["Name"] = "Manager Collection"; 10138d1b46d7Szhanghch05 asyncResp->res.jsonValue["Members@odata.count"] = 1; 10141476687dSEd Tanous nlohmann::json::array_t members; 10151476687dSEd Tanous nlohmann::json& bmc = members.emplace_back(); 1016*96153bdeSMyung Bae bmc["@odata.id"] = boost::urls::format("/redfish/v1/Managers/{}", 1017*96153bdeSMyung Bae BMCWEB_REDFISH_MANAGER_URI_NAME); 10181476687dSEd Tanous asyncResp->res.jsonValue["Members"] = std::move(members); 1019*96153bdeSMyung Bae } 1020*96153bdeSMyung Bae 1021*96153bdeSMyung Bae inline void requestRoutesManager(App& app) 1022*96153bdeSMyung Bae { 1023*96153bdeSMyung Bae BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/") 1024*96153bdeSMyung Bae .privileges(redfish::privileges::getManager) 1025*96153bdeSMyung Bae .methods(boost::beast::http::verb::get)( 1026*96153bdeSMyung Bae std::bind_front(handleManagerGet, std::ref(app))); 1027*96153bdeSMyung Bae 1028*96153bdeSMyung Bae BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/") 1029*96153bdeSMyung Bae .privileges(redfish::privileges::patchManager) 1030*96153bdeSMyung Bae .methods(boost::beast::http::verb::patch)( 1031*96153bdeSMyung Bae std::bind_front(handleManagerPatch, std::ref(app))); 1032*96153bdeSMyung Bae } 1033*96153bdeSMyung Bae 1034*96153bdeSMyung Bae inline void requestRoutesManagerCollection(App& app) 1035*96153bdeSMyung Bae { 1036*96153bdeSMyung Bae BMCWEB_ROUTE(app, "/redfish/v1/Managers/") 1037*96153bdeSMyung Bae .privileges(redfish::privileges::getManagerCollection) 1038*96153bdeSMyung Bae .methods(boost::beast::http::verb::get)( 1039*96153bdeSMyung Bae std::bind_front(handleManagerCollectionGet, std::ref(app))); 10409c310685SBorawski.Lukasz } 10419c310685SBorawski.Lukasz } // namespace redfish 1042