xref: /openbmc/bmcweb/features/redfish/lib/chassis.hpp (revision 1c8fba97b1feb4164e9b54cd66aad530bbfc1826)
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"
19*1c8fba97SJames Feist #include "led.hpp"
20e37f8451SRapkiewicz, Pawel #include "node.hpp"
211abe55efSEd Tanous 
22e37f8451SRapkiewicz, Pawel #include <boost/container/flat_map.hpp>
23abf2add6SEd Tanous #include <variant>
24e37f8451SRapkiewicz, Pawel 
251abe55efSEd Tanous namespace redfish
261abe55efSEd Tanous {
27e37f8451SRapkiewicz, Pawel 
28e37f8451SRapkiewicz, Pawel /**
29beeca0aeSGunnar Mills  * @brief Retrieves chassis state properties over dbus
30beeca0aeSGunnar Mills  *
31beeca0aeSGunnar Mills  * @param[in] aResp - Shared pointer for completing asynchronous calls.
32beeca0aeSGunnar Mills  *
33beeca0aeSGunnar Mills  * @return None.
34beeca0aeSGunnar Mills  */
35beeca0aeSGunnar Mills void getChassisState(std::shared_ptr<AsyncResp> aResp)
36beeca0aeSGunnar Mills {
37beeca0aeSGunnar Mills     crow::connections::systemBus->async_method_call(
38beeca0aeSGunnar Mills         [aResp{std::move(aResp)}](
39beeca0aeSGunnar Mills             const boost::system::error_code ec,
40beeca0aeSGunnar Mills             const std::variant<std::string> &chassisState) {
41beeca0aeSGunnar Mills             if (ec)
42beeca0aeSGunnar Mills             {
43beeca0aeSGunnar Mills                 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
44beeca0aeSGunnar Mills                 messages::internalError(aResp->res);
45beeca0aeSGunnar Mills                 return;
46beeca0aeSGunnar Mills             }
47beeca0aeSGunnar Mills 
48beeca0aeSGunnar Mills             const std::string *s = std::get_if<std::string>(&chassisState);
49beeca0aeSGunnar Mills             BMCWEB_LOG_DEBUG << "Chassis state: " << *s;
50beeca0aeSGunnar Mills             if (s != nullptr)
51beeca0aeSGunnar Mills             {
52beeca0aeSGunnar Mills                 // Verify Chassis State
53beeca0aeSGunnar Mills                 if (*s == "xyz.openbmc_project.State.Chassis.PowerState.On")
54beeca0aeSGunnar Mills                 {
55beeca0aeSGunnar Mills                     aResp->res.jsonValue["PowerState"] = "On";
56beeca0aeSGunnar Mills                     aResp->res.jsonValue["Status"]["State"] = "Enabled";
57beeca0aeSGunnar Mills                 }
58beeca0aeSGunnar Mills                 else if (*s ==
59beeca0aeSGunnar Mills                          "xyz.openbmc_project.State.Chassis.PowerState.Off")
60beeca0aeSGunnar Mills                 {
61beeca0aeSGunnar Mills                     aResp->res.jsonValue["PowerState"] = "Off";
62beeca0aeSGunnar Mills                     aResp->res.jsonValue["Status"]["State"] = "StandbyOffline";
63beeca0aeSGunnar Mills                 }
64beeca0aeSGunnar Mills             }
65beeca0aeSGunnar Mills         },
66beeca0aeSGunnar Mills         "xyz.openbmc_project.State.Chassis",
67beeca0aeSGunnar Mills         "/xyz/openbmc_project/state/chassis0",
68beeca0aeSGunnar Mills         "org.freedesktop.DBus.Properties", "Get",
69beeca0aeSGunnar Mills         "xyz.openbmc_project.State.Chassis", "CurrentPowerState");
70beeca0aeSGunnar Mills }
71beeca0aeSGunnar Mills 
72beeca0aeSGunnar Mills /**
73e37f8451SRapkiewicz, Pawel  * DBus types primitives for several generic DBus interfaces
74e37f8451SRapkiewicz, Pawel  * TODO(Pawel) consider move this to separate file into boost::dbus
75e37f8451SRapkiewicz, Pawel  */
7655c7b7a2SEd Tanous // Note, this is not a very useful Variant, but because it isn't used to get
77aa2e59c1SEd Tanous // values, it should be as simple as possible
78aa2e59c1SEd Tanous // TODO(ed) invent a nullvariant type
795fd7ba65SCheng C Yang using VariantType = std::variant<bool, std::string, uint64_t, uint32_t>;
80aa2e59c1SEd Tanous using ManagedObjectsType = std::vector<std::pair<
81aa2e59c1SEd Tanous     sdbusplus::message::object_path,
82aa2e59c1SEd Tanous     std::vector<std::pair<std::string,
83aa2e59c1SEd Tanous                           std::vector<std::pair<std::string, VariantType>>>>>>;
84e37f8451SRapkiewicz, Pawel 
85aa2e59c1SEd Tanous using PropertiesType = boost::container::flat_map<std::string, VariantType>;
86e37f8451SRapkiewicz, Pawel 
87c181942fSQiang XU void getIntrusionByService(std::shared_ptr<AsyncResp> aResp,
88c181942fSQiang XU                            const std::string &service,
89c181942fSQiang XU                            const std::string &objPath)
90c181942fSQiang XU {
91c181942fSQiang XU     BMCWEB_LOG_DEBUG << "Get intrusion status by service \n";
92c181942fSQiang XU 
93c181942fSQiang XU     crow::connections::systemBus->async_method_call(
94c181942fSQiang XU         [aResp{std::move(aResp)}](const boost::system::error_code ec,
95c181942fSQiang XU                                   const std::variant<std::string> &value) {
96c181942fSQiang XU             if (ec)
97c181942fSQiang XU             {
98c181942fSQiang XU                 // do not add err msg in redfish response, becaues this is not
99c181942fSQiang XU                 //     mandatory property
100c181942fSQiang XU                 BMCWEB_LOG_ERROR << "DBUS response error " << ec << "\n";
101c181942fSQiang XU                 return;
102c181942fSQiang XU             }
103c181942fSQiang XU 
104c181942fSQiang XU             const std::string *status = std::get_if<std::string>(&value);
105c181942fSQiang XU 
106c181942fSQiang XU             if (status == nullptr)
107c181942fSQiang XU             {
108c181942fSQiang XU                 BMCWEB_LOG_ERROR << "intrusion status read error \n";
109c181942fSQiang XU                 return;
110c181942fSQiang XU             }
111c181942fSQiang XU 
112c181942fSQiang XU             aResp->res.jsonValue["PhysicalSecurity"] = {
113c181942fSQiang XU                 {"IntrusionSensorNumber", 1}, {"IntrusionSensor", *status}};
114c181942fSQiang XU         },
115c181942fSQiang XU         service, objPath, "org.freedesktop.DBus.Properties", "Get",
116c181942fSQiang XU         "xyz.openbmc_project.Chassis.Intrusion", "Status");
117c181942fSQiang XU }
118c181942fSQiang XU 
119c181942fSQiang XU /**
120c181942fSQiang XU  * Retrieves physical security properties over dbus
121c181942fSQiang XU  */
122c181942fSQiang XU void getPhysicalSecurityData(std::shared_ptr<AsyncResp> aResp)
123c181942fSQiang XU {
124c181942fSQiang XU     crow::connections::systemBus->async_method_call(
125c181942fSQiang XU         [aResp{std::move(aResp)}](
126c181942fSQiang XU             const boost::system::error_code ec,
127c181942fSQiang XU             const std::vector<std::pair<
128c181942fSQiang XU                 std::string,
129c181942fSQiang XU                 std::vector<std::pair<std::string, std::vector<std::string>>>>>
130c181942fSQiang XU                 &subtree) {
131c181942fSQiang XU             if (ec)
132c181942fSQiang XU             {
133c181942fSQiang XU                 // do not add err msg in redfish response, becaues this is not
134c181942fSQiang XU                 //     mandatory property
135c181942fSQiang XU                 BMCWEB_LOG_ERROR << "DBUS error: no matched iface " << ec
136c181942fSQiang XU                                  << "\n";
137c181942fSQiang XU                 return;
138c181942fSQiang XU             }
139c181942fSQiang XU             // Iterate over all retrieved ObjectPaths.
140c181942fSQiang XU             for (const auto &object : subtree)
141c181942fSQiang XU             {
142c181942fSQiang XU                 for (const auto &service : object.second)
143c181942fSQiang XU                 {
144c181942fSQiang XU                     getIntrusionByService(aResp, service.first, object.first);
145c181942fSQiang XU                     return;
146c181942fSQiang XU                 }
147c181942fSQiang XU             }
148c181942fSQiang XU         },
149c181942fSQiang XU         "xyz.openbmc_project.ObjectMapper",
150c181942fSQiang XU         "/xyz/openbmc_project/object_mapper",
151c181942fSQiang XU         "xyz.openbmc_project.ObjectMapper", "GetSubTree",
152271584abSEd Tanous         "/xyz/openbmc_project/Intrusion", 1,
153c181942fSQiang XU         std::array<const char *, 1>{"xyz.openbmc_project.Chassis.Intrusion"});
154c181942fSQiang XU }
155c181942fSQiang XU 
156e37f8451SRapkiewicz, Pawel /**
157e37f8451SRapkiewicz, Pawel  * ChassisCollection derived class for delivering Chassis Collection Schema
158e37f8451SRapkiewicz, Pawel  */
1591abe55efSEd Tanous class ChassisCollection : public Node
1601abe55efSEd Tanous {
161e37f8451SRapkiewicz, Pawel   public:
1621abe55efSEd Tanous     ChassisCollection(CrowApp &app) : Node(app, "/redfish/v1/Chassis/")
1631abe55efSEd Tanous     {
164e0d918bcSEd Tanous         entityPrivileges = {
165e0d918bcSEd Tanous             {boost::beast::http::verb::get, {{"Login"}}},
166e0d918bcSEd Tanous             {boost::beast::http::verb::head, {{"Login"}}},
167e0d918bcSEd Tanous             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
168e0d918bcSEd Tanous             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
169e0d918bcSEd Tanous             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
170e0d918bcSEd Tanous             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
171e37f8451SRapkiewicz, Pawel     }
172e37f8451SRapkiewicz, Pawel 
173e37f8451SRapkiewicz, Pawel   private:
174e37f8451SRapkiewicz, Pawel     /**
175e37f8451SRapkiewicz, Pawel      * Functions triggers appropriate requests on DBus
176e37f8451SRapkiewicz, Pawel      */
17755c7b7a2SEd Tanous     void doGet(crow::Response &res, const crow::Request &req,
1781abe55efSEd Tanous                const std::vector<std::string> &params) override
1791abe55efSEd Tanous     {
1800f74e643SEd Tanous         res.jsonValue["@odata.type"] = "#ChassisCollection.ChassisCollection";
1810f74e643SEd Tanous         res.jsonValue["@odata.id"] = "/redfish/v1/Chassis";
1820f74e643SEd Tanous         res.jsonValue["@odata.context"] =
1830f74e643SEd Tanous             "/redfish/v1/$metadata#ChassisCollection.ChassisCollection";
1840f74e643SEd Tanous         res.jsonValue["Name"] = "Chassis Collection";
1850f74e643SEd Tanous 
186adc4f0dbSShawn McCarney         const std::array<const char *, 2> interfaces = {
187603a6640SGunnar Mills             "xyz.openbmc_project.Inventory.Item.Board",
188adc4f0dbSShawn McCarney             "xyz.openbmc_project.Inventory.Item.Chassis"};
189603a6640SGunnar Mills 
19062d5e2e4SEd Tanous         auto asyncResp = std::make_shared<AsyncResp>(res);
19162d5e2e4SEd Tanous         crow::connections::systemBus->async_method_call(
19262d5e2e4SEd Tanous             [asyncResp](const boost::system::error_code ec,
19362d5e2e4SEd Tanous                         const std::vector<std::string> &chassisList) {
19462d5e2e4SEd Tanous                 if (ec)
1951abe55efSEd Tanous                 {
196f12894f8SJason M. Bills                     messages::internalError(asyncResp->res);
19762d5e2e4SEd Tanous                     return;
198e37f8451SRapkiewicz, Pawel                 }
19962d5e2e4SEd Tanous                 nlohmann::json &chassisArray =
20062d5e2e4SEd Tanous                     asyncResp->res.jsonValue["Members"];
20162d5e2e4SEd Tanous                 chassisArray = nlohmann::json::array();
20262d5e2e4SEd Tanous                 for (const std::string &objpath : chassisList)
20362d5e2e4SEd Tanous                 {
20462d5e2e4SEd Tanous                     std::size_t lastPos = objpath.rfind("/");
20562d5e2e4SEd Tanous                     if (lastPos == std::string::npos)
20662d5e2e4SEd Tanous                     {
20762d5e2e4SEd Tanous                         BMCWEB_LOG_ERROR << "Failed to find '/' in " << objpath;
20862d5e2e4SEd Tanous                         continue;
20962d5e2e4SEd Tanous                     }
21062d5e2e4SEd Tanous                     chassisArray.push_back(
21162d5e2e4SEd Tanous                         {{"@odata.id", "/redfish/v1/Chassis/" +
21262d5e2e4SEd Tanous                                            objpath.substr(lastPos + 1)}});
213e37f8451SRapkiewicz, Pawel                 }
214e37f8451SRapkiewicz, Pawel 
21562d5e2e4SEd Tanous                 asyncResp->res.jsonValue["Members@odata.count"] =
21662d5e2e4SEd Tanous                     chassisArray.size();
21762d5e2e4SEd Tanous             },
21862d5e2e4SEd Tanous             "xyz.openbmc_project.ObjectMapper",
21962d5e2e4SEd Tanous             "/xyz/openbmc_project/object_mapper",
22062d5e2e4SEd Tanous             "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
221271584abSEd Tanous             "/xyz/openbmc_project/inventory", 0, interfaces);
22262d5e2e4SEd Tanous     }
223e37f8451SRapkiewicz, Pawel };
224e37f8451SRapkiewicz, Pawel 
225e37f8451SRapkiewicz, Pawel /**
226e37f8451SRapkiewicz, Pawel  * Chassis override class for delivering Chassis Schema
227e37f8451SRapkiewicz, Pawel  */
2281abe55efSEd Tanous class Chassis : public Node
2291abe55efSEd Tanous {
230e37f8451SRapkiewicz, Pawel   public:
2311abe55efSEd Tanous     Chassis(CrowApp &app) :
2321abe55efSEd Tanous         Node(app, "/redfish/v1/Chassis/<str>/", std::string())
2331abe55efSEd Tanous     {
234e0d918bcSEd Tanous         entityPrivileges = {
235e0d918bcSEd Tanous             {boost::beast::http::verb::get, {{"Login"}}},
236e0d918bcSEd Tanous             {boost::beast::http::verb::head, {{"Login"}}},
237e0d918bcSEd Tanous             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
238e0d918bcSEd Tanous             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
239e0d918bcSEd Tanous             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
240e0d918bcSEd Tanous             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
241e37f8451SRapkiewicz, Pawel     }
242e37f8451SRapkiewicz, Pawel 
243e37f8451SRapkiewicz, Pawel   private:
244e37f8451SRapkiewicz, Pawel     /**
245e37f8451SRapkiewicz, Pawel      * Functions triggers appropriate requests on DBus
246e37f8451SRapkiewicz, Pawel      */
24755c7b7a2SEd Tanous     void doGet(crow::Response &res, const crow::Request &req,
2481abe55efSEd Tanous                const std::vector<std::string> &params) override
2491abe55efSEd Tanous     {
250adc4f0dbSShawn McCarney         const std::array<const char *, 2> interfaces = {
251734bfe90SGunnar Mills             "xyz.openbmc_project.Inventory.Item.Board",
252adc4f0dbSShawn McCarney             "xyz.openbmc_project.Inventory.Item.Chassis"};
253734bfe90SGunnar Mills 
254e37f8451SRapkiewicz, Pawel         // Check if there is required param, truly entering this shall be
255e37f8451SRapkiewicz, Pawel         // impossible.
2561abe55efSEd Tanous         if (params.size() != 1)
2571abe55efSEd Tanous         {
258f12894f8SJason M. Bills             messages::internalError(res);
259e37f8451SRapkiewicz, Pawel             res.end();
260e37f8451SRapkiewicz, Pawel             return;
261e37f8451SRapkiewicz, Pawel         }
26299cffd7fSShawn McCarney         const std::string &chassisId = params[0];
263e37f8451SRapkiewicz, Pawel 
26462d5e2e4SEd Tanous         auto asyncResp = std::make_shared<AsyncResp>(res);
26555c7b7a2SEd Tanous         crow::connections::systemBus->async_method_call(
26662d5e2e4SEd Tanous             [asyncResp, chassisId(std::string(chassisId))](
26762d5e2e4SEd Tanous                 const boost::system::error_code ec,
268*1c8fba97SJames Feist                 const crow::openbmc_mapper::GetSubTreeType &subtree) {
26962d5e2e4SEd Tanous                 if (ec)
2701abe55efSEd Tanous                 {
271f12894f8SJason M. Bills                     messages::internalError(asyncResp->res);
272daf36e2eSEd Tanous                     return;
273daf36e2eSEd Tanous                 }
274daf36e2eSEd Tanous                 // Iterate over all retrieved ObjectPaths.
2751abe55efSEd Tanous                 for (const std::pair<
2761abe55efSEd Tanous                          std::string,
2771abe55efSEd Tanous                          std::vector<
2781abe55efSEd Tanous                              std::pair<std::string, std::vector<std::string>>>>
2791abe55efSEd Tanous                          &object : subtree)
2801abe55efSEd Tanous                 {
281daf36e2eSEd Tanous                     const std::string &path = object.first;
2821abe55efSEd Tanous                     const std::vector<
2831abe55efSEd Tanous                         std::pair<std::string, std::vector<std::string>>>
284daf36e2eSEd Tanous                         &connectionNames = object.second;
285e0d918bcSEd Tanous 
2861abe55efSEd Tanous                     if (!boost::ends_with(path, chassisId))
2871abe55efSEd Tanous                     {
288daf36e2eSEd Tanous                         continue;
289daf36e2eSEd Tanous                     }
29026f03899SShawn McCarney 
291b49ac873SJames Feist                     auto health = std::make_shared<HealthPopulate>(asyncResp);
292b49ac873SJames Feist 
293b49ac873SJames Feist                     crow::connections::systemBus->async_method_call(
294b49ac873SJames Feist                         [health](const boost::system::error_code ec,
295b49ac873SJames Feist                                  std::variant<std::vector<std::string>> &resp) {
296b49ac873SJames Feist                             if (ec)
297b49ac873SJames Feist                             {
298b49ac873SJames Feist                                 return; // no sensors = no failures
299b49ac873SJames Feist                             }
300b49ac873SJames Feist                             std::vector<std::string> *data =
301b49ac873SJames Feist                                 std::get_if<std::vector<std::string>>(&resp);
302b49ac873SJames Feist                             if (data == nullptr)
303b49ac873SJames Feist                             {
304b49ac873SJames Feist                                 return;
305b49ac873SJames Feist                             }
306b49ac873SJames Feist                             health->inventory = std::move(*data);
307b49ac873SJames Feist                         },
308b49ac873SJames Feist                         "xyz.openbmc_project.ObjectMapper",
309b49ac873SJames Feist                         path + "/all_sensors",
310b49ac873SJames Feist                         "org.freedesktop.DBus.Properties", "Get",
311b49ac873SJames Feist                         "xyz.openbmc_project.Association", "endpoints");
312b49ac873SJames Feist 
313b49ac873SJames Feist                     health->populate();
314b49ac873SJames Feist 
3151abe55efSEd Tanous                     if (connectionNames.size() < 1)
3161abe55efSEd Tanous                     {
317*1c8fba97SJames Feist                         BMCWEB_LOG_ERROR << "Got 0 Connection names";
318e0d918bcSEd Tanous                         continue;
319daf36e2eSEd Tanous                     }
320e0d918bcSEd Tanous 
32149c53ac9SJohnathan Mantey                     asyncResp->res.jsonValue["@odata.type"] =
322adbe192aSJason M. Bills                         "#Chassis.v1_10_0.Chassis";
32349c53ac9SJohnathan Mantey                     asyncResp->res.jsonValue["@odata.id"] =
32449c53ac9SJohnathan Mantey                         "/redfish/v1/Chassis/" + chassisId;
32549c53ac9SJohnathan Mantey                     asyncResp->res.jsonValue["@odata.context"] =
32649c53ac9SJohnathan Mantey                         "/redfish/v1/$metadata#Chassis.Chassis";
32749c53ac9SJohnathan Mantey                     asyncResp->res.jsonValue["Name"] = "Chassis Collection";
32849c53ac9SJohnathan Mantey                     asyncResp->res.jsonValue["ChassisType"] = "RackMount";
329adbe192aSJason M. Bills                     asyncResp->res.jsonValue["PCIeDevices"] = {
330adbe192aSJason M. Bills                         {"@odata.id",
331adbe192aSJason M. Bills                          "/redfish/v1/Systems/system/PCIeDevices"}};
33249c53ac9SJohnathan Mantey 
33349c53ac9SJohnathan Mantey                     const std::string &connectionName =
33449c53ac9SJohnathan Mantey                         connectionNames[0].first;
335*1c8fba97SJames Feist 
336*1c8fba97SJames Feist                     const std::vector<std::string> &interfaces =
337*1c8fba97SJames Feist                         connectionNames[0].second;
338*1c8fba97SJames Feist                     const std::array<const char *, 2> hasIndicatorLed = {
339*1c8fba97SJames Feist                         "xyz.openbmc_project.Inventory.Item.Panel",
340*1c8fba97SJames Feist                         "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
341*1c8fba97SJames Feist 
342*1c8fba97SJames Feist                     for (const char *interface : hasIndicatorLed)
343*1c8fba97SJames Feist                     {
344*1c8fba97SJames Feist                         if (std::find(interfaces.begin(), interfaces.end(),
345*1c8fba97SJames Feist                                       interface) != interfaces.end())
346*1c8fba97SJames Feist                         {
347*1c8fba97SJames Feist                             getIndicatorLedState(asyncResp);
348*1c8fba97SJames Feist                             break;
349*1c8fba97SJames Feist                         }
350*1c8fba97SJames Feist                     }
351*1c8fba97SJames Feist 
35255c7b7a2SEd Tanous                     crow::connections::systemBus->async_method_call(
35362d5e2e4SEd Tanous                         [asyncResp, chassisId(std::string(chassisId))](
35462d5e2e4SEd Tanous                             const boost::system::error_code ec,
3551abe55efSEd Tanous                             const std::vector<std::pair<
3561abe55efSEd Tanous                                 std::string, VariantType>> &propertiesList) {
3571abe55efSEd Tanous                             for (const std::pair<std::string, VariantType>
3581abe55efSEd Tanous                                      &property : propertiesList)
3591abe55efSEd Tanous                             {
36099cffd7fSShawn McCarney                                 // Store DBus properties that are also Redfish
36199cffd7fSShawn McCarney                                 // properties with same name and a string value
36299cffd7fSShawn McCarney                                 const std::string &propertyName =
36399cffd7fSShawn McCarney                                     property.first;
36499cffd7fSShawn McCarney                                 if ((propertyName == "PartNumber") ||
36599cffd7fSShawn McCarney                                     (propertyName == "SerialNumber") ||
36699cffd7fSShawn McCarney                                     (propertyName == "Manufacturer") ||
36799cffd7fSShawn McCarney                                     (propertyName == "Model"))
36899cffd7fSShawn McCarney                                 {
369daf36e2eSEd Tanous                                     const std::string *value =
37099cffd7fSShawn McCarney                                         std::get_if<std::string>(
37199cffd7fSShawn McCarney                                             &property.second);
3721abe55efSEd Tanous                                     if (value != nullptr)
3731abe55efSEd Tanous                                     {
37499cffd7fSShawn McCarney                                         asyncResp->res.jsonValue[propertyName] =
37562d5e2e4SEd Tanous                                             *value;
376daf36e2eSEd Tanous                                     }
377daf36e2eSEd Tanous                                 }
37899cffd7fSShawn McCarney                             }
37962d5e2e4SEd Tanous                             asyncResp->res.jsonValue["Name"] = chassisId;
38062d5e2e4SEd Tanous                             asyncResp->res.jsonValue["Id"] = chassisId;
38162d5e2e4SEd Tanous                             asyncResp->res.jsonValue["Thermal"] = {
3821abe55efSEd Tanous                                 {"@odata.id", "/redfish/v1/Chassis/" +
3831abe55efSEd Tanous                                                   chassisId + "/Thermal"}};
3842474adfaSEd Tanous                             // Power object
3852474adfaSEd Tanous                             asyncResp->res.jsonValue["Power"] = {
3862474adfaSEd Tanous                                 {"@odata.id", "/redfish/v1/Chassis/" +
3872474adfaSEd Tanous                                                   chassisId + "/Power"}};
38895a3ecadSAnthony Wilson                             // SensorCollection
38995a3ecadSAnthony Wilson                             asyncResp->res.jsonValue["Sensors"] = {
39095a3ecadSAnthony Wilson                                 {"@odata.id", "/redfish/v1/Chassis/" +
39195a3ecadSAnthony Wilson                                                   chassisId + "/Sensors"}};
392029573d4SEd Tanous                             asyncResp->res.jsonValue["Status"] = {
393029573d4SEd Tanous                                 {"State", "Enabled"},
394029573d4SEd Tanous                             };
3952474adfaSEd Tanous 
396029573d4SEd Tanous                             asyncResp->res
397029573d4SEd Tanous                                 .jsonValue["Links"]["ComputerSystems"] = {
398029573d4SEd Tanous                                 {{"@odata.id", "/redfish/v1/Systems/system"}}};
399029573d4SEd Tanous                             asyncResp->res.jsonValue["Links"]["ManagedBy"] = {
400029573d4SEd Tanous                                 {{"@odata.id", "/redfish/v1/Managers/bmc"}}};
401beeca0aeSGunnar Mills                             getChassisState(asyncResp);
402daf36e2eSEd Tanous                         },
403daf36e2eSEd Tanous                         connectionName, path, "org.freedesktop.DBus.Properties",
4041abe55efSEd Tanous                         "GetAll",
4051abe55efSEd Tanous                         "xyz.openbmc_project.Inventory.Decorator.Asset");
406daf36e2eSEd Tanous                     return;
407daf36e2eSEd Tanous                 }
408e0d918bcSEd Tanous 
409daf36e2eSEd Tanous                 // Couldn't find an object with that name.  return an error
410f12894f8SJason M. Bills                 messages::resourceNotFound(
411adbe192aSJason M. Bills                     asyncResp->res, "#Chassis.v1_10_0.Chassis", chassisId);
412daf36e2eSEd Tanous             },
413daf36e2eSEd Tanous             "xyz.openbmc_project.ObjectMapper",
414daf36e2eSEd Tanous             "/xyz/openbmc_project/object_mapper",
415daf36e2eSEd Tanous             "xyz.openbmc_project.ObjectMapper", "GetSubTree",
416271584abSEd Tanous             "/xyz/openbmc_project/inventory", 0, interfaces);
417c181942fSQiang XU 
418c181942fSQiang XU         getPhysicalSecurityData(asyncResp);
419e37f8451SRapkiewicz, Pawel     }
420*1c8fba97SJames Feist 
421*1c8fba97SJames Feist     void doPatch(crow::Response &res, const crow::Request &req,
422*1c8fba97SJames Feist                  const std::vector<std::string> &params) override
423*1c8fba97SJames Feist     {
424*1c8fba97SJames Feist         std::optional<std::string> indicatorLed;
425*1c8fba97SJames Feist         auto asyncResp = std::make_shared<AsyncResp>(res);
426*1c8fba97SJames Feist 
427*1c8fba97SJames Feist         if (params.size() != 1)
428*1c8fba97SJames Feist         {
429*1c8fba97SJames Feist             return;
430*1c8fba97SJames Feist         }
431*1c8fba97SJames Feist 
432*1c8fba97SJames Feist         if (!json_util::readJson(req, res, "IndicatorLED", indicatorLed))
433*1c8fba97SJames Feist         {
434*1c8fba97SJames Feist             return;
435*1c8fba97SJames Feist         }
436*1c8fba97SJames Feist 
437*1c8fba97SJames Feist         if (!indicatorLed)
438*1c8fba97SJames Feist         {
439*1c8fba97SJames Feist             return; // delete this when we support more patch properties
440*1c8fba97SJames Feist         }
441*1c8fba97SJames Feist 
442*1c8fba97SJames Feist         const std::array<const char *, 2> interfaces = {
443*1c8fba97SJames Feist             "xyz.openbmc_project.Inventory.Item.Board",
444*1c8fba97SJames Feist             "xyz.openbmc_project.Inventory.Item.Chassis"};
445*1c8fba97SJames Feist 
446*1c8fba97SJames Feist         const std::string &chassisId = params[0];
447*1c8fba97SJames Feist 
448*1c8fba97SJames Feist         crow::connections::systemBus->async_method_call(
449*1c8fba97SJames Feist             [asyncResp, chassisId, indicatorLed](
450*1c8fba97SJames Feist                 const boost::system::error_code ec,
451*1c8fba97SJames Feist                 const crow::openbmc_mapper::GetSubTreeType &subtree) {
452*1c8fba97SJames Feist                 if (ec)
453*1c8fba97SJames Feist                 {
454*1c8fba97SJames Feist                     messages::internalError(asyncResp->res);
455*1c8fba97SJames Feist                     return;
456*1c8fba97SJames Feist                 }
457*1c8fba97SJames Feist 
458*1c8fba97SJames Feist                 // Iterate over all retrieved ObjectPaths.
459*1c8fba97SJames Feist                 for (const std::pair<
460*1c8fba97SJames Feist                          std::string,
461*1c8fba97SJames Feist                          std::vector<
462*1c8fba97SJames Feist                              std::pair<std::string, std::vector<std::string>>>>
463*1c8fba97SJames Feist                          &object : subtree)
464*1c8fba97SJames Feist                 {
465*1c8fba97SJames Feist                     const std::string &path = object.first;
466*1c8fba97SJames Feist                     const std::vector<
467*1c8fba97SJames Feist                         std::pair<std::string, std::vector<std::string>>>
468*1c8fba97SJames Feist                         &connectionNames = object.second;
469*1c8fba97SJames Feist 
470*1c8fba97SJames Feist                     if (!boost::ends_with(path, chassisId))
471*1c8fba97SJames Feist                     {
472*1c8fba97SJames Feist                         continue;
473*1c8fba97SJames Feist                     }
474*1c8fba97SJames Feist 
475*1c8fba97SJames Feist                     if (connectionNames.size() < 1)
476*1c8fba97SJames Feist                     {
477*1c8fba97SJames Feist                         BMCWEB_LOG_ERROR << "Got 0 Connection names";
478*1c8fba97SJames Feist                         continue;
479*1c8fba97SJames Feist                     }
480*1c8fba97SJames Feist 
481*1c8fba97SJames Feist                     const std::vector<std::string> &interfaces =
482*1c8fba97SJames Feist                         connectionNames[0].second;
483*1c8fba97SJames Feist 
484*1c8fba97SJames Feist                     if (indicatorLed)
485*1c8fba97SJames Feist                     {
486*1c8fba97SJames Feist                         const std::array<const char *, 2> hasIndicatorLed = {
487*1c8fba97SJames Feist                             "xyz.openbmc_project.Inventory.Item.Panel",
488*1c8fba97SJames Feist                             "xyz.openbmc_project.Inventory.Item.Board."
489*1c8fba97SJames Feist                             "Motherboard"};
490*1c8fba97SJames Feist                         bool indicatorChassis = false;
491*1c8fba97SJames Feist                         for (const char *interface : hasIndicatorLed)
492*1c8fba97SJames Feist                         {
493*1c8fba97SJames Feist                             if (std::find(interfaces.begin(), interfaces.end(),
494*1c8fba97SJames Feist                                           interface) != interfaces.end())
495*1c8fba97SJames Feist                             {
496*1c8fba97SJames Feist                                 indicatorChassis = true;
497*1c8fba97SJames Feist                                 break;
498*1c8fba97SJames Feist                             }
499*1c8fba97SJames Feist                         }
500*1c8fba97SJames Feist                         if (indicatorChassis)
501*1c8fba97SJames Feist                         {
502*1c8fba97SJames Feist                             setIndicatorLedState(asyncResp,
503*1c8fba97SJames Feist                                                  std::move(*indicatorLed));
504*1c8fba97SJames Feist                         }
505*1c8fba97SJames Feist                         else
506*1c8fba97SJames Feist                         {
507*1c8fba97SJames Feist                             messages::propertyUnknown(asyncResp->res,
508*1c8fba97SJames Feist                                                       "IndicatorLED");
509*1c8fba97SJames Feist                         }
510*1c8fba97SJames Feist                     }
511*1c8fba97SJames Feist                     return;
512*1c8fba97SJames Feist                 }
513*1c8fba97SJames Feist 
514*1c8fba97SJames Feist                 messages::resourceNotFound(
515*1c8fba97SJames Feist                     asyncResp->res, "#Chassis.v1_10_0.Chassis", chassisId);
516*1c8fba97SJames Feist             },
517*1c8fba97SJames Feist             "xyz.openbmc_project.ObjectMapper",
518*1c8fba97SJames Feist             "/xyz/openbmc_project/object_mapper",
519*1c8fba97SJames Feist             "xyz.openbmc_project.ObjectMapper", "GetSubTree",
520*1c8fba97SJames Feist             "/xyz/openbmc_project/inventory", 0, interfaces);
521*1c8fba97SJames Feist     }
52262d5e2e4SEd Tanous };
523e37f8451SRapkiewicz, Pawel } // namespace redfish
524