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 44*0fa34188SGunnar Mills #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> 565b4aa86bSJames Feist 571abe55efSEd Tanous namespace redfish 581abe55efSEd Tanous { 59ed5befbdSJennifer Lee 60*0fa34188SGunnar Mills inline void handleSetLocationIndicatorActive( 61*0fa34188SGunnar Mills const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 62*0fa34188SGunnar Mills bool locationIndicatorActive, const std::string& managerId, 63*0fa34188SGunnar Mills const boost::system::error_code& ec, 64*0fa34188SGunnar Mills const dbus::utility::MapperGetSubTreePathsResponse& subtreePaths) 65*0fa34188SGunnar Mills { 66*0fa34188SGunnar Mills if (ec) 67*0fa34188SGunnar Mills { 68*0fa34188SGunnar Mills if (ec == boost::system::errc::io_error) 69*0fa34188SGunnar Mills { 70*0fa34188SGunnar Mills // Not found 71*0fa34188SGunnar Mills BMCWEB_LOG_WARNING("Manager {} not found", managerId); 72*0fa34188SGunnar Mills messages::resourceNotFound(asyncResp->res, "Manager", managerId); 73*0fa34188SGunnar Mills return; 74*0fa34188SGunnar Mills } 75*0fa34188SGunnar Mills BMCWEB_LOG_ERROR("D-Bus response error {}", ec.value()); 76*0fa34188SGunnar Mills messages::internalError(asyncResp->res); 77*0fa34188SGunnar Mills return; 78*0fa34188SGunnar Mills } 79*0fa34188SGunnar Mills if (subtreePaths.empty()) 80*0fa34188SGunnar Mills { 81*0fa34188SGunnar Mills BMCWEB_LOG_WARNING("Manager {} not found", managerId); 82*0fa34188SGunnar Mills messages::resourceNotFound(asyncResp->res, "Manager", managerId); 83*0fa34188SGunnar Mills return; 84*0fa34188SGunnar Mills } 85*0fa34188SGunnar Mills // Assume only 1 bmc D-Bus object 86*0fa34188SGunnar Mills // Throw an error if there is more than 1 87*0fa34188SGunnar Mills if (subtreePaths.size() != 1) 88*0fa34188SGunnar Mills { 89*0fa34188SGunnar Mills BMCWEB_LOG_ERROR("Found {} Bmc D-Bus paths", subtreePaths.size()); 90*0fa34188SGunnar Mills messages::internalError(asyncResp->res); 91*0fa34188SGunnar Mills return; 92*0fa34188SGunnar Mills } 93*0fa34188SGunnar Mills 94*0fa34188SGunnar Mills setLocationIndicatorActive(asyncResp, subtreePaths[0], 95*0fa34188SGunnar Mills locationIndicatorActive); 96*0fa34188SGunnar Mills } 97*0fa34188SGunnar Mills 9879f3b6a1SGeorge Liu /** 9979f3b6a1SGeorge Liu * Set the locationIndicatorActive. 10079f3b6a1SGeorge Liu * 10179f3b6a1SGeorge Liu * @param[in,out] asyncResp Async HTTP response. 10279f3b6a1SGeorge Liu * @param[in] locationIndicatorActive Value of the property 10379f3b6a1SGeorge Liu */ 10479f3b6a1SGeorge Liu inline void setLocationIndicatorActiveState( 10579f3b6a1SGeorge Liu const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 10679f3b6a1SGeorge Liu bool locationIndicatorActive, const std::string& managerId) 10779f3b6a1SGeorge Liu { 108*0fa34188SGunnar Mills // GetSubTree on all interfaces which provide info about a Manager 109*0fa34188SGunnar Mills constexpr std::array<std::string_view, 1> interfaces = { 110*0fa34188SGunnar Mills "xyz.openbmc_project.Inventory.Item.Bmc"}; 111*0fa34188SGunnar Mills dbus::utility::getSubTreePaths( 112*0fa34188SGunnar Mills "/xyz/openbmc_project/inventory", 0, interfaces, 113*0fa34188SGunnar Mills std::bind_front(handleSetLocationIndicatorActive, asyncResp, 114*0fa34188SGunnar Mills locationIndicatorActive, managerId)); 11579f3b6a1SGeorge Liu } 11679f3b6a1SGeorge Liu 117d27c31e9SJagpal Singh Gill inline std::string getBMCUpdateServiceName() 118d27c31e9SJagpal Singh Gill { 119d27c31e9SJagpal Singh Gill if constexpr (BMCWEB_REDFISH_UPDATESERVICE_USE_DBUS) 120d27c31e9SJagpal Singh Gill { 121d27c31e9SJagpal Singh Gill return "xyz.openbmc_project.Software.Manager"; 122d27c31e9SJagpal Singh Gill } 123d27c31e9SJagpal Singh Gill return "xyz.openbmc_project.Software.BMC.Updater"; 124d27c31e9SJagpal Singh Gill } 125d27c31e9SJagpal Singh Gill 126d27c31e9SJagpal Singh Gill inline std::string getBMCUpdateServicePath() 127d27c31e9SJagpal Singh Gill { 128d27c31e9SJagpal Singh Gill if constexpr (BMCWEB_REDFISH_UPDATESERVICE_USE_DBUS) 129d27c31e9SJagpal Singh Gill { 130d27c31e9SJagpal Singh Gill return "/xyz/openbmc_project/software/bmc"; 131d27c31e9SJagpal Singh Gill } 132d27c31e9SJagpal Singh Gill return "/xyz/openbmc_project/software"; 133d27c31e9SJagpal Singh Gill } 134d27c31e9SJagpal Singh Gill 135ed5befbdSJennifer Lee /** 1362a5c4407SGunnar Mills * Function reboots the BMC. 1372a5c4407SGunnar Mills * 1382a5c4407SGunnar Mills * @param[in] asyncResp - Shared pointer for completing asynchronous calls 139ed5befbdSJennifer Lee */ 140504af5a0SPatrick Williams inline void doBMCGracefulRestart( 141504af5a0SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 142ed5befbdSJennifer Lee { 143ed5befbdSJennifer Lee const char* processName = "xyz.openbmc_project.State.BMC"; 144ed5befbdSJennifer Lee const char* objectPath = "/xyz/openbmc_project/state/bmc0"; 145ed5befbdSJennifer Lee const char* interfaceName = "xyz.openbmc_project.State.BMC"; 146ed5befbdSJennifer Lee const std::string& propertyValue = 147ed5befbdSJennifer Lee "xyz.openbmc_project.State.BMC.Transition.Reboot"; 148ed5befbdSJennifer Lee const char* destProperty = "RequestedBMCTransition"; 149ed5befbdSJennifer Lee 150ed5befbdSJennifer Lee // Create the D-Bus variant for D-Bus call. 1519ae226faSGeorge Liu sdbusplus::asio::setProperty( 1529ae226faSGeorge Liu *crow::connections::systemBus, processName, objectPath, interfaceName, 1539ae226faSGeorge Liu destProperty, propertyValue, 1545e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 155ed5befbdSJennifer Lee // Use "Set" method to set the property value. 156ed5befbdSJennifer Lee if (ec) 157ed5befbdSJennifer Lee { 15862598e31SEd Tanous BMCWEB_LOG_DEBUG("[Set] Bad D-Bus request error: {}", ec); 159ed5befbdSJennifer Lee messages::internalError(asyncResp->res); 160ed5befbdSJennifer Lee return; 161ed5befbdSJennifer Lee } 162ed5befbdSJennifer Lee 163ed5befbdSJennifer Lee messages::success(asyncResp->res); 1649ae226faSGeorge Liu }); 165ed5befbdSJennifer Lee } 1662a5c4407SGunnar Mills 167504af5a0SPatrick Williams inline void doBMCForceRestart( 168504af5a0SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 169f92af389SJayaprakash Mutyala { 170f92af389SJayaprakash Mutyala const char* processName = "xyz.openbmc_project.State.BMC"; 171f92af389SJayaprakash Mutyala const char* objectPath = "/xyz/openbmc_project/state/bmc0"; 172f92af389SJayaprakash Mutyala const char* interfaceName = "xyz.openbmc_project.State.BMC"; 173f92af389SJayaprakash Mutyala const std::string& propertyValue = 174f92af389SJayaprakash Mutyala "xyz.openbmc_project.State.BMC.Transition.HardReboot"; 175f92af389SJayaprakash Mutyala const char* destProperty = "RequestedBMCTransition"; 176f92af389SJayaprakash Mutyala 177f92af389SJayaprakash Mutyala // Create the D-Bus variant for D-Bus call. 1789ae226faSGeorge Liu sdbusplus::asio::setProperty( 1799ae226faSGeorge Liu *crow::connections::systemBus, processName, objectPath, interfaceName, 1809ae226faSGeorge Liu destProperty, propertyValue, 1815e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 182f92af389SJayaprakash Mutyala // Use "Set" method to set the property value. 183f92af389SJayaprakash Mutyala if (ec) 184f92af389SJayaprakash Mutyala { 18562598e31SEd Tanous BMCWEB_LOG_DEBUG("[Set] Bad D-Bus request error: {}", ec); 186f92af389SJayaprakash Mutyala messages::internalError(asyncResp->res); 187f92af389SJayaprakash Mutyala return; 188f92af389SJayaprakash Mutyala } 189f92af389SJayaprakash Mutyala 190f92af389SJayaprakash Mutyala messages::success(asyncResp->res); 1919ae226faSGeorge Liu }); 192f92af389SJayaprakash Mutyala } 193f92af389SJayaprakash Mutyala 1942a5c4407SGunnar Mills /** 19564acd268SMyung Bae * ManagerResetAction handles POST method request. 1962a5c4407SGunnar Mills * Analyzes POST body before sending Reset (Reboot) request data to D-Bus. 197f92af389SJayaprakash Mutyala * OpenBMC supports ResetType "GracefulRestart" and "ForceRestart". 1982a5c4407SGunnar Mills */ 1997e860f15SJohn Edward Broadbent 20064acd268SMyung Bae inline void handleManagerResetAction( 20164acd268SMyung Bae crow::App& app, const crow::Request& req, 202253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 20364acd268SMyung Bae const std::string& managerId) 20464acd268SMyung Bae { 2053ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 20645ca1b86SEd Tanous { 20745ca1b86SEd Tanous return; 20845ca1b86SEd Tanous } 209253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 210253f11b8SEd Tanous { 21164acd268SMyung Bae messages::resourceNotFound(asyncResp->res, "Manager", managerId); 212253f11b8SEd Tanous return; 213253f11b8SEd Tanous } 214253f11b8SEd Tanous 21562598e31SEd Tanous BMCWEB_LOG_DEBUG("Post Manager Reset."); 2162a5c4407SGunnar Mills 2172a5c4407SGunnar Mills std::string resetType; 2182a5c4407SGunnar Mills 21964acd268SMyung Bae if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", resetType)) 2202a5c4407SGunnar Mills { 2212a5c4407SGunnar Mills return; 2222a5c4407SGunnar Mills } 2232a5c4407SGunnar Mills 224f92af389SJayaprakash Mutyala if (resetType == "GracefulRestart") 225f92af389SJayaprakash Mutyala { 22662598e31SEd Tanous BMCWEB_LOG_DEBUG("Proceeding with {}", resetType); 227f92af389SJayaprakash Mutyala doBMCGracefulRestart(asyncResp); 228f92af389SJayaprakash Mutyala return; 229f92af389SJayaprakash Mutyala } 2303174e4dfSEd Tanous if (resetType == "ForceRestart") 231f92af389SJayaprakash Mutyala { 23262598e31SEd Tanous BMCWEB_LOG_DEBUG("Proceeding with {}", resetType); 233f92af389SJayaprakash Mutyala doBMCForceRestart(asyncResp); 234f92af389SJayaprakash Mutyala return; 235f92af389SJayaprakash Mutyala } 23664acd268SMyung Bae BMCWEB_LOG_DEBUG("Invalid property value for ResetType: {}", resetType); 2372a5c4407SGunnar Mills messages::actionParameterNotSupported(asyncResp->res, resetType, 2382a5c4407SGunnar Mills "ResetType"); 2392a5c4407SGunnar Mills } 240ed5befbdSJennifer Lee 2413e40fc74SGunnar Mills /** 2423e40fc74SGunnar Mills * Function handles ResetToDefaults POST method request. 2433e40fc74SGunnar Mills * 2443e40fc74SGunnar Mills * Analyzes POST body message and factory resets BMC by calling 2453e40fc74SGunnar Mills * BMC code updater factory reset followed by a BMC reboot. 2463e40fc74SGunnar Mills * 2473e40fc74SGunnar Mills * BMC code updater factory reset wipes the whole BMC read-write 2483e40fc74SGunnar Mills * filesystem which includes things like the network settings. 2493e40fc74SGunnar Mills * 25018bf4bf6SGunnar Mills * OpenBMC only supports ResetType "ResetAll". 2513e40fc74SGunnar Mills */ 2527e860f15SJohn Edward Broadbent 25364acd268SMyung Bae inline void handleManagerResetToDefaultsAction( 25464acd268SMyung Bae crow::App& app, const crow::Request& req, 255253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 25664acd268SMyung Bae const std::string& managerId) 25764acd268SMyung Bae { 2583ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 25945ca1b86SEd Tanous { 26045ca1b86SEd Tanous return; 26145ca1b86SEd Tanous } 262253f11b8SEd Tanous 263253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 264253f11b8SEd Tanous { 26564acd268SMyung Bae messages::resourceNotFound(asyncResp->res, "Manager", managerId); 266253f11b8SEd Tanous return; 267253f11b8SEd Tanous } 268253f11b8SEd Tanous 26962598e31SEd Tanous BMCWEB_LOG_DEBUG("Post ResetToDefaults."); 2703e40fc74SGunnar Mills 2719970e93fSKonstantin Aladyshev std::optional<std::string> resetType; 2723e40fc74SGunnar Mills 273afc474aeSMyung Bae if (!json_util::readJsonAction( // 274afc474aeSMyung Bae req, asyncResp->res, // 275afc474aeSMyung Bae "ResetType", resetType // 276afc474aeSMyung Bae )) 2773e40fc74SGunnar Mills { 2789970e93fSKonstantin Aladyshev BMCWEB_LOG_DEBUG("Missing property ResetType."); 2793e40fc74SGunnar Mills 28064acd268SMyung Bae messages::actionParameterMissing(asyncResp->res, "ResetToDefaults", 28164acd268SMyung Bae "ResetType"); 2823e40fc74SGunnar Mills return; 2833e40fc74SGunnar Mills } 2843e40fc74SGunnar Mills 28564acd268SMyung Bae if (resetType.value_or("") != "ResetAll") 2863e40fc74SGunnar Mills { 2879970e93fSKonstantin Aladyshev BMCWEB_LOG_DEBUG("Invalid property value for ResetType: {}", 28864acd268SMyung Bae resetType.value_or("")); 28918bf4bf6SGunnar Mills messages::actionParameterNotSupported( 29064acd268SMyung Bae asyncResp->res, resetType.value_or(""), "ResetType"); 2913e40fc74SGunnar Mills return; 2923e40fc74SGunnar Mills } 2933e40fc74SGunnar Mills 2943e40fc74SGunnar Mills crow::connections::systemBus->async_method_call( 2955e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 2963e40fc74SGunnar Mills if (ec) 2973e40fc74SGunnar Mills { 29864acd268SMyung Bae BMCWEB_LOG_DEBUG("Failed to ResetToDefaults: {}", ec); 2993e40fc74SGunnar Mills messages::internalError(asyncResp->res); 3003e40fc74SGunnar Mills return; 3013e40fc74SGunnar Mills } 3023e40fc74SGunnar Mills // Factory Reset doesn't actually happen until a reboot 3033e40fc74SGunnar Mills // Can't erase what the BMC is running on 3043e40fc74SGunnar Mills doBMCGracefulRestart(asyncResp); 3053e40fc74SGunnar Mills }, 306d27c31e9SJagpal Singh Gill getBMCUpdateServiceName(), getBMCUpdateServicePath(), 3073e40fc74SGunnar Mills "xyz.openbmc_project.Common.FactoryReset", "Reset"); 3083e40fc74SGunnar Mills } 3093e40fc74SGunnar Mills 3101cb1a9e6SAppaRao Puli /** 3111cb1a9e6SAppaRao Puli * ManagerResetActionInfo derived class for delivering Manager 3121cb1a9e6SAppaRao Puli * ResetType AllowableValues using ResetInfo schema. 3131cb1a9e6SAppaRao Puli */ 31464acd268SMyung Bae inline void handleManagerResetActionInfo( 31564acd268SMyung Bae crow::App& app, const crow::Request& req, 316253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 31764acd268SMyung Bae const std::string& managerId) 31864acd268SMyung Bae { 3193ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 32045ca1b86SEd Tanous { 32145ca1b86SEd Tanous return; 32245ca1b86SEd Tanous } 3231476687dSEd Tanous 324253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 325253f11b8SEd Tanous { 32664acd268SMyung Bae messages::resourceNotFound(asyncResp->res, "Manager", managerId); 327253f11b8SEd Tanous return; 328253f11b8SEd Tanous } 329253f11b8SEd Tanous 33064acd268SMyung Bae asyncResp->res.jsonValue["@odata.type"] = "#ActionInfo.v1_1_2.ActionInfo"; 33164acd268SMyung Bae asyncResp->res.jsonValue["@odata.id"] = 33264acd268SMyung Bae boost::urls::format("/redfish/v1/Managers/{}/ResetActionInfo", 333253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 3341476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "Reset Action Info"; 3351476687dSEd Tanous asyncResp->res.jsonValue["Id"] = "ResetActionInfo"; 3361476687dSEd Tanous nlohmann::json::object_t parameter; 3371476687dSEd Tanous parameter["Name"] = "ResetType"; 3381476687dSEd Tanous parameter["Required"] = true; 339539d8c6bSEd Tanous parameter["DataType"] = action_info::ParameterTypes::String; 3401476687dSEd Tanous 3411476687dSEd Tanous nlohmann::json::array_t allowableValues; 342ad539545SPatrick Williams allowableValues.emplace_back("GracefulRestart"); 343ad539545SPatrick Williams allowableValues.emplace_back("ForceRestart"); 3441476687dSEd Tanous parameter["AllowableValues"] = std::move(allowableValues); 3451476687dSEd Tanous 3461476687dSEd Tanous nlohmann::json::array_t parameters; 347ad539545SPatrick Williams parameters.emplace_back(std::move(parameter)); 3481476687dSEd Tanous 3491476687dSEd Tanous asyncResp->res.jsonValue["Parameters"] = std::move(parameters); 3501cb1a9e6SAppaRao Puli } 3511cb1a9e6SAppaRao Puli 352071d8fdfSSunnySrivastava1984 /** 353071d8fdfSSunnySrivastava1984 * @brief Retrieves BMC manager location data over DBus 354071d8fdfSSunnySrivastava1984 * 355ac106bf6SEd Tanous * @param[in] asyncResp Shared pointer for completing asynchronous calls 356071d8fdfSSunnySrivastava1984 * @param[in] connectionName - service name 357071d8fdfSSunnySrivastava1984 * @param[in] path - object path 358071d8fdfSSunnySrivastava1984 * @return none 359071d8fdfSSunnySrivastava1984 */ 360ac106bf6SEd Tanous inline void getLocation(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 361071d8fdfSSunnySrivastava1984 const std::string& connectionName, 362071d8fdfSSunnySrivastava1984 const std::string& path) 363071d8fdfSSunnySrivastava1984 { 36462598e31SEd Tanous BMCWEB_LOG_DEBUG("Get BMC manager Location data."); 365071d8fdfSSunnySrivastava1984 366deae6a78SEd Tanous dbus::utility::getProperty<std::string>( 367deae6a78SEd Tanous connectionName, path, 3681e1e598dSJonathan Doman "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode", 369ac106bf6SEd Tanous [asyncResp](const boost::system::error_code& ec, 3701e1e598dSJonathan Doman const std::string& property) { 371071d8fdfSSunnySrivastava1984 if (ec) 372071d8fdfSSunnySrivastava1984 { 37362598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error for " 37462598e31SEd Tanous "Location"); 375ac106bf6SEd Tanous messages::internalError(asyncResp->res); 376071d8fdfSSunnySrivastava1984 return; 377071d8fdfSSunnySrivastava1984 } 378071d8fdfSSunnySrivastava1984 379bd79bce8SPatrick Williams asyncResp->res 380bd79bce8SPatrick Williams .jsonValue["Location"]["PartLocation"]["ServiceLabel"] = 3811e1e598dSJonathan Doman property; 3821e1e598dSJonathan Doman }); 383071d8fdfSSunnySrivastava1984 } 3847e860f15SJohn Edward Broadbent // avoid name collision systems.hpp 385504af5a0SPatrick Williams inline void managerGetLastResetTime( 386504af5a0SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 3874bf2b033SGunnar Mills { 38862598e31SEd Tanous BMCWEB_LOG_DEBUG("Getting Manager Last Reset Time"); 3894bf2b033SGunnar Mills 390deae6a78SEd Tanous dbus::utility::getProperty<uint64_t>( 391deae6a78SEd Tanous "xyz.openbmc_project.State.BMC", "/xyz/openbmc_project/state/bmc0", 392deae6a78SEd Tanous "xyz.openbmc_project.State.BMC", "LastRebootTime", 393ac106bf6SEd Tanous [asyncResp](const boost::system::error_code& ec, 3941e1e598dSJonathan Doman const uint64_t lastResetTime) { 3954bf2b033SGunnar Mills if (ec) 3964bf2b033SGunnar Mills { 39762598e31SEd Tanous BMCWEB_LOG_DEBUG("D-BUS response error {}", ec); 3984bf2b033SGunnar Mills return; 3994bf2b033SGunnar Mills } 4004bf2b033SGunnar Mills 4014bf2b033SGunnar Mills // LastRebootTime is epoch time, in milliseconds 4024bf2b033SGunnar Mills // https://github.com/openbmc/phosphor-dbus-interfaces/blob/7f9a128eb9296e926422ddc312c148b625890bb6/xyz/openbmc_project/State/BMC.interface.yaml#L19 4031e1e598dSJonathan Doman uint64_t lastResetTimeStamp = lastResetTime / 1000; 4044bf2b033SGunnar Mills 4054bf2b033SGunnar Mills // Convert to ISO 8601 standard 406ac106bf6SEd Tanous asyncResp->res.jsonValue["LastResetTime"] = 4072b82937eSEd Tanous redfish::time_utils::getDateTimeUint(lastResetTimeStamp); 4081e1e598dSJonathan Doman }); 4094bf2b033SGunnar Mills } 4104bf2b033SGunnar Mills 4114bfefa74SGunnar Mills /** 4124bfefa74SGunnar Mills * @brief Set the running firmware image 4134bfefa74SGunnar Mills * 414ac106bf6SEd Tanous * @param[i,o] asyncResp - Async response object 4154bfefa74SGunnar Mills * @param[i] runningFirmwareTarget - Image to make the running image 4164bfefa74SGunnar Mills * 4174bfefa74SGunnar Mills * @return void 4184bfefa74SGunnar Mills */ 419504af5a0SPatrick Williams inline void setActiveFirmwareImage( 420504af5a0SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 421f23b7296SEd Tanous const std::string& runningFirmwareTarget) 4224bfefa74SGunnar Mills { 4234bfefa74SGunnar Mills // Get the Id from /redfish/v1/UpdateService/FirmwareInventory/<Id> 424f23b7296SEd Tanous std::string::size_type idPos = runningFirmwareTarget.rfind('/'); 4254bfefa74SGunnar Mills if (idPos == std::string::npos) 4264bfefa74SGunnar Mills { 427ac106bf6SEd Tanous messages::propertyValueNotInList(asyncResp->res, runningFirmwareTarget, 4284bfefa74SGunnar Mills "@odata.id"); 42962598e31SEd Tanous BMCWEB_LOG_DEBUG("Can't parse firmware ID!"); 4304bfefa74SGunnar Mills return; 4314bfefa74SGunnar Mills } 4324bfefa74SGunnar Mills idPos++; 4334bfefa74SGunnar Mills if (idPos >= runningFirmwareTarget.size()) 4344bfefa74SGunnar Mills { 435ac106bf6SEd Tanous messages::propertyValueNotInList(asyncResp->res, runningFirmwareTarget, 4364bfefa74SGunnar Mills "@odata.id"); 43762598e31SEd Tanous BMCWEB_LOG_DEBUG("Invalid firmware ID."); 4384bfefa74SGunnar Mills return; 4394bfefa74SGunnar Mills } 4404bfefa74SGunnar Mills std::string firmwareId = runningFirmwareTarget.substr(idPos); 4414bfefa74SGunnar Mills 4424bfefa74SGunnar Mills // Make sure the image is valid before setting priority 4435eb468daSGeorge Liu sdbusplus::message::object_path objPath("/xyz/openbmc_project/software"); 4445eb468daSGeorge Liu dbus::utility::getManagedObjects( 445d27c31e9SJagpal Singh Gill getBMCUpdateServiceName(), objPath, 4465eb468daSGeorge Liu [asyncResp, firmwareId, runningFirmwareTarget]( 4475eb468daSGeorge Liu const boost::system::error_code& ec, 4485eb468daSGeorge Liu const dbus::utility::ManagedObjectType& subtree) { 4494bfefa74SGunnar Mills if (ec) 4504bfefa74SGunnar Mills { 45162598e31SEd Tanous BMCWEB_LOG_DEBUG("D-Bus response error getting objects."); 452ac106bf6SEd Tanous messages::internalError(asyncResp->res); 4534bfefa74SGunnar Mills return; 4544bfefa74SGunnar Mills } 4554bfefa74SGunnar Mills 45626f6976fSEd Tanous if (subtree.empty()) 4574bfefa74SGunnar Mills { 45862598e31SEd Tanous BMCWEB_LOG_DEBUG("Can't find image!"); 459ac106bf6SEd Tanous messages::internalError(asyncResp->res); 4604bfefa74SGunnar Mills return; 4614bfefa74SGunnar Mills } 4624bfefa74SGunnar Mills 4634bfefa74SGunnar Mills bool foundImage = false; 46402cad96eSEd Tanous for (const auto& object : subtree) 4654bfefa74SGunnar Mills { 4664bfefa74SGunnar Mills const std::string& path = 4674bfefa74SGunnar Mills static_cast<const std::string&>(object.first); 468f23b7296SEd Tanous std::size_t idPos2 = path.rfind('/'); 4694bfefa74SGunnar Mills 4704bfefa74SGunnar Mills if (idPos2 == std::string::npos) 4714bfefa74SGunnar Mills { 4724bfefa74SGunnar Mills continue; 4734bfefa74SGunnar Mills } 4744bfefa74SGunnar Mills 4754bfefa74SGunnar Mills idPos2++; 4764bfefa74SGunnar Mills if (idPos2 >= path.size()) 4774bfefa74SGunnar Mills { 4784bfefa74SGunnar Mills continue; 4794bfefa74SGunnar Mills } 4804bfefa74SGunnar Mills 4814bfefa74SGunnar Mills if (path.substr(idPos2) == firmwareId) 4824bfefa74SGunnar Mills { 4834bfefa74SGunnar Mills foundImage = true; 4844bfefa74SGunnar Mills break; 4854bfefa74SGunnar Mills } 4864bfefa74SGunnar Mills } 4874bfefa74SGunnar Mills 4884bfefa74SGunnar Mills if (!foundImage) 4894bfefa74SGunnar Mills { 490ac106bf6SEd Tanous messages::propertyValueNotInList( 491ac106bf6SEd Tanous asyncResp->res, runningFirmwareTarget, "@odata.id"); 49262598e31SEd Tanous BMCWEB_LOG_DEBUG("Invalid firmware ID."); 4934bfefa74SGunnar Mills return; 4944bfefa74SGunnar Mills } 4954bfefa74SGunnar Mills 49662598e31SEd Tanous BMCWEB_LOG_DEBUG("Setting firmware version {} to priority 0.", 49762598e31SEd Tanous firmwareId); 4984bfefa74SGunnar Mills 4994bfefa74SGunnar Mills // Only support Immediate 5004bfefa74SGunnar Mills // An addition could be a Redfish Setting like 5014bfefa74SGunnar Mills // ActiveSoftwareImageApplyTime and support OnReset 5029ae226faSGeorge Liu sdbusplus::asio::setProperty( 503d27c31e9SJagpal Singh Gill *crow::connections::systemBus, getBMCUpdateServiceName(), 5049ae226faSGeorge Liu "/xyz/openbmc_project/software/" + firmwareId, 5059ae226faSGeorge Liu "xyz.openbmc_project.Software.RedundancyPriority", "Priority", 5069ae226faSGeorge Liu static_cast<uint8_t>(0), 507ac106bf6SEd Tanous [asyncResp](const boost::system::error_code& ec2) { 5088a592810SEd Tanous if (ec2) 5094bfefa74SGunnar Mills { 51062598e31SEd Tanous BMCWEB_LOG_DEBUG("D-Bus response error setting."); 511ac106bf6SEd Tanous messages::internalError(asyncResp->res); 5124bfefa74SGunnar Mills return; 5134bfefa74SGunnar Mills } 514ac106bf6SEd Tanous doBMCGracefulRestart(asyncResp); 5159ae226faSGeorge Liu }); 5165eb468daSGeorge Liu }); 5174bfefa74SGunnar Mills } 5184bfefa74SGunnar Mills 519bd79bce8SPatrick Williams inline void afterSetDateTime( 520bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 521bd79bce8SPatrick Williams const boost::system::error_code& ec, const sdbusplus::message_t& msg) 522c51afd54SEd Tanous { 523c51afd54SEd Tanous if (ec) 524c51afd54SEd Tanous { 525c51afd54SEd Tanous BMCWEB_LOG_DEBUG("Failed to set elapsed time. DBUS response error {}", 526c51afd54SEd Tanous ec); 527c51afd54SEd Tanous const sd_bus_error* dbusError = msg.get_error(); 528c51afd54SEd Tanous if (dbusError != nullptr) 529c51afd54SEd Tanous { 530c51afd54SEd Tanous std::string_view errorName(dbusError->name); 531c51afd54SEd Tanous if (errorName == 532c51afd54SEd Tanous "org.freedesktop.timedate1.AutomaticTimeSyncEnabled") 533c51afd54SEd Tanous { 534c51afd54SEd Tanous BMCWEB_LOG_DEBUG("Setting conflict"); 535c51afd54SEd Tanous messages::propertyValueConflict( 536c51afd54SEd Tanous asyncResp->res, "DateTime", 537c51afd54SEd Tanous "Managers/NetworkProtocol/NTPProcotolEnabled"); 538c51afd54SEd Tanous return; 539c51afd54SEd Tanous } 540c51afd54SEd Tanous } 541c51afd54SEd Tanous messages::internalError(asyncResp->res); 542c51afd54SEd Tanous return; 543c51afd54SEd Tanous } 544c51afd54SEd Tanous asyncResp->res.result(boost::beast::http::status::no_content); 545c51afd54SEd Tanous } 546c51afd54SEd Tanous 547c51afd54SEd Tanous inline void setDateTime(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 548c51afd54SEd Tanous const std::string& datetime) 549af5d6058SSantosh Puranik { 55062598e31SEd Tanous BMCWEB_LOG_DEBUG("Set date time: {}", datetime); 551af5d6058SSantosh Puranik 552c2e32007SEd Tanous std::optional<redfish::time_utils::usSinceEpoch> us = 553c2e32007SEd Tanous redfish::time_utils::dateStringToEpoch(datetime); 554c2e32007SEd Tanous if (!us) 555af5d6058SSantosh Puranik { 556ac106bf6SEd Tanous messages::propertyValueFormatError(asyncResp->res, datetime, 557ac106bf6SEd Tanous "DateTime"); 558c2e32007SEd Tanous return; 559c2e32007SEd Tanous } 560c51afd54SEd Tanous // Set the absolute datetime 561c51afd54SEd Tanous bool relative = false; 562c51afd54SEd Tanous bool interactive = false; 563c51afd54SEd Tanous crow::connections::systemBus->async_method_call( 564c51afd54SEd Tanous [asyncResp](const boost::system::error_code& ec, 565c51afd54SEd Tanous const sdbusplus::message_t& msg) { 566c51afd54SEd Tanous afterSetDateTime(asyncResp, ec, msg); 567c51afd54SEd Tanous }, 568c51afd54SEd Tanous "org.freedesktop.timedate1", "/org/freedesktop/timedate1", 569c51afd54SEd Tanous "org.freedesktop.timedate1", "SetTime", us->count(), relative, 570c51afd54SEd Tanous interactive); 57183ff9ab6SJames Feist } 5729c310685SBorawski.Lukasz 573504af5a0SPatrick Williams inline void checkForQuiesced( 574504af5a0SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 57575815e5cSEd Tanous { 576deae6a78SEd Tanous dbus::utility::getProperty<std::string>( 577deae6a78SEd Tanous "org.freedesktop.systemd1", 57875815e5cSEd Tanous "/org/freedesktop/systemd1/unit/obmc-bmc-service-quiesce@0.target", 57975815e5cSEd Tanous "org.freedesktop.systemd1.Unit", "ActiveState", 58075815e5cSEd Tanous [asyncResp](const boost::system::error_code& ec, 58175815e5cSEd Tanous const std::string& val) { 58275815e5cSEd Tanous if (!ec) 58375815e5cSEd Tanous { 58475815e5cSEd Tanous if (val == "active") 58575815e5cSEd Tanous { 586539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["Health"] = 587539d8c6bSEd Tanous resource::Health::Critical; 588539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = 589539d8c6bSEd Tanous resource::State::Quiesced; 59075815e5cSEd Tanous return; 59175815e5cSEd Tanous } 59275815e5cSEd Tanous } 593539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK; 594bd79bce8SPatrick Williams asyncResp->res.jsonValue["Status"]["State"] = 595bd79bce8SPatrick Williams resource::State::Enabled; 59675815e5cSEd Tanous }); 59775815e5cSEd Tanous } 59875815e5cSEd Tanous 599e2cdf06fSJanet Adkins inline void getPhysicalAssets( 600e2cdf06fSJanet Adkins const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 601e2cdf06fSJanet Adkins const boost::system::error_code& ec, 602e2cdf06fSJanet Adkins const dbus::utility::DBusPropertiesMap& propertiesList) 603e2cdf06fSJanet Adkins { 604e2cdf06fSJanet Adkins if (ec) 605e2cdf06fSJanet Adkins { 606e2cdf06fSJanet Adkins BMCWEB_LOG_DEBUG("Can't get bmc asset!"); 607e2cdf06fSJanet Adkins return; 608e2cdf06fSJanet Adkins } 609e2cdf06fSJanet Adkins 610e2cdf06fSJanet Adkins const std::string* partNumber = nullptr; 611e2cdf06fSJanet Adkins const std::string* serialNumber = nullptr; 612e2cdf06fSJanet Adkins const std::string* manufacturer = nullptr; 613e2cdf06fSJanet Adkins const std::string* model = nullptr; 614e2cdf06fSJanet Adkins const std::string* sparePartNumber = nullptr; 615e2cdf06fSJanet Adkins 616e2cdf06fSJanet Adkins const bool success = sdbusplus::unpackPropertiesNoThrow( 617e2cdf06fSJanet Adkins dbus_utils::UnpackErrorPrinter(), propertiesList, "PartNumber", 618e2cdf06fSJanet Adkins partNumber, "SerialNumber", serialNumber, "Manufacturer", manufacturer, 619e2cdf06fSJanet Adkins "Model", model, "SparePartNumber", sparePartNumber); 620e2cdf06fSJanet Adkins 621e2cdf06fSJanet Adkins if (!success) 622e2cdf06fSJanet Adkins { 623e2cdf06fSJanet Adkins messages::internalError(asyncResp->res); 624e2cdf06fSJanet Adkins return; 625e2cdf06fSJanet Adkins } 626e2cdf06fSJanet Adkins 627e2cdf06fSJanet Adkins if (partNumber != nullptr) 628e2cdf06fSJanet Adkins { 629e2cdf06fSJanet Adkins asyncResp->res.jsonValue["PartNumber"] = *partNumber; 630e2cdf06fSJanet Adkins } 631e2cdf06fSJanet Adkins 632e2cdf06fSJanet Adkins if (serialNumber != nullptr) 633e2cdf06fSJanet Adkins { 634e2cdf06fSJanet Adkins asyncResp->res.jsonValue["SerialNumber"] = *serialNumber; 635e2cdf06fSJanet Adkins } 636e2cdf06fSJanet Adkins 637e2cdf06fSJanet Adkins if (manufacturer != nullptr) 638e2cdf06fSJanet Adkins { 639e2cdf06fSJanet Adkins asyncResp->res.jsonValue["Manufacturer"] = *manufacturer; 640e2cdf06fSJanet Adkins } 641e2cdf06fSJanet Adkins 642e2cdf06fSJanet Adkins if (model != nullptr) 643e2cdf06fSJanet Adkins { 644e2cdf06fSJanet Adkins asyncResp->res.jsonValue["Model"] = *model; 645e2cdf06fSJanet Adkins } 646e2cdf06fSJanet Adkins 647e2cdf06fSJanet Adkins if (sparePartNumber != nullptr) 648e2cdf06fSJanet Adkins { 649e2cdf06fSJanet Adkins asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber; 650e2cdf06fSJanet Adkins } 651e2cdf06fSJanet Adkins } 652e2cdf06fSJanet Adkins 653e2cdf06fSJanet Adkins inline void getManagerData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 654e2cdf06fSJanet Adkins const std::string& managerPath, 655e2cdf06fSJanet Adkins const dbus::utility::MapperServiceMap& serviceMap) 656e2cdf06fSJanet Adkins { 657e2cdf06fSJanet Adkins if (managerPath.empty() || serviceMap.size() != 1) 658e2cdf06fSJanet Adkins { 659e2cdf06fSJanet Adkins BMCWEB_LOG_DEBUG("Error getting bmc D-Bus object!"); 660e2cdf06fSJanet Adkins messages::internalError(asyncResp->res); 661e2cdf06fSJanet Adkins return; 662e2cdf06fSJanet Adkins } 663e2cdf06fSJanet Adkins 664*0fa34188SGunnar Mills for (const auto& [connectionName, interfaces] : serviceMap) 665*0fa34188SGunnar Mills { 666*0fa34188SGunnar Mills for (const auto& interfaceName : interfaces) 667*0fa34188SGunnar Mills { 668*0fa34188SGunnar Mills if (interfaceName == 669*0fa34188SGunnar Mills "xyz.openbmc_project.Inventory.Decorator.Asset") 670*0fa34188SGunnar Mills { 671*0fa34188SGunnar Mills dbus::utility::getAllProperties( 672*0fa34188SGunnar Mills *crow::connections::systemBus, connectionName, managerPath, 673*0fa34188SGunnar Mills "xyz.openbmc_project.Inventory.Decorator.Asset", 674*0fa34188SGunnar Mills std::bind_front(getPhysicalAssets, asyncResp)); 675*0fa34188SGunnar Mills } 676*0fa34188SGunnar Mills else if (interfaceName == 677*0fa34188SGunnar Mills "xyz.openbmc_project.Inventory.Decorator.LocationCode") 678*0fa34188SGunnar Mills { 679*0fa34188SGunnar Mills getLocation(asyncResp, connectionName, managerPath); 680*0fa34188SGunnar Mills } 681*0fa34188SGunnar Mills else if (interfaceName == 682*0fa34188SGunnar Mills "xyz.openbmc_project.Association.Definitions") 683*0fa34188SGunnar Mills { 684*0fa34188SGunnar Mills getLocationIndicatorActive(asyncResp, managerPath); 685*0fa34188SGunnar Mills } 686*0fa34188SGunnar Mills } 687*0fa34188SGunnar Mills } 688*0fa34188SGunnar Mills } 689*0fa34188SGunnar Mills 690*0fa34188SGunnar Mills inline void afterGetManagerObject( 691*0fa34188SGunnar Mills const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 692*0fa34188SGunnar Mills const boost::system::error_code& ec, 693*0fa34188SGunnar Mills const dbus::utility::MapperGetSubTreeResponse& subtree, 694*0fa34188SGunnar Mills const std::function< 695*0fa34188SGunnar Mills void(const std::string& managerPath, 696*0fa34188SGunnar Mills const dbus::utility::MapperServiceMap& serviceMap)>& callback) 697*0fa34188SGunnar Mills { 698*0fa34188SGunnar Mills if (ec) 699*0fa34188SGunnar Mills { 700*0fa34188SGunnar Mills BMCWEB_LOG_DEBUG("D-Bus response error on GetSubTree {}", ec); 701*0fa34188SGunnar Mills return; 702*0fa34188SGunnar Mills } 703*0fa34188SGunnar Mills if (subtree.empty()) 704*0fa34188SGunnar Mills { 705*0fa34188SGunnar Mills BMCWEB_LOG_DEBUG("Can't find bmc D-Bus object!"); 706*0fa34188SGunnar Mills return; 707*0fa34188SGunnar Mills } 708*0fa34188SGunnar Mills // Assume only 1 bmc D-Bus object 709*0fa34188SGunnar Mills // Throw an error if there is more than 1 710*0fa34188SGunnar Mills if (subtree.size() > 1) 711*0fa34188SGunnar Mills { 712*0fa34188SGunnar Mills BMCWEB_LOG_ERROR("Found more than 1 bmc D-Bus object!"); 713*0fa34188SGunnar Mills messages::internalError(asyncResp->res); 714*0fa34188SGunnar Mills return; 715*0fa34188SGunnar Mills } 716*0fa34188SGunnar Mills 717*0fa34188SGunnar Mills callback(subtree[0].first, subtree[0].second); 718*0fa34188SGunnar Mills } 719*0fa34188SGunnar Mills 720*0fa34188SGunnar Mills inline void getManagerObject( 721*0fa34188SGunnar Mills const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 722*0fa34188SGunnar Mills const std::string& /* managerId */, 723*0fa34188SGunnar Mills std::function<void(const std::string& managerPath, 724*0fa34188SGunnar Mills const dbus::utility::MapperServiceMap& serviceMap)>&& 725*0fa34188SGunnar Mills callback) 726*0fa34188SGunnar Mills { 727*0fa34188SGunnar Mills constexpr std::array<std::string_view, 1> interfaces = { 728*0fa34188SGunnar Mills "xyz.openbmc_project.Inventory.Item.Bmc"}; 729*0fa34188SGunnar Mills dbus::utility::getSubTree( 730*0fa34188SGunnar Mills "/xyz/openbmc_project/inventory", 0, interfaces, 731*0fa34188SGunnar Mills [asyncResp, callback{std::move(callback)}]( 732*0fa34188SGunnar Mills const boost::system::error_code& ec, 733*0fa34188SGunnar Mills const dbus::utility::MapperGetSubTreeResponse& subtree) { 734*0fa34188SGunnar Mills afterGetManagerObject(asyncResp, ec, subtree, callback); 735*0fa34188SGunnar Mills }); 736*0fa34188SGunnar Mills } 737*0fa34188SGunnar Mills 738*0fa34188SGunnar Mills inline void handleManagerGet( 739*0fa34188SGunnar Mills App& app, const crow::Request& req, 740*0fa34188SGunnar Mills const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 741*0fa34188SGunnar Mills const std::string& managerId) 742*0fa34188SGunnar Mills { 743*0fa34188SGunnar Mills if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 744*0fa34188SGunnar Mills { 745*0fa34188SGunnar Mills return; 746*0fa34188SGunnar Mills } 747*0fa34188SGunnar Mills 748*0fa34188SGunnar Mills if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 749*0fa34188SGunnar Mills { 750*0fa34188SGunnar Mills messages::resourceNotFound(asyncResp->res, "Manager", managerId); 751*0fa34188SGunnar Mills return; 752*0fa34188SGunnar Mills } 753*0fa34188SGunnar Mills 75496153bdeSMyung Bae std::string uuid = persistent_data::getConfig().systemUuid; 75596153bdeSMyung Bae 756*0fa34188SGunnar Mills asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 757*0fa34188SGunnar Mills "/redfish/v1/Managers/{}", BMCWEB_REDFISH_MANAGER_URI_NAME); 75896153bdeSMyung Bae asyncResp->res.jsonValue["@odata.type"] = "#Manager.v1_15_0.Manager"; 759*0fa34188SGunnar Mills asyncResp->res.jsonValue["Id"] = BMCWEB_REDFISH_MANAGER_URI_NAME; 7607e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Name"] = "OpenBmc Manager"; 76196153bdeSMyung Bae asyncResp->res.jsonValue["Description"] = "Baseboard Management Controller"; 762539d8c6bSEd Tanous asyncResp->res.jsonValue["PowerState"] = resource::PowerState::On; 7631476687dSEd Tanous 764539d8c6bSEd Tanous asyncResp->res.jsonValue["ManagerType"] = manager::ManagerType::BMC; 7657e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["UUID"] = systemd_utils::getUuid(); 7667e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["ServiceEntryPointUUID"] = uuid; 76796153bdeSMyung Bae asyncResp->res.jsonValue["Model"] = "OpenBmc"; // TODO(ed), get model 7687e860f15SJohn Edward Broadbent 769*0fa34188SGunnar Mills asyncResp->res.jsonValue["LogServices"]["@odata.id"] = boost::urls::format( 770*0fa34188SGunnar Mills "/redfish/v1/Managers/{}/LogServices", BMCWEB_REDFISH_MANAGER_URI_NAME); 7711476687dSEd Tanous asyncResp->res.jsonValue["NetworkProtocol"]["@odata.id"] = 772253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}/NetworkProtocol", 773*0fa34188SGunnar Mills BMCWEB_REDFISH_MANAGER_URI_NAME); 7741476687dSEd Tanous asyncResp->res.jsonValue["EthernetInterfaces"]["@odata.id"] = 77596153bdeSMyung Bae boost::urls::format("/redfish/v1/Managers/{}/EthernetInterfaces", 776*0fa34188SGunnar Mills BMCWEB_REDFISH_MANAGER_URI_NAME); 7777e860f15SJohn Edward Broadbent 778e30d3345SCorey Ethington manager_utils::getServiceIdentification(asyncResp, false); 779e30d3345SCorey Ethington 78025b54dbaSEd Tanous if constexpr (BMCWEB_VM_NBDPROXY) 78136c0f2a3SEd Tanous { 7821476687dSEd Tanous asyncResp->res.jsonValue["VirtualMedia"]["@odata.id"] = 783253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}/VirtualMedia", 784*0fa34188SGunnar Mills BMCWEB_REDFISH_MANAGER_URI_NAME); 78536c0f2a3SEd Tanous } 7867e860f15SJohn Edward Broadbent 7877e860f15SJohn Edward Broadbent // Manager.Reset (an action) can be many values, OpenBMC only 7887e860f15SJohn Edward Broadbent // supports BMC reboot. 7897e860f15SJohn Edward Broadbent nlohmann::json& managerReset = 7907e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Actions"]["#Manager.Reset"]; 791*0fa34188SGunnar Mills managerReset["target"] = 792*0fa34188SGunnar Mills boost::urls::format("/redfish/v1/Managers/{}/Actions/Manager.Reset", 793*0fa34188SGunnar Mills BMCWEB_REDFISH_MANAGER_URI_NAME); 794*0fa34188SGunnar Mills managerReset["@Redfish.ActionInfo"] = 795*0fa34188SGunnar Mills boost::urls::format("/redfish/v1/Managers/{}/ResetActionInfo", 796*0fa34188SGunnar Mills BMCWEB_REDFISH_MANAGER_URI_NAME); 7977e860f15SJohn Edward Broadbent 7987e860f15SJohn Edward Broadbent // ResetToDefaults (Factory Reset) has values like 7997e860f15SJohn Edward Broadbent // PreserveNetworkAndUsers and PreserveNetwork that aren't supported 8007e860f15SJohn Edward Broadbent // on OpenBMC 8017e860f15SJohn Edward Broadbent nlohmann::json& resetToDefaults = 8027e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Actions"]["#Manager.ResetToDefaults"]; 803253f11b8SEd Tanous resetToDefaults["target"] = boost::urls::format( 804*0fa34188SGunnar Mills "/redfish/v1/Managers/{}/Actions/Manager.ResetToDefaults", 805*0fa34188SGunnar Mills BMCWEB_REDFISH_MANAGER_URI_NAME); 806613dabeaSEd Tanous resetToDefaults["ResetType@Redfish.AllowableValues"] = 807613dabeaSEd Tanous nlohmann::json::array_t({"ResetAll"}); 8087e860f15SJohn Edward Broadbent 8097c8c4058STejas Patil std::pair<std::string, std::string> redfishDateTimeOffset = 8102b82937eSEd Tanous redfish::time_utils::getDateTimeOffsetNow(); 8117c8c4058STejas Patil 8127c8c4058STejas Patil asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first; 8137c8c4058STejas Patil asyncResp->res.jsonValue["DateTimeLocalOffset"] = 8147c8c4058STejas Patil redfishDateTimeOffset.second; 8157e860f15SJohn Edward Broadbent 81625b54dbaSEd Tanous if constexpr (BMCWEB_KVM) 81725b54dbaSEd Tanous { 8187e860f15SJohn Edward Broadbent // Fill in GraphicalConsole info 81996153bdeSMyung Bae asyncResp->res.jsonValue["GraphicalConsole"]["ServiceEnabled"] = true; 82096153bdeSMyung Bae asyncResp->res.jsonValue["GraphicalConsole"]["MaxConcurrentSessions"] = 82196153bdeSMyung Bae 4; 82296153bdeSMyung Bae asyncResp->res.jsonValue["GraphicalConsole"]["ConnectTypesSupported"] = 823613dabeaSEd Tanous nlohmann::json::array_t({"KVMIP"}); 82425b54dbaSEd Tanous } 82525b54dbaSEd Tanous if constexpr (!BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM) 8267f3e84a1SEd Tanous { 82796153bdeSMyung Bae asyncResp->res.jsonValue["Links"]["ManagerForServers@odata.count"] = 1; 8281476687dSEd Tanous 8291476687dSEd Tanous nlohmann::json::array_t managerForServers; 8301476687dSEd Tanous nlohmann::json::object_t manager; 83196153bdeSMyung Bae manager["@odata.id"] = std::format("/redfish/v1/Systems/{}", 83296153bdeSMyung Bae BMCWEB_REDFISH_SYSTEM_URI_NAME); 833ad539545SPatrick Williams managerForServers.emplace_back(std::move(manager)); 8341476687dSEd Tanous 8351476687dSEd Tanous asyncResp->res.jsonValue["Links"]["ManagerForServers"] = 8361476687dSEd Tanous std::move(managerForServers); 8377f3e84a1SEd Tanous } 8387e860f15SJohn Edward Broadbent 839eee0013eSWilly Tu sw_util::populateSoftwareInformation(asyncResp, sw_util::bmcPurpose, 8407e860f15SJohn Edward Broadbent "FirmwareVersion", true); 8417e860f15SJohn Edward Broadbent 8427e860f15SJohn Edward Broadbent managerGetLastResetTime(asyncResp); 8437e860f15SJohn Edward Broadbent 844a51fc2d2SSui Chen // ManagerDiagnosticData is added for all BMCs. 845a51fc2d2SSui Chen nlohmann::json& managerDiagnosticData = 846a51fc2d2SSui Chen asyncResp->res.jsonValue["ManagerDiagnosticData"]; 847*0fa34188SGunnar Mills managerDiagnosticData["@odata.id"] = 848*0fa34188SGunnar Mills boost::urls::format("/redfish/v1/Managers/{}/ManagerDiagnosticData", 849*0fa34188SGunnar Mills BMCWEB_REDFISH_MANAGER_URI_NAME); 850a51fc2d2SSui Chen 85196153bdeSMyung Bae getMainChassisId( 85296153bdeSMyung Bae asyncResp, [](const std::string& chassisId, 85396153bdeSMyung Bae const std::shared_ptr<bmcweb::AsyncResp>& aRsp) { 85496153bdeSMyung Bae aRsp->res.jsonValue["Links"]["ManagerForChassis@odata.count"] = 1; 8551476687dSEd Tanous nlohmann::json::array_t managerForChassis; 8568a592810SEd Tanous nlohmann::json::object_t managerObj; 857ef4c65b7SEd Tanous boost::urls::url chassiUrl = 858ef4c65b7SEd Tanous boost::urls::format("/redfish/v1/Chassis/{}", chassisId); 859eddfc437SWilly Tu managerObj["@odata.id"] = chassiUrl; 860ad539545SPatrick Williams managerForChassis.emplace_back(std::move(managerObj)); 8611476687dSEd Tanous aRsp->res.jsonValue["Links"]["ManagerForChassis"] = 8621476687dSEd Tanous std::move(managerForChassis); 8631476687dSEd Tanous aRsp->res.jsonValue["Links"]["ManagerInChassis"]["@odata.id"] = 864eddfc437SWilly Tu chassiUrl; 8657e860f15SJohn Edward Broadbent }); 8667e860f15SJohn Edward Broadbent 867deae6a78SEd Tanous dbus::utility::getProperty<double>( 868deae6a78SEd Tanous "org.freedesktop.systemd1", "/org/freedesktop/systemd1", 869deae6a78SEd Tanous "org.freedesktop.systemd1.Manager", "Progress", 87075815e5cSEd Tanous [asyncResp](const boost::system::error_code& ec, double val) { 8717e860f15SJohn Edward Broadbent if (ec) 8721abe55efSEd Tanous { 87362598e31SEd Tanous BMCWEB_LOG_ERROR("Error while getting progress"); 8747e860f15SJohn Edward Broadbent messages::internalError(asyncResp->res); 8757e860f15SJohn Edward Broadbent return; 8767e860f15SJohn Edward Broadbent } 8771e1e598dSJonathan Doman if (val < 1.0) 8787e860f15SJohn Edward Broadbent { 879539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["Health"] = 880539d8c6bSEd Tanous resource::Health::OK; 881539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = 882539d8c6bSEd Tanous resource::State::Starting; 88375815e5cSEd Tanous return; 8847e860f15SJohn Edward Broadbent } 88575815e5cSEd Tanous checkForQuiesced(asyncResp); 8861e1e598dSJonathan Doman }); 8879c310685SBorawski.Lukasz 888*0fa34188SGunnar Mills getManagerObject(asyncResp, managerId, 889*0fa34188SGunnar Mills std::bind_front(getManagerData, asyncResp)); 890c1a75ebcSrohitpai 891c1a75ebcSrohitpai RedfishService::getInstance(app).handleSubRoute(req, asyncResp); 89296153bdeSMyung Bae } 8937e860f15SJohn Edward Broadbent 89496153bdeSMyung Bae inline void handleManagerPatch( 89596153bdeSMyung Bae App& app, const crow::Request& req, 896253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 89796153bdeSMyung Bae const std::string& managerId) 89896153bdeSMyung Bae { 8993ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 90045ca1b86SEd Tanous { 90145ca1b86SEd Tanous return; 90245ca1b86SEd Tanous } 903253f11b8SEd Tanous 904253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 905253f11b8SEd Tanous { 90696153bdeSMyung Bae messages::resourceNotFound(asyncResp->res, "Manager", managerId); 907253f11b8SEd Tanous return; 908253f11b8SEd Tanous } 909253f11b8SEd Tanous 9109e9b6049SEd Tanous std::optional<std::string> activeSoftwareImageOdataId; 9117e860f15SJohn Edward Broadbent std::optional<std::string> datetime; 91279f3b6a1SGeorge Liu std::optional<bool> locationIndicatorActive; 9139e9b6049SEd Tanous std::optional<nlohmann::json::object_t> pidControllers; 9149e9b6049SEd Tanous std::optional<nlohmann::json::object_t> fanControllers; 9159e9b6049SEd Tanous std::optional<nlohmann::json::object_t> fanZones; 9169e9b6049SEd Tanous std::optional<nlohmann::json::object_t> stepwiseControllers; 9179e9b6049SEd Tanous std::optional<std::string> profile; 918e30d3345SCorey Ethington std::optional<std::string> serviceIdentification; 9197e860f15SJohn Edward Broadbent 920afc474aeSMyung Bae if (!json_util::readJsonPatch( // 921afc474aeSMyung Bae req, asyncResp->res, // 922afc474aeSMyung Bae "DateTime", datetime, // 923afc474aeSMyung Bae "Links/ActiveSoftwareImage/@odata.id", 924afc474aeSMyung Bae activeSoftwareImageOdataId, // 92579f3b6a1SGeorge Liu "LocationIndicatorActive", 92679f3b6a1SGeorge Liu locationIndicatorActive, // 927afc474aeSMyung Bae "Oem/OpenBmc/Fan/FanControllers", fanControllers, // 928afc474aeSMyung Bae "Oem/OpenBmc/Fan/FanZones", fanZones, // 929afc474aeSMyung Bae "Oem/OpenBmc/Fan/PidControllers", pidControllers, // 930afc474aeSMyung Bae "Oem/OpenBmc/Fan/Profile", profile, // 931afc474aeSMyung Bae "Oem/OpenBmc/Fan/StepwiseControllers", 932e30d3345SCorey Ethington stepwiseControllers, // 933e30d3345SCorey Ethington "ServiceIdentification", serviceIdentification // 9349e9b6049SEd Tanous )) 9357e860f15SJohn Edward Broadbent { 9367e860f15SJohn Edward Broadbent return; 9377e860f15SJohn Edward Broadbent } 9387e860f15SJohn Edward Broadbent 9399e9b6049SEd Tanous if (activeSoftwareImageOdataId) 9407e860f15SJohn Edward Broadbent { 94196153bdeSMyung Bae setActiveFirmwareImage(asyncResp, *activeSoftwareImageOdataId); 9427e860f15SJohn Edward Broadbent } 9437e860f15SJohn Edward Broadbent 9447e860f15SJohn Edward Broadbent if (datetime) 9457e860f15SJohn Edward Broadbent { 946c51afd54SEd Tanous setDateTime(asyncResp, *datetime); 9477e860f15SJohn Edward Broadbent } 94884aad24dSrohitpai 94979f3b6a1SGeorge Liu if (locationIndicatorActive) 95079f3b6a1SGeorge Liu { 95196153bdeSMyung Bae setLocationIndicatorActiveState(asyncResp, *locationIndicatorActive, 95296153bdeSMyung Bae managerId); 95379f3b6a1SGeorge Liu } 95479f3b6a1SGeorge Liu 955e30d3345SCorey Ethington if (serviceIdentification) 956e30d3345SCorey Ethington { 95796153bdeSMyung Bae manager_utils::setServiceIdentification(asyncResp, 95896153bdeSMyung Bae serviceIdentification.value()); 959e30d3345SCorey Ethington } 960e30d3345SCorey Ethington 96184aad24dSrohitpai RedfishService::getInstance(app).handleSubRoute(req, asyncResp); 9627e860f15SJohn Edward Broadbent } 9637e860f15SJohn Edward Broadbent 96496153bdeSMyung Bae inline void handleManagerCollectionGet( 96596153bdeSMyung Bae crow::App& app, const crow::Request& req, 96696153bdeSMyung Bae const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 9677e860f15SJohn Edward Broadbent { 9683ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 96945ca1b86SEd Tanous { 97045ca1b86SEd Tanous return; 97145ca1b86SEd Tanous } 97283ff9ab6SJames Feist // Collections don't include the static data added by SubRoute 97383ff9ab6SJames Feist // because it has a duplicate entry for members 9748d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Managers"; 9758d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 9768d1b46d7Szhanghch05 "#ManagerCollection.ManagerCollection"; 9778d1b46d7Szhanghch05 asyncResp->res.jsonValue["Name"] = "Manager Collection"; 9788d1b46d7Szhanghch05 asyncResp->res.jsonValue["Members@odata.count"] = 1; 9791476687dSEd Tanous nlohmann::json::array_t members; 9801476687dSEd Tanous nlohmann::json& bmc = members.emplace_back(); 98196153bdeSMyung Bae bmc["@odata.id"] = boost::urls::format("/redfish/v1/Managers/{}", 98296153bdeSMyung Bae BMCWEB_REDFISH_MANAGER_URI_NAME); 9831476687dSEd Tanous asyncResp->res.jsonValue["Members"] = std::move(members); 98496153bdeSMyung Bae } 98596153bdeSMyung Bae 98696153bdeSMyung Bae inline void requestRoutesManager(App& app) 98796153bdeSMyung Bae { 98896153bdeSMyung Bae BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/") 98996153bdeSMyung Bae .privileges(redfish::privileges::getManager) 99096153bdeSMyung Bae .methods(boost::beast::http::verb::get)( 99196153bdeSMyung Bae std::bind_front(handleManagerGet, std::ref(app))); 99296153bdeSMyung Bae 99396153bdeSMyung Bae BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/") 99496153bdeSMyung Bae .privileges(redfish::privileges::patchManager) 99596153bdeSMyung Bae .methods(boost::beast::http::verb::patch)( 99696153bdeSMyung Bae std::bind_front(handleManagerPatch, std::ref(app))); 99796153bdeSMyung Bae 99896153bdeSMyung Bae BMCWEB_ROUTE(app, "/redfish/v1/Managers/") 99996153bdeSMyung Bae .privileges(redfish::privileges::getManagerCollection) 100096153bdeSMyung Bae .methods(boost::beast::http::verb::get)( 100196153bdeSMyung Bae std::bind_front(handleManagerCollectionGet, std::ref(app))); 10029c310685SBorawski.Lukasz } 100364acd268SMyung Bae 100464acd268SMyung Bae inline void requestRoutesManagerResetAction(App& app) 100564acd268SMyung Bae { 100664acd268SMyung Bae BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/Actions/Manager.Reset/") 100764acd268SMyung Bae .privileges(redfish::privileges::postManager) 100864acd268SMyung Bae .methods(boost::beast::http::verb::post)( 100964acd268SMyung Bae std::bind_front(handleManagerResetAction, std::ref(app))); 101064acd268SMyung Bae 101164acd268SMyung Bae BMCWEB_ROUTE(app, 101264acd268SMyung Bae "/redfish/v1/Managers/<str>/Actions/Manager.ResetToDefaults/") 101364acd268SMyung Bae .privileges(redfish::privileges::postManager) 101464acd268SMyung Bae .methods(boost::beast::http::verb::post)( 101564acd268SMyung Bae std::bind_front(handleManagerResetToDefaultsAction, std::ref(app))); 101664acd268SMyung Bae 101764acd268SMyung Bae BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/ResetActionInfo/") 101864acd268SMyung Bae .privileges(redfish::privileges::getActionInfo) 101964acd268SMyung Bae .methods(boost::beast::http::verb::get)( 102064acd268SMyung Bae std::bind_front(handleManagerResetActionInfo, std::ref(app))); 102164acd268SMyung Bae } 102264acd268SMyung Bae 10239c310685SBorawski.Lukasz } // namespace redfish 1024