xref: /openbmc/bmcweb/features/redfish/lib/chassis.hpp (revision fc903b3d9b6b61a6b215aabf4ae68408c04787ef)
1e37f8451SRapkiewicz, Pawel /*
2e37f8451SRapkiewicz, Pawel // Copyright (c) 2018 Intel Corporation
3e37f8451SRapkiewicz, Pawel //
4e37f8451SRapkiewicz, Pawel // Licensed under the Apache License, Version 2.0 (the "License");
5e37f8451SRapkiewicz, Pawel // you may not use this file except in compliance with the License.
6e37f8451SRapkiewicz, Pawel // You may obtain a copy of the License at
7e37f8451SRapkiewicz, Pawel //
8e37f8451SRapkiewicz, Pawel //      http://www.apache.org/licenses/LICENSE-2.0
9e37f8451SRapkiewicz, Pawel //
10e37f8451SRapkiewicz, Pawel // Unless required by applicable law or agreed to in writing, software
11e37f8451SRapkiewicz, Pawel // distributed under the License is distributed on an "AS IS" BASIS,
12e37f8451SRapkiewicz, Pawel // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e37f8451SRapkiewicz, Pawel // See the License for the specific language governing permissions and
14e37f8451SRapkiewicz, Pawel // limitations under the License.
15e37f8451SRapkiewicz, Pawel */
16e37f8451SRapkiewicz, Pawel #pragma once
17e37f8451SRapkiewicz, Pawel 
1813451e39SWilly Tu #include "bmcweb_config.h"
1913451e39SWilly Tu 
203ccb3adbSEd Tanous #include "app.hpp"
217a1dbc48SGeorge Liu #include "dbus_utility.hpp"
22b49ac873SJames Feist #include "health.hpp"
231c8fba97SJames Feist #include "led.hpp"
243ccb3adbSEd Tanous #include "query.hpp"
253ccb3adbSEd Tanous #include "registries/privilege_registry.hpp"
263ccb3adbSEd Tanous #include "utils/collection.hpp"
273ccb3adbSEd Tanous #include "utils/dbus_utils.hpp"
28cf7eba09SNan Zhou #include "utils/json_utils.hpp"
291abe55efSEd Tanous 
30e99073f5SGeorge Liu #include <boost/system/error_code.hpp>
31ef4c65b7SEd Tanous #include <boost/url/format.hpp>
321e1e598dSJonathan Doman #include <sdbusplus/asio/property.hpp>
33*fc903b3dSAndrew Geissler #include <sdbusplus/message.hpp>
3486d89ed7SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp>
351214b7e7SGunnar Mills 
367a1dbc48SGeorge Liu #include <array>
377a1dbc48SGeorge Liu #include <string_view>
387a1dbc48SGeorge Liu 
391abe55efSEd Tanous namespace redfish
401abe55efSEd Tanous {
41e37f8451SRapkiewicz, Pawel 
42e37f8451SRapkiewicz, Pawel /**
43beeca0aeSGunnar Mills  * @brief Retrieves chassis state properties over dbus
44beeca0aeSGunnar Mills  *
45beeca0aeSGunnar Mills  * @param[in] aResp - Shared pointer for completing asynchronous calls.
46beeca0aeSGunnar Mills  *
47beeca0aeSGunnar Mills  * @return None.
48beeca0aeSGunnar Mills  */
498d1b46d7Szhanghch05 inline void getChassisState(std::shared_ptr<bmcweb::AsyncResp> aResp)
50beeca0aeSGunnar Mills {
511e1e598dSJonathan Doman     // crow::connections::systemBus->async_method_call(
521e1e598dSJonathan Doman     sdbusplus::asio::getProperty<std::string>(
531e1e598dSJonathan Doman         *crow::connections::systemBus, "xyz.openbmc_project.State.Chassis",
541e1e598dSJonathan Doman         "/xyz/openbmc_project/state/chassis0",
551e1e598dSJonathan Doman         "xyz.openbmc_project.State.Chassis", "CurrentPowerState",
565e7e2dc5SEd Tanous         [aResp{std::move(aResp)}](const boost::system::error_code& ec,
571e1e598dSJonathan Doman                                   const std::string& chassisState) {
58beeca0aeSGunnar Mills         if (ec)
59beeca0aeSGunnar Mills         {
60a6e5e0abSCarson Labrado             if (ec == boost::system::errc::host_unreachable)
61a6e5e0abSCarson Labrado             {
62a6e5e0abSCarson Labrado                 // Service not available, no error, just don't return
63a6e5e0abSCarson Labrado                 // chassis state info
64a6e5e0abSCarson Labrado                 BMCWEB_LOG_DEBUG << "Service not available " << ec;
65a6e5e0abSCarson Labrado                 return;
66a6e5e0abSCarson Labrado             }
6751dab2a7SAndrew Geissler             BMCWEB_LOG_ERROR << "DBUS response error " << ec;
68beeca0aeSGunnar Mills             messages::internalError(aResp->res);
69beeca0aeSGunnar Mills             return;
70beeca0aeSGunnar Mills         }
71beeca0aeSGunnar Mills 
721e1e598dSJonathan Doman         BMCWEB_LOG_DEBUG << "Chassis state: " << chassisState;
73beeca0aeSGunnar Mills         // Verify Chassis State
74002d39b4SEd Tanous         if (chassisState == "xyz.openbmc_project.State.Chassis.PowerState.On")
75beeca0aeSGunnar Mills         {
76beeca0aeSGunnar Mills             aResp->res.jsonValue["PowerState"] = "On";
77beeca0aeSGunnar Mills             aResp->res.jsonValue["Status"]["State"] = "Enabled";
78beeca0aeSGunnar Mills         }
791e1e598dSJonathan Doman         else if (chassisState ==
80beeca0aeSGunnar Mills                  "xyz.openbmc_project.State.Chassis.PowerState.Off")
81beeca0aeSGunnar Mills         {
82beeca0aeSGunnar Mills             aResp->res.jsonValue["PowerState"] = "Off";
83beeca0aeSGunnar Mills             aResp->res.jsonValue["Status"]["State"] = "StandbyOffline";
84beeca0aeSGunnar Mills         }
851e1e598dSJonathan Doman         });
86beeca0aeSGunnar Mills }
87beeca0aeSGunnar Mills 
888d1b46d7Szhanghch05 inline void getIntrusionByService(std::shared_ptr<bmcweb::AsyncResp> aResp,
89c181942fSQiang XU                                   const std::string& service,
90c181942fSQiang XU                                   const std::string& objPath)
91c181942fSQiang XU {
92c181942fSQiang XU     BMCWEB_LOG_DEBUG << "Get intrusion status by service \n";
93c181942fSQiang XU 
941e1e598dSJonathan Doman     sdbusplus::asio::getProperty<std::string>(
951e1e598dSJonathan Doman         *crow::connections::systemBus, service, objPath,
961e1e598dSJonathan Doman         "xyz.openbmc_project.Chassis.Intrusion", "Status",
975e7e2dc5SEd Tanous         [aResp{std::move(aResp)}](const boost::system::error_code& ec,
981e1e598dSJonathan Doman                                   const std::string& value) {
99c181942fSQiang XU         if (ec)
100c181942fSQiang XU         {
1014e0453b1SGunnar Mills             // do not add err msg in redfish response, because this is not
102c181942fSQiang XU             //     mandatory property
103c181942fSQiang XU             BMCWEB_LOG_ERROR << "DBUS response error " << ec << "\n";
104c181942fSQiang XU             return;
105c181942fSQiang XU         }
106c181942fSQiang XU 
107002d39b4SEd Tanous         aResp->res.jsonValue["PhysicalSecurity"]["IntrusionSensorNumber"] = 1;
1081476687dSEd Tanous         aResp->res.jsonValue["PhysicalSecurity"]["IntrusionSensor"] = value;
1091e1e598dSJonathan Doman         });
110c181942fSQiang XU }
111c181942fSQiang XU 
112c181942fSQiang XU /**
113c181942fSQiang XU  * Retrieves physical security properties over dbus
114c181942fSQiang XU  */
1158d1b46d7Szhanghch05 inline void getPhysicalSecurityData(std::shared_ptr<bmcweb::AsyncResp> aResp)
116c181942fSQiang XU {
117e99073f5SGeorge Liu     constexpr std::array<std::string_view, 1> interfaces = {
118e99073f5SGeorge Liu         "xyz.openbmc_project.Chassis.Intrusion"};
119e99073f5SGeorge Liu     dbus::utility::getSubTree(
120e99073f5SGeorge Liu         "/xyz/openbmc_project/Intrusion", 1, interfaces,
121c181942fSQiang XU         [aResp{std::move(aResp)}](
122e99073f5SGeorge Liu             const boost::system::error_code& ec,
123b9d36b47SEd Tanous             const dbus::utility::MapperGetSubTreeResponse& subtree) {
124c181942fSQiang XU         if (ec)
125c181942fSQiang XU         {
1264e0453b1SGunnar Mills             // do not add err msg in redfish response, because this is not
127c181942fSQiang XU             //     mandatory property
128002d39b4SEd Tanous             BMCWEB_LOG_INFO << "DBUS error: no matched iface " << ec << "\n";
129c181942fSQiang XU             return;
130c181942fSQiang XU         }
131c181942fSQiang XU         // Iterate over all retrieved ObjectPaths.
132c181942fSQiang XU         for (const auto& object : subtree)
133c181942fSQiang XU         {
134840a9ffcSPatrick Williams             if (!object.second.empty())
135c181942fSQiang XU             {
136840a9ffcSPatrick Williams                 const auto service = object.second.front();
137c181942fSQiang XU                 getIntrusionByService(aResp, service.first, object.first);
138c181942fSQiang XU                 return;
139c181942fSQiang XU             }
140c181942fSQiang XU         }
141e99073f5SGeorge Liu         });
142c181942fSQiang XU }
143c181942fSQiang XU 
144cf7eba09SNan Zhou inline void handleChassisCollectionGet(
145cf7eba09SNan Zhou     App& app, const crow::Request& req,
146cf7eba09SNan Zhou     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1471abe55efSEd Tanous {
1483ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
14945ca1b86SEd Tanous     {
15045ca1b86SEd Tanous         return;
15145ca1b86SEd Tanous     }
1528d1b46d7Szhanghch05     asyncResp->res.jsonValue["@odata.type"] =
1538d1b46d7Szhanghch05         "#ChassisCollection.ChassisCollection";
1548d1b46d7Szhanghch05     asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Chassis";
1558d1b46d7Szhanghch05     asyncResp->res.jsonValue["Name"] = "Chassis Collection";
156e37f8451SRapkiewicz, Pawel 
1577a1dbc48SGeorge Liu     constexpr std::array<std::string_view, 2> interfaces{
1587a1dbc48SGeorge Liu         "xyz.openbmc_project.Inventory.Item.Board",
1597a1dbc48SGeorge Liu         "xyz.openbmc_project.Inventory.Item.Chassis"};
16002f6ff19SGunnar Mills     collection_util::getCollectionMembers(
1617a1dbc48SGeorge Liu         asyncResp, boost::urls::url("/redfish/v1/Chassis"), interfaces);
162cf7eba09SNan Zhou }
163cf7eba09SNan Zhou 
164cf7eba09SNan Zhou /**
165cf7eba09SNan Zhou  * ChassisCollection derived class for delivering Chassis Collection Schema
166cf7eba09SNan Zhou  *  Functions triggers appropriate requests on DBus
167cf7eba09SNan Zhou  */
168cf7eba09SNan Zhou inline void requestRoutesChassisCollection(App& app)
169cf7eba09SNan Zhou {
170cf7eba09SNan Zhou     BMCWEB_ROUTE(app, "/redfish/v1/Chassis/")
171cf7eba09SNan Zhou         .privileges(redfish::privileges::getChassisCollection)
172cf7eba09SNan Zhou         .methods(boost::beast::http::verb::get)(
173cf7eba09SNan Zhou             std::bind_front(handleChassisCollectionGet, std::ref(app)));
17462d5e2e4SEd Tanous }
175e37f8451SRapkiewicz, Pawel 
176308f70c7SWilly Tu inline void
177308f70c7SWilly Tu     getChassisLocationCode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
178308f70c7SWilly Tu                            const std::string& connectionName,
179308f70c7SWilly Tu                            const std::string& path)
180308f70c7SWilly Tu {
1811e1e598dSJonathan Doman     sdbusplus::asio::getProperty<std::string>(
1821e1e598dSJonathan Doman         *crow::connections::systemBus, connectionName, path,
1831e1e598dSJonathan Doman         "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode",
1845e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec,
1851e1e598dSJonathan Doman                     const std::string& property) {
186308f70c7SWilly Tu         if (ec)
187308f70c7SWilly Tu         {
18851dab2a7SAndrew Geissler             BMCWEB_LOG_ERROR << "DBUS response error for Location";
189308f70c7SWilly Tu             messages::internalError(asyncResp->res);
190308f70c7SWilly Tu             return;
191308f70c7SWilly Tu         }
192308f70c7SWilly Tu 
193002d39b4SEd Tanous         asyncResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
1941e1e598dSJonathan Doman             property;
1951e1e598dSJonathan Doman         });
196308f70c7SWilly Tu }
197308f70c7SWilly Tu 
198308f70c7SWilly Tu inline void getChassisUUID(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
199308f70c7SWilly Tu                            const std::string& connectionName,
200308f70c7SWilly Tu                            const std::string& path)
201308f70c7SWilly Tu {
2021e1e598dSJonathan Doman     sdbusplus::asio::getProperty<std::string>(
2031e1e598dSJonathan Doman         *crow::connections::systemBus, connectionName, path,
2041e1e598dSJonathan Doman         "xyz.openbmc_project.Common.UUID", "UUID",
2055e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec,
2061e1e598dSJonathan Doman                     const std::string& chassisUUID) {
207308f70c7SWilly Tu         if (ec)
208308f70c7SWilly Tu         {
20951dab2a7SAndrew Geissler             BMCWEB_LOG_ERROR << "DBUS response error for UUID";
210308f70c7SWilly Tu             messages::internalError(asyncResp->res);
211308f70c7SWilly Tu             return;
212308f70c7SWilly Tu         }
2131e1e598dSJonathan Doman         asyncResp->res.jsonValue["UUID"] = chassisUUID;
2141e1e598dSJonathan Doman         });
215308f70c7SWilly Tu }
216308f70c7SWilly Tu 
217cf7eba09SNan Zhou inline void
218cf7eba09SNan Zhou     handleChassisGet(App& app, const crow::Request& req,
21945ca1b86SEd Tanous                      const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
220cf7eba09SNan Zhou                      const std::string& chassisId)
221cf7eba09SNan Zhou {
2223ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
22345ca1b86SEd Tanous     {
22445ca1b86SEd Tanous         return;
22545ca1b86SEd Tanous     }
226e99073f5SGeorge Liu     constexpr std::array<std::string_view, 2> interfaces = {
227734bfe90SGunnar Mills         "xyz.openbmc_project.Inventory.Item.Board",
228adc4f0dbSShawn McCarney         "xyz.openbmc_project.Inventory.Item.Chassis"};
229734bfe90SGunnar Mills 
230e99073f5SGeorge Liu     dbus::utility::getSubTree(
231e99073f5SGeorge Liu         "/xyz/openbmc_project/inventory", 0, interfaces,
23262d5e2e4SEd Tanous         [asyncResp, chassisId(std::string(chassisId))](
233e99073f5SGeorge Liu             const boost::system::error_code& ec,
234b9d36b47SEd Tanous             const dbus::utility::MapperGetSubTreeResponse& subtree) {
23562d5e2e4SEd Tanous         if (ec)
2361abe55efSEd Tanous         {
23751dab2a7SAndrew Geissler             BMCWEB_LOG_ERROR << "DBUS response error " << ec;
238f12894f8SJason M. Bills             messages::internalError(asyncResp->res);
239daf36e2eSEd Tanous             return;
240daf36e2eSEd Tanous         }
241daf36e2eSEd Tanous         // Iterate over all retrieved ObjectPaths.
242cf7eba09SNan Zhou         for (const std::pair<
243cf7eba09SNan Zhou                  std::string,
244cf7eba09SNan Zhou                  std::vector<std::pair<std::string, std::vector<std::string>>>>&
2451214b7e7SGunnar Mills                  object : subtree)
2461abe55efSEd Tanous         {
247daf36e2eSEd Tanous             const std::string& path = object.first;
248cf7eba09SNan Zhou             const std::vector<std::pair<std::string, std::vector<std::string>>>&
2491214b7e7SGunnar Mills                 connectionNames = object.second;
2507e860f15SJohn Edward Broadbent 
251997093ebSGeorge Liu             sdbusplus::message::object_path objPath(path);
252997093ebSGeorge Liu             if (objPath.filename() != chassisId)
2531abe55efSEd Tanous             {
254daf36e2eSEd Tanous                 continue;
255daf36e2eSEd Tanous             }
25626f03899SShawn McCarney 
257002d39b4SEd Tanous             auto health = std::make_shared<HealthPopulate>(asyncResp);
258b49ac873SJames Feist 
25913451e39SWilly Tu             if constexpr (bmcwebEnableHealthPopulate)
26013451e39SWilly Tu             {
2616c3e9451SGeorge Liu                 dbus::utility::getAssociationEndPoints(
2626c3e9451SGeorge Liu                     path + "/all_sensors",
2635e7e2dc5SEd Tanous                     [health](const boost::system::error_code& ec2,
2646c3e9451SGeorge Liu                              const dbus::utility::MapperEndPoints& resp) {
26523a21a1cSEd Tanous                     if (ec2)
266b49ac873SJames Feist                     {
267b49ac873SJames Feist                         return; // no sensors = no failures
268b49ac873SJames Feist                     }
2691e1e598dSJonathan Doman                     health->inventory = resp;
2701e1e598dSJonathan Doman                     });
271b49ac873SJames Feist 
272b49ac873SJames Feist                 health->populate();
27313451e39SWilly Tu             }
274b49ac873SJames Feist 
27526f6976fSEd Tanous             if (connectionNames.empty())
2761abe55efSEd Tanous             {
2771c8fba97SJames Feist                 BMCWEB_LOG_ERROR << "Got 0 Connection names";
278e0d918bcSEd Tanous                 continue;
279daf36e2eSEd Tanous             }
280e0d918bcSEd Tanous 
28149c53ac9SJohnathan Mantey             asyncResp->res.jsonValue["@odata.type"] =
282523d4868SLogananth Sundararaj                 "#Chassis.v1_22_0.Chassis";
28349c53ac9SJohnathan Mantey             asyncResp->res.jsonValue["@odata.id"] =
284ef4c65b7SEd Tanous                 boost::urls::format("/redfish/v1/Chassis/{}", chassisId);
28549c53ac9SJohnathan Mantey             asyncResp->res.jsonValue["Name"] = "Chassis Collection";
28649c53ac9SJohnathan Mantey             asyncResp->res.jsonValue["ChassisType"] = "RackMount";
287cf7eba09SNan Zhou             asyncResp->res.jsonValue["Actions"]["#Chassis.Reset"]["target"] =
288ef4c65b7SEd Tanous                 boost::urls::format(
289ef4c65b7SEd Tanous                     "/redfish/v1/Chassis/{}/Actions/Chassis.Reset", chassisId);
2901476687dSEd Tanous             asyncResp->res
291cf7eba09SNan Zhou                 .jsonValue["Actions"]["#Chassis.Reset"]["@Redfish.ActionInfo"] =
292ef4c65b7SEd Tanous                 boost::urls::format("/redfish/v1/Chassis/{}/ResetActionInfo",
293ef4c65b7SEd Tanous                                     chassisId);
2941476687dSEd Tanous             asyncResp->res.jsonValue["PCIeDevices"]["@odata.id"] =
295ef4c65b7SEd Tanous                 "/redfish/v1/Systems/system/PCIeDevices";
29649c53ac9SJohnathan Mantey 
2976c3e9451SGeorge Liu             dbus::utility::getAssociationEndPoints(
2986c3e9451SGeorge Liu                 path + "/drive",
2996c3e9451SGeorge Liu                 [asyncResp,
3006c3e9451SGeorge Liu                  chassisId](const boost::system::error_code& ec3,
3016c3e9451SGeorge Liu                             const dbus::utility::MapperEndPoints& resp) {
30292903bd4SJohn Edward Broadbent                 if (ec3 || resp.empty())
30392903bd4SJohn Edward Broadbent                 {
30492903bd4SJohn Edward Broadbent                     return; // no drives = no failures
30592903bd4SJohn Edward Broadbent                 }
30692903bd4SJohn Edward Broadbent 
30792903bd4SJohn Edward Broadbent                 nlohmann::json reference;
308ef4c65b7SEd Tanous                 reference["@odata.id"] = boost::urls::format(
309ef4c65b7SEd Tanous                     "/redfish/v1/Chassis/{}/Drives", chassisId);
31092903bd4SJohn Edward Broadbent                 asyncResp->res.jsonValue["Drives"] = std::move(reference);
31192903bd4SJohn Edward Broadbent                 });
31292903bd4SJohn Edward Broadbent 
313002d39b4SEd Tanous             const std::string& connectionName = connectionNames[0].first;
3141c8fba97SJames Feist 
31523a21a1cSEd Tanous             const std::vector<std::string>& interfaces2 =
3161c8fba97SJames Feist                 connectionNames[0].second;
3171c8fba97SJames Feist             const std::array<const char*, 2> hasIndicatorLed = {
3181c8fba97SJames Feist                 "xyz.openbmc_project.Inventory.Item.Panel",
3190fda0f12SGeorge Liu                 "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
3201c8fba97SJames Feist 
321476b9cc5STejas Patil             const std::string assetTagInterface =
3220fda0f12SGeorge Liu                 "xyz.openbmc_project.Inventory.Decorator.AssetTag";
323523d4868SLogananth Sundararaj             const std::string replaceableInterface =
324523d4868SLogananth Sundararaj                 "xyz.openbmc_project.Inventory.Decorator.Replaceable";
325523d4868SLogananth Sundararaj             for (const auto& interface : interfaces2)
326523d4868SLogananth Sundararaj             {
327523d4868SLogananth Sundararaj                 if (interface == assetTagInterface)
328476b9cc5STejas Patil                 {
3291e1e598dSJonathan Doman                     sdbusplus::asio::getProperty<std::string>(
330002d39b4SEd Tanous                         *crow::connections::systemBus, connectionName, path,
331002d39b4SEd Tanous                         assetTagInterface, "AssetTag",
332523d4868SLogananth Sundararaj                         [asyncResp,
333523d4868SLogananth Sundararaj                          chassisId](const boost::system::error_code& ec2,
3341e1e598dSJonathan Doman                                     const std::string& property) {
3358a592810SEd Tanous                         if (ec2)
336476b9cc5STejas Patil                         {
337523d4868SLogananth Sundararaj                             BMCWEB_LOG_ERROR
338523d4868SLogananth Sundararaj                                 << "DBus response error for AssetTag: " << ec2;
339476b9cc5STejas Patil                             messages::internalError(asyncResp->res);
340476b9cc5STejas Patil                             return;
341476b9cc5STejas Patil                         }
342002d39b4SEd Tanous                         asyncResp->res.jsonValue["AssetTag"] = property;
3431e1e598dSJonathan Doman                         });
344476b9cc5STejas Patil                 }
345523d4868SLogananth Sundararaj                 else if (interface == replaceableInterface)
346523d4868SLogananth Sundararaj                 {
347523d4868SLogananth Sundararaj                     sdbusplus::asio::getProperty<bool>(
348523d4868SLogananth Sundararaj                         *crow::connections::systemBus, connectionName, path,
349523d4868SLogananth Sundararaj                         replaceableInterface, "HotPluggable",
350523d4868SLogananth Sundararaj                         [asyncResp,
351523d4868SLogananth Sundararaj                          chassisId](const boost::system::error_code& ec2,
352523d4868SLogananth Sundararaj                                     const bool property) {
353523d4868SLogananth Sundararaj                         if (ec2)
354523d4868SLogananth Sundararaj                         {
355523d4868SLogananth Sundararaj                             BMCWEB_LOG_ERROR
356523d4868SLogananth Sundararaj                                 << "DBus response error for HotPluggable: "
357523d4868SLogananth Sundararaj                                 << ec2;
358523d4868SLogananth Sundararaj                             messages::internalError(asyncResp->res);
359523d4868SLogananth Sundararaj                             return;
360523d4868SLogananth Sundararaj                         }
361523d4868SLogananth Sundararaj                         asyncResp->res.jsonValue["HotPluggable"] = property;
362523d4868SLogananth Sundararaj                         });
363523d4868SLogananth Sundararaj                 }
364523d4868SLogananth Sundararaj             }
365476b9cc5STejas Patil 
3661c8fba97SJames Feist             for (const char* interface : hasIndicatorLed)
3671c8fba97SJames Feist             {
368002d39b4SEd Tanous                 if (std::find(interfaces2.begin(), interfaces2.end(),
36923a21a1cSEd Tanous                               interface) != interfaces2.end())
3701c8fba97SJames Feist                 {
3711c8fba97SJames Feist                     getIndicatorLedState(asyncResp);
3729f8bfa7cSGunnar Mills                     getLocationIndicatorActive(asyncResp);
3731c8fba97SJames Feist                     break;
3741c8fba97SJames Feist                 }
3751c8fba97SJames Feist             }
3761c8fba97SJames Feist 
37786d89ed7SKrzysztof Grobelny             sdbusplus::asio::getAllProperties(
37886d89ed7SKrzysztof Grobelny                 *crow::connections::systemBus, connectionName, path,
37986d89ed7SKrzysztof Grobelny                 "xyz.openbmc_project.Inventory.Decorator.Asset",
38062d5e2e4SEd Tanous                 [asyncResp, chassisId(std::string(chassisId))](
3815e7e2dc5SEd Tanous                     const boost::system::error_code& /*ec2*/,
382cf7eba09SNan Zhou                     const dbus::utility::DBusPropertiesMap& propertiesList) {
38386d89ed7SKrzysztof Grobelny                 const std::string* partNumber = nullptr;
38486d89ed7SKrzysztof Grobelny                 const std::string* serialNumber = nullptr;
38586d89ed7SKrzysztof Grobelny                 const std::string* manufacturer = nullptr;
38686d89ed7SKrzysztof Grobelny                 const std::string* model = nullptr;
38786d89ed7SKrzysztof Grobelny                 const std::string* sparePartNumber = nullptr;
38886d89ed7SKrzysztof Grobelny 
38986d89ed7SKrzysztof Grobelny                 const bool success = sdbusplus::unpackPropertiesNoThrow(
39086d89ed7SKrzysztof Grobelny                     dbus_utils::UnpackErrorPrinter(), propertiesList,
39186d89ed7SKrzysztof Grobelny                     "PartNumber", partNumber, "SerialNumber", serialNumber,
39286d89ed7SKrzysztof Grobelny                     "Manufacturer", manufacturer, "Model", model,
39386d89ed7SKrzysztof Grobelny                     "SparePartNumber", sparePartNumber);
39486d89ed7SKrzysztof Grobelny 
39586d89ed7SKrzysztof Grobelny                 if (!success)
3961abe55efSEd Tanous                 {
397002d39b4SEd Tanous                     messages::internalError(asyncResp->res);
398caa11f7aSAlpana Kumari                     return;
399daf36e2eSEd Tanous                 }
40086d89ed7SKrzysztof Grobelny 
40186d89ed7SKrzysztof Grobelny                 if (partNumber != nullptr)
40286d89ed7SKrzysztof Grobelny                 {
40386d89ed7SKrzysztof Grobelny                     asyncResp->res.jsonValue["PartNumber"] = *partNumber;
40486d89ed7SKrzysztof Grobelny                 }
40586d89ed7SKrzysztof Grobelny 
40686d89ed7SKrzysztof Grobelny                 if (serialNumber != nullptr)
40786d89ed7SKrzysztof Grobelny                 {
40886d89ed7SKrzysztof Grobelny                     asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
40986d89ed7SKrzysztof Grobelny                 }
41086d89ed7SKrzysztof Grobelny 
41186d89ed7SKrzysztof Grobelny                 if (manufacturer != nullptr)
41286d89ed7SKrzysztof Grobelny                 {
41386d89ed7SKrzysztof Grobelny                     asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
41486d89ed7SKrzysztof Grobelny                 }
41586d89ed7SKrzysztof Grobelny 
41686d89ed7SKrzysztof Grobelny                 if (model != nullptr)
41786d89ed7SKrzysztof Grobelny                 {
41886d89ed7SKrzysztof Grobelny                     asyncResp->res.jsonValue["Model"] = *model;
41986d89ed7SKrzysztof Grobelny                 }
42086d89ed7SKrzysztof Grobelny 
421caa11f7aSAlpana Kumari                 // SparePartNumber is optional on D-Bus
422caa11f7aSAlpana Kumari                 // so skip if it is empty
42386d89ed7SKrzysztof Grobelny                 if (sparePartNumber != nullptr && !sparePartNumber->empty())
424caa11f7aSAlpana Kumari                 {
42586d89ed7SKrzysztof Grobelny                     asyncResp->res.jsonValue["SparePartNumber"] =
42686d89ed7SKrzysztof Grobelny                         *sparePartNumber;
427caa11f7aSAlpana Kumari                 }
42886d89ed7SKrzysztof Grobelny 
42962d5e2e4SEd Tanous                 asyncResp->res.jsonValue["Name"] = chassisId;
43062d5e2e4SEd Tanous                 asyncResp->res.jsonValue["Id"] = chassisId;
4310256b694Szhanghch05 #ifdef BMCWEB_ALLOW_DEPRECATED_POWER_THERMAL
432002d39b4SEd Tanous                 asyncResp->res.jsonValue["Thermal"]["@odata.id"] =
433ef4c65b7SEd Tanous                     boost::urls::format("/redfish/v1/Chassis/{}/Thermal",
434ef4c65b7SEd Tanous                                         chassisId);
4352474adfaSEd Tanous                 // Power object
4361476687dSEd Tanous                 asyncResp->res.jsonValue["Power"]["@odata.id"] =
437ef4c65b7SEd Tanous                     boost::urls::format("/redfish/v1/Chassis/{}/Power",
438ef4c65b7SEd Tanous                                         chassisId);
4390256b694Szhanghch05 #endif
4402973963eSXiaochao Ma #ifdef BMCWEB_NEW_POWERSUBSYSTEM_THERMALSUBSYSTEM
4412973963eSXiaochao Ma                 asyncResp->res.jsonValue["ThermalSubsystem"]["@odata.id"] =
442ef4c65b7SEd Tanous                     boost::urls::format(
443ef4c65b7SEd Tanous                         "/redfish/v1/Chassis/{}/ThermalSubsystem", chassisId);
44477b36437SChicago Duan                 asyncResp->res.jsonValue["PowerSubsystem"]["@odata.id"] =
445ef4c65b7SEd Tanous                     boost::urls::format("/redfish/v1/Chassis/{}/PowerSubsystem",
446ef4c65b7SEd Tanous                                         chassisId);
4474ca3ec3cSAlbert Zhang                 asyncResp->res.jsonValue["EnvironmentMetrics"]["@odata.id"] =
448ef4c65b7SEd Tanous                     boost::urls::format(
449ef4c65b7SEd Tanous                         "/redfish/v1/Chassis/{}/EnvironmentMetrics", chassisId);
4502973963eSXiaochao Ma #endif
45195a3ecadSAnthony Wilson                 // SensorCollection
452002d39b4SEd Tanous                 asyncResp->res.jsonValue["Sensors"]["@odata.id"] =
453ef4c65b7SEd Tanous                     boost::urls::format("/redfish/v1/Chassis/{}/Sensors",
454ef4c65b7SEd Tanous                                         chassisId);
455002d39b4SEd Tanous                 asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
4561476687dSEd Tanous 
4571476687dSEd Tanous                 nlohmann::json::array_t computerSystems;
4581476687dSEd Tanous                 nlohmann::json::object_t system;
459002d39b4SEd Tanous                 system["@odata.id"] = "/redfish/v1/Systems/system";
460ad539545SPatrick Williams                 computerSystems.emplace_back(std::move(system));
461002d39b4SEd Tanous                 asyncResp->res.jsonValue["Links"]["ComputerSystems"] =
4621476687dSEd Tanous                     std::move(computerSystems);
4631476687dSEd Tanous 
4641476687dSEd Tanous                 nlohmann::json::array_t managedBy;
4651476687dSEd Tanous                 nlohmann::json::object_t manager;
466002d39b4SEd Tanous                 manager["@odata.id"] = "/redfish/v1/Managers/bmc";
467ad539545SPatrick Williams                 managedBy.emplace_back(std::move(manager));
4687e860f15SJohn Edward Broadbent                 asyncResp->res.jsonValue["Links"]["ManagedBy"] =
4691476687dSEd Tanous                     std::move(managedBy);
470beeca0aeSGunnar Mills                 getChassisState(asyncResp);
47186d89ed7SKrzysztof Grobelny                 });
4722c37b4b0SSharad Yadav 
473308f70c7SWilly Tu             for (const auto& interface : interfaces2)
4742c37b4b0SSharad Yadav             {
475308f70c7SWilly Tu                 if (interface == "xyz.openbmc_project.Common.UUID")
4762c37b4b0SSharad Yadav                 {
477308f70c7SWilly Tu                     getChassisUUID(asyncResp, connectionName, path);
4782c37b4b0SSharad Yadav                 }
479cf7eba09SNan Zhou                 else if (interface ==
4800fda0f12SGeorge Liu                          "xyz.openbmc_project.Inventory.Decorator.LocationCode")
4812c37b4b0SSharad Yadav                 {
482002d39b4SEd Tanous                     getChassisLocationCode(asyncResp, connectionName, path);
4832c37b4b0SSharad Yadav                 }
4842c37b4b0SSharad Yadav             }
4852c37b4b0SSharad Yadav 
486daf36e2eSEd Tanous             return;
487daf36e2eSEd Tanous         }
488e0d918bcSEd Tanous 
489daf36e2eSEd Tanous         // Couldn't find an object with that name.  return an error
490d8a5d5d8SJiaqing Zhao         messages::resourceNotFound(asyncResp->res, "Chassis", chassisId);
491e99073f5SGeorge Liu         });
492c181942fSQiang XU 
493c181942fSQiang XU     getPhysicalSecurityData(asyncResp);
494cf7eba09SNan Zhou }
4951c8fba97SJames Feist 
496cf7eba09SNan Zhou inline void
497cf7eba09SNan Zhou     handleChassisPatch(App& app, const crow::Request& req,
4987e860f15SJohn Edward Broadbent                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
499cf7eba09SNan Zhou                        const std::string& param)
500cf7eba09SNan Zhou {
5013ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
50245ca1b86SEd Tanous     {
50345ca1b86SEd Tanous         return;
50445ca1b86SEd Tanous     }
5059f8bfa7cSGunnar Mills     std::optional<bool> locationIndicatorActive;
5061c8fba97SJames Feist     std::optional<std::string> indicatorLed;
5071c8fba97SJames Feist 
5087e860f15SJohn Edward Broadbent     if (param.empty())
5091c8fba97SJames Feist     {
5101c8fba97SJames Feist         return;
5111c8fba97SJames Feist     }
5121c8fba97SJames Feist 
51315ed6780SWilly Tu     if (!json_util::readJsonPatch(
5147e860f15SJohn Edward Broadbent             req, asyncResp->res, "LocationIndicatorActive",
5157e860f15SJohn Edward Broadbent             locationIndicatorActive, "IndicatorLED", indicatorLed))
5161c8fba97SJames Feist     {
5171c8fba97SJames Feist         return;
5181c8fba97SJames Feist     }
5191c8fba97SJames Feist 
5209f8bfa7cSGunnar Mills     // TODO (Gunnar): Remove IndicatorLED after enough time has passed
5219f8bfa7cSGunnar Mills     if (!locationIndicatorActive && !indicatorLed)
5221c8fba97SJames Feist     {
5231c8fba97SJames Feist         return; // delete this when we support more patch properties
5241c8fba97SJames Feist     }
525d6aa0093SGunnar Mills     if (indicatorLed)
526d6aa0093SGunnar Mills     {
5277e860f15SJohn Edward Broadbent         asyncResp->res.addHeader(
5287e860f15SJohn Edward Broadbent             boost::beast::http::field::warning,
5290fda0f12SGeorge Liu             "299 - \"IndicatorLED is deprecated. Use LocationIndicatorActive instead.\"");
530d6aa0093SGunnar Mills     }
5311c8fba97SJames Feist 
532e99073f5SGeorge Liu     constexpr std::array<std::string_view, 2> interfaces = {
5331c8fba97SJames Feist         "xyz.openbmc_project.Inventory.Item.Board",
5341c8fba97SJames Feist         "xyz.openbmc_project.Inventory.Item.Chassis"};
5351c8fba97SJames Feist 
5367e860f15SJohn Edward Broadbent     const std::string& chassisId = param;
5371c8fba97SJames Feist 
538e99073f5SGeorge Liu     dbus::utility::getSubTree(
539e99073f5SGeorge Liu         "/xyz/openbmc_project/inventory", 0, interfaces,
540cf7eba09SNan Zhou         [asyncResp, chassisId, locationIndicatorActive,
5415e7e2dc5SEd Tanous          indicatorLed](const boost::system::error_code& ec,
542b9d36b47SEd Tanous                        const dbus::utility::MapperGetSubTreeResponse& subtree) {
5431c8fba97SJames Feist         if (ec)
5441c8fba97SJames Feist         {
54551dab2a7SAndrew Geissler             BMCWEB_LOG_ERROR << "DBUS response error " << ec;
5461c8fba97SJames Feist             messages::internalError(asyncResp->res);
5471c8fba97SJames Feist             return;
5481c8fba97SJames Feist         }
5491c8fba97SJames Feist 
5501c8fba97SJames Feist         // Iterate over all retrieved ObjectPaths.
551cf7eba09SNan Zhou         for (const std::pair<
552cf7eba09SNan Zhou                  std::string,
553cf7eba09SNan Zhou                  std::vector<std::pair<std::string, std::vector<std::string>>>>&
5541214b7e7SGunnar Mills                  object : subtree)
5551c8fba97SJames Feist         {
5561c8fba97SJames Feist             const std::string& path = object.first;
557cf7eba09SNan Zhou             const std::vector<std::pair<std::string, std::vector<std::string>>>&
5581214b7e7SGunnar Mills                 connectionNames = object.second;
5591c8fba97SJames Feist 
560997093ebSGeorge Liu             sdbusplus::message::object_path objPath(path);
561997093ebSGeorge Liu             if (objPath.filename() != chassisId)
5621c8fba97SJames Feist             {
5631c8fba97SJames Feist                 continue;
5641c8fba97SJames Feist             }
5651c8fba97SJames Feist 
56626f6976fSEd Tanous             if (connectionNames.empty())
5671c8fba97SJames Feist             {
5681c8fba97SJames Feist                 BMCWEB_LOG_ERROR << "Got 0 Connection names";
5691c8fba97SJames Feist                 continue;
5701c8fba97SJames Feist             }
5711c8fba97SJames Feist 
57223a21a1cSEd Tanous             const std::vector<std::string>& interfaces3 =
5731c8fba97SJames Feist                 connectionNames[0].second;
5741c8fba97SJames Feist 
5751c8fba97SJames Feist             const std::array<const char*, 2> hasIndicatorLed = {
5761c8fba97SJames Feist                 "xyz.openbmc_project.Inventory.Item.Panel",
5770fda0f12SGeorge Liu                 "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
5781c8fba97SJames Feist             bool indicatorChassis = false;
5791c8fba97SJames Feist             for (const char* interface : hasIndicatorLed)
5801c8fba97SJames Feist             {
581002d39b4SEd Tanous                 if (std::find(interfaces3.begin(), interfaces3.end(),
58223a21a1cSEd Tanous                               interface) != interfaces3.end())
5831c8fba97SJames Feist                 {
5841c8fba97SJames Feist                     indicatorChassis = true;
5851c8fba97SJames Feist                     break;
5861c8fba97SJames Feist                 }
5871c8fba97SJames Feist             }
5889f8bfa7cSGunnar Mills             if (locationIndicatorActive)
5899f8bfa7cSGunnar Mills             {
5909f8bfa7cSGunnar Mills                 if (indicatorChassis)
5919f8bfa7cSGunnar Mills                 {
592002d39b4SEd Tanous                     setLocationIndicatorActive(asyncResp,
593002d39b4SEd Tanous                                                *locationIndicatorActive);
5949f8bfa7cSGunnar Mills                 }
5959f8bfa7cSGunnar Mills                 else
5969f8bfa7cSGunnar Mills                 {
597002d39b4SEd Tanous                     messages::propertyUnknown(asyncResp->res,
598002d39b4SEd Tanous                                               "LocationIndicatorActive");
5999f8bfa7cSGunnar Mills                 }
6009f8bfa7cSGunnar Mills             }
6019f8bfa7cSGunnar Mills             if (indicatorLed)
6029f8bfa7cSGunnar Mills             {
6031c8fba97SJames Feist                 if (indicatorChassis)
6041c8fba97SJames Feist                 {
605f23b7296SEd Tanous                     setIndicatorLedState(asyncResp, *indicatorLed);
6061c8fba97SJames Feist                 }
6071c8fba97SJames Feist                 else
6081c8fba97SJames Feist                 {
609cf7eba09SNan Zhou                     messages::propertyUnknown(asyncResp->res, "IndicatorLED");
6101c8fba97SJames Feist                 }
6111c8fba97SJames Feist             }
6121c8fba97SJames Feist             return;
6131c8fba97SJames Feist         }
6141c8fba97SJames Feist 
615d8a5d5d8SJiaqing Zhao         messages::resourceNotFound(asyncResp->res, "Chassis", chassisId);
616e99073f5SGeorge Liu         });
617cf7eba09SNan Zhou }
618cf7eba09SNan Zhou 
619cf7eba09SNan Zhou /**
620cf7eba09SNan Zhou  * Chassis override class for delivering Chassis Schema
621cf7eba09SNan Zhou  * Functions triggers appropriate requests on DBus
622cf7eba09SNan Zhou  */
623cf7eba09SNan Zhou inline void requestRoutesChassis(App& app)
624cf7eba09SNan Zhou {
625cf7eba09SNan Zhou     BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/")
626cf7eba09SNan Zhou         .privileges(redfish::privileges::getChassis)
627cf7eba09SNan Zhou         .methods(boost::beast::http::verb::get)(
628cf7eba09SNan Zhou             std::bind_front(handleChassisGet, std::ref(app)));
629cf7eba09SNan Zhou 
630cf7eba09SNan Zhou     BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/")
631cf7eba09SNan Zhou         .privileges(redfish::privileges::patchChassis)
632cf7eba09SNan Zhou         .methods(boost::beast::http::verb::patch)(
633cf7eba09SNan Zhou             std::bind_front(handleChassisPatch, std::ref(app)));
6341c8fba97SJames Feist }
635dd99e04bSP.K. Lee 
636*fc903b3dSAndrew Geissler /**
637*fc903b3dSAndrew Geissler  * Handle error responses from d-bus for chassis power cycles
638*fc903b3dSAndrew Geissler  */
639*fc903b3dSAndrew Geissler inline void handleChassisPowerCycleError(const boost::system::error_code& ec,
640*fc903b3dSAndrew Geissler                                          const sdbusplus::message_t& eMsg,
641*fc903b3dSAndrew Geissler                                          crow::Response& res)
642*fc903b3dSAndrew Geissler {
643*fc903b3dSAndrew Geissler     if (eMsg.get_error() == nullptr)
644*fc903b3dSAndrew Geissler     {
645*fc903b3dSAndrew Geissler         BMCWEB_LOG_ERROR << "D-Bus response error: " << ec;
646*fc903b3dSAndrew Geissler         messages::internalError(res);
647*fc903b3dSAndrew Geissler         return;
648*fc903b3dSAndrew Geissler     }
649*fc903b3dSAndrew Geissler     std::string_view errorMessage = eMsg.get_error()->name;
650*fc903b3dSAndrew Geissler 
651*fc903b3dSAndrew Geissler     // If operation failed due to BMC not being in Ready state, tell
652*fc903b3dSAndrew Geissler     // user to retry in a bit
653*fc903b3dSAndrew Geissler     if (errorMessage ==
654*fc903b3dSAndrew Geissler         std::string_view("xyz.openbmc_project.State.Chassis.Error.BMCNotReady"))
655*fc903b3dSAndrew Geissler     {
656*fc903b3dSAndrew Geissler         BMCWEB_LOG_DEBUG << "BMC not ready, operation not allowed right now";
657*fc903b3dSAndrew Geissler         messages::serviceTemporarilyUnavailable(res, "10");
658*fc903b3dSAndrew Geissler         return;
659*fc903b3dSAndrew Geissler     }
660*fc903b3dSAndrew Geissler 
661*fc903b3dSAndrew Geissler     BMCWEB_LOG_ERROR << "Chassis Power Cycle fail " << ec
662*fc903b3dSAndrew Geissler                      << " sdbusplus:" << errorMessage;
663*fc903b3dSAndrew Geissler     messages::internalError(res);
664*fc903b3dSAndrew Geissler }
665*fc903b3dSAndrew Geissler 
6668d1b46d7Szhanghch05 inline void
6678d1b46d7Szhanghch05     doChassisPowerCycle(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
668dd99e04bSP.K. Lee {
6697a1dbc48SGeorge Liu     constexpr std::array<std::string_view, 1> interfaces = {
670c3b3c92aSVijay Khemka         "xyz.openbmc_project.State.Chassis"};
671c3b3c92aSVijay Khemka 
672c3b3c92aSVijay Khemka     // Use mapper to get subtree paths.
6737a1dbc48SGeorge Liu     dbus::utility::getSubTreePaths(
6747a1dbc48SGeorge Liu         "/", 0, interfaces,
675b9d36b47SEd Tanous         [asyncResp](
6767a1dbc48SGeorge Liu             const boost::system::error_code& ec,
677b9d36b47SEd Tanous             const dbus::utility::MapperGetSubTreePathsResponse& chassisList) {
678c3b3c92aSVijay Khemka         if (ec)
679c3b3c92aSVijay Khemka         {
68051dab2a7SAndrew Geissler             BMCWEB_LOG_ERROR << "[mapper] Bad D-Bus request error: " << ec;
681c3b3c92aSVijay Khemka             messages::internalError(asyncResp->res);
682c3b3c92aSVijay Khemka             return;
683c3b3c92aSVijay Khemka         }
684c3b3c92aSVijay Khemka 
685dd99e04bSP.K. Lee         const char* processName = "xyz.openbmc_project.State.Chassis";
686dd99e04bSP.K. Lee         const char* interfaceName = "xyz.openbmc_project.State.Chassis";
687dd99e04bSP.K. Lee         const char* destProperty = "RequestedPowerTransition";
688dd99e04bSP.K. Lee         const std::string propertyValue =
689dd99e04bSP.K. Lee             "xyz.openbmc_project.State.Chassis.Transition.PowerCycle";
690002d39b4SEd Tanous         std::string objectPath = "/xyz/openbmc_project/state/chassis_system0";
691c3b3c92aSVijay Khemka 
692c3b3c92aSVijay Khemka         /* Look for system reset chassis path */
693002d39b4SEd Tanous         if ((std::find(chassisList.begin(), chassisList.end(), objectPath)) ==
694002d39b4SEd Tanous             chassisList.end())
695c3b3c92aSVijay Khemka         {
696c3b3c92aSVijay Khemka             /* We prefer to reset the full chassis_system, but if it doesn't
697c3b3c92aSVijay Khemka              * exist on some platforms, fall back to a host-only power reset
698c3b3c92aSVijay Khemka              */
699c3b3c92aSVijay Khemka             objectPath = "/xyz/openbmc_project/state/chassis0";
700c3b3c92aSVijay Khemka         }
701dd99e04bSP.K. Lee 
702dd99e04bSP.K. Lee         crow::connections::systemBus->async_method_call(
703*fc903b3dSAndrew Geissler             [asyncResp](const boost::system::error_code& ec2,
704*fc903b3dSAndrew Geissler                         sdbusplus::message_t& sdbusErrMsg) {
705dd99e04bSP.K. Lee             // Use "Set" method to set the property value.
7068a592810SEd Tanous             if (ec2)
707dd99e04bSP.K. Lee             {
708*fc903b3dSAndrew Geissler                 handleChassisPowerCycleError(ec2, sdbusErrMsg, asyncResp->res);
709*fc903b3dSAndrew Geissler 
710dd99e04bSP.K. Lee                 return;
711dd99e04bSP.K. Lee             }
712dd99e04bSP.K. Lee 
713dd99e04bSP.K. Lee             messages::success(asyncResp->res);
714dd99e04bSP.K. Lee             },
715002d39b4SEd Tanous             processName, objectPath, "org.freedesktop.DBus.Properties", "Set",
716002d39b4SEd Tanous             interfaceName, destProperty,
717168e20c1SEd Tanous             dbus::utility::DbusVariantType{propertyValue});
7187a1dbc48SGeorge Liu         });
719dd99e04bSP.K. Lee }
720dd99e04bSP.K. Lee 
721cf7eba09SNan Zhou inline void handleChassisResetActionInfoPost(
722cf7eba09SNan Zhou     App& app, const crow::Request& req,
7237e860f15SJohn Edward Broadbent     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
724cf7eba09SNan Zhou     const std::string& /*chassisId*/)
725cf7eba09SNan Zhou {
7263ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
72745ca1b86SEd Tanous     {
72845ca1b86SEd Tanous         return;
72945ca1b86SEd Tanous     }
730dd99e04bSP.K. Lee     BMCWEB_LOG_DEBUG << "Post Chassis Reset.";
731dd99e04bSP.K. Lee 
732dd99e04bSP.K. Lee     std::string resetType;
733dd99e04bSP.K. Lee 
734cf7eba09SNan Zhou     if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", resetType))
735dd99e04bSP.K. Lee     {
736dd99e04bSP.K. Lee         return;
737dd99e04bSP.K. Lee     }
738dd99e04bSP.K. Lee 
739dd99e04bSP.K. Lee     if (resetType != "PowerCycle")
740dd99e04bSP.K. Lee     {
741dd99e04bSP.K. Lee         BMCWEB_LOG_DEBUG << "Invalid property value for ResetType: "
742dd99e04bSP.K. Lee                          << resetType;
743002d39b4SEd Tanous         messages::actionParameterNotSupported(asyncResp->res, resetType,
744002d39b4SEd Tanous                                               "ResetType");
745dd99e04bSP.K. Lee 
746dd99e04bSP.K. Lee         return;
747dd99e04bSP.K. Lee     }
748dd99e04bSP.K. Lee     doChassisPowerCycle(asyncResp);
749dd99e04bSP.K. Lee }
7501cb1a9e6SAppaRao Puli 
7511cb1a9e6SAppaRao Puli /**
752cf7eba09SNan Zhou  * ChassisResetAction class supports the POST method for the Reset
753cf7eba09SNan Zhou  * action.
754cf7eba09SNan Zhou  * Function handles POST method request.
755cf7eba09SNan Zhou  * Analyzes POST body before sending Reset request data to D-Bus.
7561cb1a9e6SAppaRao Puli  */
757cf7eba09SNan Zhou 
758cf7eba09SNan Zhou inline void requestRoutesChassisResetAction(App& app)
7591cb1a9e6SAppaRao Puli {
760cf7eba09SNan Zhou     BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Actions/Chassis.Reset/")
761cf7eba09SNan Zhou         .privileges(redfish::privileges::postChassis)
762cf7eba09SNan Zhou         .methods(boost::beast::http::verb::post)(
763cf7eba09SNan Zhou             std::bind_front(handleChassisResetActionInfoPost, std::ref(app)));
764cf7eba09SNan Zhou }
765cf7eba09SNan Zhou 
766cf7eba09SNan Zhou inline void handleChassisResetActionInfoGet(
767cf7eba09SNan Zhou     App& app, const crow::Request& req,
7687e860f15SJohn Edward Broadbent     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
769cf7eba09SNan Zhou     const std::string& chassisId)
770cf7eba09SNan Zhou {
7713ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
7721cb1a9e6SAppaRao Puli     {
77345ca1b86SEd Tanous         return;
77445ca1b86SEd Tanous     }
775cf7eba09SNan Zhou     asyncResp->res.jsonValue["@odata.type"] = "#ActionInfo.v1_1_2.ActionInfo";
776ef4c65b7SEd Tanous     asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
777ef4c65b7SEd Tanous         "/redfish/v1/Chassis/{}/ResetActionInfo", chassisId);
7781476687dSEd Tanous     asyncResp->res.jsonValue["Name"] = "Reset Action Info";
7791476687dSEd Tanous 
7801476687dSEd Tanous     asyncResp->res.jsonValue["Id"] = "ResetActionInfo";
7815b9e95a1SNan Zhou     nlohmann::json::array_t parameters;
7825b9e95a1SNan Zhou     nlohmann::json::object_t parameter;
7835b9e95a1SNan Zhou     parameter["Name"] = "ResetType";
7845b9e95a1SNan Zhou     parameter["Required"] = true;
7855b9e95a1SNan Zhou     parameter["DataType"] = "String";
7861476687dSEd Tanous     nlohmann::json::array_t allowed;
787ad539545SPatrick Williams     allowed.emplace_back("PowerCycle");
7885b9e95a1SNan Zhou     parameter["AllowableValues"] = std::move(allowed);
789ad539545SPatrick Williams     parameters.emplace_back(std::move(parameter));
7905b9e95a1SNan Zhou 
7911476687dSEd Tanous     asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
792cf7eba09SNan Zhou }
793cf7eba09SNan Zhou 
794cf7eba09SNan Zhou /**
795cf7eba09SNan Zhou  * ChassisResetActionInfo derived class for delivering Chassis
796cf7eba09SNan Zhou  * ResetType AllowableValues using ResetInfo schema.
797cf7eba09SNan Zhou  */
798cf7eba09SNan Zhou inline void requestRoutesChassisResetActionInfo(App& app)
799cf7eba09SNan Zhou {
800cf7eba09SNan Zhou     BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ResetActionInfo/")
801cf7eba09SNan Zhou         .privileges(redfish::privileges::getActionInfo)
802cf7eba09SNan Zhou         .methods(boost::beast::http::verb::get)(
803cf7eba09SNan Zhou             std::bind_front(handleChassisResetActionInfoGet, std::ref(app)));
8041cb1a9e6SAppaRao Puli }
8051cb1a9e6SAppaRao Puli 
806e37f8451SRapkiewicz, Pawel } // namespace redfish
807