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" 17d7857201SEd Tanous #include "logging.hpp" 18d7857201SEd Tanous #include "persistent_data.hpp" 19a51fc2d2SSui Chen #include "query.hpp" 20c1a75ebcSrohitpai #include "redfish.hpp" 21c5d03ff4SJennifer Lee #include "redfish_util.hpp" 22a51fc2d2SSui Chen #include "registries/privilege_registry.hpp" 23fac6e53bSKrzysztof Grobelny #include "utils/dbus_utils.hpp" 243ccb3adbSEd Tanous #include "utils/json_utils.hpp" 25a51fc2d2SSui Chen #include "utils/sw_utils.hpp" 26a51fc2d2SSui Chen #include "utils/systemd_utils.hpp" 272b82937eSEd Tanous #include "utils/time_utils.hpp" 289c310685SBorawski.Lukasz 29d7857201SEd Tanous #include <systemd/sd-bus.h> 30d7857201SEd Tanous 31d7857201SEd Tanous #include <boost/beast/http/status.hpp> 32d7857201SEd Tanous #include <boost/beast/http/verb.hpp> 33e99073f5SGeorge Liu #include <boost/system/error_code.hpp> 34ef4c65b7SEd Tanous #include <boost/url/format.hpp> 35d7857201SEd Tanous #include <boost/url/url.hpp> 36d7857201SEd Tanous #include <nlohmann/json.hpp> 37fac6e53bSKrzysztof Grobelny #include <sdbusplus/asio/property.hpp> 38d7857201SEd Tanous #include <sdbusplus/message.hpp> 39d7857201SEd Tanous #include <sdbusplus/message/native_types.hpp> 40fac6e53bSKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp> 411214b7e7SGunnar Mills 42e99073f5SGeorge Liu #include <array> 43d7857201SEd Tanous #include <cstddef> 444bfefa74SGunnar Mills #include <cstdint> 45d7857201SEd Tanous #include <format> 46d7857201SEd Tanous #include <functional> 47d7857201SEd Tanous #include <map> 481214b7e7SGunnar Mills #include <memory> 499970e93fSKonstantin Aladyshev #include <optional> 503544d2a7SEd Tanous #include <ranges> 519970e93fSKonstantin Aladyshev #include <string> 52e99073f5SGeorge Liu #include <string_view> 53d7857201SEd Tanous #include <utility> 54d7857201SEd Tanous #include <vector> 555b4aa86bSJames Feist 561abe55efSEd Tanous namespace redfish 571abe55efSEd Tanous { 58ed5befbdSJennifer Lee 59d27c31e9SJagpal Singh Gill inline std::string getBMCUpdateServiceName() 60d27c31e9SJagpal Singh Gill { 61d27c31e9SJagpal Singh Gill if constexpr (BMCWEB_REDFISH_UPDATESERVICE_USE_DBUS) 62d27c31e9SJagpal Singh Gill { 63d27c31e9SJagpal Singh Gill return "xyz.openbmc_project.Software.Manager"; 64d27c31e9SJagpal Singh Gill } 65d27c31e9SJagpal Singh Gill return "xyz.openbmc_project.Software.BMC.Updater"; 66d27c31e9SJagpal Singh Gill } 67d27c31e9SJagpal Singh Gill 68d27c31e9SJagpal Singh Gill inline std::string getBMCUpdateServicePath() 69d27c31e9SJagpal Singh Gill { 70d27c31e9SJagpal Singh Gill if constexpr (BMCWEB_REDFISH_UPDATESERVICE_USE_DBUS) 71d27c31e9SJagpal Singh Gill { 72d27c31e9SJagpal Singh Gill return "/xyz/openbmc_project/software/bmc"; 73d27c31e9SJagpal Singh Gill } 74d27c31e9SJagpal Singh Gill return "/xyz/openbmc_project/software"; 75d27c31e9SJagpal Singh Gill } 76d27c31e9SJagpal Singh Gill 77ed5befbdSJennifer Lee /** 782a5c4407SGunnar Mills * Function reboots the BMC. 792a5c4407SGunnar Mills * 802a5c4407SGunnar Mills * @param[in] asyncResp - Shared pointer for completing asynchronous calls 81ed5befbdSJennifer Lee */ 82504af5a0SPatrick Williams inline void doBMCGracefulRestart( 83504af5a0SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 84ed5befbdSJennifer Lee { 85ed5befbdSJennifer Lee const char* processName = "xyz.openbmc_project.State.BMC"; 86ed5befbdSJennifer Lee const char* objectPath = "/xyz/openbmc_project/state/bmc0"; 87ed5befbdSJennifer Lee const char* interfaceName = "xyz.openbmc_project.State.BMC"; 88ed5befbdSJennifer Lee const std::string& propertyValue = 89ed5befbdSJennifer Lee "xyz.openbmc_project.State.BMC.Transition.Reboot"; 90ed5befbdSJennifer Lee const char* destProperty = "RequestedBMCTransition"; 91ed5befbdSJennifer Lee 92ed5befbdSJennifer Lee // Create the D-Bus variant for D-Bus call. 939ae226faSGeorge Liu sdbusplus::asio::setProperty( 949ae226faSGeorge Liu *crow::connections::systemBus, processName, objectPath, interfaceName, 959ae226faSGeorge Liu destProperty, propertyValue, 965e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 97ed5befbdSJennifer Lee // Use "Set" method to set the property value. 98ed5befbdSJennifer Lee if (ec) 99ed5befbdSJennifer Lee { 10062598e31SEd Tanous BMCWEB_LOG_DEBUG("[Set] Bad D-Bus request error: {}", ec); 101ed5befbdSJennifer Lee messages::internalError(asyncResp->res); 102ed5befbdSJennifer Lee return; 103ed5befbdSJennifer Lee } 104ed5befbdSJennifer Lee 105ed5befbdSJennifer Lee messages::success(asyncResp->res); 1069ae226faSGeorge Liu }); 107ed5befbdSJennifer Lee } 1082a5c4407SGunnar Mills 109504af5a0SPatrick Williams inline void doBMCForceRestart( 110504af5a0SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 111f92af389SJayaprakash Mutyala { 112f92af389SJayaprakash Mutyala const char* processName = "xyz.openbmc_project.State.BMC"; 113f92af389SJayaprakash Mutyala const char* objectPath = "/xyz/openbmc_project/state/bmc0"; 114f92af389SJayaprakash Mutyala const char* interfaceName = "xyz.openbmc_project.State.BMC"; 115f92af389SJayaprakash Mutyala const std::string& propertyValue = 116f92af389SJayaprakash Mutyala "xyz.openbmc_project.State.BMC.Transition.HardReboot"; 117f92af389SJayaprakash Mutyala const char* destProperty = "RequestedBMCTransition"; 118f92af389SJayaprakash Mutyala 119f92af389SJayaprakash Mutyala // Create the D-Bus variant for D-Bus call. 1209ae226faSGeorge Liu sdbusplus::asio::setProperty( 1219ae226faSGeorge Liu *crow::connections::systemBus, processName, objectPath, interfaceName, 1229ae226faSGeorge Liu destProperty, propertyValue, 1235e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 124f92af389SJayaprakash Mutyala // Use "Set" method to set the property value. 125f92af389SJayaprakash Mutyala if (ec) 126f92af389SJayaprakash Mutyala { 12762598e31SEd Tanous BMCWEB_LOG_DEBUG("[Set] Bad D-Bus request error: {}", ec); 128f92af389SJayaprakash Mutyala messages::internalError(asyncResp->res); 129f92af389SJayaprakash Mutyala return; 130f92af389SJayaprakash Mutyala } 131f92af389SJayaprakash Mutyala 132f92af389SJayaprakash Mutyala messages::success(asyncResp->res); 1339ae226faSGeorge Liu }); 134f92af389SJayaprakash Mutyala } 135f92af389SJayaprakash Mutyala 1362a5c4407SGunnar Mills /** 1372a5c4407SGunnar Mills * ManagerResetAction class supports the POST method for the Reset (reboot) 1382a5c4407SGunnar Mills * action. 1392a5c4407SGunnar Mills */ 1407e860f15SJohn Edward Broadbent inline void requestRoutesManagerResetAction(App& app) 1412a5c4407SGunnar Mills { 1422a5c4407SGunnar Mills /** 1432a5c4407SGunnar Mills * Function handles POST method request. 1442a5c4407SGunnar Mills * Analyzes POST body before sending Reset (Reboot) request data to D-Bus. 145f92af389SJayaprakash Mutyala * OpenBMC supports ResetType "GracefulRestart" and "ForceRestart". 1462a5c4407SGunnar Mills */ 1477e860f15SJohn Edward Broadbent 148253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/Actions/Manager.Reset/") 149ed398213SEd Tanous .privileges(redfish::privileges::postManager) 1507e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 15145ca1b86SEd Tanous [&app](const crow::Request& req, 152253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 153253f11b8SEd Tanous const std::string& managerId) { 1543ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 15545ca1b86SEd Tanous { 15645ca1b86SEd Tanous return; 15745ca1b86SEd Tanous } 158253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 159253f11b8SEd Tanous { 160bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "Manager", 161bd79bce8SPatrick Williams managerId); 162253f11b8SEd Tanous return; 163253f11b8SEd Tanous } 164253f11b8SEd Tanous 16562598e31SEd Tanous BMCWEB_LOG_DEBUG("Post Manager Reset."); 1662a5c4407SGunnar Mills 1672a5c4407SGunnar Mills std::string resetType; 1682a5c4407SGunnar Mills 16915ed6780SWilly Tu if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", 1707e860f15SJohn Edward Broadbent resetType)) 1712a5c4407SGunnar Mills { 1722a5c4407SGunnar Mills return; 1732a5c4407SGunnar Mills } 1742a5c4407SGunnar Mills 175f92af389SJayaprakash Mutyala if (resetType == "GracefulRestart") 176f92af389SJayaprakash Mutyala { 17762598e31SEd Tanous BMCWEB_LOG_DEBUG("Proceeding with {}", resetType); 178f92af389SJayaprakash Mutyala doBMCGracefulRestart(asyncResp); 179f92af389SJayaprakash Mutyala return; 180f92af389SJayaprakash Mutyala } 1813174e4dfSEd Tanous if (resetType == "ForceRestart") 182f92af389SJayaprakash Mutyala { 18362598e31SEd Tanous BMCWEB_LOG_DEBUG("Proceeding with {}", resetType); 184f92af389SJayaprakash Mutyala doBMCForceRestart(asyncResp); 185f92af389SJayaprakash Mutyala return; 186f92af389SJayaprakash Mutyala } 187bd79bce8SPatrick Williams BMCWEB_LOG_DEBUG("Invalid property value for ResetType: {}", 188bd79bce8SPatrick Williams resetType); 1892a5c4407SGunnar Mills messages::actionParameterNotSupported(asyncResp->res, resetType, 1902a5c4407SGunnar Mills "ResetType"); 1912a5c4407SGunnar Mills 1922a5c4407SGunnar Mills return; 1937e860f15SJohn Edward Broadbent }); 1942a5c4407SGunnar Mills } 195ed5befbdSJennifer Lee 1963e40fc74SGunnar Mills /** 1973e40fc74SGunnar Mills * ManagerResetToDefaultsAction class supports POST method for factory reset 1983e40fc74SGunnar Mills * action. 1993e40fc74SGunnar Mills */ 2007e860f15SJohn Edward Broadbent inline void requestRoutesManagerResetToDefaultsAction(App& app) 2013e40fc74SGunnar Mills { 2023e40fc74SGunnar Mills /** 2033e40fc74SGunnar Mills * Function handles ResetToDefaults POST method request. 2043e40fc74SGunnar Mills * 2053e40fc74SGunnar Mills * Analyzes POST body message and factory resets BMC by calling 2063e40fc74SGunnar Mills * BMC code updater factory reset followed by a BMC reboot. 2073e40fc74SGunnar Mills * 2083e40fc74SGunnar Mills * BMC code updater factory reset wipes the whole BMC read-write 2093e40fc74SGunnar Mills * filesystem which includes things like the network settings. 2103e40fc74SGunnar Mills * 21118bf4bf6SGunnar Mills * OpenBMC only supports ResetType "ResetAll". 2123e40fc74SGunnar Mills */ 2137e860f15SJohn Edward Broadbent 2147e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 215253f11b8SEd Tanous "/redfish/v1/Managers/<str>/Actions/Manager.ResetToDefaults/") 216ed398213SEd Tanous .privileges(redfish::privileges::postManager) 21718bf4bf6SGunnar Mills .methods(boost::beast::http::verb::post)( 21818bf4bf6SGunnar Mills [&app](const crow::Request& req, 219253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 220253f11b8SEd Tanous const std::string& managerId) { 2213ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 22245ca1b86SEd Tanous { 22345ca1b86SEd Tanous return; 22445ca1b86SEd Tanous } 225253f11b8SEd Tanous 226253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 227253f11b8SEd Tanous { 228bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "Manager", 229bd79bce8SPatrick Williams managerId); 230253f11b8SEd Tanous return; 231253f11b8SEd Tanous } 232253f11b8SEd Tanous 23362598e31SEd Tanous BMCWEB_LOG_DEBUG("Post ResetToDefaults."); 2343e40fc74SGunnar Mills 2359970e93fSKonstantin Aladyshev std::optional<std::string> resetType; 2363e40fc74SGunnar Mills 237afc474aeSMyung Bae if (!json_util::readJsonAction( // 238afc474aeSMyung Bae req, asyncResp->res, // 239afc474aeSMyung Bae "ResetType", resetType // 240afc474aeSMyung Bae )) 2413e40fc74SGunnar Mills { 2429970e93fSKonstantin Aladyshev BMCWEB_LOG_DEBUG("Missing property ResetType."); 2433e40fc74SGunnar Mills 244bd79bce8SPatrick Williams messages::actionParameterMissing( 245bd79bce8SPatrick Williams asyncResp->res, "ResetToDefaults", "ResetType"); 2463e40fc74SGunnar Mills return; 2473e40fc74SGunnar Mills } 2483e40fc74SGunnar Mills 2493e40fc74SGunnar Mills if (resetType != "ResetAll") 2503e40fc74SGunnar Mills { 2519970e93fSKonstantin Aladyshev BMCWEB_LOG_DEBUG("Invalid property value for ResetType: {}", 2529970e93fSKonstantin Aladyshev *resetType); 25318bf4bf6SGunnar Mills messages::actionParameterNotSupported( 25418bf4bf6SGunnar Mills asyncResp->res, *resetType, "ResetType"); 2553e40fc74SGunnar Mills return; 2563e40fc74SGunnar Mills } 2573e40fc74SGunnar Mills 2583e40fc74SGunnar Mills crow::connections::systemBus->async_method_call( 2595e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 2603e40fc74SGunnar Mills if (ec) 2613e40fc74SGunnar Mills { 26218bf4bf6SGunnar Mills BMCWEB_LOG_DEBUG("Failed to ResetToDefaults: {}", 26318bf4bf6SGunnar Mills ec); 2643e40fc74SGunnar Mills messages::internalError(asyncResp->res); 2653e40fc74SGunnar Mills return; 2663e40fc74SGunnar Mills } 2673e40fc74SGunnar Mills // Factory Reset doesn't actually happen until a reboot 2683e40fc74SGunnar Mills // Can't erase what the BMC is running on 2693e40fc74SGunnar Mills doBMCGracefulRestart(asyncResp); 2703e40fc74SGunnar Mills }, 271d27c31e9SJagpal Singh Gill getBMCUpdateServiceName(), getBMCUpdateServicePath(), 2723e40fc74SGunnar Mills "xyz.openbmc_project.Common.FactoryReset", "Reset"); 2737e860f15SJohn Edward Broadbent }); 2743e40fc74SGunnar Mills } 2753e40fc74SGunnar Mills 2761cb1a9e6SAppaRao Puli /** 2771cb1a9e6SAppaRao Puli * ManagerResetActionInfo derived class for delivering Manager 2781cb1a9e6SAppaRao Puli * ResetType AllowableValues using ResetInfo schema. 2791cb1a9e6SAppaRao Puli */ 2807e860f15SJohn Edward Broadbent inline void requestRoutesManagerResetActionInfo(App& app) 2811cb1a9e6SAppaRao Puli { 2821cb1a9e6SAppaRao Puli /** 2831cb1a9e6SAppaRao Puli * Functions triggers appropriate requests on DBus 2841cb1a9e6SAppaRao Puli */ 2857e860f15SJohn Edward Broadbent 286253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/ResetActionInfo/") 287ed398213SEd Tanous .privileges(redfish::privileges::getActionInfo) 2887e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 28945ca1b86SEd Tanous [&app](const crow::Request& req, 290253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 291253f11b8SEd Tanous const std::string& managerId) { 2923ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 29345ca1b86SEd Tanous { 29445ca1b86SEd Tanous return; 29545ca1b86SEd Tanous } 2961476687dSEd Tanous 297253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 298253f11b8SEd Tanous { 299bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "Manager", 300bd79bce8SPatrick Williams managerId); 301253f11b8SEd Tanous return; 302253f11b8SEd Tanous } 303253f11b8SEd Tanous 3041476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 3051476687dSEd Tanous "#ActionInfo.v1_1_2.ActionInfo"; 306bd79bce8SPatrick Williams asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 307bd79bce8SPatrick Williams "/redfish/v1/Managers/{}/ResetActionInfo", 308253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 3091476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "Reset Action Info"; 3101476687dSEd Tanous asyncResp->res.jsonValue["Id"] = "ResetActionInfo"; 3111476687dSEd Tanous nlohmann::json::object_t parameter; 3121476687dSEd Tanous parameter["Name"] = "ResetType"; 3131476687dSEd Tanous parameter["Required"] = true; 314539d8c6bSEd Tanous parameter["DataType"] = action_info::ParameterTypes::String; 3151476687dSEd Tanous 3161476687dSEd Tanous nlohmann::json::array_t allowableValues; 317ad539545SPatrick Williams allowableValues.emplace_back("GracefulRestart"); 318ad539545SPatrick Williams allowableValues.emplace_back("ForceRestart"); 3191476687dSEd Tanous parameter["AllowableValues"] = std::move(allowableValues); 3201476687dSEd Tanous 3211476687dSEd Tanous nlohmann::json::array_t parameters; 322ad539545SPatrick Williams parameters.emplace_back(std::move(parameter)); 3231476687dSEd Tanous 3241476687dSEd Tanous asyncResp->res.jsonValue["Parameters"] = std::move(parameters); 3257e860f15SJohn Edward Broadbent }); 3261cb1a9e6SAppaRao Puli } 3271cb1a9e6SAppaRao Puli 328071d8fdfSSunnySrivastava1984 /** 329071d8fdfSSunnySrivastava1984 * @brief Retrieves BMC manager location data over DBus 330071d8fdfSSunnySrivastava1984 * 331ac106bf6SEd Tanous * @param[in] asyncResp Shared pointer for completing asynchronous calls 332071d8fdfSSunnySrivastava1984 * @param[in] connectionName - service name 333071d8fdfSSunnySrivastava1984 * @param[in] path - object path 334071d8fdfSSunnySrivastava1984 * @return none 335071d8fdfSSunnySrivastava1984 */ 336ac106bf6SEd Tanous inline void getLocation(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 337071d8fdfSSunnySrivastava1984 const std::string& connectionName, 338071d8fdfSSunnySrivastava1984 const std::string& path) 339071d8fdfSSunnySrivastava1984 { 34062598e31SEd Tanous BMCWEB_LOG_DEBUG("Get BMC manager Location data."); 341071d8fdfSSunnySrivastava1984 342deae6a78SEd Tanous dbus::utility::getProperty<std::string>( 343deae6a78SEd Tanous connectionName, path, 3441e1e598dSJonathan Doman "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode", 345ac106bf6SEd Tanous [asyncResp](const boost::system::error_code& ec, 3461e1e598dSJonathan Doman const std::string& property) { 347071d8fdfSSunnySrivastava1984 if (ec) 348071d8fdfSSunnySrivastava1984 { 34962598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error for " 35062598e31SEd Tanous "Location"); 351ac106bf6SEd Tanous messages::internalError(asyncResp->res); 352071d8fdfSSunnySrivastava1984 return; 353071d8fdfSSunnySrivastava1984 } 354071d8fdfSSunnySrivastava1984 355bd79bce8SPatrick Williams asyncResp->res 356bd79bce8SPatrick Williams .jsonValue["Location"]["PartLocation"]["ServiceLabel"] = 3571e1e598dSJonathan Doman property; 3581e1e598dSJonathan Doman }); 359071d8fdfSSunnySrivastava1984 } 3607e860f15SJohn Edward Broadbent // avoid name collision systems.hpp 361504af5a0SPatrick Williams inline void managerGetLastResetTime( 362504af5a0SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 3634bf2b033SGunnar Mills { 36462598e31SEd Tanous BMCWEB_LOG_DEBUG("Getting Manager Last Reset Time"); 3654bf2b033SGunnar Mills 366deae6a78SEd Tanous dbus::utility::getProperty<uint64_t>( 367deae6a78SEd Tanous "xyz.openbmc_project.State.BMC", "/xyz/openbmc_project/state/bmc0", 368deae6a78SEd Tanous "xyz.openbmc_project.State.BMC", "LastRebootTime", 369ac106bf6SEd Tanous [asyncResp](const boost::system::error_code& ec, 3701e1e598dSJonathan Doman const uint64_t lastResetTime) { 3714bf2b033SGunnar Mills if (ec) 3724bf2b033SGunnar Mills { 37362598e31SEd Tanous BMCWEB_LOG_DEBUG("D-BUS response error {}", ec); 3744bf2b033SGunnar Mills return; 3754bf2b033SGunnar Mills } 3764bf2b033SGunnar Mills 3774bf2b033SGunnar Mills // LastRebootTime is epoch time, in milliseconds 3784bf2b033SGunnar Mills // https://github.com/openbmc/phosphor-dbus-interfaces/blob/7f9a128eb9296e926422ddc312c148b625890bb6/xyz/openbmc_project/State/BMC.interface.yaml#L19 3791e1e598dSJonathan Doman uint64_t lastResetTimeStamp = lastResetTime / 1000; 3804bf2b033SGunnar Mills 3814bf2b033SGunnar Mills // Convert to ISO 8601 standard 382ac106bf6SEd Tanous asyncResp->res.jsonValue["LastResetTime"] = 3832b82937eSEd Tanous redfish::time_utils::getDateTimeUint(lastResetTimeStamp); 3841e1e598dSJonathan Doman }); 3854bf2b033SGunnar Mills } 3864bf2b033SGunnar Mills 3874bfefa74SGunnar Mills /** 3884bfefa74SGunnar Mills * @brief Set the running firmware image 3894bfefa74SGunnar Mills * 390ac106bf6SEd Tanous * @param[i,o] asyncResp - Async response object 3914bfefa74SGunnar Mills * @param[i] runningFirmwareTarget - Image to make the running image 3924bfefa74SGunnar Mills * 3934bfefa74SGunnar Mills * @return void 3944bfefa74SGunnar Mills */ 395504af5a0SPatrick Williams inline void setActiveFirmwareImage( 396504af5a0SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 397f23b7296SEd Tanous const std::string& runningFirmwareTarget) 3984bfefa74SGunnar Mills { 3994bfefa74SGunnar Mills // Get the Id from /redfish/v1/UpdateService/FirmwareInventory/<Id> 400f23b7296SEd Tanous std::string::size_type idPos = runningFirmwareTarget.rfind('/'); 4014bfefa74SGunnar Mills if (idPos == std::string::npos) 4024bfefa74SGunnar Mills { 403ac106bf6SEd Tanous messages::propertyValueNotInList(asyncResp->res, runningFirmwareTarget, 4044bfefa74SGunnar Mills "@odata.id"); 40562598e31SEd Tanous BMCWEB_LOG_DEBUG("Can't parse firmware ID!"); 4064bfefa74SGunnar Mills return; 4074bfefa74SGunnar Mills } 4084bfefa74SGunnar Mills idPos++; 4094bfefa74SGunnar Mills if (idPos >= runningFirmwareTarget.size()) 4104bfefa74SGunnar Mills { 411ac106bf6SEd Tanous messages::propertyValueNotInList(asyncResp->res, runningFirmwareTarget, 4124bfefa74SGunnar Mills "@odata.id"); 41362598e31SEd Tanous BMCWEB_LOG_DEBUG("Invalid firmware ID."); 4144bfefa74SGunnar Mills return; 4154bfefa74SGunnar Mills } 4164bfefa74SGunnar Mills std::string firmwareId = runningFirmwareTarget.substr(idPos); 4174bfefa74SGunnar Mills 4184bfefa74SGunnar Mills // Make sure the image is valid before setting priority 4195eb468daSGeorge Liu sdbusplus::message::object_path objPath("/xyz/openbmc_project/software"); 4205eb468daSGeorge Liu dbus::utility::getManagedObjects( 421d27c31e9SJagpal Singh Gill getBMCUpdateServiceName(), objPath, 4225eb468daSGeorge Liu [asyncResp, firmwareId, runningFirmwareTarget]( 4235eb468daSGeorge Liu const boost::system::error_code& ec, 4245eb468daSGeorge Liu const dbus::utility::ManagedObjectType& subtree) { 4254bfefa74SGunnar Mills if (ec) 4264bfefa74SGunnar Mills { 42762598e31SEd Tanous BMCWEB_LOG_DEBUG("D-Bus response error getting objects."); 428ac106bf6SEd Tanous messages::internalError(asyncResp->res); 4294bfefa74SGunnar Mills return; 4304bfefa74SGunnar Mills } 4314bfefa74SGunnar Mills 43226f6976fSEd Tanous if (subtree.empty()) 4334bfefa74SGunnar Mills { 43462598e31SEd Tanous BMCWEB_LOG_DEBUG("Can't find image!"); 435ac106bf6SEd Tanous messages::internalError(asyncResp->res); 4364bfefa74SGunnar Mills return; 4374bfefa74SGunnar Mills } 4384bfefa74SGunnar Mills 4394bfefa74SGunnar Mills bool foundImage = false; 44002cad96eSEd Tanous for (const auto& object : subtree) 4414bfefa74SGunnar Mills { 4424bfefa74SGunnar Mills const std::string& path = 4434bfefa74SGunnar Mills static_cast<const std::string&>(object.first); 444f23b7296SEd Tanous std::size_t idPos2 = path.rfind('/'); 4454bfefa74SGunnar Mills 4464bfefa74SGunnar Mills if (idPos2 == std::string::npos) 4474bfefa74SGunnar Mills { 4484bfefa74SGunnar Mills continue; 4494bfefa74SGunnar Mills } 4504bfefa74SGunnar Mills 4514bfefa74SGunnar Mills idPos2++; 4524bfefa74SGunnar Mills if (idPos2 >= path.size()) 4534bfefa74SGunnar Mills { 4544bfefa74SGunnar Mills continue; 4554bfefa74SGunnar Mills } 4564bfefa74SGunnar Mills 4574bfefa74SGunnar Mills if (path.substr(idPos2) == firmwareId) 4584bfefa74SGunnar Mills { 4594bfefa74SGunnar Mills foundImage = true; 4604bfefa74SGunnar Mills break; 4614bfefa74SGunnar Mills } 4624bfefa74SGunnar Mills } 4634bfefa74SGunnar Mills 4644bfefa74SGunnar Mills if (!foundImage) 4654bfefa74SGunnar Mills { 466ac106bf6SEd Tanous messages::propertyValueNotInList( 467ac106bf6SEd Tanous asyncResp->res, runningFirmwareTarget, "@odata.id"); 46862598e31SEd Tanous BMCWEB_LOG_DEBUG("Invalid firmware ID."); 4694bfefa74SGunnar Mills return; 4704bfefa74SGunnar Mills } 4714bfefa74SGunnar Mills 47262598e31SEd Tanous BMCWEB_LOG_DEBUG("Setting firmware version {} to priority 0.", 47362598e31SEd Tanous firmwareId); 4744bfefa74SGunnar Mills 4754bfefa74SGunnar Mills // Only support Immediate 4764bfefa74SGunnar Mills // An addition could be a Redfish Setting like 4774bfefa74SGunnar Mills // ActiveSoftwareImageApplyTime and support OnReset 4789ae226faSGeorge Liu sdbusplus::asio::setProperty( 479d27c31e9SJagpal Singh Gill *crow::connections::systemBus, getBMCUpdateServiceName(), 4809ae226faSGeorge Liu "/xyz/openbmc_project/software/" + firmwareId, 4819ae226faSGeorge Liu "xyz.openbmc_project.Software.RedundancyPriority", "Priority", 4829ae226faSGeorge Liu static_cast<uint8_t>(0), 483ac106bf6SEd Tanous [asyncResp](const boost::system::error_code& ec2) { 4848a592810SEd Tanous if (ec2) 4854bfefa74SGunnar Mills { 48662598e31SEd Tanous BMCWEB_LOG_DEBUG("D-Bus response error setting."); 487ac106bf6SEd Tanous messages::internalError(asyncResp->res); 4884bfefa74SGunnar Mills return; 4894bfefa74SGunnar Mills } 490ac106bf6SEd Tanous doBMCGracefulRestart(asyncResp); 4919ae226faSGeorge Liu }); 4925eb468daSGeorge Liu }); 4934bfefa74SGunnar Mills } 4944bfefa74SGunnar Mills 495bd79bce8SPatrick Williams inline void afterSetDateTime( 496bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 497bd79bce8SPatrick Williams const boost::system::error_code& ec, const sdbusplus::message_t& msg) 498c51afd54SEd Tanous { 499c51afd54SEd Tanous if (ec) 500c51afd54SEd Tanous { 501c51afd54SEd Tanous BMCWEB_LOG_DEBUG("Failed to set elapsed time. DBUS response error {}", 502c51afd54SEd Tanous ec); 503c51afd54SEd Tanous const sd_bus_error* dbusError = msg.get_error(); 504c51afd54SEd Tanous if (dbusError != nullptr) 505c51afd54SEd Tanous { 506c51afd54SEd Tanous std::string_view errorName(dbusError->name); 507c51afd54SEd Tanous if (errorName == 508c51afd54SEd Tanous "org.freedesktop.timedate1.AutomaticTimeSyncEnabled") 509c51afd54SEd Tanous { 510c51afd54SEd Tanous BMCWEB_LOG_DEBUG("Setting conflict"); 511c51afd54SEd Tanous messages::propertyValueConflict( 512c51afd54SEd Tanous asyncResp->res, "DateTime", 513c51afd54SEd Tanous "Managers/NetworkProtocol/NTPProcotolEnabled"); 514c51afd54SEd Tanous return; 515c51afd54SEd Tanous } 516c51afd54SEd Tanous } 517c51afd54SEd Tanous messages::internalError(asyncResp->res); 518c51afd54SEd Tanous return; 519c51afd54SEd Tanous } 520c51afd54SEd Tanous asyncResp->res.result(boost::beast::http::status::no_content); 521c51afd54SEd Tanous } 522c51afd54SEd Tanous 523c51afd54SEd Tanous inline void setDateTime(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 524c51afd54SEd Tanous const std::string& datetime) 525af5d6058SSantosh Puranik { 52662598e31SEd Tanous BMCWEB_LOG_DEBUG("Set date time: {}", datetime); 527af5d6058SSantosh Puranik 528c2e32007SEd Tanous std::optional<redfish::time_utils::usSinceEpoch> us = 529c2e32007SEd Tanous redfish::time_utils::dateStringToEpoch(datetime); 530c2e32007SEd Tanous if (!us) 531af5d6058SSantosh Puranik { 532ac106bf6SEd Tanous messages::propertyValueFormatError(asyncResp->res, datetime, 533ac106bf6SEd Tanous "DateTime"); 534c2e32007SEd Tanous return; 535c2e32007SEd Tanous } 536c51afd54SEd Tanous // Set the absolute datetime 537c51afd54SEd Tanous bool relative = false; 538c51afd54SEd Tanous bool interactive = false; 539c51afd54SEd Tanous crow::connections::systemBus->async_method_call( 540c51afd54SEd Tanous [asyncResp](const boost::system::error_code& ec, 541c51afd54SEd Tanous const sdbusplus::message_t& msg) { 542c51afd54SEd Tanous afterSetDateTime(asyncResp, ec, msg); 543c51afd54SEd Tanous }, 544c51afd54SEd Tanous "org.freedesktop.timedate1", "/org/freedesktop/timedate1", 545c51afd54SEd Tanous "org.freedesktop.timedate1", "SetTime", us->count(), relative, 546c51afd54SEd Tanous interactive); 54783ff9ab6SJames Feist } 5489c310685SBorawski.Lukasz 549504af5a0SPatrick Williams inline void checkForQuiesced( 550504af5a0SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 55175815e5cSEd Tanous { 552deae6a78SEd Tanous dbus::utility::getProperty<std::string>( 553deae6a78SEd Tanous "org.freedesktop.systemd1", 55475815e5cSEd Tanous "/org/freedesktop/systemd1/unit/obmc-bmc-service-quiesce@0.target", 55575815e5cSEd Tanous "org.freedesktop.systemd1.Unit", "ActiveState", 55675815e5cSEd Tanous [asyncResp](const boost::system::error_code& ec, 55775815e5cSEd Tanous const std::string& val) { 55875815e5cSEd Tanous if (!ec) 55975815e5cSEd Tanous { 56075815e5cSEd Tanous if (val == "active") 56175815e5cSEd Tanous { 562539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["Health"] = 563539d8c6bSEd Tanous resource::Health::Critical; 564539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = 565539d8c6bSEd Tanous resource::State::Quiesced; 56675815e5cSEd Tanous return; 56775815e5cSEd Tanous } 56875815e5cSEd Tanous } 569539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK; 570bd79bce8SPatrick Williams asyncResp->res.jsonValue["Status"]["State"] = 571bd79bce8SPatrick Williams resource::State::Enabled; 57275815e5cSEd Tanous }); 57375815e5cSEd Tanous } 57475815e5cSEd Tanous 575*e2cdf06fSJanet Adkins inline void getPhysicalAssets( 576*e2cdf06fSJanet Adkins const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 577*e2cdf06fSJanet Adkins const boost::system::error_code& ec, 578*e2cdf06fSJanet Adkins const dbus::utility::DBusPropertiesMap& propertiesList) 579*e2cdf06fSJanet Adkins { 580*e2cdf06fSJanet Adkins if (ec) 581*e2cdf06fSJanet Adkins { 582*e2cdf06fSJanet Adkins BMCWEB_LOG_DEBUG("Can't get bmc asset!"); 583*e2cdf06fSJanet Adkins return; 584*e2cdf06fSJanet Adkins } 585*e2cdf06fSJanet Adkins 586*e2cdf06fSJanet Adkins const std::string* partNumber = nullptr; 587*e2cdf06fSJanet Adkins const std::string* serialNumber = nullptr; 588*e2cdf06fSJanet Adkins const std::string* manufacturer = nullptr; 589*e2cdf06fSJanet Adkins const std::string* model = nullptr; 590*e2cdf06fSJanet Adkins const std::string* sparePartNumber = nullptr; 591*e2cdf06fSJanet Adkins 592*e2cdf06fSJanet Adkins const bool success = sdbusplus::unpackPropertiesNoThrow( 593*e2cdf06fSJanet Adkins dbus_utils::UnpackErrorPrinter(), propertiesList, "PartNumber", 594*e2cdf06fSJanet Adkins partNumber, "SerialNumber", serialNumber, "Manufacturer", manufacturer, 595*e2cdf06fSJanet Adkins "Model", model, "SparePartNumber", sparePartNumber); 596*e2cdf06fSJanet Adkins 597*e2cdf06fSJanet Adkins if (!success) 598*e2cdf06fSJanet Adkins { 599*e2cdf06fSJanet Adkins messages::internalError(asyncResp->res); 600*e2cdf06fSJanet Adkins return; 601*e2cdf06fSJanet Adkins } 602*e2cdf06fSJanet Adkins 603*e2cdf06fSJanet Adkins if (partNumber != nullptr) 604*e2cdf06fSJanet Adkins { 605*e2cdf06fSJanet Adkins asyncResp->res.jsonValue["PartNumber"] = *partNumber; 606*e2cdf06fSJanet Adkins } 607*e2cdf06fSJanet Adkins 608*e2cdf06fSJanet Adkins if (serialNumber != nullptr) 609*e2cdf06fSJanet Adkins { 610*e2cdf06fSJanet Adkins asyncResp->res.jsonValue["SerialNumber"] = *serialNumber; 611*e2cdf06fSJanet Adkins } 612*e2cdf06fSJanet Adkins 613*e2cdf06fSJanet Adkins if (manufacturer != nullptr) 614*e2cdf06fSJanet Adkins { 615*e2cdf06fSJanet Adkins asyncResp->res.jsonValue["Manufacturer"] = *manufacturer; 616*e2cdf06fSJanet Adkins } 617*e2cdf06fSJanet Adkins 618*e2cdf06fSJanet Adkins if (model != nullptr) 619*e2cdf06fSJanet Adkins { 620*e2cdf06fSJanet Adkins asyncResp->res.jsonValue["Model"] = *model; 621*e2cdf06fSJanet Adkins } 622*e2cdf06fSJanet Adkins 623*e2cdf06fSJanet Adkins if (sparePartNumber != nullptr) 624*e2cdf06fSJanet Adkins { 625*e2cdf06fSJanet Adkins asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber; 626*e2cdf06fSJanet Adkins } 627*e2cdf06fSJanet Adkins } 628*e2cdf06fSJanet Adkins 629*e2cdf06fSJanet Adkins inline void getManagerData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 630*e2cdf06fSJanet Adkins const std::string& managerPath, 631*e2cdf06fSJanet Adkins const dbus::utility::MapperServiceMap& serviceMap) 632*e2cdf06fSJanet Adkins { 633*e2cdf06fSJanet Adkins if (managerPath.empty() || serviceMap.size() != 1) 634*e2cdf06fSJanet Adkins { 635*e2cdf06fSJanet Adkins BMCWEB_LOG_DEBUG("Error getting bmc D-Bus object!"); 636*e2cdf06fSJanet Adkins messages::internalError(asyncResp->res); 637*e2cdf06fSJanet Adkins return; 638*e2cdf06fSJanet Adkins } 639*e2cdf06fSJanet Adkins 640*e2cdf06fSJanet Adkins for (const auto& [connectionName, interfaces] : serviceMap) 641*e2cdf06fSJanet Adkins { 642*e2cdf06fSJanet Adkins for (const auto& interfaceName : interfaces) 643*e2cdf06fSJanet Adkins { 644*e2cdf06fSJanet Adkins if (interfaceName == 645*e2cdf06fSJanet Adkins "xyz.openbmc_project.Inventory.Decorator.Asset") 646*e2cdf06fSJanet Adkins { 647*e2cdf06fSJanet Adkins dbus::utility::getAllProperties( 648*e2cdf06fSJanet Adkins *crow::connections::systemBus, connectionName, managerPath, 649*e2cdf06fSJanet Adkins "xyz.openbmc_project.Inventory.Decorator.Asset", 650*e2cdf06fSJanet Adkins std::bind_front(getPhysicalAssets, asyncResp)); 651*e2cdf06fSJanet Adkins } 652*e2cdf06fSJanet Adkins else if (interfaceName == 653*e2cdf06fSJanet Adkins "xyz.openbmc_project.Inventory.Decorator.LocationCode") 654*e2cdf06fSJanet Adkins { 655*e2cdf06fSJanet Adkins getLocation(asyncResp, connectionName, managerPath); 656*e2cdf06fSJanet Adkins } 657*e2cdf06fSJanet Adkins } 658*e2cdf06fSJanet Adkins } 659*e2cdf06fSJanet Adkins } 660*e2cdf06fSJanet Adkins 661*e2cdf06fSJanet Adkins inline void afterGetManagerObject( 662*e2cdf06fSJanet Adkins const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 663*e2cdf06fSJanet Adkins const boost::system::error_code& ec, 664*e2cdf06fSJanet Adkins const dbus::utility::MapperGetSubTreeResponse& subtree, 665*e2cdf06fSJanet Adkins const std::function< 666*e2cdf06fSJanet Adkins void(const std::string& managerPath, 667*e2cdf06fSJanet Adkins const dbus::utility::MapperServiceMap& serviceMap)>& callback) 668*e2cdf06fSJanet Adkins { 669*e2cdf06fSJanet Adkins if (ec) 670*e2cdf06fSJanet Adkins { 671*e2cdf06fSJanet Adkins BMCWEB_LOG_DEBUG("D-Bus response error on GetSubTree {}", ec); 672*e2cdf06fSJanet Adkins return; 673*e2cdf06fSJanet Adkins } 674*e2cdf06fSJanet Adkins if (subtree.empty()) 675*e2cdf06fSJanet Adkins { 676*e2cdf06fSJanet Adkins BMCWEB_LOG_DEBUG("Can't find bmc D-Bus object!"); 677*e2cdf06fSJanet Adkins return; 678*e2cdf06fSJanet Adkins } 679*e2cdf06fSJanet Adkins // Assume only 1 bmc D-Bus object 680*e2cdf06fSJanet Adkins // Throw an error if there is more than 1 681*e2cdf06fSJanet Adkins if (subtree.size() > 1) 682*e2cdf06fSJanet Adkins { 683*e2cdf06fSJanet Adkins BMCWEB_LOG_ERROR("Found more than 1 bmc D-Bus object!"); 684*e2cdf06fSJanet Adkins messages::internalError(asyncResp->res); 685*e2cdf06fSJanet Adkins return; 686*e2cdf06fSJanet Adkins } 687*e2cdf06fSJanet Adkins 688*e2cdf06fSJanet Adkins callback(subtree[0].first, subtree[0].second); 689*e2cdf06fSJanet Adkins } 690*e2cdf06fSJanet Adkins 691*e2cdf06fSJanet Adkins inline void getManagerObject( 692*e2cdf06fSJanet Adkins const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 693*e2cdf06fSJanet Adkins const std::string& /* managerId */, 694*e2cdf06fSJanet Adkins std::function<void(const std::string& managerPath, 695*e2cdf06fSJanet Adkins const dbus::utility::MapperServiceMap& serviceMap)>&& 696*e2cdf06fSJanet Adkins callback) 697*e2cdf06fSJanet Adkins { 698*e2cdf06fSJanet Adkins constexpr std::array<std::string_view, 1> interfaces = { 699*e2cdf06fSJanet Adkins "xyz.openbmc_project.Inventory.Item.Bmc"}; 700*e2cdf06fSJanet Adkins dbus::utility::getSubTree( 701*e2cdf06fSJanet Adkins "/xyz/openbmc_project/inventory", 0, interfaces, 702*e2cdf06fSJanet Adkins [asyncResp, callback{std::move(callback)}]( 703*e2cdf06fSJanet Adkins const boost::system::error_code& ec, 704*e2cdf06fSJanet Adkins const dbus::utility::MapperGetSubTreeResponse& subtree) { 705*e2cdf06fSJanet Adkins afterGetManagerObject(asyncResp, ec, subtree, callback); 706*e2cdf06fSJanet Adkins }); 707*e2cdf06fSJanet Adkins } 708*e2cdf06fSJanet Adkins 7097e860f15SJohn Edward Broadbent inline void requestRoutesManager(App& app) 7107e860f15SJohn Edward Broadbent { 7117e860f15SJohn Edward Broadbent std::string uuid = persistent_data::getConfig().systemUuid; 7129c310685SBorawski.Lukasz 713253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/") 714ed398213SEd Tanous .privileges(redfish::privileges::getManager) 715bd79bce8SPatrick Williams .methods( 716bd79bce8SPatrick Williams boost::beast::http::verb:: 717bd79bce8SPatrick Williams get)([&app, 718bd79bce8SPatrick Williams uuid](const crow::Request& req, 719253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 720253f11b8SEd Tanous const std::string& managerId) { 7213ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 72245ca1b86SEd Tanous { 72345ca1b86SEd Tanous return; 72445ca1b86SEd Tanous } 725253f11b8SEd Tanous 726253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 727253f11b8SEd Tanous { 728bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "Manager", 729bd79bce8SPatrick Williams managerId); 730253f11b8SEd Tanous return; 731253f11b8SEd Tanous } 732253f11b8SEd Tanous 733253f11b8SEd Tanous asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 734253f11b8SEd Tanous "/redfish/v1/Managers/{}", BMCWEB_REDFISH_MANAGER_URI_NAME); 735bd79bce8SPatrick Williams asyncResp->res.jsonValue["@odata.type"] = 736bd79bce8SPatrick Williams "#Manager.v1_14_0.Manager"; 737253f11b8SEd Tanous asyncResp->res.jsonValue["Id"] = BMCWEB_REDFISH_MANAGER_URI_NAME; 7387e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Name"] = "OpenBmc Manager"; 7397e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Description"] = 7407e860f15SJohn Edward Broadbent "Baseboard Management Controller"; 741539d8c6bSEd Tanous asyncResp->res.jsonValue["PowerState"] = resource::PowerState::On; 7421476687dSEd Tanous 743539d8c6bSEd Tanous asyncResp->res.jsonValue["ManagerType"] = manager::ManagerType::BMC; 7447e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["UUID"] = systemd_utils::getUuid(); 7457e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["ServiceEntryPointUUID"] = uuid; 746bd79bce8SPatrick Williams asyncResp->res.jsonValue["Model"] = 747bd79bce8SPatrick Williams "OpenBmc"; // TODO(ed), get model 7487e860f15SJohn Edward Broadbent 7491476687dSEd Tanous asyncResp->res.jsonValue["LogServices"]["@odata.id"] = 750253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}/LogServices", 751253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 7521476687dSEd Tanous asyncResp->res.jsonValue["NetworkProtocol"]["@odata.id"] = 753253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}/NetworkProtocol", 754253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 7551476687dSEd Tanous asyncResp->res.jsonValue["EthernetInterfaces"]["@odata.id"] = 756bd79bce8SPatrick Williams boost::urls::format( 757bd79bce8SPatrick Williams "/redfish/v1/Managers/{}/EthernetInterfaces", 758253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 7597e860f15SJohn Edward Broadbent 76025b54dbaSEd Tanous if constexpr (BMCWEB_VM_NBDPROXY) 76136c0f2a3SEd Tanous { 7621476687dSEd Tanous asyncResp->res.jsonValue["VirtualMedia"]["@odata.id"] = 763253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}/VirtualMedia", 764253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 76536c0f2a3SEd Tanous } 7667e860f15SJohn Edward Broadbent 7677e860f15SJohn Edward Broadbent // Manager.Reset (an action) can be many values, OpenBMC only 7687e860f15SJohn Edward Broadbent // supports BMC reboot. 7697e860f15SJohn Edward Broadbent nlohmann::json& managerReset = 7707e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Actions"]["#Manager.Reset"]; 771bd79bce8SPatrick Williams managerReset["target"] = boost::urls::format( 772bd79bce8SPatrick Williams "/redfish/v1/Managers/{}/Actions/Manager.Reset", 773253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 7747e860f15SJohn Edward Broadbent managerReset["@Redfish.ActionInfo"] = 775253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}/ResetActionInfo", 776253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 7777e860f15SJohn Edward Broadbent 7787e860f15SJohn Edward Broadbent // ResetToDefaults (Factory Reset) has values like 7797e860f15SJohn Edward Broadbent // PreserveNetworkAndUsers and PreserveNetwork that aren't supported 7807e860f15SJohn Edward Broadbent // on OpenBMC 7817e860f15SJohn Edward Broadbent nlohmann::json& resetToDefaults = 7827e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Actions"]["#Manager.ResetToDefaults"]; 783253f11b8SEd Tanous resetToDefaults["target"] = boost::urls::format( 784253f11b8SEd Tanous "/redfish/v1/Managers/{}/Actions/Manager.ResetToDefaults", 785253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 786613dabeaSEd Tanous resetToDefaults["ResetType@Redfish.AllowableValues"] = 787613dabeaSEd Tanous nlohmann::json::array_t({"ResetAll"}); 7887e860f15SJohn Edward Broadbent 7897c8c4058STejas Patil std::pair<std::string, std::string> redfishDateTimeOffset = 7902b82937eSEd Tanous redfish::time_utils::getDateTimeOffsetNow(); 7917c8c4058STejas Patil 7927c8c4058STejas Patil asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first; 7937c8c4058STejas Patil asyncResp->res.jsonValue["DateTimeLocalOffset"] = 7947c8c4058STejas Patil redfishDateTimeOffset.second; 7957e860f15SJohn Edward Broadbent 79625b54dbaSEd Tanous if constexpr (BMCWEB_KVM) 79725b54dbaSEd Tanous { 7987e860f15SJohn Edward Broadbent // Fill in GraphicalConsole info 79925b54dbaSEd Tanous asyncResp->res.jsonValue["GraphicalConsole"]["ServiceEnabled"] = 80025b54dbaSEd Tanous true; 80125b54dbaSEd Tanous asyncResp->res 80225b54dbaSEd Tanous .jsonValue["GraphicalConsole"]["MaxConcurrentSessions"] = 4; 80325b54dbaSEd Tanous asyncResp->res 80425b54dbaSEd Tanous .jsonValue["GraphicalConsole"]["ConnectTypesSupported"] = 805613dabeaSEd Tanous nlohmann::json::array_t({"KVMIP"}); 80625b54dbaSEd Tanous } 80725b54dbaSEd Tanous if constexpr (!BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 8087f3e84a1SEd Tanous { 809bd79bce8SPatrick Williams asyncResp->res 810bd79bce8SPatrick Williams .jsonValue["Links"]["ManagerForServers@odata.count"] = 1; 8111476687dSEd Tanous 8121476687dSEd Tanous nlohmann::json::array_t managerForServers; 8131476687dSEd Tanous nlohmann::json::object_t manager; 814bd79bce8SPatrick Williams manager["@odata.id"] = std::format( 815bd79bce8SPatrick Williams "/redfish/v1/Systems/{}", BMCWEB_REDFISH_SYSTEM_URI_NAME); 816ad539545SPatrick Williams managerForServers.emplace_back(std::move(manager)); 8171476687dSEd Tanous 8181476687dSEd Tanous asyncResp->res.jsonValue["Links"]["ManagerForServers"] = 8191476687dSEd Tanous std::move(managerForServers); 8207f3e84a1SEd Tanous } 8217e860f15SJohn Edward Broadbent 822eee0013eSWilly Tu sw_util::populateSoftwareInformation(asyncResp, sw_util::bmcPurpose, 8237e860f15SJohn Edward Broadbent "FirmwareVersion", true); 8247e860f15SJohn Edward Broadbent 8257e860f15SJohn Edward Broadbent managerGetLastResetTime(asyncResp); 8267e860f15SJohn Edward Broadbent 827a51fc2d2SSui Chen // ManagerDiagnosticData is added for all BMCs. 828a51fc2d2SSui Chen nlohmann::json& managerDiagnosticData = 829a51fc2d2SSui Chen asyncResp->res.jsonValue["ManagerDiagnosticData"]; 830bd79bce8SPatrick Williams managerDiagnosticData["@odata.id"] = boost::urls::format( 831bd79bce8SPatrick Williams "/redfish/v1/Managers/{}/ManagerDiagnosticData", 832253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 833a51fc2d2SSui Chen 834bd79bce8SPatrick Williams getMainChassisId(asyncResp, [](const std::string& chassisId, 835bd79bce8SPatrick Williams const std::shared_ptr< 836bd79bce8SPatrick Williams bmcweb::AsyncResp>& aRsp) { 837bd79bce8SPatrick Williams aRsp->res.jsonValue["Links"]["ManagerForChassis@odata.count"] = 838bd79bce8SPatrick Williams 1; 8391476687dSEd Tanous nlohmann::json::array_t managerForChassis; 8408a592810SEd Tanous nlohmann::json::object_t managerObj; 841ef4c65b7SEd Tanous boost::urls::url chassiUrl = 842ef4c65b7SEd Tanous boost::urls::format("/redfish/v1/Chassis/{}", chassisId); 843eddfc437SWilly Tu managerObj["@odata.id"] = chassiUrl; 844ad539545SPatrick Williams managerForChassis.emplace_back(std::move(managerObj)); 8451476687dSEd Tanous aRsp->res.jsonValue["Links"]["ManagerForChassis"] = 8461476687dSEd Tanous std::move(managerForChassis); 8471476687dSEd Tanous aRsp->res.jsonValue["Links"]["ManagerInChassis"]["@odata.id"] = 848eddfc437SWilly Tu chassiUrl; 8497e860f15SJohn Edward Broadbent }); 8507e860f15SJohn Edward Broadbent 851deae6a78SEd Tanous dbus::utility::getProperty<double>( 852deae6a78SEd Tanous "org.freedesktop.systemd1", "/org/freedesktop/systemd1", 853deae6a78SEd Tanous "org.freedesktop.systemd1.Manager", "Progress", 85475815e5cSEd Tanous [asyncResp](const boost::system::error_code& ec, double val) { 8557e860f15SJohn Edward Broadbent if (ec) 8561abe55efSEd Tanous { 85762598e31SEd Tanous BMCWEB_LOG_ERROR("Error while getting progress"); 8587e860f15SJohn Edward Broadbent messages::internalError(asyncResp->res); 8597e860f15SJohn Edward Broadbent return; 8607e860f15SJohn Edward Broadbent } 8611e1e598dSJonathan Doman if (val < 1.0) 8627e860f15SJohn Edward Broadbent { 863539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["Health"] = 864539d8c6bSEd Tanous resource::Health::OK; 865539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = 866539d8c6bSEd Tanous resource::State::Starting; 86775815e5cSEd Tanous return; 8687e860f15SJohn Edward Broadbent } 86975815e5cSEd Tanous checkForQuiesced(asyncResp); 8701e1e598dSJonathan Doman }); 8719c310685SBorawski.Lukasz 872*e2cdf06fSJanet Adkins getManagerObject(asyncResp, managerId, 873*e2cdf06fSJanet Adkins std::bind_front(getManagerData, asyncResp)); 874c1a75ebcSrohitpai 875c1a75ebcSrohitpai RedfishService::getInstance(app).handleSubRoute(req, asyncResp); 8767e860f15SJohn Edward Broadbent }); 8777e860f15SJohn Edward Broadbent 878253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/") 879ed398213SEd Tanous .privileges(redfish::privileges::patchManager) 88045ca1b86SEd Tanous .methods(boost::beast::http::verb::patch)( 88145ca1b86SEd Tanous [&app](const crow::Request& req, 882253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 883253f11b8SEd Tanous const std::string& managerId) { 8843ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 88545ca1b86SEd Tanous { 88645ca1b86SEd Tanous return; 88745ca1b86SEd Tanous } 888253f11b8SEd Tanous 889253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 890253f11b8SEd Tanous { 891bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "Manager", 892bd79bce8SPatrick Williams managerId); 893253f11b8SEd Tanous return; 894253f11b8SEd Tanous } 895253f11b8SEd Tanous 8969e9b6049SEd Tanous std::optional<std::string> activeSoftwareImageOdataId; 8977e860f15SJohn Edward Broadbent std::optional<std::string> datetime; 8989e9b6049SEd Tanous std::optional<nlohmann::json::object_t> pidControllers; 8999e9b6049SEd Tanous std::optional<nlohmann::json::object_t> fanControllers; 9009e9b6049SEd Tanous std::optional<nlohmann::json::object_t> fanZones; 9019e9b6049SEd Tanous std::optional<nlohmann::json::object_t> stepwiseControllers; 9029e9b6049SEd Tanous std::optional<std::string> profile; 9037e860f15SJohn Edward Broadbent 904afc474aeSMyung Bae if (!json_util::readJsonPatch( // 905afc474aeSMyung Bae req, asyncResp->res, // 906afc474aeSMyung Bae "DateTime", datetime, // 907afc474aeSMyung Bae "Links/ActiveSoftwareImage/@odata.id", 908afc474aeSMyung Bae activeSoftwareImageOdataId, // 909afc474aeSMyung Bae "Oem/OpenBmc/Fan/FanControllers", fanControllers, // 910afc474aeSMyung Bae "Oem/OpenBmc/Fan/FanZones", fanZones, // 911afc474aeSMyung Bae "Oem/OpenBmc/Fan/PidControllers", pidControllers, // 912afc474aeSMyung Bae "Oem/OpenBmc/Fan/Profile", profile, // 913afc474aeSMyung Bae "Oem/OpenBmc/Fan/StepwiseControllers", 914afc474aeSMyung Bae stepwiseControllers // 9159e9b6049SEd Tanous )) 9167e860f15SJohn Edward Broadbent { 9177e860f15SJohn Edward Broadbent return; 9187e860f15SJohn Edward Broadbent } 9197e860f15SJohn Edward Broadbent 9209e9b6049SEd Tanous if (activeSoftwareImageOdataId) 9217e860f15SJohn Edward Broadbent { 922bd79bce8SPatrick Williams setActiveFirmwareImage(asyncResp, 923bd79bce8SPatrick Williams *activeSoftwareImageOdataId); 9247e860f15SJohn Edward Broadbent } 9257e860f15SJohn Edward Broadbent 9267e860f15SJohn Edward Broadbent if (datetime) 9277e860f15SJohn Edward Broadbent { 928c51afd54SEd Tanous setDateTime(asyncResp, *datetime); 9297e860f15SJohn Edward Broadbent } 93084aad24dSrohitpai 93184aad24dSrohitpai RedfishService::getInstance(app).handleSubRoute(req, asyncResp); 9327e860f15SJohn Edward Broadbent }); 9337e860f15SJohn Edward Broadbent } 9347e860f15SJohn Edward Broadbent 9357e860f15SJohn Edward Broadbent inline void requestRoutesManagerCollection(App& app) 9367e860f15SJohn Edward Broadbent { 9377e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Managers/") 938ed398213SEd Tanous .privileges(redfish::privileges::getManagerCollection) 9397e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 94045ca1b86SEd Tanous [&app](const crow::Request& req, 9417e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 9423ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 94345ca1b86SEd Tanous { 94445ca1b86SEd Tanous return; 94545ca1b86SEd Tanous } 94683ff9ab6SJames Feist // Collections don't include the static data added by SubRoute 94783ff9ab6SJames Feist // because it has a duplicate entry for members 9488d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Managers"; 9498d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 9508d1b46d7Szhanghch05 "#ManagerCollection.ManagerCollection"; 9518d1b46d7Szhanghch05 asyncResp->res.jsonValue["Name"] = "Manager Collection"; 9528d1b46d7Szhanghch05 asyncResp->res.jsonValue["Members@odata.count"] = 1; 9531476687dSEd Tanous nlohmann::json::array_t members; 9541476687dSEd Tanous nlohmann::json& bmc = members.emplace_back(); 955bd79bce8SPatrick Williams bmc["@odata.id"] = boost::urls::format( 956bd79bce8SPatrick Williams "/redfish/v1/Managers/{}", BMCWEB_REDFISH_MANAGER_URI_NAME); 9571476687dSEd Tanous asyncResp->res.jsonValue["Members"] = std::move(members); 9587e860f15SJohn Edward Broadbent }); 9599c310685SBorawski.Lukasz } 9609c310685SBorawski.Lukasz } // namespace redfish 961