xref: /openbmc/bmcweb/features/redfish/lib/managers.hpp (revision 08fad5d9dc59323a8916ff97a035221621047d8c)
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"
25*08fad5d9SCorey Ethington #include "utils/etag_utils.hpp"
263ccb3adbSEd Tanous #include "utils/json_utils.hpp"
27e30d3345SCorey Ethington #include "utils/manager_utils.hpp"
28a51fc2d2SSui Chen #include "utils/sw_utils.hpp"
29a51fc2d2SSui Chen #include "utils/systemd_utils.hpp"
302b82937eSEd Tanous #include "utils/time_utils.hpp"
319c310685SBorawski.Lukasz 
32d7857201SEd Tanous #include <systemd/sd-bus.h>
33d7857201SEd Tanous 
34d7857201SEd Tanous #include <boost/beast/http/status.hpp>
35d7857201SEd Tanous #include <boost/beast/http/verb.hpp>
36e99073f5SGeorge Liu #include <boost/system/error_code.hpp>
37ef4c65b7SEd Tanous #include <boost/url/format.hpp>
38d7857201SEd Tanous #include <boost/url/url.hpp>
39d7857201SEd Tanous #include <nlohmann/json.hpp>
40fac6e53bSKrzysztof Grobelny #include <sdbusplus/asio/property.hpp>
41d7857201SEd Tanous #include <sdbusplus/message.hpp>
42d7857201SEd Tanous #include <sdbusplus/message/native_types.hpp>
43fac6e53bSKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp>
441214b7e7SGunnar Mills 
450fa34188SGunnar Mills #include <array>
46d7857201SEd Tanous #include <cstddef>
474bfefa74SGunnar Mills #include <cstdint>
48d7857201SEd Tanous #include <format>
49d7857201SEd Tanous #include <functional>
50d7857201SEd Tanous #include <map>
511214b7e7SGunnar Mills #include <memory>
529970e93fSKonstantin Aladyshev #include <optional>
533544d2a7SEd Tanous #include <ranges>
549970e93fSKonstantin Aladyshev #include <string>
55e99073f5SGeorge Liu #include <string_view>
56d7857201SEd Tanous #include <utility>
575b4aa86bSJames Feist 
581abe55efSEd Tanous namespace redfish
591abe55efSEd Tanous {
60ed5befbdSJennifer Lee 
610fa34188SGunnar Mills inline void handleSetLocationIndicatorActive(
620fa34188SGunnar Mills     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
630fa34188SGunnar Mills     bool locationIndicatorActive, const std::string& managerId,
640fa34188SGunnar Mills     const boost::system::error_code& ec,
650fa34188SGunnar Mills     const dbus::utility::MapperGetSubTreePathsResponse& subtreePaths)
660fa34188SGunnar Mills {
670fa34188SGunnar Mills     if (ec)
680fa34188SGunnar Mills     {
690fa34188SGunnar Mills         if (ec == boost::system::errc::io_error)
700fa34188SGunnar Mills         {
710fa34188SGunnar Mills             // Not found
720fa34188SGunnar Mills             BMCWEB_LOG_WARNING("Manager {} not found", managerId);
730fa34188SGunnar Mills             messages::resourceNotFound(asyncResp->res, "Manager", managerId);
740fa34188SGunnar Mills             return;
750fa34188SGunnar Mills         }
760fa34188SGunnar Mills         BMCWEB_LOG_ERROR("D-Bus response error {}", ec.value());
770fa34188SGunnar Mills         messages::internalError(asyncResp->res);
780fa34188SGunnar Mills         return;
790fa34188SGunnar Mills     }
800fa34188SGunnar Mills     if (subtreePaths.empty())
810fa34188SGunnar Mills     {
820fa34188SGunnar Mills         BMCWEB_LOG_WARNING("Manager {} not found", managerId);
830fa34188SGunnar Mills         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
840fa34188SGunnar Mills         return;
850fa34188SGunnar Mills     }
860fa34188SGunnar Mills     // Assume only 1 bmc D-Bus object
870fa34188SGunnar Mills     // Throw an error if there is more than 1
880fa34188SGunnar Mills     if (subtreePaths.size() != 1)
890fa34188SGunnar Mills     {
900fa34188SGunnar Mills         BMCWEB_LOG_ERROR("Found {} Bmc D-Bus paths", subtreePaths.size());
910fa34188SGunnar Mills         messages::internalError(asyncResp->res);
920fa34188SGunnar Mills         return;
930fa34188SGunnar Mills     }
940fa34188SGunnar Mills 
950fa34188SGunnar Mills     setLocationIndicatorActive(asyncResp, subtreePaths[0],
960fa34188SGunnar Mills                                locationIndicatorActive);
970fa34188SGunnar Mills }
980fa34188SGunnar Mills 
9979f3b6a1SGeorge Liu /**
10079f3b6a1SGeorge Liu  * Set the locationIndicatorActive.
10179f3b6a1SGeorge Liu  *
10279f3b6a1SGeorge Liu  * @param[in,out]   asyncResp                   Async HTTP response.
10379f3b6a1SGeorge Liu  * @param[in]       locationIndicatorActive     Value of the property
10479f3b6a1SGeorge Liu  */
10579f3b6a1SGeorge Liu inline void setLocationIndicatorActiveState(
10679f3b6a1SGeorge Liu     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
10779f3b6a1SGeorge Liu     bool locationIndicatorActive, const std::string& managerId)
10879f3b6a1SGeorge Liu {
1090fa34188SGunnar Mills     // GetSubTree on all interfaces which provide info about a Manager
1100fa34188SGunnar Mills     constexpr std::array<std::string_view, 1> interfaces = {
1110fa34188SGunnar Mills         "xyz.openbmc_project.Inventory.Item.Bmc"};
1120fa34188SGunnar Mills     dbus::utility::getSubTreePaths(
1130fa34188SGunnar Mills         "/xyz/openbmc_project/inventory", 0, interfaces,
1140fa34188SGunnar Mills         std::bind_front(handleSetLocationIndicatorActive, asyncResp,
1150fa34188SGunnar Mills                         locationIndicatorActive, managerId));
11679f3b6a1SGeorge Liu }
11779f3b6a1SGeorge Liu 
118d27c31e9SJagpal Singh Gill inline std::string getBMCUpdateServiceName()
119d27c31e9SJagpal Singh Gill {
120d27c31e9SJagpal Singh Gill     if constexpr (BMCWEB_REDFISH_UPDATESERVICE_USE_DBUS)
121d27c31e9SJagpal Singh Gill     {
122d27c31e9SJagpal Singh Gill         return "xyz.openbmc_project.Software.Manager";
123d27c31e9SJagpal Singh Gill     }
124d27c31e9SJagpal Singh Gill     return "xyz.openbmc_project.Software.BMC.Updater";
125d27c31e9SJagpal Singh Gill }
126d27c31e9SJagpal Singh Gill 
127d27c31e9SJagpal Singh Gill inline std::string getBMCUpdateServicePath()
128d27c31e9SJagpal Singh Gill {
129d27c31e9SJagpal Singh Gill     if constexpr (BMCWEB_REDFISH_UPDATESERVICE_USE_DBUS)
130d27c31e9SJagpal Singh Gill     {
131d27c31e9SJagpal Singh Gill         return "/xyz/openbmc_project/software/bmc";
132d27c31e9SJagpal Singh Gill     }
133d27c31e9SJagpal Singh Gill     return "/xyz/openbmc_project/software";
134d27c31e9SJagpal Singh Gill }
135d27c31e9SJagpal Singh Gill 
136ed5befbdSJennifer Lee /**
1372a5c4407SGunnar Mills  * Function reboots the BMC.
1382a5c4407SGunnar Mills  *
1392a5c4407SGunnar Mills  * @param[in] asyncResp - Shared pointer for completing asynchronous calls
140ed5befbdSJennifer Lee  */
141504af5a0SPatrick Williams inline void doBMCGracefulRestart(
142504af5a0SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
143ed5befbdSJennifer Lee {
144ed5befbdSJennifer Lee     const char* processName = "xyz.openbmc_project.State.BMC";
145ed5befbdSJennifer Lee     const char* objectPath = "/xyz/openbmc_project/state/bmc0";
146ed5befbdSJennifer Lee     const char* interfaceName = "xyz.openbmc_project.State.BMC";
147ed5befbdSJennifer Lee     const std::string& propertyValue =
148ed5befbdSJennifer Lee         "xyz.openbmc_project.State.BMC.Transition.Reboot";
149ed5befbdSJennifer Lee     const char* destProperty = "RequestedBMCTransition";
150ed5befbdSJennifer Lee 
151ed5befbdSJennifer Lee     // Create the D-Bus variant for D-Bus call.
1529ae226faSGeorge Liu     sdbusplus::asio::setProperty(
1539ae226faSGeorge Liu         *crow::connections::systemBus, processName, objectPath, interfaceName,
1549ae226faSGeorge Liu         destProperty, propertyValue,
1555e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
156ed5befbdSJennifer Lee             // Use "Set" method to set the property value.
157ed5befbdSJennifer Lee             if (ec)
158ed5befbdSJennifer Lee             {
15962598e31SEd Tanous                 BMCWEB_LOG_DEBUG("[Set] Bad D-Bus request error: {}", ec);
160ed5befbdSJennifer Lee                 messages::internalError(asyncResp->res);
161ed5befbdSJennifer Lee                 return;
162ed5befbdSJennifer Lee             }
163ed5befbdSJennifer Lee 
164ed5befbdSJennifer Lee             messages::success(asyncResp->res);
1659ae226faSGeorge Liu         });
166ed5befbdSJennifer Lee }
1672a5c4407SGunnar Mills 
168504af5a0SPatrick Williams inline void doBMCForceRestart(
169504af5a0SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
170f92af389SJayaprakash Mutyala {
171f92af389SJayaprakash Mutyala     const char* processName = "xyz.openbmc_project.State.BMC";
172f92af389SJayaprakash Mutyala     const char* objectPath = "/xyz/openbmc_project/state/bmc0";
173f92af389SJayaprakash Mutyala     const char* interfaceName = "xyz.openbmc_project.State.BMC";
174f92af389SJayaprakash Mutyala     const std::string& propertyValue =
175f92af389SJayaprakash Mutyala         "xyz.openbmc_project.State.BMC.Transition.HardReboot";
176f92af389SJayaprakash Mutyala     const char* destProperty = "RequestedBMCTransition";
177f92af389SJayaprakash Mutyala 
178f92af389SJayaprakash Mutyala     // Create the D-Bus variant for D-Bus call.
1799ae226faSGeorge Liu     sdbusplus::asio::setProperty(
1809ae226faSGeorge Liu         *crow::connections::systemBus, processName, objectPath, interfaceName,
1819ae226faSGeorge Liu         destProperty, propertyValue,
1825e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
183f92af389SJayaprakash Mutyala             // Use "Set" method to set the property value.
184f92af389SJayaprakash Mutyala             if (ec)
185f92af389SJayaprakash Mutyala             {
18662598e31SEd Tanous                 BMCWEB_LOG_DEBUG("[Set] Bad D-Bus request error: {}", ec);
187f92af389SJayaprakash Mutyala                 messages::internalError(asyncResp->res);
188f92af389SJayaprakash Mutyala                 return;
189f92af389SJayaprakash Mutyala             }
190f92af389SJayaprakash Mutyala 
191f92af389SJayaprakash Mutyala             messages::success(asyncResp->res);
1929ae226faSGeorge Liu         });
193f92af389SJayaprakash Mutyala }
194f92af389SJayaprakash Mutyala 
1952a5c4407SGunnar Mills /**
19664acd268SMyung Bae  * ManagerResetAction handles POST method request.
1972a5c4407SGunnar Mills  * Analyzes POST body before sending Reset (Reboot) request data to D-Bus.
198f92af389SJayaprakash Mutyala  * OpenBMC supports ResetType "GracefulRestart" and "ForceRestart".
1992a5c4407SGunnar Mills  */
2007e860f15SJohn Edward Broadbent 
20164acd268SMyung Bae inline void handleManagerResetAction(
20264acd268SMyung Bae     crow::App& app, const crow::Request& req,
203253f11b8SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
20464acd268SMyung Bae     const std::string& managerId)
20564acd268SMyung Bae {
2063ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
20745ca1b86SEd Tanous     {
20845ca1b86SEd Tanous         return;
20945ca1b86SEd Tanous     }
210253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
211253f11b8SEd Tanous     {
21264acd268SMyung Bae         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
213253f11b8SEd Tanous         return;
214253f11b8SEd Tanous     }
215253f11b8SEd Tanous 
21662598e31SEd Tanous     BMCWEB_LOG_DEBUG("Post Manager Reset.");
2172a5c4407SGunnar Mills 
2182a5c4407SGunnar Mills     std::string resetType;
2192a5c4407SGunnar Mills 
22064acd268SMyung Bae     if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", resetType))
2212a5c4407SGunnar Mills     {
2222a5c4407SGunnar Mills         return;
2232a5c4407SGunnar Mills     }
2242a5c4407SGunnar Mills 
225f92af389SJayaprakash Mutyala     if (resetType == "GracefulRestart")
226f92af389SJayaprakash Mutyala     {
22762598e31SEd Tanous         BMCWEB_LOG_DEBUG("Proceeding with {}", resetType);
228f92af389SJayaprakash Mutyala         doBMCGracefulRestart(asyncResp);
229f92af389SJayaprakash Mutyala         return;
230f92af389SJayaprakash Mutyala     }
2313174e4dfSEd Tanous     if (resetType == "ForceRestart")
232f92af389SJayaprakash Mutyala     {
23362598e31SEd Tanous         BMCWEB_LOG_DEBUG("Proceeding with {}", resetType);
234f92af389SJayaprakash Mutyala         doBMCForceRestart(asyncResp);
235f92af389SJayaprakash Mutyala         return;
236f92af389SJayaprakash Mutyala     }
23764acd268SMyung Bae     BMCWEB_LOG_DEBUG("Invalid property value for ResetType: {}", resetType);
2382a5c4407SGunnar Mills     messages::actionParameterNotSupported(asyncResp->res, resetType,
2392a5c4407SGunnar Mills                                           "ResetType");
2402a5c4407SGunnar Mills }
241ed5befbdSJennifer Lee 
2423e40fc74SGunnar Mills /**
2433e40fc74SGunnar Mills  * Function handles ResetToDefaults POST method request.
2443e40fc74SGunnar Mills  *
2453e40fc74SGunnar Mills  * Analyzes POST body message and factory resets BMC by calling
2463e40fc74SGunnar Mills  * BMC code updater factory reset followed by a BMC reboot.
2473e40fc74SGunnar Mills  *
2483e40fc74SGunnar Mills  * BMC code updater factory reset wipes the whole BMC read-write
2493e40fc74SGunnar Mills  * filesystem which includes things like the network settings.
2503e40fc74SGunnar Mills  *
25118bf4bf6SGunnar Mills  * OpenBMC only supports ResetType "ResetAll".
2523e40fc74SGunnar Mills  */
2537e860f15SJohn Edward Broadbent 
25464acd268SMyung Bae inline void handleManagerResetToDefaultsAction(
25564acd268SMyung Bae     crow::App& app, const crow::Request& req,
256253f11b8SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
25764acd268SMyung Bae     const std::string& managerId)
25864acd268SMyung Bae {
2593ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
26045ca1b86SEd Tanous     {
26145ca1b86SEd Tanous         return;
26245ca1b86SEd Tanous     }
263253f11b8SEd Tanous 
264253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
265253f11b8SEd Tanous     {
26664acd268SMyung Bae         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
267253f11b8SEd Tanous         return;
268253f11b8SEd Tanous     }
269253f11b8SEd Tanous 
27062598e31SEd Tanous     BMCWEB_LOG_DEBUG("Post ResetToDefaults.");
2713e40fc74SGunnar Mills 
2729970e93fSKonstantin Aladyshev     std::optional<std::string> resetType;
2733e40fc74SGunnar Mills 
274afc474aeSMyung Bae     if (!json_util::readJsonAction( //
275afc474aeSMyung Bae             req, asyncResp->res,    //
276afc474aeSMyung Bae             "ResetType", resetType  //
277afc474aeSMyung Bae             ))
2783e40fc74SGunnar Mills     {
2799970e93fSKonstantin Aladyshev         BMCWEB_LOG_DEBUG("Missing property ResetType.");
2803e40fc74SGunnar Mills 
28164acd268SMyung Bae         messages::actionParameterMissing(asyncResp->res, "ResetToDefaults",
28264acd268SMyung Bae                                          "ResetType");
2833e40fc74SGunnar Mills         return;
2843e40fc74SGunnar Mills     }
2853e40fc74SGunnar Mills 
28664acd268SMyung Bae     if (resetType.value_or("") != "ResetAll")
2873e40fc74SGunnar Mills     {
2889970e93fSKonstantin Aladyshev         BMCWEB_LOG_DEBUG("Invalid property value for ResetType: {}",
28964acd268SMyung Bae                          resetType.value_or(""));
29018bf4bf6SGunnar Mills         messages::actionParameterNotSupported(
29164acd268SMyung Bae             asyncResp->res, resetType.value_or(""), "ResetType");
2923e40fc74SGunnar Mills         return;
2933e40fc74SGunnar Mills     }
2943e40fc74SGunnar Mills 
2953e40fc74SGunnar Mills     crow::connections::systemBus->async_method_call(
2965e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
2973e40fc74SGunnar Mills             if (ec)
2983e40fc74SGunnar Mills             {
29964acd268SMyung Bae                 BMCWEB_LOG_DEBUG("Failed to ResetToDefaults: {}", ec);
3003e40fc74SGunnar Mills                 messages::internalError(asyncResp->res);
3013e40fc74SGunnar Mills                 return;
3023e40fc74SGunnar Mills             }
3033e40fc74SGunnar Mills             // Factory Reset doesn't actually happen until a reboot
3043e40fc74SGunnar Mills             // Can't erase what the BMC is running on
3053e40fc74SGunnar Mills             doBMCGracefulRestart(asyncResp);
3063e40fc74SGunnar Mills         },
307d27c31e9SJagpal Singh Gill         getBMCUpdateServiceName(), getBMCUpdateServicePath(),
3083e40fc74SGunnar Mills         "xyz.openbmc_project.Common.FactoryReset", "Reset");
3093e40fc74SGunnar Mills }
3103e40fc74SGunnar Mills 
3111cb1a9e6SAppaRao Puli /**
3121cb1a9e6SAppaRao Puli  * ManagerResetActionInfo derived class for delivering Manager
3131cb1a9e6SAppaRao Puli  * ResetType AllowableValues using ResetInfo schema.
3141cb1a9e6SAppaRao Puli  */
31564acd268SMyung Bae inline void handleManagerResetActionInfo(
31664acd268SMyung Bae     crow::App& app, const crow::Request& req,
317253f11b8SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
31864acd268SMyung Bae     const std::string& managerId)
31964acd268SMyung Bae {
3203ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
32145ca1b86SEd Tanous     {
32245ca1b86SEd Tanous         return;
32345ca1b86SEd Tanous     }
3241476687dSEd Tanous 
325253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
326253f11b8SEd Tanous     {
32764acd268SMyung Bae         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
328253f11b8SEd Tanous         return;
329253f11b8SEd Tanous     }
330253f11b8SEd Tanous 
33164acd268SMyung Bae     asyncResp->res.jsonValue["@odata.type"] = "#ActionInfo.v1_1_2.ActionInfo";
33264acd268SMyung Bae     asyncResp->res.jsonValue["@odata.id"] =
33364acd268SMyung Bae         boost::urls::format("/redfish/v1/Managers/{}/ResetActionInfo",
334253f11b8SEd Tanous                             BMCWEB_REDFISH_MANAGER_URI_NAME);
3351476687dSEd Tanous     asyncResp->res.jsonValue["Name"] = "Reset Action Info";
3361476687dSEd Tanous     asyncResp->res.jsonValue["Id"] = "ResetActionInfo";
3371476687dSEd Tanous     nlohmann::json::object_t parameter;
3381476687dSEd Tanous     parameter["Name"] = "ResetType";
3391476687dSEd Tanous     parameter["Required"] = true;
340539d8c6bSEd Tanous     parameter["DataType"] = action_info::ParameterTypes::String;
3411476687dSEd Tanous 
3421476687dSEd Tanous     nlohmann::json::array_t allowableValues;
343ad539545SPatrick Williams     allowableValues.emplace_back("GracefulRestart");
344ad539545SPatrick Williams     allowableValues.emplace_back("ForceRestart");
3451476687dSEd Tanous     parameter["AllowableValues"] = std::move(allowableValues);
3461476687dSEd Tanous 
3471476687dSEd Tanous     nlohmann::json::array_t parameters;
348ad539545SPatrick Williams     parameters.emplace_back(std::move(parameter));
3491476687dSEd Tanous 
3501476687dSEd Tanous     asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
3511cb1a9e6SAppaRao Puli }
3521cb1a9e6SAppaRao Puli 
353071d8fdfSSunnySrivastava1984 /**
354071d8fdfSSunnySrivastava1984  * @brief Retrieves BMC manager location data over DBus
355071d8fdfSSunnySrivastava1984  *
356ac106bf6SEd Tanous  * @param[in] asyncResp Shared pointer for completing asynchronous calls
357071d8fdfSSunnySrivastava1984  * @param[in] connectionName - service name
358071d8fdfSSunnySrivastava1984  * @param[in] path - object path
359071d8fdfSSunnySrivastava1984  * @return none
360071d8fdfSSunnySrivastava1984  */
361ac106bf6SEd Tanous inline void getLocation(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
362071d8fdfSSunnySrivastava1984                         const std::string& connectionName,
363071d8fdfSSunnySrivastava1984                         const std::string& path)
364071d8fdfSSunnySrivastava1984 {
36562598e31SEd Tanous     BMCWEB_LOG_DEBUG("Get BMC manager Location data.");
366071d8fdfSSunnySrivastava1984 
367deae6a78SEd Tanous     dbus::utility::getProperty<std::string>(
368deae6a78SEd Tanous         connectionName, path,
3691e1e598dSJonathan Doman         "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode",
370ac106bf6SEd Tanous         [asyncResp](const boost::system::error_code& ec,
3711e1e598dSJonathan Doman                     const std::string& property) {
372071d8fdfSSunnySrivastava1984             if (ec)
373071d8fdfSSunnySrivastava1984             {
37462598e31SEd Tanous                 BMCWEB_LOG_DEBUG("DBUS response error for "
37562598e31SEd Tanous                                  "Location");
376ac106bf6SEd Tanous                 messages::internalError(asyncResp->res);
377071d8fdfSSunnySrivastava1984                 return;
378071d8fdfSSunnySrivastava1984             }
379071d8fdfSSunnySrivastava1984 
380bd79bce8SPatrick Williams             asyncResp->res
381bd79bce8SPatrick Williams                 .jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
3821e1e598dSJonathan Doman                 property;
3831e1e598dSJonathan Doman         });
384071d8fdfSSunnySrivastava1984 }
3857e860f15SJohn Edward Broadbent // avoid name collision systems.hpp
386504af5a0SPatrick Williams inline void managerGetLastResetTime(
387504af5a0SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
3884bf2b033SGunnar Mills {
38962598e31SEd Tanous     BMCWEB_LOG_DEBUG("Getting Manager Last Reset Time");
3904bf2b033SGunnar Mills 
391deae6a78SEd Tanous     dbus::utility::getProperty<uint64_t>(
392deae6a78SEd Tanous         "xyz.openbmc_project.State.BMC", "/xyz/openbmc_project/state/bmc0",
393deae6a78SEd Tanous         "xyz.openbmc_project.State.BMC", "LastRebootTime",
394ac106bf6SEd Tanous         [asyncResp](const boost::system::error_code& ec,
3951e1e598dSJonathan Doman                     const uint64_t lastResetTime) {
3964bf2b033SGunnar Mills             if (ec)
3974bf2b033SGunnar Mills             {
39862598e31SEd Tanous                 BMCWEB_LOG_DEBUG("D-BUS response error {}", ec);
3994bf2b033SGunnar Mills                 return;
4004bf2b033SGunnar Mills             }
4014bf2b033SGunnar Mills 
4024bf2b033SGunnar Mills             // LastRebootTime is epoch time, in milliseconds
4034bf2b033SGunnar Mills             // https://github.com/openbmc/phosphor-dbus-interfaces/blob/7f9a128eb9296e926422ddc312c148b625890bb6/xyz/openbmc_project/State/BMC.interface.yaml#L19
4041e1e598dSJonathan Doman             uint64_t lastResetTimeStamp = lastResetTime / 1000;
4054bf2b033SGunnar Mills 
4064bf2b033SGunnar Mills             // Convert to ISO 8601 standard
407ac106bf6SEd Tanous             asyncResp->res.jsonValue["LastResetTime"] =
4082b82937eSEd Tanous                 redfish::time_utils::getDateTimeUint(lastResetTimeStamp);
4091e1e598dSJonathan Doman         });
4104bf2b033SGunnar Mills }
4114bf2b033SGunnar Mills 
4124bfefa74SGunnar Mills /**
4134bfefa74SGunnar Mills  * @brief Set the running firmware image
4144bfefa74SGunnar Mills  *
415ac106bf6SEd Tanous  * @param[i,o] asyncResp - Async response object
4164bfefa74SGunnar Mills  * @param[i] runningFirmwareTarget - Image to make the running image
4174bfefa74SGunnar Mills  *
4184bfefa74SGunnar Mills  * @return void
4194bfefa74SGunnar Mills  */
420504af5a0SPatrick Williams inline void setActiveFirmwareImage(
421504af5a0SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
422f23b7296SEd Tanous     const std::string& runningFirmwareTarget)
4234bfefa74SGunnar Mills {
4244bfefa74SGunnar Mills     // Get the Id from /redfish/v1/UpdateService/FirmwareInventory/<Id>
425f23b7296SEd Tanous     std::string::size_type idPos = runningFirmwareTarget.rfind('/');
4264bfefa74SGunnar Mills     if (idPos == std::string::npos)
4274bfefa74SGunnar Mills     {
428ac106bf6SEd Tanous         messages::propertyValueNotInList(asyncResp->res, runningFirmwareTarget,
4294bfefa74SGunnar Mills                                          "@odata.id");
43062598e31SEd Tanous         BMCWEB_LOG_DEBUG("Can't parse firmware ID!");
4314bfefa74SGunnar Mills         return;
4324bfefa74SGunnar Mills     }
4334bfefa74SGunnar Mills     idPos++;
4344bfefa74SGunnar Mills     if (idPos >= runningFirmwareTarget.size())
4354bfefa74SGunnar Mills     {
436ac106bf6SEd Tanous         messages::propertyValueNotInList(asyncResp->res, runningFirmwareTarget,
4374bfefa74SGunnar Mills                                          "@odata.id");
43862598e31SEd Tanous         BMCWEB_LOG_DEBUG("Invalid firmware ID.");
4394bfefa74SGunnar Mills         return;
4404bfefa74SGunnar Mills     }
4414bfefa74SGunnar Mills     std::string firmwareId = runningFirmwareTarget.substr(idPos);
4424bfefa74SGunnar Mills 
4434bfefa74SGunnar Mills     // Make sure the image is valid before setting priority
4445eb468daSGeorge Liu     sdbusplus::message::object_path objPath("/xyz/openbmc_project/software");
4455eb468daSGeorge Liu     dbus::utility::getManagedObjects(
446d27c31e9SJagpal Singh Gill         getBMCUpdateServiceName(), objPath,
4475eb468daSGeorge Liu         [asyncResp, firmwareId, runningFirmwareTarget](
4485eb468daSGeorge Liu             const boost::system::error_code& ec,
4495eb468daSGeorge Liu             const dbus::utility::ManagedObjectType& subtree) {
4504bfefa74SGunnar Mills             if (ec)
4514bfefa74SGunnar Mills             {
45262598e31SEd Tanous                 BMCWEB_LOG_DEBUG("D-Bus response error getting objects.");
453ac106bf6SEd Tanous                 messages::internalError(asyncResp->res);
4544bfefa74SGunnar Mills                 return;
4554bfefa74SGunnar Mills             }
4564bfefa74SGunnar Mills 
45726f6976fSEd Tanous             if (subtree.empty())
4584bfefa74SGunnar Mills             {
45962598e31SEd Tanous                 BMCWEB_LOG_DEBUG("Can't find image!");
460ac106bf6SEd Tanous                 messages::internalError(asyncResp->res);
4614bfefa74SGunnar Mills                 return;
4624bfefa74SGunnar Mills             }
4634bfefa74SGunnar Mills 
4644bfefa74SGunnar Mills             bool foundImage = false;
46502cad96eSEd Tanous             for (const auto& object : subtree)
4664bfefa74SGunnar Mills             {
4674bfefa74SGunnar Mills                 const std::string& path =
4684bfefa74SGunnar Mills                     static_cast<const std::string&>(object.first);
469f23b7296SEd Tanous                 std::size_t idPos2 = path.rfind('/');
4704bfefa74SGunnar Mills 
4714bfefa74SGunnar Mills                 if (idPos2 == std::string::npos)
4724bfefa74SGunnar Mills                 {
4734bfefa74SGunnar Mills                     continue;
4744bfefa74SGunnar Mills                 }
4754bfefa74SGunnar Mills 
4764bfefa74SGunnar Mills                 idPos2++;
4774bfefa74SGunnar Mills                 if (idPos2 >= path.size())
4784bfefa74SGunnar Mills                 {
4794bfefa74SGunnar Mills                     continue;
4804bfefa74SGunnar Mills                 }
4814bfefa74SGunnar Mills 
4824bfefa74SGunnar Mills                 if (path.substr(idPos2) == firmwareId)
4834bfefa74SGunnar Mills                 {
4844bfefa74SGunnar Mills                     foundImage = true;
4854bfefa74SGunnar Mills                     break;
4864bfefa74SGunnar Mills                 }
4874bfefa74SGunnar Mills             }
4884bfefa74SGunnar Mills 
4894bfefa74SGunnar Mills             if (!foundImage)
4904bfefa74SGunnar Mills             {
491ac106bf6SEd Tanous                 messages::propertyValueNotInList(
492ac106bf6SEd Tanous                     asyncResp->res, runningFirmwareTarget, "@odata.id");
49362598e31SEd Tanous                 BMCWEB_LOG_DEBUG("Invalid firmware ID.");
4944bfefa74SGunnar Mills                 return;
4954bfefa74SGunnar Mills             }
4964bfefa74SGunnar Mills 
49762598e31SEd Tanous             BMCWEB_LOG_DEBUG("Setting firmware version {} to priority 0.",
49862598e31SEd Tanous                              firmwareId);
4994bfefa74SGunnar Mills 
5004bfefa74SGunnar Mills             // Only support Immediate
5014bfefa74SGunnar Mills             // An addition could be a Redfish Setting like
5024bfefa74SGunnar Mills             // ActiveSoftwareImageApplyTime and support OnReset
5039ae226faSGeorge Liu             sdbusplus::asio::setProperty(
504d27c31e9SJagpal Singh Gill                 *crow::connections::systemBus, getBMCUpdateServiceName(),
5059ae226faSGeorge Liu                 "/xyz/openbmc_project/software/" + firmwareId,
5069ae226faSGeorge Liu                 "xyz.openbmc_project.Software.RedundancyPriority", "Priority",
5079ae226faSGeorge Liu                 static_cast<uint8_t>(0),
508ac106bf6SEd Tanous                 [asyncResp](const boost::system::error_code& ec2) {
5098a592810SEd Tanous                     if (ec2)
5104bfefa74SGunnar Mills                     {
51162598e31SEd Tanous                         BMCWEB_LOG_DEBUG("D-Bus response error setting.");
512ac106bf6SEd Tanous                         messages::internalError(asyncResp->res);
5134bfefa74SGunnar Mills                         return;
5144bfefa74SGunnar Mills                     }
515ac106bf6SEd Tanous                     doBMCGracefulRestart(asyncResp);
5169ae226faSGeorge Liu                 });
5175eb468daSGeorge Liu         });
5184bfefa74SGunnar Mills }
5194bfefa74SGunnar Mills 
520bd79bce8SPatrick Williams inline void afterSetDateTime(
521bd79bce8SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
522bd79bce8SPatrick Williams     const boost::system::error_code& ec, const sdbusplus::message_t& msg)
523c51afd54SEd Tanous {
524c51afd54SEd Tanous     if (ec)
525c51afd54SEd Tanous     {
526c51afd54SEd Tanous         BMCWEB_LOG_DEBUG("Failed to set elapsed time. DBUS response error {}",
527c51afd54SEd Tanous                          ec);
528c51afd54SEd Tanous         const sd_bus_error* dbusError = msg.get_error();
529c51afd54SEd Tanous         if (dbusError != nullptr)
530c51afd54SEd Tanous         {
531c51afd54SEd Tanous             std::string_view errorName(dbusError->name);
532c51afd54SEd Tanous             if (errorName ==
533c51afd54SEd Tanous                 "org.freedesktop.timedate1.AutomaticTimeSyncEnabled")
534c51afd54SEd Tanous             {
535c51afd54SEd Tanous                 BMCWEB_LOG_DEBUG("Setting conflict");
536c51afd54SEd Tanous                 messages::propertyValueConflict(
537c51afd54SEd Tanous                     asyncResp->res, "DateTime",
538c51afd54SEd Tanous                     "Managers/NetworkProtocol/NTPProcotolEnabled");
539c51afd54SEd Tanous                 return;
540c51afd54SEd Tanous             }
541c51afd54SEd Tanous         }
542c51afd54SEd Tanous         messages::internalError(asyncResp->res);
543c51afd54SEd Tanous         return;
544c51afd54SEd Tanous     }
545c51afd54SEd Tanous     asyncResp->res.result(boost::beast::http::status::no_content);
546c51afd54SEd Tanous }
547c51afd54SEd Tanous 
548c51afd54SEd Tanous inline void setDateTime(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
549c51afd54SEd Tanous                         const std::string& datetime)
550af5d6058SSantosh Puranik {
55162598e31SEd Tanous     BMCWEB_LOG_DEBUG("Set date time: {}", datetime);
552af5d6058SSantosh Puranik 
553c2e32007SEd Tanous     std::optional<redfish::time_utils::usSinceEpoch> us =
554c2e32007SEd Tanous         redfish::time_utils::dateStringToEpoch(datetime);
555c2e32007SEd Tanous     if (!us)
556af5d6058SSantosh Puranik     {
557ac106bf6SEd Tanous         messages::propertyValueFormatError(asyncResp->res, datetime,
558ac106bf6SEd Tanous                                            "DateTime");
559c2e32007SEd Tanous         return;
560c2e32007SEd Tanous     }
561c51afd54SEd Tanous     // Set the absolute datetime
562c51afd54SEd Tanous     bool relative = false;
563c51afd54SEd Tanous     bool interactive = false;
564c51afd54SEd Tanous     crow::connections::systemBus->async_method_call(
565c51afd54SEd Tanous         [asyncResp](const boost::system::error_code& ec,
566c51afd54SEd Tanous                     const sdbusplus::message_t& msg) {
567c51afd54SEd Tanous             afterSetDateTime(asyncResp, ec, msg);
568c51afd54SEd Tanous         },
569c51afd54SEd Tanous         "org.freedesktop.timedate1", "/org/freedesktop/timedate1",
570c51afd54SEd Tanous         "org.freedesktop.timedate1", "SetTime", us->count(), relative,
571c51afd54SEd Tanous         interactive);
57283ff9ab6SJames Feist }
5739c310685SBorawski.Lukasz 
574504af5a0SPatrick Williams inline void checkForQuiesced(
575504af5a0SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
57675815e5cSEd Tanous {
577deae6a78SEd Tanous     dbus::utility::getProperty<std::string>(
578deae6a78SEd Tanous         "org.freedesktop.systemd1",
57975815e5cSEd Tanous         "/org/freedesktop/systemd1/unit/obmc-bmc-service-quiesce@0.target",
58075815e5cSEd Tanous         "org.freedesktop.systemd1.Unit", "ActiveState",
58175815e5cSEd Tanous         [asyncResp](const boost::system::error_code& ec,
58275815e5cSEd Tanous                     const std::string& val) {
58375815e5cSEd Tanous             if (!ec)
58475815e5cSEd Tanous             {
58575815e5cSEd Tanous                 if (val == "active")
58675815e5cSEd Tanous                 {
587539d8c6bSEd Tanous                     asyncResp->res.jsonValue["Status"]["Health"] =
588539d8c6bSEd Tanous                         resource::Health::Critical;
589539d8c6bSEd Tanous                     asyncResp->res.jsonValue["Status"]["State"] =
590539d8c6bSEd Tanous                         resource::State::Quiesced;
59175815e5cSEd Tanous                     return;
59275815e5cSEd Tanous                 }
59375815e5cSEd Tanous             }
594539d8c6bSEd Tanous             asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK;
595bd79bce8SPatrick Williams             asyncResp->res.jsonValue["Status"]["State"] =
596bd79bce8SPatrick Williams                 resource::State::Enabled;
59775815e5cSEd Tanous         });
59875815e5cSEd Tanous }
59975815e5cSEd Tanous 
600e2cdf06fSJanet Adkins inline void getPhysicalAssets(
601e2cdf06fSJanet Adkins     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
602e2cdf06fSJanet Adkins     const boost::system::error_code& ec,
603e2cdf06fSJanet Adkins     const dbus::utility::DBusPropertiesMap& propertiesList)
604e2cdf06fSJanet Adkins {
605e2cdf06fSJanet Adkins     if (ec)
606e2cdf06fSJanet Adkins     {
607e2cdf06fSJanet Adkins         BMCWEB_LOG_DEBUG("Can't get bmc asset!");
608e2cdf06fSJanet Adkins         return;
609e2cdf06fSJanet Adkins     }
610e2cdf06fSJanet Adkins 
611e2cdf06fSJanet Adkins     const std::string* partNumber = nullptr;
612e2cdf06fSJanet Adkins     const std::string* serialNumber = nullptr;
613e2cdf06fSJanet Adkins     const std::string* manufacturer = nullptr;
614e2cdf06fSJanet Adkins     const std::string* model = nullptr;
615e2cdf06fSJanet Adkins     const std::string* sparePartNumber = nullptr;
616e2cdf06fSJanet Adkins 
617e2cdf06fSJanet Adkins     const bool success = sdbusplus::unpackPropertiesNoThrow(
618e2cdf06fSJanet Adkins         dbus_utils::UnpackErrorPrinter(), propertiesList, "PartNumber",
619e2cdf06fSJanet Adkins         partNumber, "SerialNumber", serialNumber, "Manufacturer", manufacturer,
620e2cdf06fSJanet Adkins         "Model", model, "SparePartNumber", sparePartNumber);
621e2cdf06fSJanet Adkins 
622e2cdf06fSJanet Adkins     if (!success)
623e2cdf06fSJanet Adkins     {
624e2cdf06fSJanet Adkins         messages::internalError(asyncResp->res);
625e2cdf06fSJanet Adkins         return;
626e2cdf06fSJanet Adkins     }
627e2cdf06fSJanet Adkins 
628e2cdf06fSJanet Adkins     if (partNumber != nullptr)
629e2cdf06fSJanet Adkins     {
630e2cdf06fSJanet Adkins         asyncResp->res.jsonValue["PartNumber"] = *partNumber;
631e2cdf06fSJanet Adkins     }
632e2cdf06fSJanet Adkins 
633e2cdf06fSJanet Adkins     if (serialNumber != nullptr)
634e2cdf06fSJanet Adkins     {
635e2cdf06fSJanet Adkins         asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
636e2cdf06fSJanet Adkins     }
637e2cdf06fSJanet Adkins 
638e2cdf06fSJanet Adkins     if (manufacturer != nullptr)
639e2cdf06fSJanet Adkins     {
640e2cdf06fSJanet Adkins         asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
641e2cdf06fSJanet Adkins     }
642e2cdf06fSJanet Adkins 
643e2cdf06fSJanet Adkins     if (model != nullptr)
644e2cdf06fSJanet Adkins     {
645e2cdf06fSJanet Adkins         asyncResp->res.jsonValue["Model"] = *model;
646e2cdf06fSJanet Adkins     }
647e2cdf06fSJanet Adkins 
648e2cdf06fSJanet Adkins     if (sparePartNumber != nullptr)
649e2cdf06fSJanet Adkins     {
650e2cdf06fSJanet Adkins         asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber;
651e2cdf06fSJanet Adkins     }
652e2cdf06fSJanet Adkins }
653e2cdf06fSJanet Adkins 
654e2cdf06fSJanet Adkins inline void getManagerData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
655e2cdf06fSJanet Adkins                            const std::string& managerPath,
656e2cdf06fSJanet Adkins                            const dbus::utility::MapperServiceMap& serviceMap)
657e2cdf06fSJanet Adkins {
658e2cdf06fSJanet Adkins     if (managerPath.empty() || serviceMap.size() != 1)
659e2cdf06fSJanet Adkins     {
660e2cdf06fSJanet Adkins         BMCWEB_LOG_DEBUG("Error getting bmc D-Bus object!");
661e2cdf06fSJanet Adkins         messages::internalError(asyncResp->res);
662e2cdf06fSJanet Adkins         return;
663e2cdf06fSJanet Adkins     }
664e2cdf06fSJanet Adkins 
6650fa34188SGunnar Mills     for (const auto& [connectionName, interfaces] : serviceMap)
6660fa34188SGunnar Mills     {
6670fa34188SGunnar Mills         for (const auto& interfaceName : interfaces)
6680fa34188SGunnar Mills         {
6690fa34188SGunnar Mills             if (interfaceName ==
6700fa34188SGunnar Mills                 "xyz.openbmc_project.Inventory.Decorator.Asset")
6710fa34188SGunnar Mills             {
6720fa34188SGunnar Mills                 dbus::utility::getAllProperties(
6730fa34188SGunnar Mills                     *crow::connections::systemBus, connectionName, managerPath,
6740fa34188SGunnar Mills                     "xyz.openbmc_project.Inventory.Decorator.Asset",
6750fa34188SGunnar Mills                     std::bind_front(getPhysicalAssets, asyncResp));
6760fa34188SGunnar Mills             }
6770fa34188SGunnar Mills             else if (interfaceName ==
6780fa34188SGunnar Mills                      "xyz.openbmc_project.Inventory.Decorator.LocationCode")
6790fa34188SGunnar Mills             {
6800fa34188SGunnar Mills                 getLocation(asyncResp, connectionName, managerPath);
6810fa34188SGunnar Mills             }
6820fa34188SGunnar Mills             else if (interfaceName ==
6830fa34188SGunnar Mills                      "xyz.openbmc_project.Association.Definitions")
6840fa34188SGunnar Mills             {
6850fa34188SGunnar Mills                 getLocationIndicatorActive(asyncResp, managerPath);
6860fa34188SGunnar Mills             }
6870fa34188SGunnar Mills         }
6880fa34188SGunnar Mills     }
6890fa34188SGunnar Mills }
6900fa34188SGunnar Mills 
6910fa34188SGunnar Mills inline void afterGetManagerObject(
6920fa34188SGunnar Mills     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
6930fa34188SGunnar Mills     const boost::system::error_code& ec,
6940fa34188SGunnar Mills     const dbus::utility::MapperGetSubTreeResponse& subtree,
6950fa34188SGunnar Mills     const std::function<
6960fa34188SGunnar Mills         void(const std::string& managerPath,
6970fa34188SGunnar Mills              const dbus::utility::MapperServiceMap& serviceMap)>& callback)
6980fa34188SGunnar Mills {
6990fa34188SGunnar Mills     if (ec)
7000fa34188SGunnar Mills     {
7010fa34188SGunnar Mills         BMCWEB_LOG_DEBUG("D-Bus response error on GetSubTree {}", ec);
7020fa34188SGunnar Mills         return;
7030fa34188SGunnar Mills     }
7040fa34188SGunnar Mills     if (subtree.empty())
7050fa34188SGunnar Mills     {
7060fa34188SGunnar Mills         BMCWEB_LOG_DEBUG("Can't find bmc D-Bus object!");
7070fa34188SGunnar Mills         return;
7080fa34188SGunnar Mills     }
7090fa34188SGunnar Mills     // Assume only 1 bmc D-Bus object
7100fa34188SGunnar Mills     // Throw an error if there is more than 1
7110fa34188SGunnar Mills     if (subtree.size() > 1)
7120fa34188SGunnar Mills     {
7130fa34188SGunnar Mills         BMCWEB_LOG_ERROR("Found more than 1 bmc D-Bus object!");
7140fa34188SGunnar Mills         messages::internalError(asyncResp->res);
7150fa34188SGunnar Mills         return;
7160fa34188SGunnar Mills     }
7170fa34188SGunnar Mills 
7180fa34188SGunnar Mills     callback(subtree[0].first, subtree[0].second);
7190fa34188SGunnar Mills }
7200fa34188SGunnar Mills 
7210fa34188SGunnar Mills inline void getManagerObject(
7220fa34188SGunnar Mills     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
7230fa34188SGunnar Mills     const std::string& /* managerId */,
7240fa34188SGunnar Mills     std::function<void(const std::string& managerPath,
7250fa34188SGunnar Mills                        const dbus::utility::MapperServiceMap& serviceMap)>&&
7260fa34188SGunnar Mills         callback)
7270fa34188SGunnar Mills {
7280fa34188SGunnar Mills     constexpr std::array<std::string_view, 1> interfaces = {
7290fa34188SGunnar Mills         "xyz.openbmc_project.Inventory.Item.Bmc"};
7300fa34188SGunnar Mills     dbus::utility::getSubTree(
7310fa34188SGunnar Mills         "/xyz/openbmc_project/inventory", 0, interfaces,
7320fa34188SGunnar Mills         [asyncResp, callback{std::move(callback)}](
7330fa34188SGunnar Mills             const boost::system::error_code& ec,
7340fa34188SGunnar Mills             const dbus::utility::MapperGetSubTreeResponse& subtree) {
7350fa34188SGunnar Mills             afterGetManagerObject(asyncResp, ec, subtree, callback);
7360fa34188SGunnar Mills         });
7370fa34188SGunnar Mills }
7380fa34188SGunnar Mills 
7390fa34188SGunnar Mills inline void handleManagerGet(
7400fa34188SGunnar Mills     App& app, const crow::Request& req,
7410fa34188SGunnar Mills     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
7420fa34188SGunnar Mills     const std::string& managerId)
7430fa34188SGunnar Mills {
7440fa34188SGunnar Mills     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
7450fa34188SGunnar Mills     {
7460fa34188SGunnar Mills         return;
7470fa34188SGunnar Mills     }
7480fa34188SGunnar Mills 
7490fa34188SGunnar Mills     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
7500fa34188SGunnar Mills     {
7510fa34188SGunnar Mills         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
7520fa34188SGunnar Mills         return;
7530fa34188SGunnar Mills     }
7540fa34188SGunnar Mills 
75596153bdeSMyung Bae     std::string uuid = persistent_data::getConfig().systemUuid;
75696153bdeSMyung Bae 
7570fa34188SGunnar Mills     asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
7580fa34188SGunnar Mills         "/redfish/v1/Managers/{}", BMCWEB_REDFISH_MANAGER_URI_NAME);
75996153bdeSMyung Bae     asyncResp->res.jsonValue["@odata.type"] = "#Manager.v1_15_0.Manager";
7600fa34188SGunnar Mills     asyncResp->res.jsonValue["Id"] = BMCWEB_REDFISH_MANAGER_URI_NAME;
7617e860f15SJohn Edward Broadbent     asyncResp->res.jsonValue["Name"] = "OpenBmc Manager";
76296153bdeSMyung Bae     asyncResp->res.jsonValue["Description"] = "Baseboard Management Controller";
763539d8c6bSEd Tanous     asyncResp->res.jsonValue["PowerState"] = resource::PowerState::On;
7641476687dSEd Tanous 
765539d8c6bSEd Tanous     asyncResp->res.jsonValue["ManagerType"] = manager::ManagerType::BMC;
7667e860f15SJohn Edward Broadbent     asyncResp->res.jsonValue["UUID"] = systemd_utils::getUuid();
7677e860f15SJohn Edward Broadbent     asyncResp->res.jsonValue["ServiceEntryPointUUID"] = uuid;
76896153bdeSMyung Bae     asyncResp->res.jsonValue["Model"] = "OpenBmc"; // TODO(ed), get model
7697e860f15SJohn Edward Broadbent 
7700fa34188SGunnar Mills     asyncResp->res.jsonValue["LogServices"]["@odata.id"] = boost::urls::format(
7710fa34188SGunnar Mills         "/redfish/v1/Managers/{}/LogServices", BMCWEB_REDFISH_MANAGER_URI_NAME);
7721476687dSEd Tanous     asyncResp->res.jsonValue["NetworkProtocol"]["@odata.id"] =
773253f11b8SEd Tanous         boost::urls::format("/redfish/v1/Managers/{}/NetworkProtocol",
7740fa34188SGunnar Mills                             BMCWEB_REDFISH_MANAGER_URI_NAME);
7751476687dSEd Tanous     asyncResp->res.jsonValue["EthernetInterfaces"]["@odata.id"] =
77696153bdeSMyung Bae         boost::urls::format("/redfish/v1/Managers/{}/EthernetInterfaces",
7770fa34188SGunnar Mills                             BMCWEB_REDFISH_MANAGER_URI_NAME);
7787e860f15SJohn Edward Broadbent 
779e30d3345SCorey Ethington     manager_utils::getServiceIdentification(asyncResp, false);
780e30d3345SCorey Ethington 
78125b54dbaSEd Tanous     if constexpr (BMCWEB_VM_NBDPROXY)
78236c0f2a3SEd Tanous     {
7831476687dSEd Tanous         asyncResp->res.jsonValue["VirtualMedia"]["@odata.id"] =
784253f11b8SEd Tanous             boost::urls::format("/redfish/v1/Managers/{}/VirtualMedia",
7850fa34188SGunnar Mills                                 BMCWEB_REDFISH_MANAGER_URI_NAME);
78636c0f2a3SEd Tanous     }
7877e860f15SJohn Edward Broadbent 
7887e860f15SJohn Edward Broadbent     // Manager.Reset (an action) can be many values, OpenBMC only
7897e860f15SJohn Edward Broadbent     // supports BMC reboot.
7907e860f15SJohn Edward Broadbent     nlohmann::json& managerReset =
7917e860f15SJohn Edward Broadbent         asyncResp->res.jsonValue["Actions"]["#Manager.Reset"];
7920fa34188SGunnar Mills     managerReset["target"] =
7930fa34188SGunnar Mills         boost::urls::format("/redfish/v1/Managers/{}/Actions/Manager.Reset",
7940fa34188SGunnar Mills                             BMCWEB_REDFISH_MANAGER_URI_NAME);
7950fa34188SGunnar Mills     managerReset["@Redfish.ActionInfo"] =
7960fa34188SGunnar Mills         boost::urls::format("/redfish/v1/Managers/{}/ResetActionInfo",
7970fa34188SGunnar Mills                             BMCWEB_REDFISH_MANAGER_URI_NAME);
7987e860f15SJohn Edward Broadbent 
7997e860f15SJohn Edward Broadbent     // ResetToDefaults (Factory Reset) has values like
8007e860f15SJohn Edward Broadbent     // PreserveNetworkAndUsers and PreserveNetwork that aren't supported
8017e860f15SJohn Edward Broadbent     // on OpenBMC
8027e860f15SJohn Edward Broadbent     nlohmann::json& resetToDefaults =
8037e860f15SJohn Edward Broadbent         asyncResp->res.jsonValue["Actions"]["#Manager.ResetToDefaults"];
804253f11b8SEd Tanous     resetToDefaults["target"] = boost::urls::format(
8050fa34188SGunnar Mills         "/redfish/v1/Managers/{}/Actions/Manager.ResetToDefaults",
8060fa34188SGunnar Mills         BMCWEB_REDFISH_MANAGER_URI_NAME);
807613dabeaSEd Tanous     resetToDefaults["ResetType@Redfish.AllowableValues"] =
808613dabeaSEd Tanous         nlohmann::json::array_t({"ResetAll"});
8097e860f15SJohn Edward Broadbent 
8107c8c4058STejas Patil     std::pair<std::string, std::string> redfishDateTimeOffset =
8112b82937eSEd Tanous         redfish::time_utils::getDateTimeOffsetNow();
8127c8c4058STejas Patil 
8137c8c4058STejas Patil     asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
8147c8c4058STejas Patil     asyncResp->res.jsonValue["DateTimeLocalOffset"] =
8157c8c4058STejas Patil         redfishDateTimeOffset.second;
8167e860f15SJohn Edward Broadbent 
81725b54dbaSEd Tanous     if constexpr (BMCWEB_KVM)
81825b54dbaSEd Tanous     {
8197e860f15SJohn Edward Broadbent         // Fill in GraphicalConsole info
82096153bdeSMyung Bae         asyncResp->res.jsonValue["GraphicalConsole"]["ServiceEnabled"] = true;
82196153bdeSMyung Bae         asyncResp->res.jsonValue["GraphicalConsole"]["MaxConcurrentSessions"] =
82296153bdeSMyung Bae             4;
82396153bdeSMyung Bae         asyncResp->res.jsonValue["GraphicalConsole"]["ConnectTypesSupported"] =
824613dabeaSEd Tanous             nlohmann::json::array_t({"KVMIP"});
82525b54dbaSEd Tanous     }
82625b54dbaSEd Tanous     if constexpr (!BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
8277f3e84a1SEd Tanous     {
82896153bdeSMyung Bae         asyncResp->res.jsonValue["Links"]["ManagerForServers@odata.count"] = 1;
8291476687dSEd Tanous 
8301476687dSEd Tanous         nlohmann::json::array_t managerForServers;
8311476687dSEd Tanous         nlohmann::json::object_t manager;
83296153bdeSMyung Bae         manager["@odata.id"] = std::format("/redfish/v1/Systems/{}",
83396153bdeSMyung Bae                                            BMCWEB_REDFISH_SYSTEM_URI_NAME);
834ad539545SPatrick Williams         managerForServers.emplace_back(std::move(manager));
8351476687dSEd Tanous 
8361476687dSEd Tanous         asyncResp->res.jsonValue["Links"]["ManagerForServers"] =
8371476687dSEd Tanous             std::move(managerForServers);
8387f3e84a1SEd Tanous     }
8397e860f15SJohn Edward Broadbent 
840eee0013eSWilly Tu     sw_util::populateSoftwareInformation(asyncResp, sw_util::bmcPurpose,
8417e860f15SJohn Edward Broadbent                                          "FirmwareVersion", true);
8427e860f15SJohn Edward Broadbent 
8437e860f15SJohn Edward Broadbent     managerGetLastResetTime(asyncResp);
8447e860f15SJohn Edward Broadbent 
845a51fc2d2SSui Chen     // ManagerDiagnosticData is added for all BMCs.
846a51fc2d2SSui Chen     nlohmann::json& managerDiagnosticData =
847a51fc2d2SSui Chen         asyncResp->res.jsonValue["ManagerDiagnosticData"];
8480fa34188SGunnar Mills     managerDiagnosticData["@odata.id"] =
8490fa34188SGunnar Mills         boost::urls::format("/redfish/v1/Managers/{}/ManagerDiagnosticData",
8500fa34188SGunnar Mills                             BMCWEB_REDFISH_MANAGER_URI_NAME);
851a51fc2d2SSui Chen 
85296153bdeSMyung Bae     getMainChassisId(
85396153bdeSMyung Bae         asyncResp, [](const std::string& chassisId,
85496153bdeSMyung Bae                       const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
85596153bdeSMyung Bae             aRsp->res.jsonValue["Links"]["ManagerForChassis@odata.count"] = 1;
8561476687dSEd Tanous             nlohmann::json::array_t managerForChassis;
8578a592810SEd Tanous             nlohmann::json::object_t managerObj;
858ef4c65b7SEd Tanous             boost::urls::url chassiUrl =
859ef4c65b7SEd Tanous                 boost::urls::format("/redfish/v1/Chassis/{}", chassisId);
860eddfc437SWilly Tu             managerObj["@odata.id"] = chassiUrl;
861ad539545SPatrick Williams             managerForChassis.emplace_back(std::move(managerObj));
8621476687dSEd Tanous             aRsp->res.jsonValue["Links"]["ManagerForChassis"] =
8631476687dSEd Tanous                 std::move(managerForChassis);
8641476687dSEd Tanous             aRsp->res.jsonValue["Links"]["ManagerInChassis"]["@odata.id"] =
865eddfc437SWilly Tu                 chassiUrl;
8667e860f15SJohn Edward Broadbent         });
8677e860f15SJohn Edward Broadbent 
868deae6a78SEd Tanous     dbus::utility::getProperty<double>(
869deae6a78SEd Tanous         "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
870deae6a78SEd Tanous         "org.freedesktop.systemd1.Manager", "Progress",
87175815e5cSEd Tanous         [asyncResp](const boost::system::error_code& ec, double val) {
8727e860f15SJohn Edward Broadbent             if (ec)
8731abe55efSEd Tanous             {
87462598e31SEd Tanous                 BMCWEB_LOG_ERROR("Error while getting progress");
8757e860f15SJohn Edward Broadbent                 messages::internalError(asyncResp->res);
8767e860f15SJohn Edward Broadbent                 return;
8777e860f15SJohn Edward Broadbent             }
8781e1e598dSJonathan Doman             if (val < 1.0)
8797e860f15SJohn Edward Broadbent             {
880539d8c6bSEd Tanous                 asyncResp->res.jsonValue["Status"]["Health"] =
881539d8c6bSEd Tanous                     resource::Health::OK;
882539d8c6bSEd Tanous                 asyncResp->res.jsonValue["Status"]["State"] =
883539d8c6bSEd Tanous                     resource::State::Starting;
88475815e5cSEd Tanous                 return;
8857e860f15SJohn Edward Broadbent             }
88675815e5cSEd Tanous             checkForQuiesced(asyncResp);
8871e1e598dSJonathan Doman         });
8889c310685SBorawski.Lukasz 
8890fa34188SGunnar Mills     getManagerObject(asyncResp, managerId,
8900fa34188SGunnar Mills                      std::bind_front(getManagerData, asyncResp));
891*08fad5d9SCorey Ethington     etag_utils::setEtagOmitDateTimeHandler(asyncResp);
892c1a75ebcSrohitpai 
893c1a75ebcSrohitpai     RedfishService::getInstance(app).handleSubRoute(req, asyncResp);
89496153bdeSMyung Bae }
8957e860f15SJohn Edward Broadbent 
89696153bdeSMyung Bae inline void handleManagerPatch(
89796153bdeSMyung Bae     App& app, const crow::Request& req,
898253f11b8SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
89996153bdeSMyung Bae     const std::string& managerId)
90096153bdeSMyung Bae {
9013ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
90245ca1b86SEd Tanous     {
90345ca1b86SEd Tanous         return;
90445ca1b86SEd Tanous     }
905253f11b8SEd Tanous 
906253f11b8SEd Tanous     if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
907253f11b8SEd Tanous     {
90896153bdeSMyung Bae         messages::resourceNotFound(asyncResp->res, "Manager", managerId);
909253f11b8SEd Tanous         return;
910253f11b8SEd Tanous     }
911253f11b8SEd Tanous 
9129e9b6049SEd Tanous     std::optional<std::string> activeSoftwareImageOdataId;
9137e860f15SJohn Edward Broadbent     std::optional<std::string> datetime;
91479f3b6a1SGeorge Liu     std::optional<bool> locationIndicatorActive;
9159e9b6049SEd Tanous     std::optional<nlohmann::json::object_t> pidControllers;
9169e9b6049SEd Tanous     std::optional<nlohmann::json::object_t> fanControllers;
9179e9b6049SEd Tanous     std::optional<nlohmann::json::object_t> fanZones;
9189e9b6049SEd Tanous     std::optional<nlohmann::json::object_t> stepwiseControllers;
9199e9b6049SEd Tanous     std::optional<std::string> profile;
920e30d3345SCorey Ethington     std::optional<std::string> serviceIdentification;
9217e860f15SJohn Edward Broadbent 
922afc474aeSMyung Bae     if (!json_util::readJsonPatch(                            //
923afc474aeSMyung Bae             req, asyncResp->res,                              //
924afc474aeSMyung Bae             "DateTime", datetime,                             //
925afc474aeSMyung Bae             "Links/ActiveSoftwareImage/@odata.id",
926afc474aeSMyung Bae             activeSoftwareImageOdataId,                       //
92779f3b6a1SGeorge Liu             "LocationIndicatorActive",
92879f3b6a1SGeorge Liu             locationIndicatorActive,                          //
929afc474aeSMyung Bae             "Oem/OpenBmc/Fan/FanControllers", fanControllers, //
930afc474aeSMyung Bae             "Oem/OpenBmc/Fan/FanZones", fanZones,             //
931afc474aeSMyung Bae             "Oem/OpenBmc/Fan/PidControllers", pidControllers, //
932afc474aeSMyung Bae             "Oem/OpenBmc/Fan/Profile", profile,               //
933afc474aeSMyung Bae             "Oem/OpenBmc/Fan/StepwiseControllers",
934e30d3345SCorey Ethington             stepwiseControllers,                              //
935e30d3345SCorey Ethington             "ServiceIdentification", serviceIdentification    //
9369e9b6049SEd Tanous             ))
9377e860f15SJohn Edward Broadbent     {
9387e860f15SJohn Edward Broadbent         return;
9397e860f15SJohn Edward Broadbent     }
9407e860f15SJohn Edward Broadbent 
9419e9b6049SEd Tanous     if (activeSoftwareImageOdataId)
9427e860f15SJohn Edward Broadbent     {
94396153bdeSMyung Bae         setActiveFirmwareImage(asyncResp, *activeSoftwareImageOdataId);
9447e860f15SJohn Edward Broadbent     }
9457e860f15SJohn Edward Broadbent 
9467e860f15SJohn Edward Broadbent     if (datetime)
9477e860f15SJohn Edward Broadbent     {
948c51afd54SEd Tanous         setDateTime(asyncResp, *datetime);
9497e860f15SJohn Edward Broadbent     }
95084aad24dSrohitpai 
95179f3b6a1SGeorge Liu     if (locationIndicatorActive)
95279f3b6a1SGeorge Liu     {
95396153bdeSMyung Bae         setLocationIndicatorActiveState(asyncResp, *locationIndicatorActive,
95496153bdeSMyung Bae                                         managerId);
95579f3b6a1SGeorge Liu     }
95679f3b6a1SGeorge Liu 
957e30d3345SCorey Ethington     if (serviceIdentification)
958e30d3345SCorey Ethington     {
95996153bdeSMyung Bae         manager_utils::setServiceIdentification(asyncResp,
96096153bdeSMyung Bae                                                 serviceIdentification.value());
961e30d3345SCorey Ethington     }
962e30d3345SCorey Ethington 
96384aad24dSrohitpai     RedfishService::getInstance(app).handleSubRoute(req, asyncResp);
9647e860f15SJohn Edward Broadbent }
9657e860f15SJohn Edward Broadbent 
96696153bdeSMyung Bae inline void handleManagerCollectionGet(
96796153bdeSMyung Bae     crow::App& app, const crow::Request& req,
96896153bdeSMyung Bae     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
9697e860f15SJohn Edward Broadbent {
9703ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
97145ca1b86SEd Tanous     {
97245ca1b86SEd Tanous         return;
97345ca1b86SEd Tanous     }
97483ff9ab6SJames Feist     // Collections don't include the static data added by SubRoute
97583ff9ab6SJames Feist     // because it has a duplicate entry for members
9768d1b46d7Szhanghch05     asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Managers";
9778d1b46d7Szhanghch05     asyncResp->res.jsonValue["@odata.type"] =
9788d1b46d7Szhanghch05         "#ManagerCollection.ManagerCollection";
9798d1b46d7Szhanghch05     asyncResp->res.jsonValue["Name"] = "Manager Collection";
9808d1b46d7Szhanghch05     asyncResp->res.jsonValue["Members@odata.count"] = 1;
9811476687dSEd Tanous     nlohmann::json::array_t members;
9821476687dSEd Tanous     nlohmann::json& bmc = members.emplace_back();
98396153bdeSMyung Bae     bmc["@odata.id"] = boost::urls::format("/redfish/v1/Managers/{}",
98496153bdeSMyung Bae                                            BMCWEB_REDFISH_MANAGER_URI_NAME);
9851476687dSEd Tanous     asyncResp->res.jsonValue["Members"] = std::move(members);
98696153bdeSMyung Bae }
98796153bdeSMyung Bae 
98896153bdeSMyung Bae inline void requestRoutesManager(App& app)
98996153bdeSMyung Bae {
99096153bdeSMyung Bae     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/")
99196153bdeSMyung Bae         .privileges(redfish::privileges::getManager)
99296153bdeSMyung Bae         .methods(boost::beast::http::verb::get)(
99396153bdeSMyung Bae             std::bind_front(handleManagerGet, std::ref(app)));
99496153bdeSMyung Bae 
99596153bdeSMyung Bae     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/")
99696153bdeSMyung Bae         .privileges(redfish::privileges::patchManager)
99796153bdeSMyung Bae         .methods(boost::beast::http::verb::patch)(
99896153bdeSMyung Bae             std::bind_front(handleManagerPatch, std::ref(app)));
99996153bdeSMyung Bae 
100096153bdeSMyung Bae     BMCWEB_ROUTE(app, "/redfish/v1/Managers/")
100196153bdeSMyung Bae         .privileges(redfish::privileges::getManagerCollection)
100296153bdeSMyung Bae         .methods(boost::beast::http::verb::get)(
100396153bdeSMyung Bae             std::bind_front(handleManagerCollectionGet, std::ref(app)));
10049c310685SBorawski.Lukasz }
100564acd268SMyung Bae 
100664acd268SMyung Bae inline void requestRoutesManagerResetAction(App& app)
100764acd268SMyung Bae {
100864acd268SMyung Bae     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/Actions/Manager.Reset/")
100964acd268SMyung Bae         .privileges(redfish::privileges::postManager)
101064acd268SMyung Bae         .methods(boost::beast::http::verb::post)(
101164acd268SMyung Bae             std::bind_front(handleManagerResetAction, std::ref(app)));
101264acd268SMyung Bae 
101364acd268SMyung Bae     BMCWEB_ROUTE(app,
101464acd268SMyung Bae                  "/redfish/v1/Managers/<str>/Actions/Manager.ResetToDefaults/")
101564acd268SMyung Bae         .privileges(redfish::privileges::postManager)
101664acd268SMyung Bae         .methods(boost::beast::http::verb::post)(
101764acd268SMyung Bae             std::bind_front(handleManagerResetToDefaultsAction, std::ref(app)));
101864acd268SMyung Bae 
101964acd268SMyung Bae     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/ResetActionInfo/")
102064acd268SMyung Bae         .privileges(redfish::privileges::getActionInfo)
102164acd268SMyung Bae         .methods(boost::beast::http::verb::get)(
102264acd268SMyung Bae             std::bind_front(handleManagerResetActionInfo, std::ref(app)));
102364acd268SMyung Bae }
102464acd268SMyung Bae 
10259c310685SBorawski.Lukasz } // namespace redfish
1026