xref: /openbmc/bmcweb/features/redfish/lib/chassis.hpp (revision 1e1e598df6d1d9530dde6e92d8f74f8143f60e50)
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 
18b49ac873SJames Feist #include "health.hpp"
191c8fba97SJames Feist #include "led.hpp"
201abe55efSEd Tanous 
217e860f15SJohn Edward Broadbent #include <app.hpp>
22e37f8451SRapkiewicz, Pawel #include <boost/container/flat_map.hpp>
23168e20c1SEd Tanous #include <dbus_utility.hpp>
24ed398213SEd Tanous #include <registries/privilege_registry.hpp>
25*1e1e598dSJonathan Doman #include <sdbusplus/asio/property.hpp>
2602f6ff19SGunnar Mills #include <utils/collection.hpp>
271214b7e7SGunnar Mills 
281abe55efSEd Tanous namespace redfish
291abe55efSEd Tanous {
30e37f8451SRapkiewicz, Pawel 
31e37f8451SRapkiewicz, Pawel /**
32beeca0aeSGunnar Mills  * @brief Retrieves chassis state properties over dbus
33beeca0aeSGunnar Mills  *
34beeca0aeSGunnar Mills  * @param[in] aResp - Shared pointer for completing asynchronous calls.
35beeca0aeSGunnar Mills  *
36beeca0aeSGunnar Mills  * @return None.
37beeca0aeSGunnar Mills  */
388d1b46d7Szhanghch05 inline void getChassisState(std::shared_ptr<bmcweb::AsyncResp> aResp)
39beeca0aeSGunnar Mills {
40*1e1e598dSJonathan Doman     // crow::connections::systemBus->async_method_call(
41*1e1e598dSJonathan Doman     sdbusplus::asio::getProperty<std::string>(
42*1e1e598dSJonathan Doman         *crow::connections::systemBus, "xyz.openbmc_project.State.Chassis",
43*1e1e598dSJonathan Doman         "/xyz/openbmc_project/state/chassis0",
44*1e1e598dSJonathan Doman         "xyz.openbmc_project.State.Chassis", "CurrentPowerState",
45*1e1e598dSJonathan Doman         [aResp{std::move(aResp)}](const boost::system::error_code ec,
46*1e1e598dSJonathan Doman                                   const std::string& chassisState) {
47beeca0aeSGunnar Mills             if (ec)
48beeca0aeSGunnar Mills             {
49beeca0aeSGunnar Mills                 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
50beeca0aeSGunnar Mills                 messages::internalError(aResp->res);
51beeca0aeSGunnar Mills                 return;
52beeca0aeSGunnar Mills             }
53beeca0aeSGunnar Mills 
54*1e1e598dSJonathan Doman             BMCWEB_LOG_DEBUG << "Chassis state: " << chassisState;
55beeca0aeSGunnar Mills             // Verify Chassis State
56*1e1e598dSJonathan Doman             if (chassisState ==
57*1e1e598dSJonathan Doman                 "xyz.openbmc_project.State.Chassis.PowerState.On")
58beeca0aeSGunnar Mills             {
59beeca0aeSGunnar Mills                 aResp->res.jsonValue["PowerState"] = "On";
60beeca0aeSGunnar Mills                 aResp->res.jsonValue["Status"]["State"] = "Enabled";
61beeca0aeSGunnar Mills             }
62*1e1e598dSJonathan Doman             else if (chassisState ==
63beeca0aeSGunnar Mills                      "xyz.openbmc_project.State.Chassis.PowerState.Off")
64beeca0aeSGunnar Mills             {
65beeca0aeSGunnar Mills                 aResp->res.jsonValue["PowerState"] = "Off";
66beeca0aeSGunnar Mills                 aResp->res.jsonValue["Status"]["State"] = "StandbyOffline";
67beeca0aeSGunnar Mills             }
68*1e1e598dSJonathan Doman         });
69beeca0aeSGunnar Mills }
70beeca0aeSGunnar Mills 
71beeca0aeSGunnar Mills /**
72e37f8451SRapkiewicz, Pawel  * DBus types primitives for several generic DBus interfaces
73e37f8451SRapkiewicz, Pawel  * TODO(Pawel) consider move this to separate file into boost::dbus
74e37f8451SRapkiewicz, Pawel  */
75aa2e59c1SEd Tanous using ManagedObjectsType = std::vector<std::pair<
76aa2e59c1SEd Tanous     sdbusplus::message::object_path,
77168e20c1SEd Tanous     std::vector<std::pair<
78168e20c1SEd Tanous         std::string,
79168e20c1SEd Tanous         std::vector<std::pair<std::string, dbus::utility::DbusVariantType>>>>>>;
80e37f8451SRapkiewicz, Pawel 
81168e20c1SEd Tanous using PropertiesType =
82168e20c1SEd Tanous     boost::container::flat_map<std::string, dbus::utility::DbusVariantType>;
83e37f8451SRapkiewicz, Pawel 
848d1b46d7Szhanghch05 inline void getIntrusionByService(std::shared_ptr<bmcweb::AsyncResp> aResp,
85c181942fSQiang XU                                   const std::string& service,
86c181942fSQiang XU                                   const std::string& objPath)
87c181942fSQiang XU {
88c181942fSQiang XU     BMCWEB_LOG_DEBUG << "Get intrusion status by service \n";
89c181942fSQiang XU 
90*1e1e598dSJonathan Doman     sdbusplus::asio::getProperty<std::string>(
91*1e1e598dSJonathan Doman         *crow::connections::systemBus, service, objPath,
92*1e1e598dSJonathan Doman         "xyz.openbmc_project.Chassis.Intrusion", "Status",
93c181942fSQiang XU         [aResp{std::move(aResp)}](const boost::system::error_code ec,
94*1e1e598dSJonathan Doman                                   const std::string& value) {
95c181942fSQiang XU             if (ec)
96c181942fSQiang XU             {
974e0453b1SGunnar Mills                 // do not add err msg in redfish response, because this is not
98c181942fSQiang XU                 //     mandatory property
99c181942fSQiang XU                 BMCWEB_LOG_ERROR << "DBUS response error " << ec << "\n";
100c181942fSQiang XU                 return;
101c181942fSQiang XU             }
102c181942fSQiang XU 
103c181942fSQiang XU             aResp->res.jsonValue["PhysicalSecurity"] = {
104*1e1e598dSJonathan Doman                 {"IntrusionSensorNumber", 1}, {"IntrusionSensor", value}};
105*1e1e598dSJonathan Doman         });
106c181942fSQiang XU }
107c181942fSQiang XU 
108c181942fSQiang XU /**
109c181942fSQiang XU  * Retrieves physical security properties over dbus
110c181942fSQiang XU  */
1118d1b46d7Szhanghch05 inline void getPhysicalSecurityData(std::shared_ptr<bmcweb::AsyncResp> aResp)
112c181942fSQiang XU {
113c181942fSQiang XU     crow::connections::systemBus->async_method_call(
114c181942fSQiang XU         [aResp{std::move(aResp)}](
115c181942fSQiang XU             const boost::system::error_code ec,
116c181942fSQiang XU             const std::vector<std::pair<
117c181942fSQiang XU                 std::string,
1181214b7e7SGunnar Mills                 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1191214b7e7SGunnar Mills                 subtree) {
120c181942fSQiang XU             if (ec)
121c181942fSQiang XU             {
1224e0453b1SGunnar Mills                 // do not add err msg in redfish response, because this is not
123c181942fSQiang XU                 //     mandatory property
12454fbf177SAndrew Geissler                 BMCWEB_LOG_INFO << "DBUS error: no matched iface " << ec
125c181942fSQiang XU                                 << "\n";
126c181942fSQiang XU                 return;
127c181942fSQiang XU             }
128c181942fSQiang XU             // Iterate over all retrieved ObjectPaths.
129c181942fSQiang XU             for (const auto& object : subtree)
130c181942fSQiang XU             {
131c181942fSQiang XU                 for (const auto& service : object.second)
132c181942fSQiang XU                 {
133c181942fSQiang XU                     getIntrusionByService(aResp, service.first, object.first);
134c181942fSQiang XU                     return;
135c181942fSQiang XU                 }
136c181942fSQiang XU             }
137c181942fSQiang XU         },
138c181942fSQiang XU         "xyz.openbmc_project.ObjectMapper",
139c181942fSQiang XU         "/xyz/openbmc_project/object_mapper",
140c181942fSQiang XU         "xyz.openbmc_project.ObjectMapper", "GetSubTree",
141271584abSEd Tanous         "/xyz/openbmc_project/Intrusion", 1,
142c181942fSQiang XU         std::array<const char*, 1>{"xyz.openbmc_project.Chassis.Intrusion"});
143c181942fSQiang XU }
144c181942fSQiang XU 
145e37f8451SRapkiewicz, Pawel /**
146e37f8451SRapkiewicz, Pawel  * ChassisCollection derived class for delivering Chassis Collection Schema
147e37f8451SRapkiewicz, Pawel  *  Functions triggers appropriate requests on DBus
148e37f8451SRapkiewicz, Pawel  */
1497e860f15SJohn Edward Broadbent inline void requestRoutesChassisCollection(App& app)
1501abe55efSEd Tanous {
1517e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Chassis/")
152ed398213SEd Tanous         .privileges(redfish::privileges::getChassisCollection)
1537e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
1547e860f15SJohn Edward Broadbent             [](const crow::Request&,
1557e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
1568d1b46d7Szhanghch05                 asyncResp->res.jsonValue["@odata.type"] =
1578d1b46d7Szhanghch05                     "#ChassisCollection.ChassisCollection";
1588d1b46d7Szhanghch05                 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Chassis";
1598d1b46d7Szhanghch05                 asyncResp->res.jsonValue["Name"] = "Chassis Collection";
160e37f8451SRapkiewicz, Pawel 
16102f6ff19SGunnar Mills                 collection_util::getCollectionMembers(
16202f6ff19SGunnar Mills                     asyncResp, "/redfish/v1/Chassis",
16302f6ff19SGunnar Mills                     {"xyz.openbmc_project.Inventory.Item.Board",
16402f6ff19SGunnar Mills                      "xyz.openbmc_project.Inventory.Item.Chassis"});
1657e860f15SJohn Edward Broadbent             });
16662d5e2e4SEd Tanous }
167e37f8451SRapkiewicz, Pawel 
168308f70c7SWilly Tu inline void
169308f70c7SWilly Tu     getChassisLocationCode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
170308f70c7SWilly Tu                            const std::string& connectionName,
171308f70c7SWilly Tu                            const std::string& path)
172308f70c7SWilly Tu {
173*1e1e598dSJonathan Doman     sdbusplus::asio::getProperty<std::string>(
174*1e1e598dSJonathan Doman         *crow::connections::systemBus, connectionName, path,
175*1e1e598dSJonathan Doman         "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode",
176308f70c7SWilly Tu         [asyncResp](const boost::system::error_code ec,
177*1e1e598dSJonathan Doman                     const std::string& property) {
178308f70c7SWilly Tu             if (ec)
179308f70c7SWilly Tu             {
1800fda0f12SGeorge Liu                 BMCWEB_LOG_DEBUG << "DBUS response error for Location";
181308f70c7SWilly Tu                 messages::internalError(asyncResp->res);
182308f70c7SWilly Tu                 return;
183308f70c7SWilly Tu             }
184308f70c7SWilly Tu 
185308f70c7SWilly Tu             asyncResp->res
186*1e1e598dSJonathan Doman                 .jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
187*1e1e598dSJonathan Doman                 property;
188*1e1e598dSJonathan Doman         });
189308f70c7SWilly Tu }
190308f70c7SWilly Tu 
191308f70c7SWilly Tu inline void getChassisUUID(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
192308f70c7SWilly Tu                            const std::string& connectionName,
193308f70c7SWilly Tu                            const std::string& path)
194308f70c7SWilly Tu {
195*1e1e598dSJonathan Doman     sdbusplus::asio::getProperty<std::string>(
196*1e1e598dSJonathan Doman         *crow::connections::systemBus, connectionName, path,
197*1e1e598dSJonathan Doman         "xyz.openbmc_project.Common.UUID", "UUID",
198308f70c7SWilly Tu         [asyncResp](const boost::system::error_code ec,
199*1e1e598dSJonathan Doman                     const std::string& chassisUUID) {
200308f70c7SWilly Tu             if (ec)
201308f70c7SWilly Tu             {
2020fda0f12SGeorge Liu                 BMCWEB_LOG_DEBUG << "DBUS response error for UUID";
203308f70c7SWilly Tu                 messages::internalError(asyncResp->res);
204308f70c7SWilly Tu                 return;
205308f70c7SWilly Tu             }
206*1e1e598dSJonathan Doman             asyncResp->res.jsonValue["UUID"] = chassisUUID;
207*1e1e598dSJonathan Doman         });
208308f70c7SWilly Tu }
209308f70c7SWilly Tu 
210e37f8451SRapkiewicz, Pawel /**
211e37f8451SRapkiewicz, Pawel  * Chassis override class for delivering Chassis Schema
212e37f8451SRapkiewicz, Pawel  * Functions triggers appropriate requests on DBus
213e37f8451SRapkiewicz, Pawel  */
2147e860f15SJohn Edward Broadbent inline void requestRoutesChassis(App& app)
2151abe55efSEd Tanous {
2167e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/")
217ed398213SEd Tanous         .privileges(redfish::privileges::getChassis)
2187e860f15SJohn Edward Broadbent         .methods(
2197e860f15SJohn Edward Broadbent             boost::beast::http::verb::get)([](const crow::Request&,
2207e860f15SJohn Edward Broadbent                                               const std::shared_ptr<
2217e860f15SJohn Edward Broadbent                                                   bmcweb::AsyncResp>& asyncResp,
2227e860f15SJohn Edward Broadbent                                               const std::string& chassisId) {
223adc4f0dbSShawn McCarney             const std::array<const char*, 2> interfaces = {
224734bfe90SGunnar Mills                 "xyz.openbmc_project.Inventory.Item.Board",
225adc4f0dbSShawn McCarney                 "xyz.openbmc_project.Inventory.Item.Chassis"};
226734bfe90SGunnar Mills 
22755c7b7a2SEd Tanous             crow::connections::systemBus->async_method_call(
22862d5e2e4SEd Tanous                 [asyncResp, chassisId(std::string(chassisId))](
22962d5e2e4SEd Tanous                     const boost::system::error_code ec,
2301c8fba97SJames Feist                     const crow::openbmc_mapper::GetSubTreeType& subtree) {
23162d5e2e4SEd Tanous                     if (ec)
2321abe55efSEd Tanous                     {
233f12894f8SJason M. Bills                         messages::internalError(asyncResp->res);
234daf36e2eSEd Tanous                         return;
235daf36e2eSEd Tanous                     }
236daf36e2eSEd Tanous                     // Iterate over all retrieved ObjectPaths.
2371abe55efSEd Tanous                     for (const std::pair<
2381abe55efSEd Tanous                              std::string,
2397e860f15SJohn Edward Broadbent                              std::vector<std::pair<std::string,
2407e860f15SJohn Edward Broadbent                                                    std::vector<std::string>>>>&
2411214b7e7SGunnar Mills                              object : subtree)
2421abe55efSEd Tanous                     {
243daf36e2eSEd Tanous                         const std::string& path = object.first;
2441abe55efSEd Tanous                         const std::vector<
2451214b7e7SGunnar Mills                             std::pair<std::string, std::vector<std::string>>>&
2461214b7e7SGunnar Mills                             connectionNames = object.second;
2477e860f15SJohn Edward Broadbent 
248997093ebSGeorge Liu                         sdbusplus::message::object_path objPath(path);
249997093ebSGeorge Liu                         if (objPath.filename() != chassisId)
2501abe55efSEd Tanous                         {
251daf36e2eSEd Tanous                             continue;
252daf36e2eSEd Tanous                         }
25326f03899SShawn McCarney 
2547e860f15SJohn Edward Broadbent                         auto health =
2557e860f15SJohn Edward Broadbent                             std::make_shared<HealthPopulate>(asyncResp);
256b49ac873SJames Feist 
257*1e1e598dSJonathan Doman                         sdbusplus::asio::getProperty<std::vector<std::string>>(
258*1e1e598dSJonathan Doman                             *crow::connections::systemBus,
259*1e1e598dSJonathan Doman                             "xyz.openbmc_project.ObjectMapper",
260*1e1e598dSJonathan Doman                             path + "/all_sensors",
261*1e1e598dSJonathan Doman                             "xyz.openbmc_project.Association", "endpoints",
262168e20c1SEd Tanous                             [health](const boost::system::error_code ec2,
263*1e1e598dSJonathan Doman                                      const std::vector<std::string>& resp) {
26423a21a1cSEd Tanous                                 if (ec2)
265b49ac873SJames Feist                                 {
266b49ac873SJames Feist                                     return; // no sensors = no failures
267b49ac873SJames Feist                                 }
268*1e1e598dSJonathan Doman                                 health->inventory = resp;
269*1e1e598dSJonathan Doman                             });
270b49ac873SJames Feist 
271b49ac873SJames Feist                         health->populate();
272b49ac873SJames Feist 
2731abe55efSEd Tanous                         if (connectionNames.size() < 1)
2741abe55efSEd Tanous                         {
2751c8fba97SJames Feist                             BMCWEB_LOG_ERROR << "Got 0 Connection names";
276e0d918bcSEd Tanous                             continue;
277daf36e2eSEd Tanous                         }
278e0d918bcSEd Tanous 
27949c53ac9SJohnathan Mantey                         asyncResp->res.jsonValue["@odata.type"] =
2809f8bfa7cSGunnar Mills                             "#Chassis.v1_14_0.Chassis";
28149c53ac9SJohnathan Mantey                         asyncResp->res.jsonValue["@odata.id"] =
28249c53ac9SJohnathan Mantey                             "/redfish/v1/Chassis/" + chassisId;
28349c53ac9SJohnathan Mantey                         asyncResp->res.jsonValue["Name"] = "Chassis Collection";
28449c53ac9SJohnathan Mantey                         asyncResp->res.jsonValue["ChassisType"] = "RackMount";
2857e860f15SJohn Edward Broadbent                         asyncResp->res.jsonValue["Actions"]["#Chassis.Reset"] =
2867e860f15SJohn Edward Broadbent                             {{"target", "/redfish/v1/Chassis/" + chassisId +
287dd99e04bSP.K. Lee                                             "/Actions/Chassis.Reset"},
2881cb1a9e6SAppaRao Puli                              {"@Redfish.ActionInfo", "/redfish/v1/Chassis/" +
2891cb1a9e6SAppaRao Puli                                                          chassisId +
2901cb1a9e6SAppaRao Puli                                                          "/ResetActionInfo"}};
291adbe192aSJason M. Bills                         asyncResp->res.jsonValue["PCIeDevices"] = {
292adbe192aSJason M. Bills                             {"@odata.id",
293adbe192aSJason M. Bills                              "/redfish/v1/Systems/system/PCIeDevices"}};
29449c53ac9SJohnathan Mantey 
29549c53ac9SJohnathan Mantey                         const std::string& connectionName =
29649c53ac9SJohnathan Mantey                             connectionNames[0].first;
2971c8fba97SJames Feist 
29823a21a1cSEd Tanous                         const std::vector<std::string>& interfaces2 =
2991c8fba97SJames Feist                             connectionNames[0].second;
3001c8fba97SJames Feist                         const std::array<const char*, 2> hasIndicatorLed = {
3011c8fba97SJames Feist                             "xyz.openbmc_project.Inventory.Item.Panel",
3020fda0f12SGeorge Liu                             "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
3031c8fba97SJames Feist 
304476b9cc5STejas Patil                         const std::string assetTagInterface =
3050fda0f12SGeorge Liu                             "xyz.openbmc_project.Inventory.Decorator.AssetTag";
306476b9cc5STejas Patil                         if (std::find(interfaces2.begin(), interfaces2.end(),
307476b9cc5STejas Patil                                       assetTagInterface) != interfaces2.end())
308476b9cc5STejas Patil                         {
309*1e1e598dSJonathan Doman                             sdbusplus::asio::getProperty<std::string>(
310*1e1e598dSJonathan Doman                                 *crow::connections::systemBus, connectionName,
311*1e1e598dSJonathan Doman                                 path, assetTagInterface, "AssetTag",
312476b9cc5STejas Patil                                 [asyncResp, chassisId(std::string(chassisId))](
313476b9cc5STejas Patil                                     const boost::system::error_code ec,
314*1e1e598dSJonathan Doman                                     const std::string& property) {
315476b9cc5STejas Patil                                     if (ec)
316476b9cc5STejas Patil                                     {
317476b9cc5STejas Patil                                         BMCWEB_LOG_DEBUG
3180fda0f12SGeorge Liu                                             << "DBus response error for AssetTag";
319476b9cc5STejas Patil                                         messages::internalError(asyncResp->res);
320476b9cc5STejas Patil                                         return;
321476b9cc5STejas Patil                                     }
322476b9cc5STejas Patil                                     asyncResp->res.jsonValue["AssetTag"] =
323*1e1e598dSJonathan Doman                                         property;
324*1e1e598dSJonathan Doman                                 });
325476b9cc5STejas Patil                         }
326476b9cc5STejas Patil 
3271c8fba97SJames Feist                         for (const char* interface : hasIndicatorLed)
3281c8fba97SJames Feist                         {
3297e860f15SJohn Edward Broadbent                             if (std::find(interfaces2.begin(),
3307e860f15SJohn Edward Broadbent                                           interfaces2.end(),
33123a21a1cSEd Tanous                                           interface) != interfaces2.end())
3321c8fba97SJames Feist                             {
3331c8fba97SJames Feist                                 getIndicatorLedState(asyncResp);
3349f8bfa7cSGunnar Mills                                 getLocationIndicatorActive(asyncResp);
3351c8fba97SJames Feist                                 break;
3361c8fba97SJames Feist                             }
3371c8fba97SJames Feist                         }
3381c8fba97SJames Feist 
33955c7b7a2SEd Tanous                         crow::connections::systemBus->async_method_call(
34062d5e2e4SEd Tanous                             [asyncResp, chassisId(std::string(chassisId))](
34190728b54SEd Tanous                                 const boost::system::error_code /*ec2*/,
3427e860f15SJohn Edward Broadbent                                 const std::vector<
343168e20c1SEd Tanous                                     std::pair<std::string,
344168e20c1SEd Tanous                                               dbus::utility::DbusVariantType>>&
3457e860f15SJohn Edward Broadbent                                     propertiesList) {
346168e20c1SEd Tanous                                 for (const std::pair<
347168e20c1SEd Tanous                                          std::string,
348168e20c1SEd Tanous                                          dbus::utility::DbusVariantType>&
3491214b7e7SGunnar Mills                                          property : propertiesList)
3501abe55efSEd Tanous                                 {
3517e860f15SJohn Edward Broadbent                                     // Store DBus properties that are also
3527e860f15SJohn Edward Broadbent                                     // Redfish properties with same name and a
3537e860f15SJohn Edward Broadbent                                     // string value
35499cffd7fSShawn McCarney                                     const std::string& propertyName =
35599cffd7fSShawn McCarney                                         property.first;
35699cffd7fSShawn McCarney                                     if ((propertyName == "PartNumber") ||
35799cffd7fSShawn McCarney                                         (propertyName == "SerialNumber") ||
35899cffd7fSShawn McCarney                                         (propertyName == "Manufacturer") ||
359caa11f7aSAlpana Kumari                                         (propertyName == "Model") ||
360caa11f7aSAlpana Kumari                                         (propertyName == "SparePartNumber"))
36199cffd7fSShawn McCarney                                     {
362daf36e2eSEd Tanous                                         const std::string* value =
36399cffd7fSShawn McCarney                                             std::get_if<std::string>(
36499cffd7fSShawn McCarney                                                 &property.second);
365caa11f7aSAlpana Kumari                                         if (value == nullptr)
3661abe55efSEd Tanous                                         {
367caa11f7aSAlpana Kumari                                             BMCWEB_LOG_ERROR
368caa11f7aSAlpana Kumari                                                 << "Null value returned for "
369caa11f7aSAlpana Kumari                                                 << propertyName;
370caa11f7aSAlpana Kumari                                             messages::internalError(
371caa11f7aSAlpana Kumari                                                 asyncResp->res);
372caa11f7aSAlpana Kumari                                             return;
373daf36e2eSEd Tanous                                         }
374caa11f7aSAlpana Kumari                                         // SparePartNumber is optional on D-Bus
375caa11f7aSAlpana Kumari                                         // so skip if it is empty
376caa11f7aSAlpana Kumari                                         if (propertyName == "SparePartNumber")
377caa11f7aSAlpana Kumari                                         {
378caa11f7aSAlpana Kumari                                             if (*value == "")
379caa11f7aSAlpana Kumari                                             {
380caa11f7aSAlpana Kumari                                                 continue;
381caa11f7aSAlpana Kumari                                             }
382caa11f7aSAlpana Kumari                                         }
383caa11f7aSAlpana Kumari                                         asyncResp->res.jsonValue[propertyName] =
384caa11f7aSAlpana Kumari                                             *value;
385daf36e2eSEd Tanous                                     }
38699cffd7fSShawn McCarney                                 }
38762d5e2e4SEd Tanous                                 asyncResp->res.jsonValue["Name"] = chassisId;
38862d5e2e4SEd Tanous                                 asyncResp->res.jsonValue["Id"] = chassisId;
3890256b694Szhanghch05 #ifdef BMCWEB_ALLOW_DEPRECATED_POWER_THERMAL
39062d5e2e4SEd Tanous                                 asyncResp->res.jsonValue["Thermal"] = {
3911abe55efSEd Tanous                                     {"@odata.id", "/redfish/v1/Chassis/" +
3921abe55efSEd Tanous                                                       chassisId + "/Thermal"}};
3932474adfaSEd Tanous                                 // Power object
3942474adfaSEd Tanous                                 asyncResp->res.jsonValue["Power"] = {
3952474adfaSEd Tanous                                     {"@odata.id", "/redfish/v1/Chassis/" +
3962474adfaSEd Tanous                                                       chassisId + "/Power"}};
3970256b694Szhanghch05 #endif
39895a3ecadSAnthony Wilson                                 // SensorCollection
39995a3ecadSAnthony Wilson                                 asyncResp->res.jsonValue["Sensors"] = {
40095a3ecadSAnthony Wilson                                     {"@odata.id", "/redfish/v1/Chassis/" +
40195a3ecadSAnthony Wilson                                                       chassisId + "/Sensors"}};
402029573d4SEd Tanous                                 asyncResp->res.jsonValue["Status"] = {
403029573d4SEd Tanous                                     {"State", "Enabled"},
404029573d4SEd Tanous                                 };
4052474adfaSEd Tanous 
406029573d4SEd Tanous                                 asyncResp->res
407029573d4SEd Tanous                                     .jsonValue["Links"]["ComputerSystems"] = {
4087e860f15SJohn Edward Broadbent                                     {{"@odata.id",
4097e860f15SJohn Edward Broadbent                                       "/redfish/v1/Systems/system"}}};
4107e860f15SJohn Edward Broadbent                                 asyncResp->res.jsonValue["Links"]["ManagedBy"] =
4117e860f15SJohn Edward Broadbent                                     {{{"@odata.id",
4127e860f15SJohn Edward Broadbent                                        "/redfish/v1/Managers/bmc"}}};
413beeca0aeSGunnar Mills                                 getChassisState(asyncResp);
414daf36e2eSEd Tanous                             },
4157e860f15SJohn Edward Broadbent                             connectionName, path,
4167e860f15SJohn Edward Broadbent                             "org.freedesktop.DBus.Properties", "GetAll",
4171abe55efSEd Tanous                             "xyz.openbmc_project.Inventory.Decorator.Asset");
4182c37b4b0SSharad Yadav 
419308f70c7SWilly Tu                         for (const auto& interface : interfaces2)
4202c37b4b0SSharad Yadav                         {
421308f70c7SWilly Tu                             if (interface == "xyz.openbmc_project.Common.UUID")
4222c37b4b0SSharad Yadav                             {
423308f70c7SWilly Tu                                 getChassisUUID(asyncResp, connectionName, path);
4242c37b4b0SSharad Yadav                             }
4250fda0f12SGeorge Liu                             else if (
4260fda0f12SGeorge Liu                                 interface ==
4270fda0f12SGeorge Liu                                 "xyz.openbmc_project.Inventory.Decorator.LocationCode")
4282c37b4b0SSharad Yadav                             {
429308f70c7SWilly Tu                                 getChassisLocationCode(asyncResp,
430308f70c7SWilly Tu                                                        connectionName, path);
4312c37b4b0SSharad Yadav                             }
4322c37b4b0SSharad Yadav                         }
4332c37b4b0SSharad Yadav 
434daf36e2eSEd Tanous                         return;
435daf36e2eSEd Tanous                     }
436e0d918bcSEd Tanous 
437daf36e2eSEd Tanous                     // Couldn't find an object with that name.  return an error
438f12894f8SJason M. Bills                     messages::resourceNotFound(
4399f8bfa7cSGunnar Mills                         asyncResp->res, "#Chassis.v1_14_0.Chassis", chassisId);
440daf36e2eSEd Tanous                 },
441daf36e2eSEd Tanous                 "xyz.openbmc_project.ObjectMapper",
442daf36e2eSEd Tanous                 "/xyz/openbmc_project/object_mapper",
443daf36e2eSEd Tanous                 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
444271584abSEd Tanous                 "/xyz/openbmc_project/inventory", 0, interfaces);
445c181942fSQiang XU 
446c181942fSQiang XU             getPhysicalSecurityData(asyncResp);
4477e860f15SJohn Edward Broadbent         });
4481c8fba97SJames Feist 
4497e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/")
450ed398213SEd Tanous         .privileges(redfish::privileges::patchChassis)
4517e860f15SJohn Edward Broadbent         .methods(
4527e860f15SJohn Edward Broadbent             boost::beast::http::verb::
4537e860f15SJohn Edward Broadbent                 patch)([](const crow::Request& req,
4547e860f15SJohn Edward Broadbent                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
4557e860f15SJohn Edward Broadbent                           const std::string& param) {
4569f8bfa7cSGunnar Mills             std::optional<bool> locationIndicatorActive;
4571c8fba97SJames Feist             std::optional<std::string> indicatorLed;
4581c8fba97SJames Feist 
4597e860f15SJohn Edward Broadbent             if (param.empty())
4601c8fba97SJames Feist             {
4611c8fba97SJames Feist                 return;
4621c8fba97SJames Feist             }
4631c8fba97SJames Feist 
4647e860f15SJohn Edward Broadbent             if (!json_util::readJson(
4657e860f15SJohn Edward Broadbent                     req, asyncResp->res, "LocationIndicatorActive",
4667e860f15SJohn Edward Broadbent                     locationIndicatorActive, "IndicatorLED", indicatorLed))
4671c8fba97SJames Feist             {
4681c8fba97SJames Feist                 return;
4691c8fba97SJames Feist             }
4701c8fba97SJames Feist 
4719f8bfa7cSGunnar Mills             // TODO (Gunnar): Remove IndicatorLED after enough time has passed
4729f8bfa7cSGunnar Mills             if (!locationIndicatorActive && !indicatorLed)
4731c8fba97SJames Feist             {
4741c8fba97SJames Feist                 return; // delete this when we support more patch properties
4751c8fba97SJames Feist             }
476d6aa0093SGunnar Mills             if (indicatorLed)
477d6aa0093SGunnar Mills             {
4787e860f15SJohn Edward Broadbent                 asyncResp->res.addHeader(
4797e860f15SJohn Edward Broadbent                     boost::beast::http::field::warning,
4800fda0f12SGeorge Liu                     "299 - \"IndicatorLED is deprecated. Use LocationIndicatorActive instead.\"");
481d6aa0093SGunnar Mills             }
4821c8fba97SJames Feist 
4831c8fba97SJames Feist             const std::array<const char*, 2> interfaces = {
4841c8fba97SJames Feist                 "xyz.openbmc_project.Inventory.Item.Board",
4851c8fba97SJames Feist                 "xyz.openbmc_project.Inventory.Item.Chassis"};
4861c8fba97SJames Feist 
4877e860f15SJohn Edward Broadbent             const std::string& chassisId = param;
4881c8fba97SJames Feist 
4891c8fba97SJames Feist             crow::connections::systemBus->async_method_call(
4909f8bfa7cSGunnar Mills                 [asyncResp, chassisId, locationIndicatorActive, indicatorLed](
4911c8fba97SJames Feist                     const boost::system::error_code ec,
4921c8fba97SJames Feist                     const crow::openbmc_mapper::GetSubTreeType& subtree) {
4931c8fba97SJames Feist                     if (ec)
4941c8fba97SJames Feist                     {
4951c8fba97SJames Feist                         messages::internalError(asyncResp->res);
4961c8fba97SJames Feist                         return;
4971c8fba97SJames Feist                     }
4981c8fba97SJames Feist 
4991c8fba97SJames Feist                     // Iterate over all retrieved ObjectPaths.
5001c8fba97SJames Feist                     for (const std::pair<
5011c8fba97SJames Feist                              std::string,
5027e860f15SJohn Edward Broadbent                              std::vector<std::pair<std::string,
5037e860f15SJohn Edward Broadbent                                                    std::vector<std::string>>>>&
5041214b7e7SGunnar Mills                              object : subtree)
5051c8fba97SJames Feist                     {
5061c8fba97SJames Feist                         const std::string& path = object.first;
5071c8fba97SJames Feist                         const std::vector<
5081214b7e7SGunnar Mills                             std::pair<std::string, std::vector<std::string>>>&
5091214b7e7SGunnar Mills                             connectionNames = object.second;
5101c8fba97SJames Feist 
511997093ebSGeorge Liu                         sdbusplus::message::object_path objPath(path);
512997093ebSGeorge Liu                         if (objPath.filename() != chassisId)
5131c8fba97SJames Feist                         {
5141c8fba97SJames Feist                             continue;
5151c8fba97SJames Feist                         }
5161c8fba97SJames Feist 
5171c8fba97SJames Feist                         if (connectionNames.size() < 1)
5181c8fba97SJames Feist                         {
5191c8fba97SJames Feist                             BMCWEB_LOG_ERROR << "Got 0 Connection names";
5201c8fba97SJames Feist                             continue;
5211c8fba97SJames Feist                         }
5221c8fba97SJames Feist 
52323a21a1cSEd Tanous                         const std::vector<std::string>& interfaces3 =
5241c8fba97SJames Feist                             connectionNames[0].second;
5251c8fba97SJames Feist 
5261c8fba97SJames Feist                         const std::array<const char*, 2> hasIndicatorLed = {
5271c8fba97SJames Feist                             "xyz.openbmc_project.Inventory.Item.Panel",
5280fda0f12SGeorge Liu                             "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
5291c8fba97SJames Feist                         bool indicatorChassis = false;
5301c8fba97SJames Feist                         for (const char* interface : hasIndicatorLed)
5311c8fba97SJames Feist                         {
5327e860f15SJohn Edward Broadbent                             if (std::find(interfaces3.begin(),
5337e860f15SJohn Edward Broadbent                                           interfaces3.end(),
53423a21a1cSEd Tanous                                           interface) != interfaces3.end())
5351c8fba97SJames Feist                             {
5361c8fba97SJames Feist                                 indicatorChassis = true;
5371c8fba97SJames Feist                                 break;
5381c8fba97SJames Feist                             }
5391c8fba97SJames Feist                         }
5409f8bfa7cSGunnar Mills                         if (locationIndicatorActive)
5419f8bfa7cSGunnar Mills                         {
5429f8bfa7cSGunnar Mills                             if (indicatorChassis)
5439f8bfa7cSGunnar Mills                             {
5449f8bfa7cSGunnar Mills                                 setLocationIndicatorActive(
5459f8bfa7cSGunnar Mills                                     asyncResp, *locationIndicatorActive);
5469f8bfa7cSGunnar Mills                             }
5479f8bfa7cSGunnar Mills                             else
5489f8bfa7cSGunnar Mills                             {
5499f8bfa7cSGunnar Mills                                 messages::propertyUnknown(
5509f8bfa7cSGunnar Mills                                     asyncResp->res, "LocationIndicatorActive");
5519f8bfa7cSGunnar Mills                             }
5529f8bfa7cSGunnar Mills                         }
5539f8bfa7cSGunnar Mills                         if (indicatorLed)
5549f8bfa7cSGunnar Mills                         {
5551c8fba97SJames Feist                             if (indicatorChassis)
5561c8fba97SJames Feist                             {
557f23b7296SEd Tanous                                 setIndicatorLedState(asyncResp, *indicatorLed);
5581c8fba97SJames Feist                             }
5591c8fba97SJames Feist                             else
5601c8fba97SJames Feist                             {
5611c8fba97SJames Feist                                 messages::propertyUnknown(asyncResp->res,
5621c8fba97SJames Feist                                                           "IndicatorLED");
5631c8fba97SJames Feist                             }
5641c8fba97SJames Feist                         }
5651c8fba97SJames Feist                         return;
5661c8fba97SJames Feist                     }
5671c8fba97SJames Feist 
5681c8fba97SJames Feist                     messages::resourceNotFound(
5699f8bfa7cSGunnar Mills                         asyncResp->res, "#Chassis.v1_14_0.Chassis", chassisId);
5701c8fba97SJames Feist                 },
5711c8fba97SJames Feist                 "xyz.openbmc_project.ObjectMapper",
5721c8fba97SJames Feist                 "/xyz/openbmc_project/object_mapper",
5731c8fba97SJames Feist                 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
5741c8fba97SJames Feist                 "/xyz/openbmc_project/inventory", 0, interfaces);
5757e860f15SJohn Edward Broadbent         });
5761c8fba97SJames Feist }
577dd99e04bSP.K. Lee 
5788d1b46d7Szhanghch05 inline void
5798d1b46d7Szhanghch05     doChassisPowerCycle(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
580dd99e04bSP.K. Lee {
581c3b3c92aSVijay Khemka     const char* busName = "xyz.openbmc_project.ObjectMapper";
582c3b3c92aSVijay Khemka     const char* path = "/xyz/openbmc_project/object_mapper";
583c3b3c92aSVijay Khemka     const char* interface = "xyz.openbmc_project.ObjectMapper";
584c3b3c92aSVijay Khemka     const char* method = "GetSubTreePaths";
585c3b3c92aSVijay Khemka 
586c3b3c92aSVijay Khemka     const std::array<const char*, 1> interfaces = {
587c3b3c92aSVijay Khemka         "xyz.openbmc_project.State.Chassis"};
588c3b3c92aSVijay Khemka 
589c3b3c92aSVijay Khemka     // Use mapper to get subtree paths.
590c3b3c92aSVijay Khemka     crow::connections::systemBus->async_method_call(
591c3b3c92aSVijay Khemka         [asyncResp](const boost::system::error_code ec,
592c3b3c92aSVijay Khemka                     const std::vector<std::string>& chassisList) {
593c3b3c92aSVijay Khemka             if (ec)
594c3b3c92aSVijay Khemka             {
595c3b3c92aSVijay Khemka                 BMCWEB_LOG_DEBUG << "[mapper] Bad D-Bus request error: " << ec;
596c3b3c92aSVijay Khemka                 messages::internalError(asyncResp->res);
597c3b3c92aSVijay Khemka                 return;
598c3b3c92aSVijay Khemka             }
599c3b3c92aSVijay Khemka 
600dd99e04bSP.K. Lee             const char* processName = "xyz.openbmc_project.State.Chassis";
601dd99e04bSP.K. Lee             const char* interfaceName = "xyz.openbmc_project.State.Chassis";
602dd99e04bSP.K. Lee             const char* destProperty = "RequestedPowerTransition";
603dd99e04bSP.K. Lee             const std::string propertyValue =
604dd99e04bSP.K. Lee                 "xyz.openbmc_project.State.Chassis.Transition.PowerCycle";
605c3b3c92aSVijay Khemka             std::string objectPath =
606c3b3c92aSVijay Khemka                 "/xyz/openbmc_project/state/chassis_system0";
607c3b3c92aSVijay Khemka 
608c3b3c92aSVijay Khemka             /* Look for system reset chassis path */
609c3b3c92aSVijay Khemka             if ((std::find(chassisList.begin(), chassisList.end(),
610c3b3c92aSVijay Khemka                            objectPath)) == chassisList.end())
611c3b3c92aSVijay Khemka             {
612c3b3c92aSVijay Khemka                 /* We prefer to reset the full chassis_system, but if it doesn't
613c3b3c92aSVijay Khemka                  * exist on some platforms, fall back to a host-only power reset
614c3b3c92aSVijay Khemka                  */
615c3b3c92aSVijay Khemka                 objectPath = "/xyz/openbmc_project/state/chassis0";
616c3b3c92aSVijay Khemka             }
617dd99e04bSP.K. Lee 
618dd99e04bSP.K. Lee             crow::connections::systemBus->async_method_call(
619dd99e04bSP.K. Lee                 [asyncResp](const boost::system::error_code ec) {
620dd99e04bSP.K. Lee                     // Use "Set" method to set the property value.
621dd99e04bSP.K. Lee                     if (ec)
622dd99e04bSP.K. Lee                     {
623c3b3c92aSVijay Khemka                         BMCWEB_LOG_DEBUG << "[Set] Bad D-Bus request error: "
624c3b3c92aSVijay Khemka                                          << ec;
625dd99e04bSP.K. Lee                         messages::internalError(asyncResp->res);
626dd99e04bSP.K. Lee                         return;
627dd99e04bSP.K. Lee                     }
628dd99e04bSP.K. Lee 
629dd99e04bSP.K. Lee                     messages::success(asyncResp->res);
630dd99e04bSP.K. Lee                 },
631c3b3c92aSVijay Khemka                 processName, objectPath, "org.freedesktop.DBus.Properties",
632c3b3c92aSVijay Khemka                 "Set", interfaceName, destProperty,
633168e20c1SEd Tanous                 dbus::utility::DbusVariantType{propertyValue});
634c3b3c92aSVijay Khemka         },
635c3b3c92aSVijay Khemka         busName, path, interface, method, "/", 0, interfaces);
636dd99e04bSP.K. Lee }
637dd99e04bSP.K. Lee 
638dd99e04bSP.K. Lee /**
639dd99e04bSP.K. Lee  * ChassisResetAction class supports the POST method for the Reset
640dd99e04bSP.K. Lee  * action.
641dd99e04bSP.K. Lee  * Function handles POST method request.
642dd99e04bSP.K. Lee  * Analyzes POST body before sending Reset request data to D-Bus.
643dd99e04bSP.K. Lee  */
6447e860f15SJohn Edward Broadbent 
6457e860f15SJohn Edward Broadbent inline void requestRoutesChassisResetAction(App& app)
646dd99e04bSP.K. Lee {
6477e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Actions/Chassis.Reset/")
648ed398213SEd Tanous         .privileges(redfish::privileges::postChassis)
6497e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
6507e860f15SJohn Edward Broadbent             [](const crow::Request& req,
6517e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
6527e860f15SJohn Edward Broadbent                const std::string&) {
653dd99e04bSP.K. Lee                 BMCWEB_LOG_DEBUG << "Post Chassis Reset.";
654dd99e04bSP.K. Lee 
655dd99e04bSP.K. Lee                 std::string resetType;
656dd99e04bSP.K. Lee 
6577e860f15SJohn Edward Broadbent                 if (!json_util::readJson(req, asyncResp->res, "ResetType",
6587e860f15SJohn Edward Broadbent                                          resetType))
659dd99e04bSP.K. Lee                 {
660dd99e04bSP.K. Lee                     return;
661dd99e04bSP.K. Lee                 }
662dd99e04bSP.K. Lee 
663dd99e04bSP.K. Lee                 if (resetType != "PowerCycle")
664dd99e04bSP.K. Lee                 {
665dd99e04bSP.K. Lee                     BMCWEB_LOG_DEBUG << "Invalid property value for ResetType: "
666dd99e04bSP.K. Lee                                      << resetType;
6677e860f15SJohn Edward Broadbent                     messages::actionParameterNotSupported(
6687e860f15SJohn Edward Broadbent                         asyncResp->res, resetType, "ResetType");
669dd99e04bSP.K. Lee 
670dd99e04bSP.K. Lee                     return;
671dd99e04bSP.K. Lee                 }
672dd99e04bSP.K. Lee                 doChassisPowerCycle(asyncResp);
6737e860f15SJohn Edward Broadbent             });
674dd99e04bSP.K. Lee }
6751cb1a9e6SAppaRao Puli 
6761cb1a9e6SAppaRao Puli /**
6771cb1a9e6SAppaRao Puli  * ChassisResetActionInfo derived class for delivering Chassis
6781cb1a9e6SAppaRao Puli  * ResetType AllowableValues using ResetInfo schema.
6791cb1a9e6SAppaRao Puli  */
6807e860f15SJohn Edward Broadbent inline void requestRoutesChassisResetActionInfo(App& app)
6811cb1a9e6SAppaRao Puli {
6827e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ResetActionInfo/")
683ed398213SEd Tanous         .privileges(redfish::privileges::getActionInfo)
6847e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
6857e860f15SJohn Edward Broadbent             [](const crow::Request&,
6867e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
6877e860f15SJohn Edward Broadbent                const std::string& chassisId)
6881cb1a9e6SAppaRao Puli 
6891cb1a9e6SAppaRao Puli             {
6908d1b46d7Szhanghch05                 asyncResp->res.jsonValue = {
6918d1b46d7Szhanghch05                     {"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"},
6928d1b46d7Szhanghch05                     {"@odata.id",
6938d1b46d7Szhanghch05                      "/redfish/v1/Chassis/" + chassisId + "/ResetActionInfo"},
6941cb1a9e6SAppaRao Puli                     {"Name", "Reset Action Info"},
6951cb1a9e6SAppaRao Puli                     {"Id", "ResetActionInfo"},
6961cb1a9e6SAppaRao Puli                     {"Parameters",
6971cb1a9e6SAppaRao Puli                      {{{"Name", "ResetType"},
6981cb1a9e6SAppaRao Puli                        {"Required", true},
6991cb1a9e6SAppaRao Puli                        {"DataType", "String"},
7001cb1a9e6SAppaRao Puli                        {"AllowableValues", {"PowerCycle"}}}}}};
7017e860f15SJohn Edward Broadbent             });
7021cb1a9e6SAppaRao Puli }
7031cb1a9e6SAppaRao Puli 
704e37f8451SRapkiewicz, Pawel } // namespace redfish
705