xref: /openbmc/bmcweb/features/redfish/lib/chassis.hpp (revision 8d1b46d7f8d39db2ba048f9e9007106ca3a28c9b)
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"
20e37f8451SRapkiewicz, Pawel #include "node.hpp"
211abe55efSEd Tanous 
22e37f8451SRapkiewicz, Pawel #include <boost/container/flat_map.hpp>
2302f6ff19SGunnar Mills #include <utils/collection.hpp>
241214b7e7SGunnar Mills 
25abf2add6SEd Tanous #include <variant>
26e37f8451SRapkiewicz, Pawel 
271abe55efSEd Tanous namespace redfish
281abe55efSEd Tanous {
29e37f8451SRapkiewicz, Pawel 
30e37f8451SRapkiewicz, Pawel /**
31beeca0aeSGunnar Mills  * @brief Retrieves chassis state properties over dbus
32beeca0aeSGunnar Mills  *
33beeca0aeSGunnar Mills  * @param[in] aResp - Shared pointer for completing asynchronous calls.
34beeca0aeSGunnar Mills  *
35beeca0aeSGunnar Mills  * @return None.
36beeca0aeSGunnar Mills  */
37*8d1b46d7Szhanghch05 inline void getChassisState(std::shared_ptr<bmcweb::AsyncResp> aResp)
38beeca0aeSGunnar Mills {
39beeca0aeSGunnar Mills     crow::connections::systemBus->async_method_call(
40beeca0aeSGunnar Mills         [aResp{std::move(aResp)}](
41beeca0aeSGunnar Mills             const boost::system::error_code ec,
42beeca0aeSGunnar Mills             const std::variant<std::string>& chassisState) {
43beeca0aeSGunnar Mills             if (ec)
44beeca0aeSGunnar Mills             {
45beeca0aeSGunnar Mills                 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
46beeca0aeSGunnar Mills                 messages::internalError(aResp->res);
47beeca0aeSGunnar Mills                 return;
48beeca0aeSGunnar Mills             }
49beeca0aeSGunnar Mills 
50beeca0aeSGunnar Mills             const std::string* s = std::get_if<std::string>(&chassisState);
51beeca0aeSGunnar Mills             BMCWEB_LOG_DEBUG << "Chassis state: " << *s;
52beeca0aeSGunnar Mills             if (s != nullptr)
53beeca0aeSGunnar Mills             {
54beeca0aeSGunnar Mills                 // Verify Chassis State
55beeca0aeSGunnar Mills                 if (*s == "xyz.openbmc_project.State.Chassis.PowerState.On")
56beeca0aeSGunnar Mills                 {
57beeca0aeSGunnar Mills                     aResp->res.jsonValue["PowerState"] = "On";
58beeca0aeSGunnar Mills                     aResp->res.jsonValue["Status"]["State"] = "Enabled";
59beeca0aeSGunnar Mills                 }
60beeca0aeSGunnar Mills                 else if (*s ==
61beeca0aeSGunnar Mills                          "xyz.openbmc_project.State.Chassis.PowerState.Off")
62beeca0aeSGunnar Mills                 {
63beeca0aeSGunnar Mills                     aResp->res.jsonValue["PowerState"] = "Off";
64beeca0aeSGunnar Mills                     aResp->res.jsonValue["Status"]["State"] = "StandbyOffline";
65beeca0aeSGunnar Mills                 }
66beeca0aeSGunnar Mills             }
67beeca0aeSGunnar Mills         },
68beeca0aeSGunnar Mills         "xyz.openbmc_project.State.Chassis",
69beeca0aeSGunnar Mills         "/xyz/openbmc_project/state/chassis0",
70beeca0aeSGunnar Mills         "org.freedesktop.DBus.Properties", "Get",
71beeca0aeSGunnar Mills         "xyz.openbmc_project.State.Chassis", "CurrentPowerState");
72beeca0aeSGunnar Mills }
73beeca0aeSGunnar Mills 
74beeca0aeSGunnar Mills /**
75e37f8451SRapkiewicz, Pawel  * DBus types primitives for several generic DBus interfaces
76e37f8451SRapkiewicz, Pawel  * TODO(Pawel) consider move this to separate file into boost::dbus
77e37f8451SRapkiewicz, Pawel  */
7855c7b7a2SEd Tanous // Note, this is not a very useful Variant, but because it isn't used to get
79aa2e59c1SEd Tanous // values, it should be as simple as possible
80aa2e59c1SEd Tanous // TODO(ed) invent a nullvariant type
815fd7ba65SCheng C Yang using VariantType = std::variant<bool, std::string, uint64_t, uint32_t>;
82aa2e59c1SEd Tanous using ManagedObjectsType = std::vector<std::pair<
83aa2e59c1SEd Tanous     sdbusplus::message::object_path,
84aa2e59c1SEd Tanous     std::vector<std::pair<std::string,
85aa2e59c1SEd Tanous                           std::vector<std::pair<std::string, VariantType>>>>>>;
86e37f8451SRapkiewicz, Pawel 
87aa2e59c1SEd Tanous using PropertiesType = boost::container::flat_map<std::string, VariantType>;
88e37f8451SRapkiewicz, Pawel 
89*8d1b46d7Szhanghch05 inline void getIntrusionByService(std::shared_ptr<bmcweb::AsyncResp> aResp,
90c181942fSQiang XU                                   const std::string& service,
91c181942fSQiang XU                                   const std::string& objPath)
92c181942fSQiang XU {
93c181942fSQiang XU     BMCWEB_LOG_DEBUG << "Get intrusion status by service \n";
94c181942fSQiang XU 
95c181942fSQiang XU     crow::connections::systemBus->async_method_call(
96c181942fSQiang XU         [aResp{std::move(aResp)}](const boost::system::error_code ec,
97c181942fSQiang XU                                   const std::variant<std::string>& value) {
98c181942fSQiang XU             if (ec)
99c181942fSQiang XU             {
1004e0453b1SGunnar Mills                 // do not add err msg in redfish response, because this is not
101c181942fSQiang XU                 //     mandatory property
102c181942fSQiang XU                 BMCWEB_LOG_ERROR << "DBUS response error " << ec << "\n";
103c181942fSQiang XU                 return;
104c181942fSQiang XU             }
105c181942fSQiang XU 
106c181942fSQiang XU             const std::string* status = std::get_if<std::string>(&value);
107c181942fSQiang XU 
108c181942fSQiang XU             if (status == nullptr)
109c181942fSQiang XU             {
110c181942fSQiang XU                 BMCWEB_LOG_ERROR << "intrusion status read error \n";
111c181942fSQiang XU                 return;
112c181942fSQiang XU             }
113c181942fSQiang XU 
114c181942fSQiang XU             aResp->res.jsonValue["PhysicalSecurity"] = {
115c181942fSQiang XU                 {"IntrusionSensorNumber", 1}, {"IntrusionSensor", *status}};
116c181942fSQiang XU         },
117c181942fSQiang XU         service, objPath, "org.freedesktop.DBus.Properties", "Get",
118c181942fSQiang XU         "xyz.openbmc_project.Chassis.Intrusion", "Status");
119c181942fSQiang XU }
120c181942fSQiang XU 
121c181942fSQiang XU /**
122c181942fSQiang XU  * Retrieves physical security properties over dbus
123c181942fSQiang XU  */
124*8d1b46d7Szhanghch05 inline void getPhysicalSecurityData(std::shared_ptr<bmcweb::AsyncResp> aResp)
125c181942fSQiang XU {
126c181942fSQiang XU     crow::connections::systemBus->async_method_call(
127c181942fSQiang XU         [aResp{std::move(aResp)}](
128c181942fSQiang XU             const boost::system::error_code ec,
129c181942fSQiang XU             const std::vector<std::pair<
130c181942fSQiang XU                 std::string,
1311214b7e7SGunnar Mills                 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1321214b7e7SGunnar Mills                 subtree) {
133c181942fSQiang XU             if (ec)
134c181942fSQiang XU             {
1354e0453b1SGunnar Mills                 // do not add err msg in redfish response, because this is not
136c181942fSQiang XU                 //     mandatory property
137c181942fSQiang XU                 BMCWEB_LOG_ERROR << "DBUS error: no matched iface " << ec
138c181942fSQiang XU                                  << "\n";
139c181942fSQiang XU                 return;
140c181942fSQiang XU             }
141c181942fSQiang XU             // Iterate over all retrieved ObjectPaths.
142c181942fSQiang XU             for (const auto& object : subtree)
143c181942fSQiang XU             {
144c181942fSQiang XU                 for (const auto& service : object.second)
145c181942fSQiang XU                 {
146c181942fSQiang XU                     getIntrusionByService(aResp, service.first, object.first);
147c181942fSQiang XU                     return;
148c181942fSQiang XU                 }
149c181942fSQiang XU             }
150c181942fSQiang XU         },
151c181942fSQiang XU         "xyz.openbmc_project.ObjectMapper",
152c181942fSQiang XU         "/xyz/openbmc_project/object_mapper",
153c181942fSQiang XU         "xyz.openbmc_project.ObjectMapper", "GetSubTree",
154271584abSEd Tanous         "/xyz/openbmc_project/Intrusion", 1,
155c181942fSQiang XU         std::array<const char*, 1>{"xyz.openbmc_project.Chassis.Intrusion"});
156c181942fSQiang XU }
157c181942fSQiang XU 
158e37f8451SRapkiewicz, Pawel /**
159e37f8451SRapkiewicz, Pawel  * ChassisCollection derived class for delivering Chassis Collection Schema
160e37f8451SRapkiewicz, Pawel  */
1611abe55efSEd Tanous class ChassisCollection : public Node
1621abe55efSEd Tanous {
163e37f8451SRapkiewicz, Pawel   public:
16452cc112dSEd Tanous     ChassisCollection(App& app) : Node(app, "/redfish/v1/Chassis/")
1651abe55efSEd Tanous     {
166e0d918bcSEd Tanous         entityPrivileges = {
167e0d918bcSEd Tanous             {boost::beast::http::verb::get, {{"Login"}}},
168e0d918bcSEd Tanous             {boost::beast::http::verb::head, {{"Login"}}},
169e0d918bcSEd Tanous             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
170e0d918bcSEd Tanous             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
171e0d918bcSEd Tanous             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
172e0d918bcSEd Tanous             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
173e37f8451SRapkiewicz, Pawel     }
174e37f8451SRapkiewicz, Pawel 
175e37f8451SRapkiewicz, Pawel   private:
176e37f8451SRapkiewicz, Pawel     /**
177e37f8451SRapkiewicz, Pawel      * Functions triggers appropriate requests on DBus
178e37f8451SRapkiewicz, Pawel      */
179*8d1b46d7Szhanghch05     void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
180*8d1b46d7Szhanghch05                const crow::Request&, const std::vector<std::string>&) override
1811abe55efSEd Tanous     {
182*8d1b46d7Szhanghch05         asyncResp->res.jsonValue["@odata.type"] =
183*8d1b46d7Szhanghch05             "#ChassisCollection.ChassisCollection";
184*8d1b46d7Szhanghch05         asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Chassis";
185*8d1b46d7Szhanghch05         asyncResp->res.jsonValue["Name"] = "Chassis Collection";
186e37f8451SRapkiewicz, Pawel 
18702f6ff19SGunnar Mills         collection_util::getCollectionMembers(
18802f6ff19SGunnar Mills             asyncResp, "/redfish/v1/Chassis",
18902f6ff19SGunnar Mills             {"xyz.openbmc_project.Inventory.Item.Board",
19002f6ff19SGunnar Mills              "xyz.openbmc_project.Inventory.Item.Chassis"});
19162d5e2e4SEd Tanous     }
192e37f8451SRapkiewicz, Pawel };
193e37f8451SRapkiewicz, Pawel 
194e37f8451SRapkiewicz, Pawel /**
195e37f8451SRapkiewicz, Pawel  * Chassis override class for delivering Chassis Schema
196e37f8451SRapkiewicz, Pawel  */
1971abe55efSEd Tanous class Chassis : public Node
1981abe55efSEd Tanous {
199e37f8451SRapkiewicz, Pawel   public:
20052cc112dSEd Tanous     Chassis(App& app) : Node(app, "/redfish/v1/Chassis/<str>/", std::string())
2011abe55efSEd Tanous     {
202e0d918bcSEd Tanous         entityPrivileges = {
203e0d918bcSEd Tanous             {boost::beast::http::verb::get, {{"Login"}}},
204e0d918bcSEd Tanous             {boost::beast::http::verb::head, {{"Login"}}},
205e0d918bcSEd Tanous             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
206e0d918bcSEd Tanous             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
207e0d918bcSEd Tanous             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
208e0d918bcSEd Tanous             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
209e37f8451SRapkiewicz, Pawel     }
210e37f8451SRapkiewicz, Pawel 
211e37f8451SRapkiewicz, Pawel   private:
212e37f8451SRapkiewicz, Pawel     /**
213e37f8451SRapkiewicz, Pawel      * Functions triggers appropriate requests on DBus
214e37f8451SRapkiewicz, Pawel      */
215*8d1b46d7Szhanghch05     void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
216*8d1b46d7Szhanghch05                const crow::Request&,
2171abe55efSEd Tanous                const std::vector<std::string>& params) override
2181abe55efSEd Tanous     {
219adc4f0dbSShawn McCarney         const std::array<const char*, 2> interfaces = {
220734bfe90SGunnar Mills             "xyz.openbmc_project.Inventory.Item.Board",
221adc4f0dbSShawn McCarney             "xyz.openbmc_project.Inventory.Item.Chassis"};
222734bfe90SGunnar Mills 
223e37f8451SRapkiewicz, Pawel         // Check if there is required param, truly entering this shall be
224e37f8451SRapkiewicz, Pawel         // impossible.
2251abe55efSEd Tanous         if (params.size() != 1)
2261abe55efSEd Tanous         {
227*8d1b46d7Szhanghch05             messages::internalError(asyncResp->res);
228e37f8451SRapkiewicz, Pawel             return;
229e37f8451SRapkiewicz, Pawel         }
23099cffd7fSShawn McCarney         const std::string& chassisId = params[0];
231e37f8451SRapkiewicz, Pawel 
23255c7b7a2SEd Tanous         crow::connections::systemBus->async_method_call(
23362d5e2e4SEd Tanous             [asyncResp, chassisId(std::string(chassisId))](
23462d5e2e4SEd Tanous                 const boost::system::error_code ec,
2351c8fba97SJames Feist                 const crow::openbmc_mapper::GetSubTreeType& subtree) {
23662d5e2e4SEd Tanous                 if (ec)
2371abe55efSEd Tanous                 {
238f12894f8SJason M. Bills                     messages::internalError(asyncResp->res);
239daf36e2eSEd Tanous                     return;
240daf36e2eSEd Tanous                 }
241daf36e2eSEd Tanous                 // Iterate over all retrieved ObjectPaths.
2421abe55efSEd Tanous                 for (const std::pair<
2431abe55efSEd Tanous                          std::string,
2441abe55efSEd Tanous                          std::vector<
2451214b7e7SGunnar Mills                              std::pair<std::string, std::vector<std::string>>>>&
2461214b7e7SGunnar Mills                          object : subtree)
2471abe55efSEd Tanous                 {
248daf36e2eSEd Tanous                     const std::string& path = object.first;
2491abe55efSEd Tanous                     const std::vector<
2501214b7e7SGunnar Mills                         std::pair<std::string, std::vector<std::string>>>&
2511214b7e7SGunnar Mills                         connectionNames = object.second;
252e0d918bcSEd Tanous 
2531abe55efSEd Tanous                     if (!boost::ends_with(path, chassisId))
2541abe55efSEd Tanous                     {
255daf36e2eSEd Tanous                         continue;
256daf36e2eSEd Tanous                     }
25726f03899SShawn McCarney 
258b49ac873SJames Feist                     auto health = std::make_shared<HealthPopulate>(asyncResp);
259b49ac873SJames Feist 
260b49ac873SJames Feist                     crow::connections::systemBus->async_method_call(
26123a21a1cSEd Tanous                         [health](const boost::system::error_code ec2,
262b49ac873SJames Feist                                  std::variant<std::vector<std::string>>& resp) {
26323a21a1cSEd Tanous                             if (ec2)
264b49ac873SJames Feist                             {
265b49ac873SJames Feist                                 return; // no sensors = no failures
266b49ac873SJames Feist                             }
267b49ac873SJames Feist                             std::vector<std::string>* data =
268b49ac873SJames Feist                                 std::get_if<std::vector<std::string>>(&resp);
269b49ac873SJames Feist                             if (data == nullptr)
270b49ac873SJames Feist                             {
271b49ac873SJames Feist                                 return;
272b49ac873SJames Feist                             }
273b49ac873SJames Feist                             health->inventory = std::move(*data);
274b49ac873SJames Feist                         },
275b49ac873SJames Feist                         "xyz.openbmc_project.ObjectMapper",
276b49ac873SJames Feist                         path + "/all_sensors",
277b49ac873SJames Feist                         "org.freedesktop.DBus.Properties", "Get",
278b49ac873SJames Feist                         "xyz.openbmc_project.Association", "endpoints");
279b49ac873SJames Feist 
280b49ac873SJames Feist                     health->populate();
281b49ac873SJames Feist 
2821abe55efSEd Tanous                     if (connectionNames.size() < 1)
2831abe55efSEd Tanous                     {
2841c8fba97SJames Feist                         BMCWEB_LOG_ERROR << "Got 0 Connection names";
285e0d918bcSEd Tanous                         continue;
286daf36e2eSEd Tanous                     }
287e0d918bcSEd Tanous 
28849c53ac9SJohnathan Mantey                     asyncResp->res.jsonValue["@odata.type"] =
2899f8bfa7cSGunnar Mills                         "#Chassis.v1_14_0.Chassis";
29049c53ac9SJohnathan Mantey                     asyncResp->res.jsonValue["@odata.id"] =
29149c53ac9SJohnathan Mantey                         "/redfish/v1/Chassis/" + chassisId;
29249c53ac9SJohnathan Mantey                     asyncResp->res.jsonValue["Name"] = "Chassis Collection";
29349c53ac9SJohnathan Mantey                     asyncResp->res.jsonValue["ChassisType"] = "RackMount";
294dd99e04bSP.K. Lee                     asyncResp->res.jsonValue["Actions"]["#Chassis.Reset"] = {
295dd99e04bSP.K. Lee                         {"target", "/redfish/v1/Chassis/" + chassisId +
296dd99e04bSP.K. Lee                                        "/Actions/Chassis.Reset"},
2971cb1a9e6SAppaRao Puli                         {"@Redfish.ActionInfo", "/redfish/v1/Chassis/" +
2981cb1a9e6SAppaRao Puli                                                     chassisId +
2991cb1a9e6SAppaRao Puli                                                     "/ResetActionInfo"}};
300adbe192aSJason M. Bills                     asyncResp->res.jsonValue["PCIeDevices"] = {
301adbe192aSJason M. Bills                         {"@odata.id",
302adbe192aSJason M. Bills                          "/redfish/v1/Systems/system/PCIeDevices"}};
30349c53ac9SJohnathan Mantey 
30449c53ac9SJohnathan Mantey                     const std::string& connectionName =
30549c53ac9SJohnathan Mantey                         connectionNames[0].first;
3061c8fba97SJames Feist 
30723a21a1cSEd Tanous                     const std::vector<std::string>& interfaces2 =
3081c8fba97SJames Feist                         connectionNames[0].second;
3091c8fba97SJames Feist                     const std::array<const char*, 2> hasIndicatorLed = {
3101c8fba97SJames Feist                         "xyz.openbmc_project.Inventory.Item.Panel",
3111c8fba97SJames Feist                         "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
3121c8fba97SJames Feist 
3131c8fba97SJames Feist                     for (const char* interface : hasIndicatorLed)
3141c8fba97SJames Feist                     {
31523a21a1cSEd Tanous                         if (std::find(interfaces2.begin(), interfaces2.end(),
31623a21a1cSEd Tanous                                       interface) != interfaces2.end())
3171c8fba97SJames Feist                         {
3181c8fba97SJames Feist                             getIndicatorLedState(asyncResp);
3199f8bfa7cSGunnar Mills                             getLocationIndicatorActive(asyncResp);
3201c8fba97SJames Feist                             break;
3211c8fba97SJames Feist                         }
3221c8fba97SJames Feist                     }
3231c8fba97SJames Feist 
32488ad7f03SSunnySrivastava1984                     const std::string locationInterface =
32588ad7f03SSunnySrivastava1984                         "xyz.openbmc_project.Inventory.Decorator.LocationCode";
32688ad7f03SSunnySrivastava1984                     if (std::find(interfaces2.begin(), interfaces2.end(),
32788ad7f03SSunnySrivastava1984                                   locationInterface) != interfaces2.end())
32888ad7f03SSunnySrivastava1984                     {
32988ad7f03SSunnySrivastava1984                         crow::connections::systemBus->async_method_call(
33088ad7f03SSunnySrivastava1984                             [asyncResp, chassisId(std::string(chassisId))](
33188ad7f03SSunnySrivastava1984                                 const boost::system::error_code ec,
33288ad7f03SSunnySrivastava1984                                 const std::variant<std::string>& property) {
33388ad7f03SSunnySrivastava1984                                 if (ec)
33488ad7f03SSunnySrivastava1984                                 {
33588ad7f03SSunnySrivastava1984                                     BMCWEB_LOG_DEBUG
33688ad7f03SSunnySrivastava1984                                         << "DBUS response error for Location";
33788ad7f03SSunnySrivastava1984                                     messages::internalError(asyncResp->res);
33888ad7f03SSunnySrivastava1984                                     return;
33988ad7f03SSunnySrivastava1984                                 }
34088ad7f03SSunnySrivastava1984 
34188ad7f03SSunnySrivastava1984                                 const std::string* value =
34288ad7f03SSunnySrivastava1984                                     std::get_if<std::string>(&property);
34388ad7f03SSunnySrivastava1984                                 if (value == nullptr)
34488ad7f03SSunnySrivastava1984                                 {
34588ad7f03SSunnySrivastava1984                                     BMCWEB_LOG_DEBUG << "Null value returned "
34688ad7f03SSunnySrivastava1984                                                         "for locaton code";
34788ad7f03SSunnySrivastava1984                                     messages::internalError(asyncResp->res);
34888ad7f03SSunnySrivastava1984                                     return;
34988ad7f03SSunnySrivastava1984                                 }
35088ad7f03SSunnySrivastava1984                                 asyncResp->res
35188ad7f03SSunnySrivastava1984                                     .jsonValue["Location"]["PartLocation"]
35288ad7f03SSunnySrivastava1984                                               ["ServiceLabel"] = *value;
35388ad7f03SSunnySrivastava1984                             },
35488ad7f03SSunnySrivastava1984                             connectionName, path,
35588ad7f03SSunnySrivastava1984                             "org.freedesktop.DBus.Properties", "Get",
35688ad7f03SSunnySrivastava1984                             locationInterface, "LocationCode");
35788ad7f03SSunnySrivastava1984                     }
35888ad7f03SSunnySrivastava1984 
35955c7b7a2SEd Tanous                     crow::connections::systemBus->async_method_call(
36062d5e2e4SEd Tanous                         [asyncResp, chassisId(std::string(chassisId))](
36190728b54SEd Tanous                             const boost::system::error_code /*ec2*/,
3621abe55efSEd Tanous                             const std::vector<std::pair<
3631abe55efSEd Tanous                                 std::string, VariantType>>& propertiesList) {
3641214b7e7SGunnar Mills                             for (const std::pair<std::string, VariantType>&
3651214b7e7SGunnar Mills                                      property : propertiesList)
3661abe55efSEd Tanous                             {
36799cffd7fSShawn McCarney                                 // Store DBus properties that are also Redfish
36899cffd7fSShawn McCarney                                 // properties with same name and a string value
36999cffd7fSShawn McCarney                                 const std::string& propertyName =
37099cffd7fSShawn McCarney                                     property.first;
37199cffd7fSShawn McCarney                                 if ((propertyName == "PartNumber") ||
37299cffd7fSShawn McCarney                                     (propertyName == "SerialNumber") ||
37399cffd7fSShawn McCarney                                     (propertyName == "Manufacturer") ||
37499cffd7fSShawn McCarney                                     (propertyName == "Model"))
37599cffd7fSShawn McCarney                                 {
376daf36e2eSEd Tanous                                     const std::string* value =
37799cffd7fSShawn McCarney                                         std::get_if<std::string>(
37899cffd7fSShawn McCarney                                             &property.second);
3791abe55efSEd Tanous                                     if (value != nullptr)
3801abe55efSEd Tanous                                     {
38199cffd7fSShawn McCarney                                         asyncResp->res.jsonValue[propertyName] =
38262d5e2e4SEd Tanous                                             *value;
383daf36e2eSEd Tanous                                     }
384daf36e2eSEd Tanous                                 }
38599cffd7fSShawn McCarney                             }
38662d5e2e4SEd Tanous                             asyncResp->res.jsonValue["Name"] = chassisId;
38762d5e2e4SEd Tanous                             asyncResp->res.jsonValue["Id"] = chassisId;
38862d5e2e4SEd Tanous                             asyncResp->res.jsonValue["Thermal"] = {
3891abe55efSEd Tanous                                 {"@odata.id", "/redfish/v1/Chassis/" +
3901abe55efSEd Tanous                                                   chassisId + "/Thermal"}};
3912474adfaSEd Tanous                             // Power object
3922474adfaSEd Tanous                             asyncResp->res.jsonValue["Power"] = {
3932474adfaSEd Tanous                                 {"@odata.id", "/redfish/v1/Chassis/" +
3942474adfaSEd Tanous                                                   chassisId + "/Power"}};
39595a3ecadSAnthony Wilson                             // SensorCollection
39695a3ecadSAnthony Wilson                             asyncResp->res.jsonValue["Sensors"] = {
39795a3ecadSAnthony Wilson                                 {"@odata.id", "/redfish/v1/Chassis/" +
39895a3ecadSAnthony Wilson                                                   chassisId + "/Sensors"}};
399029573d4SEd Tanous                             asyncResp->res.jsonValue["Status"] = {
400029573d4SEd Tanous                                 {"State", "Enabled"},
401029573d4SEd Tanous                             };
4022474adfaSEd Tanous 
403029573d4SEd Tanous                             asyncResp->res
404029573d4SEd Tanous                                 .jsonValue["Links"]["ComputerSystems"] = {
405029573d4SEd Tanous                                 {{"@odata.id", "/redfish/v1/Systems/system"}}};
406029573d4SEd Tanous                             asyncResp->res.jsonValue["Links"]["ManagedBy"] = {
407029573d4SEd Tanous                                 {{"@odata.id", "/redfish/v1/Managers/bmc"}}};
408beeca0aeSGunnar Mills                             getChassisState(asyncResp);
409daf36e2eSEd Tanous                         },
410daf36e2eSEd Tanous                         connectionName, path, "org.freedesktop.DBus.Properties",
4111abe55efSEd Tanous                         "GetAll",
4121abe55efSEd Tanous                         "xyz.openbmc_project.Inventory.Decorator.Asset");
413daf36e2eSEd Tanous                     return;
414daf36e2eSEd Tanous                 }
415e0d918bcSEd Tanous 
416daf36e2eSEd Tanous                 // Couldn't find an object with that name.  return an error
417f12894f8SJason M. Bills                 messages::resourceNotFound(
4189f8bfa7cSGunnar Mills                     asyncResp->res, "#Chassis.v1_14_0.Chassis", chassisId);
419daf36e2eSEd Tanous             },
420daf36e2eSEd Tanous             "xyz.openbmc_project.ObjectMapper",
421daf36e2eSEd Tanous             "/xyz/openbmc_project/object_mapper",
422daf36e2eSEd Tanous             "xyz.openbmc_project.ObjectMapper", "GetSubTree",
423271584abSEd Tanous             "/xyz/openbmc_project/inventory", 0, interfaces);
424c181942fSQiang XU 
425c181942fSQiang XU         getPhysicalSecurityData(asyncResp);
426e37f8451SRapkiewicz, Pawel     }
4271c8fba97SJames Feist 
428*8d1b46d7Szhanghch05     void doPatch(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
429*8d1b46d7Szhanghch05                  const crow::Request& req,
4301c8fba97SJames Feist                  const std::vector<std::string>& params) override
4311c8fba97SJames Feist     {
4329f8bfa7cSGunnar Mills         std::optional<bool> locationIndicatorActive;
4331c8fba97SJames Feist         std::optional<std::string> indicatorLed;
4341c8fba97SJames Feist 
4351c8fba97SJames Feist         if (params.size() != 1)
4361c8fba97SJames Feist         {
4371c8fba97SJames Feist             return;
4381c8fba97SJames Feist         }
4391c8fba97SJames Feist 
440*8d1b46d7Szhanghch05         if (!json_util::readJson(req, asyncResp->res, "LocationIndicatorActive",
4419f8bfa7cSGunnar Mills                                  locationIndicatorActive, "IndicatorLED",
4429f8bfa7cSGunnar Mills                                  indicatorLed))
4431c8fba97SJames Feist         {
4441c8fba97SJames Feist             return;
4451c8fba97SJames Feist         }
4461c8fba97SJames Feist 
4479f8bfa7cSGunnar Mills         // TODO (Gunnar): Remove IndicatorLED after enough time has passed
4489f8bfa7cSGunnar Mills         if (!locationIndicatorActive && !indicatorLed)
4491c8fba97SJames Feist         {
4501c8fba97SJames Feist             return; // delete this when we support more patch properties
4511c8fba97SJames Feist         }
452d6aa0093SGunnar Mills         if (indicatorLed)
453d6aa0093SGunnar Mills         {
454*8d1b46d7Szhanghch05             asyncResp->res.addHeader(boost::beast::http::field::warning,
455d6aa0093SGunnar Mills                                      "299 - \"IndicatorLED is deprecated. Use "
456d6aa0093SGunnar Mills                                      "LocationIndicatorActive instead.\"");
457d6aa0093SGunnar Mills         }
4581c8fba97SJames Feist 
4591c8fba97SJames Feist         const std::array<const char*, 2> interfaces = {
4601c8fba97SJames Feist             "xyz.openbmc_project.Inventory.Item.Board",
4611c8fba97SJames Feist             "xyz.openbmc_project.Inventory.Item.Chassis"};
4621c8fba97SJames Feist 
4631c8fba97SJames Feist         const std::string& chassisId = params[0];
4641c8fba97SJames Feist 
4651c8fba97SJames Feist         crow::connections::systemBus->async_method_call(
4669f8bfa7cSGunnar Mills             [asyncResp, chassisId, locationIndicatorActive, indicatorLed](
4671c8fba97SJames Feist                 const boost::system::error_code ec,
4681c8fba97SJames Feist                 const crow::openbmc_mapper::GetSubTreeType& subtree) {
4691c8fba97SJames Feist                 if (ec)
4701c8fba97SJames Feist                 {
4711c8fba97SJames Feist                     messages::internalError(asyncResp->res);
4721c8fba97SJames Feist                     return;
4731c8fba97SJames Feist                 }
4741c8fba97SJames Feist 
4751c8fba97SJames Feist                 // Iterate over all retrieved ObjectPaths.
4761c8fba97SJames Feist                 for (const std::pair<
4771c8fba97SJames Feist                          std::string,
4781c8fba97SJames Feist                          std::vector<
4791214b7e7SGunnar Mills                              std::pair<std::string, std::vector<std::string>>>>&
4801214b7e7SGunnar Mills                          object : subtree)
4811c8fba97SJames Feist                 {
4821c8fba97SJames Feist                     const std::string& path = object.first;
4831c8fba97SJames Feist                     const std::vector<
4841214b7e7SGunnar Mills                         std::pair<std::string, std::vector<std::string>>>&
4851214b7e7SGunnar Mills                         connectionNames = object.second;
4861c8fba97SJames Feist 
4871c8fba97SJames Feist                     if (!boost::ends_with(path, chassisId))
4881c8fba97SJames Feist                     {
4891c8fba97SJames Feist                         continue;
4901c8fba97SJames Feist                     }
4911c8fba97SJames Feist 
4921c8fba97SJames Feist                     if (connectionNames.size() < 1)
4931c8fba97SJames Feist                     {
4941c8fba97SJames Feist                         BMCWEB_LOG_ERROR << "Got 0 Connection names";
4951c8fba97SJames Feist                         continue;
4961c8fba97SJames Feist                     }
4971c8fba97SJames Feist 
49823a21a1cSEd Tanous                     const std::vector<std::string>& interfaces3 =
4991c8fba97SJames Feist                         connectionNames[0].second;
5001c8fba97SJames Feist 
5011c8fba97SJames Feist                     const std::array<const char*, 2> hasIndicatorLed = {
5021c8fba97SJames Feist                         "xyz.openbmc_project.Inventory.Item.Panel",
5031c8fba97SJames Feist                         "xyz.openbmc_project.Inventory.Item.Board."
5041c8fba97SJames Feist                         "Motherboard"};
5051c8fba97SJames Feist                     bool indicatorChassis = false;
5061c8fba97SJames Feist                     for (const char* interface : hasIndicatorLed)
5071c8fba97SJames Feist                     {
5089f8bfa7cSGunnar Mills                         if (std::find(interfaces3.begin(), interfaces3.end(),
50923a21a1cSEd Tanous                                       interface) != interfaces3.end())
5101c8fba97SJames Feist                         {
5111c8fba97SJames Feist                             indicatorChassis = true;
5121c8fba97SJames Feist                             break;
5131c8fba97SJames Feist                         }
5141c8fba97SJames Feist                     }
5159f8bfa7cSGunnar Mills                     if (locationIndicatorActive)
5169f8bfa7cSGunnar Mills                     {
5179f8bfa7cSGunnar Mills                         if (indicatorChassis)
5189f8bfa7cSGunnar Mills                         {
5199f8bfa7cSGunnar Mills                             setLocationIndicatorActive(
5209f8bfa7cSGunnar Mills                                 asyncResp, *locationIndicatorActive);
5219f8bfa7cSGunnar Mills                         }
5229f8bfa7cSGunnar Mills                         else
5239f8bfa7cSGunnar Mills                         {
5249f8bfa7cSGunnar Mills                             messages::propertyUnknown(
5259f8bfa7cSGunnar Mills                                 asyncResp->res, "LocationIndicatorActive");
5269f8bfa7cSGunnar Mills                         }
5279f8bfa7cSGunnar Mills                     }
5289f8bfa7cSGunnar Mills                     if (indicatorLed)
5299f8bfa7cSGunnar Mills                     {
5301c8fba97SJames Feist                         if (indicatorChassis)
5311c8fba97SJames Feist                         {
532f23b7296SEd Tanous                             setIndicatorLedState(asyncResp, *indicatorLed);
5331c8fba97SJames Feist                         }
5341c8fba97SJames Feist                         else
5351c8fba97SJames Feist                         {
5361c8fba97SJames Feist                             messages::propertyUnknown(asyncResp->res,
5371c8fba97SJames Feist                                                       "IndicatorLED");
5381c8fba97SJames Feist                         }
5391c8fba97SJames Feist                     }
5401c8fba97SJames Feist                     return;
5411c8fba97SJames Feist                 }
5421c8fba97SJames Feist 
5431c8fba97SJames Feist                 messages::resourceNotFound(
5449f8bfa7cSGunnar Mills                     asyncResp->res, "#Chassis.v1_14_0.Chassis", chassisId);
5451c8fba97SJames Feist             },
5461c8fba97SJames Feist             "xyz.openbmc_project.ObjectMapper",
5471c8fba97SJames Feist             "/xyz/openbmc_project/object_mapper",
5481c8fba97SJames Feist             "xyz.openbmc_project.ObjectMapper", "GetSubTree",
5491c8fba97SJames Feist             "/xyz/openbmc_project/inventory", 0, interfaces);
5501c8fba97SJames Feist     }
55162d5e2e4SEd Tanous };
552dd99e04bSP.K. Lee 
553*8d1b46d7Szhanghch05 inline void
554*8d1b46d7Szhanghch05     doChassisPowerCycle(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
555dd99e04bSP.K. Lee {
556c3b3c92aSVijay Khemka     const char* busName = "xyz.openbmc_project.ObjectMapper";
557c3b3c92aSVijay Khemka     const char* path = "/xyz/openbmc_project/object_mapper";
558c3b3c92aSVijay Khemka     const char* interface = "xyz.openbmc_project.ObjectMapper";
559c3b3c92aSVijay Khemka     const char* method = "GetSubTreePaths";
560c3b3c92aSVijay Khemka 
561c3b3c92aSVijay Khemka     const std::array<const char*, 1> interfaces = {
562c3b3c92aSVijay Khemka         "xyz.openbmc_project.State.Chassis"};
563c3b3c92aSVijay Khemka 
564c3b3c92aSVijay Khemka     // Use mapper to get subtree paths.
565c3b3c92aSVijay Khemka     crow::connections::systemBus->async_method_call(
566c3b3c92aSVijay Khemka         [asyncResp](const boost::system::error_code ec,
567c3b3c92aSVijay Khemka                     const std::vector<std::string>& chassisList) {
568c3b3c92aSVijay Khemka             if (ec)
569c3b3c92aSVijay Khemka             {
570c3b3c92aSVijay Khemka                 BMCWEB_LOG_DEBUG << "[mapper] Bad D-Bus request error: " << ec;
571c3b3c92aSVijay Khemka                 messages::internalError(asyncResp->res);
572c3b3c92aSVijay Khemka                 return;
573c3b3c92aSVijay Khemka             }
574c3b3c92aSVijay Khemka 
575dd99e04bSP.K. Lee             const char* processName = "xyz.openbmc_project.State.Chassis";
576dd99e04bSP.K. Lee             const char* interfaceName = "xyz.openbmc_project.State.Chassis";
577dd99e04bSP.K. Lee             const char* destProperty = "RequestedPowerTransition";
578dd99e04bSP.K. Lee             const std::string propertyValue =
579dd99e04bSP.K. Lee                 "xyz.openbmc_project.State.Chassis.Transition.PowerCycle";
580c3b3c92aSVijay Khemka             std::string objectPath =
581c3b3c92aSVijay Khemka                 "/xyz/openbmc_project/state/chassis_system0";
582c3b3c92aSVijay Khemka 
583c3b3c92aSVijay Khemka             /* Look for system reset chassis path */
584c3b3c92aSVijay Khemka             if ((std::find(chassisList.begin(), chassisList.end(),
585c3b3c92aSVijay Khemka                            objectPath)) == chassisList.end())
586c3b3c92aSVijay Khemka             {
587c3b3c92aSVijay Khemka                 /* We prefer to reset the full chassis_system, but if it doesn't
588c3b3c92aSVijay Khemka                  * exist on some platforms, fall back to a host-only power reset
589c3b3c92aSVijay Khemka                  */
590c3b3c92aSVijay Khemka                 objectPath = "/xyz/openbmc_project/state/chassis0";
591c3b3c92aSVijay Khemka             }
592dd99e04bSP.K. Lee 
593dd99e04bSP.K. Lee             crow::connections::systemBus->async_method_call(
594dd99e04bSP.K. Lee                 [asyncResp](const boost::system::error_code ec) {
595dd99e04bSP.K. Lee                     // Use "Set" method to set the property value.
596dd99e04bSP.K. Lee                     if (ec)
597dd99e04bSP.K. Lee                     {
598c3b3c92aSVijay Khemka                         BMCWEB_LOG_DEBUG << "[Set] Bad D-Bus request error: "
599c3b3c92aSVijay Khemka                                          << ec;
600dd99e04bSP.K. Lee                         messages::internalError(asyncResp->res);
601dd99e04bSP.K. Lee                         return;
602dd99e04bSP.K. Lee                     }
603dd99e04bSP.K. Lee 
604dd99e04bSP.K. Lee                     messages::success(asyncResp->res);
605dd99e04bSP.K. Lee                 },
606c3b3c92aSVijay Khemka                 processName, objectPath, "org.freedesktop.DBus.Properties",
607c3b3c92aSVijay Khemka                 "Set", interfaceName, destProperty,
608c3b3c92aSVijay Khemka                 std::variant<std::string>{propertyValue});
609c3b3c92aSVijay Khemka         },
610c3b3c92aSVijay Khemka         busName, path, interface, method, "/", 0, interfaces);
611dd99e04bSP.K. Lee }
612dd99e04bSP.K. Lee 
613dd99e04bSP.K. Lee /**
614dd99e04bSP.K. Lee  * ChassisResetAction class supports the POST method for the Reset
615dd99e04bSP.K. Lee  * action.
616dd99e04bSP.K. Lee  */
617dd99e04bSP.K. Lee class ChassisResetAction : public Node
618dd99e04bSP.K. Lee {
619dd99e04bSP.K. Lee   public:
62052cc112dSEd Tanous     ChassisResetAction(App& app) :
621dd99e04bSP.K. Lee         Node(app, "/redfish/v1/Chassis/<str>/Actions/Chassis.Reset/",
622dd99e04bSP.K. Lee              std::string())
623dd99e04bSP.K. Lee     {
624dd99e04bSP.K. Lee         entityPrivileges = {
625dd99e04bSP.K. Lee             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
626dd99e04bSP.K. Lee     }
627dd99e04bSP.K. Lee 
628dd99e04bSP.K. Lee   private:
629dd99e04bSP.K. Lee     /**
630dd99e04bSP.K. Lee      * Function handles POST method request.
631dd99e04bSP.K. Lee      * Analyzes POST body before sending Reset request data to D-Bus.
632dd99e04bSP.K. Lee      */
633*8d1b46d7Szhanghch05     void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
634*8d1b46d7Szhanghch05                 const crow::Request& req,
635cb13a392SEd Tanous                 const std::vector<std::string>&) override
636dd99e04bSP.K. Lee     {
637dd99e04bSP.K. Lee         BMCWEB_LOG_DEBUG << "Post Chassis Reset.";
638dd99e04bSP.K. Lee 
639dd99e04bSP.K. Lee         std::string resetType;
640dd99e04bSP.K. Lee 
641dd99e04bSP.K. Lee         if (!json_util::readJson(req, asyncResp->res, "ResetType", resetType))
642dd99e04bSP.K. Lee         {
643dd99e04bSP.K. Lee             return;
644dd99e04bSP.K. Lee         }
645dd99e04bSP.K. Lee 
646dd99e04bSP.K. Lee         if (resetType != "PowerCycle")
647dd99e04bSP.K. Lee         {
648dd99e04bSP.K. Lee             BMCWEB_LOG_DEBUG << "Invalid property value for ResetType: "
649dd99e04bSP.K. Lee                              << resetType;
650dd99e04bSP.K. Lee             messages::actionParameterNotSupported(asyncResp->res, resetType,
651dd99e04bSP.K. Lee                                                   "ResetType");
652dd99e04bSP.K. Lee 
653dd99e04bSP.K. Lee             return;
654dd99e04bSP.K. Lee         }
655dd99e04bSP.K. Lee         doChassisPowerCycle(asyncResp);
656dd99e04bSP.K. Lee     }
657dd99e04bSP.K. Lee };
6581cb1a9e6SAppaRao Puli 
6591cb1a9e6SAppaRao Puli /**
6601cb1a9e6SAppaRao Puli  * ChassisResetActionInfo derived class for delivering Chassis
6611cb1a9e6SAppaRao Puli  * ResetType AllowableValues using ResetInfo schema.
6621cb1a9e6SAppaRao Puli  */
6631cb1a9e6SAppaRao Puli class ChassisResetActionInfo : public Node
6641cb1a9e6SAppaRao Puli {
6651cb1a9e6SAppaRao Puli   public:
6661cb1a9e6SAppaRao Puli     /*
6671cb1a9e6SAppaRao Puli      * Default Constructor
6681cb1a9e6SAppaRao Puli      */
66952cc112dSEd Tanous     ChassisResetActionInfo(App& app) :
6701cb1a9e6SAppaRao Puli         Node(app, "/redfish/v1/Chassis/<str>/ResetActionInfo/", std::string())
6711cb1a9e6SAppaRao Puli     {
6721cb1a9e6SAppaRao Puli         entityPrivileges = {
6731cb1a9e6SAppaRao Puli             {boost::beast::http::verb::get, {{"Login"}}},
6741cb1a9e6SAppaRao Puli             {boost::beast::http::verb::head, {{"Login"}}},
6751cb1a9e6SAppaRao Puli             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
6761cb1a9e6SAppaRao Puli             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
6771cb1a9e6SAppaRao Puli             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
6781cb1a9e6SAppaRao Puli             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
6791cb1a9e6SAppaRao Puli     }
6801cb1a9e6SAppaRao Puli 
6811cb1a9e6SAppaRao Puli   private:
6821cb1a9e6SAppaRao Puli     /**
6831cb1a9e6SAppaRao Puli      * Functions triggers appropriate requests on DBus
6841cb1a9e6SAppaRao Puli      */
685*8d1b46d7Szhanghch05     void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
686*8d1b46d7Szhanghch05                const crow::Request&,
6871cb1a9e6SAppaRao Puli                const std::vector<std::string>& params) override
6881cb1a9e6SAppaRao Puli     {
6891cb1a9e6SAppaRao Puli         if (params.size() != 1)
6901cb1a9e6SAppaRao Puli         {
691*8d1b46d7Szhanghch05             messages::internalError(asyncResp->res);
6921cb1a9e6SAppaRao Puli             return;
6931cb1a9e6SAppaRao Puli         }
6941cb1a9e6SAppaRao Puli         const std::string& chassisId = params[0];
6951cb1a9e6SAppaRao Puli 
696*8d1b46d7Szhanghch05         asyncResp->res.jsonValue = {
697*8d1b46d7Szhanghch05             {"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"},
698*8d1b46d7Szhanghch05             {"@odata.id",
699*8d1b46d7Szhanghch05              "/redfish/v1/Chassis/" + chassisId + "/ResetActionInfo"},
7001cb1a9e6SAppaRao Puli             {"Name", "Reset Action Info"},
7011cb1a9e6SAppaRao Puli             {"Id", "ResetActionInfo"},
7021cb1a9e6SAppaRao Puli             {"Parameters",
7031cb1a9e6SAppaRao Puli              {{{"Name", "ResetType"},
7041cb1a9e6SAppaRao Puli                {"Required", true},
7051cb1a9e6SAppaRao Puli                {"DataType", "String"},
7061cb1a9e6SAppaRao Puli                {"AllowableValues", {"PowerCycle"}}}}}};
7071cb1a9e6SAppaRao Puli     }
7081cb1a9e6SAppaRao Puli };
7091cb1a9e6SAppaRao Puli 
710e37f8451SRapkiewicz, Pawel } // namespace redfish
711