xref: /openbmc/bmcweb/features/redfish/lib/chassis.hpp (revision cb13a39253848ece442971301ade9c09d98bf08e)
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>
231214b7e7SGunnar Mills 
24abf2add6SEd Tanous #include <variant>
25e37f8451SRapkiewicz, Pawel 
261abe55efSEd Tanous namespace redfish
271abe55efSEd Tanous {
28e37f8451SRapkiewicz, Pawel 
29e37f8451SRapkiewicz, Pawel /**
30beeca0aeSGunnar Mills  * @brief Retrieves chassis state properties over dbus
31beeca0aeSGunnar Mills  *
32beeca0aeSGunnar Mills  * @param[in] aResp - Shared pointer for completing asynchronous calls.
33beeca0aeSGunnar Mills  *
34beeca0aeSGunnar Mills  * @return None.
35beeca0aeSGunnar Mills  */
3623a21a1cSEd Tanous inline void getChassisState(std::shared_ptr<AsyncResp> aResp)
37beeca0aeSGunnar Mills {
38beeca0aeSGunnar Mills     crow::connections::systemBus->async_method_call(
39beeca0aeSGunnar Mills         [aResp{std::move(aResp)}](
40beeca0aeSGunnar Mills             const boost::system::error_code ec,
41beeca0aeSGunnar Mills             const std::variant<std::string>& chassisState) {
42beeca0aeSGunnar Mills             if (ec)
43beeca0aeSGunnar Mills             {
44beeca0aeSGunnar Mills                 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
45beeca0aeSGunnar Mills                 messages::internalError(aResp->res);
46beeca0aeSGunnar Mills                 return;
47beeca0aeSGunnar Mills             }
48beeca0aeSGunnar Mills 
49beeca0aeSGunnar Mills             const std::string* s = std::get_if<std::string>(&chassisState);
50beeca0aeSGunnar Mills             BMCWEB_LOG_DEBUG << "Chassis state: " << *s;
51beeca0aeSGunnar Mills             if (s != nullptr)
52beeca0aeSGunnar Mills             {
53beeca0aeSGunnar Mills                 // Verify Chassis State
54beeca0aeSGunnar Mills                 if (*s == "xyz.openbmc_project.State.Chassis.PowerState.On")
55beeca0aeSGunnar Mills                 {
56beeca0aeSGunnar Mills                     aResp->res.jsonValue["PowerState"] = "On";
57beeca0aeSGunnar Mills                     aResp->res.jsonValue["Status"]["State"] = "Enabled";
58beeca0aeSGunnar Mills                 }
59beeca0aeSGunnar Mills                 else if (*s ==
60beeca0aeSGunnar Mills                          "xyz.openbmc_project.State.Chassis.PowerState.Off")
61beeca0aeSGunnar Mills                 {
62beeca0aeSGunnar Mills                     aResp->res.jsonValue["PowerState"] = "Off";
63beeca0aeSGunnar Mills                     aResp->res.jsonValue["Status"]["State"] = "StandbyOffline";
64beeca0aeSGunnar Mills                 }
65beeca0aeSGunnar Mills             }
66beeca0aeSGunnar Mills         },
67beeca0aeSGunnar Mills         "xyz.openbmc_project.State.Chassis",
68beeca0aeSGunnar Mills         "/xyz/openbmc_project/state/chassis0",
69beeca0aeSGunnar Mills         "org.freedesktop.DBus.Properties", "Get",
70beeca0aeSGunnar Mills         "xyz.openbmc_project.State.Chassis", "CurrentPowerState");
71beeca0aeSGunnar Mills }
72beeca0aeSGunnar Mills 
73beeca0aeSGunnar Mills /**
74e37f8451SRapkiewicz, Pawel  * DBus types primitives for several generic DBus interfaces
75e37f8451SRapkiewicz, Pawel  * TODO(Pawel) consider move this to separate file into boost::dbus
76e37f8451SRapkiewicz, Pawel  */
7755c7b7a2SEd Tanous // Note, this is not a very useful Variant, but because it isn't used to get
78aa2e59c1SEd Tanous // values, it should be as simple as possible
79aa2e59c1SEd Tanous // TODO(ed) invent a nullvariant type
805fd7ba65SCheng C Yang using VariantType = std::variant<bool, std::string, uint64_t, uint32_t>;
81aa2e59c1SEd Tanous using ManagedObjectsType = std::vector<std::pair<
82aa2e59c1SEd Tanous     sdbusplus::message::object_path,
83aa2e59c1SEd Tanous     std::vector<std::pair<std::string,
84aa2e59c1SEd Tanous                           std::vector<std::pair<std::string, VariantType>>>>>>;
85e37f8451SRapkiewicz, Pawel 
86aa2e59c1SEd Tanous using PropertiesType = boost::container::flat_map<std::string, VariantType>;
87e37f8451SRapkiewicz, Pawel 
8823a21a1cSEd Tanous inline void getIntrusionByService(std::shared_ptr<AsyncResp> aResp,
89c181942fSQiang XU                                   const std::string& service,
90c181942fSQiang XU                                   const std::string& objPath)
91c181942fSQiang XU {
92c181942fSQiang XU     BMCWEB_LOG_DEBUG << "Get intrusion status by service \n";
93c181942fSQiang XU 
94c181942fSQiang XU     crow::connections::systemBus->async_method_call(
95c181942fSQiang XU         [aResp{std::move(aResp)}](const boost::system::error_code ec,
96c181942fSQiang XU                                   const std::variant<std::string>& value) {
97c181942fSQiang XU             if (ec)
98c181942fSQiang XU             {
994e0453b1SGunnar Mills                 // do not add err msg in redfish response, because this is not
100c181942fSQiang XU                 //     mandatory property
101c181942fSQiang XU                 BMCWEB_LOG_ERROR << "DBUS response error " << ec << "\n";
102c181942fSQiang XU                 return;
103c181942fSQiang XU             }
104c181942fSQiang XU 
105c181942fSQiang XU             const std::string* status = std::get_if<std::string>(&value);
106c181942fSQiang XU 
107c181942fSQiang XU             if (status == nullptr)
108c181942fSQiang XU             {
109c181942fSQiang XU                 BMCWEB_LOG_ERROR << "intrusion status read error \n";
110c181942fSQiang XU                 return;
111c181942fSQiang XU             }
112c181942fSQiang XU 
113c181942fSQiang XU             aResp->res.jsonValue["PhysicalSecurity"] = {
114c181942fSQiang XU                 {"IntrusionSensorNumber", 1}, {"IntrusionSensor", *status}};
115c181942fSQiang XU         },
116c181942fSQiang XU         service, objPath, "org.freedesktop.DBus.Properties", "Get",
117c181942fSQiang XU         "xyz.openbmc_project.Chassis.Intrusion", "Status");
118c181942fSQiang XU }
119c181942fSQiang XU 
120c181942fSQiang XU /**
121c181942fSQiang XU  * Retrieves physical security properties over dbus
122c181942fSQiang XU  */
12323a21a1cSEd Tanous inline void getPhysicalSecurityData(std::shared_ptr<AsyncResp> aResp)
124c181942fSQiang XU {
125c181942fSQiang XU     crow::connections::systemBus->async_method_call(
126c181942fSQiang XU         [aResp{std::move(aResp)}](
127c181942fSQiang XU             const boost::system::error_code ec,
128c181942fSQiang XU             const std::vector<std::pair<
129c181942fSQiang XU                 std::string,
1301214b7e7SGunnar Mills                 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1311214b7e7SGunnar Mills                 subtree) {
132c181942fSQiang XU             if (ec)
133c181942fSQiang XU             {
1344e0453b1SGunnar Mills                 // do not add err msg in redfish response, because this is not
135c181942fSQiang XU                 //     mandatory property
136c181942fSQiang XU                 BMCWEB_LOG_ERROR << "DBUS error: no matched iface " << ec
137c181942fSQiang XU                                  << "\n";
138c181942fSQiang XU                 return;
139c181942fSQiang XU             }
140c181942fSQiang XU             // Iterate over all retrieved ObjectPaths.
141c181942fSQiang XU             for (const auto& object : subtree)
142c181942fSQiang XU             {
143c181942fSQiang XU                 for (const auto& service : object.second)
144c181942fSQiang XU                 {
145c181942fSQiang XU                     getIntrusionByService(aResp, service.first, object.first);
146c181942fSQiang XU                     return;
147c181942fSQiang XU                 }
148c181942fSQiang XU             }
149c181942fSQiang XU         },
150c181942fSQiang XU         "xyz.openbmc_project.ObjectMapper",
151c181942fSQiang XU         "/xyz/openbmc_project/object_mapper",
152c181942fSQiang XU         "xyz.openbmc_project.ObjectMapper", "GetSubTree",
153271584abSEd Tanous         "/xyz/openbmc_project/Intrusion", 1,
154c181942fSQiang XU         std::array<const char*, 1>{"xyz.openbmc_project.Chassis.Intrusion"});
155c181942fSQiang XU }
156c181942fSQiang XU 
157e37f8451SRapkiewicz, Pawel /**
158e37f8451SRapkiewicz, Pawel  * ChassisCollection derived class for delivering Chassis Collection Schema
159e37f8451SRapkiewicz, Pawel  */
1601abe55efSEd Tanous class ChassisCollection : public Node
1611abe55efSEd Tanous {
162e37f8451SRapkiewicz, Pawel   public:
16352cc112dSEd Tanous     ChassisCollection(App& app) : Node(app, "/redfish/v1/Chassis/")
1641abe55efSEd Tanous     {
165e0d918bcSEd Tanous         entityPrivileges = {
166e0d918bcSEd Tanous             {boost::beast::http::verb::get, {{"Login"}}},
167e0d918bcSEd Tanous             {boost::beast::http::verb::head, {{"Login"}}},
168e0d918bcSEd Tanous             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
169e0d918bcSEd Tanous             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
170e0d918bcSEd Tanous             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
171e0d918bcSEd Tanous             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
172e37f8451SRapkiewicz, Pawel     }
173e37f8451SRapkiewicz, Pawel 
174e37f8451SRapkiewicz, Pawel   private:
175e37f8451SRapkiewicz, Pawel     /**
176e37f8451SRapkiewicz, Pawel      * Functions triggers appropriate requests on DBus
177e37f8451SRapkiewicz, Pawel      */
178*cb13a392SEd Tanous     void doGet(crow::Response& res, const crow::Request&,
179*cb13a392SEd Tanous                const std::vector<std::string>&) override
1801abe55efSEd Tanous     {
1810f74e643SEd Tanous         res.jsonValue["@odata.type"] = "#ChassisCollection.ChassisCollection";
1820f74e643SEd Tanous         res.jsonValue["@odata.id"] = "/redfish/v1/Chassis";
1830f74e643SEd Tanous         res.jsonValue["Name"] = "Chassis Collection";
1840f74e643SEd Tanous 
185adc4f0dbSShawn McCarney         const std::array<const char*, 2> interfaces = {
186603a6640SGunnar Mills             "xyz.openbmc_project.Inventory.Item.Board",
187adc4f0dbSShawn McCarney             "xyz.openbmc_project.Inventory.Item.Chassis"};
188603a6640SGunnar Mills 
18962d5e2e4SEd Tanous         auto asyncResp = std::make_shared<AsyncResp>(res);
19062d5e2e4SEd Tanous         crow::connections::systemBus->async_method_call(
19162d5e2e4SEd Tanous             [asyncResp](const boost::system::error_code ec,
19262d5e2e4SEd Tanous                         const std::vector<std::string>& chassisList) {
19362d5e2e4SEd Tanous                 if (ec)
1941abe55efSEd Tanous                 {
195f12894f8SJason M. Bills                     messages::internalError(asyncResp->res);
19662d5e2e4SEd Tanous                     return;
197e37f8451SRapkiewicz, Pawel                 }
19862d5e2e4SEd Tanous                 nlohmann::json& chassisArray =
19962d5e2e4SEd Tanous                     asyncResp->res.jsonValue["Members"];
20062d5e2e4SEd Tanous                 chassisArray = nlohmann::json::array();
20162d5e2e4SEd Tanous                 for (const std::string& objpath : chassisList)
20262d5e2e4SEd Tanous                 {
20362d5e2e4SEd Tanous                     std::size_t lastPos = objpath.rfind("/");
20462d5e2e4SEd Tanous                     if (lastPos == std::string::npos)
20562d5e2e4SEd Tanous                     {
20662d5e2e4SEd Tanous                         BMCWEB_LOG_ERROR << "Failed to find '/' in " << objpath;
20762d5e2e4SEd Tanous                         continue;
20862d5e2e4SEd Tanous                     }
20962d5e2e4SEd Tanous                     chassisArray.push_back(
21062d5e2e4SEd Tanous                         {{"@odata.id", "/redfish/v1/Chassis/" +
21162d5e2e4SEd Tanous                                            objpath.substr(lastPos + 1)}});
212e37f8451SRapkiewicz, Pawel                 }
213e37f8451SRapkiewicz, Pawel 
21462d5e2e4SEd Tanous                 asyncResp->res.jsonValue["Members@odata.count"] =
21562d5e2e4SEd Tanous                     chassisArray.size();
21662d5e2e4SEd Tanous             },
21762d5e2e4SEd Tanous             "xyz.openbmc_project.ObjectMapper",
21862d5e2e4SEd Tanous             "/xyz/openbmc_project/object_mapper",
21962d5e2e4SEd Tanous             "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
220271584abSEd Tanous             "/xyz/openbmc_project/inventory", 0, interfaces);
22162d5e2e4SEd Tanous     }
222e37f8451SRapkiewicz, Pawel };
223e37f8451SRapkiewicz, Pawel 
224e37f8451SRapkiewicz, Pawel /**
225e37f8451SRapkiewicz, Pawel  * Chassis override class for delivering Chassis Schema
226e37f8451SRapkiewicz, Pawel  */
2271abe55efSEd Tanous class Chassis : public Node
2281abe55efSEd Tanous {
229e37f8451SRapkiewicz, Pawel   public:
23052cc112dSEd Tanous     Chassis(App& app) : Node(app, "/redfish/v1/Chassis/<str>/", std::string())
2311abe55efSEd Tanous     {
232e0d918bcSEd Tanous         entityPrivileges = {
233e0d918bcSEd Tanous             {boost::beast::http::verb::get, {{"Login"}}},
234e0d918bcSEd Tanous             {boost::beast::http::verb::head, {{"Login"}}},
235e0d918bcSEd Tanous             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
236e0d918bcSEd Tanous             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
237e0d918bcSEd Tanous             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
238e0d918bcSEd Tanous             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
239e37f8451SRapkiewicz, Pawel     }
240e37f8451SRapkiewicz, Pawel 
241e37f8451SRapkiewicz, Pawel   private:
242e37f8451SRapkiewicz, Pawel     /**
243e37f8451SRapkiewicz, Pawel      * Functions triggers appropriate requests on DBus
244e37f8451SRapkiewicz, Pawel      */
245*cb13a392SEd Tanous     void doGet(crow::Response& res, const crow::Request&,
2461abe55efSEd Tanous                const std::vector<std::string>& params) override
2471abe55efSEd Tanous     {
248adc4f0dbSShawn McCarney         const std::array<const char*, 2> interfaces = {
249734bfe90SGunnar Mills             "xyz.openbmc_project.Inventory.Item.Board",
250adc4f0dbSShawn McCarney             "xyz.openbmc_project.Inventory.Item.Chassis"};
251734bfe90SGunnar Mills 
252e37f8451SRapkiewicz, Pawel         // Check if there is required param, truly entering this shall be
253e37f8451SRapkiewicz, Pawel         // impossible.
2541abe55efSEd Tanous         if (params.size() != 1)
2551abe55efSEd Tanous         {
256f12894f8SJason M. Bills             messages::internalError(res);
257e37f8451SRapkiewicz, Pawel             res.end();
258e37f8451SRapkiewicz, Pawel             return;
259e37f8451SRapkiewicz, Pawel         }
26099cffd7fSShawn McCarney         const std::string& chassisId = params[0];
261e37f8451SRapkiewicz, Pawel 
26262d5e2e4SEd Tanous         auto asyncResp = std::make_shared<AsyncResp>(res);
26355c7b7a2SEd Tanous         crow::connections::systemBus->async_method_call(
26462d5e2e4SEd Tanous             [asyncResp, chassisId(std::string(chassisId))](
26562d5e2e4SEd Tanous                 const boost::system::error_code ec,
2661c8fba97SJames Feist                 const crow::openbmc_mapper::GetSubTreeType& subtree) {
26762d5e2e4SEd Tanous                 if (ec)
2681abe55efSEd Tanous                 {
269f12894f8SJason M. Bills                     messages::internalError(asyncResp->res);
270daf36e2eSEd Tanous                     return;
271daf36e2eSEd Tanous                 }
272daf36e2eSEd Tanous                 // Iterate over all retrieved ObjectPaths.
2731abe55efSEd Tanous                 for (const std::pair<
2741abe55efSEd Tanous                          std::string,
2751abe55efSEd Tanous                          std::vector<
2761214b7e7SGunnar Mills                              std::pair<std::string, std::vector<std::string>>>>&
2771214b7e7SGunnar Mills                          object : subtree)
2781abe55efSEd Tanous                 {
279daf36e2eSEd Tanous                     const std::string& path = object.first;
2801abe55efSEd Tanous                     const std::vector<
2811214b7e7SGunnar Mills                         std::pair<std::string, std::vector<std::string>>>&
2821214b7e7SGunnar Mills                         connectionNames = object.second;
283e0d918bcSEd Tanous 
2841abe55efSEd Tanous                     if (!boost::ends_with(path, chassisId))
2851abe55efSEd Tanous                     {
286daf36e2eSEd Tanous                         continue;
287daf36e2eSEd Tanous                     }
28826f03899SShawn McCarney 
289b49ac873SJames Feist                     auto health = std::make_shared<HealthPopulate>(asyncResp);
290b49ac873SJames Feist 
291b49ac873SJames Feist                     crow::connections::systemBus->async_method_call(
29223a21a1cSEd Tanous                         [health](const boost::system::error_code ec2,
293b49ac873SJames Feist                                  std::variant<std::vector<std::string>>& resp) {
29423a21a1cSEd Tanous                             if (ec2)
295b49ac873SJames Feist                             {
296b49ac873SJames Feist                                 return; // no sensors = no failures
297b49ac873SJames Feist                             }
298b49ac873SJames Feist                             std::vector<std::string>* data =
299b49ac873SJames Feist                                 std::get_if<std::vector<std::string>>(&resp);
300b49ac873SJames Feist                             if (data == nullptr)
301b49ac873SJames Feist                             {
302b49ac873SJames Feist                                 return;
303b49ac873SJames Feist                             }
304b49ac873SJames Feist                             health->inventory = std::move(*data);
305b49ac873SJames Feist                         },
306b49ac873SJames Feist                         "xyz.openbmc_project.ObjectMapper",
307b49ac873SJames Feist                         path + "/all_sensors",
308b49ac873SJames Feist                         "org.freedesktop.DBus.Properties", "Get",
309b49ac873SJames Feist                         "xyz.openbmc_project.Association", "endpoints");
310b49ac873SJames Feist 
311b49ac873SJames Feist                     health->populate();
312b49ac873SJames Feist 
3131abe55efSEd Tanous                     if (connectionNames.size() < 1)
3141abe55efSEd Tanous                     {
3151c8fba97SJames Feist                         BMCWEB_LOG_ERROR << "Got 0 Connection names";
316e0d918bcSEd Tanous                         continue;
317daf36e2eSEd Tanous                     }
318e0d918bcSEd Tanous 
31949c53ac9SJohnathan Mantey                     asyncResp->res.jsonValue["@odata.type"] =
320adbe192aSJason M. Bills                         "#Chassis.v1_10_0.Chassis";
32149c53ac9SJohnathan Mantey                     asyncResp->res.jsonValue["@odata.id"] =
32249c53ac9SJohnathan Mantey                         "/redfish/v1/Chassis/" + chassisId;
32349c53ac9SJohnathan Mantey                     asyncResp->res.jsonValue["Name"] = "Chassis Collection";
32449c53ac9SJohnathan Mantey                     asyncResp->res.jsonValue["ChassisType"] = "RackMount";
325dd99e04bSP.K. Lee                     asyncResp->res.jsonValue["Actions"]["#Chassis.Reset"] = {
326dd99e04bSP.K. Lee                         {"target", "/redfish/v1/Chassis/" + chassisId +
327dd99e04bSP.K. Lee                                        "/Actions/Chassis.Reset"},
3281cb1a9e6SAppaRao Puli                         {"@Redfish.ActionInfo", "/redfish/v1/Chassis/" +
3291cb1a9e6SAppaRao Puli                                                     chassisId +
3301cb1a9e6SAppaRao Puli                                                     "/ResetActionInfo"}};
331adbe192aSJason M. Bills                     asyncResp->res.jsonValue["PCIeDevices"] = {
332adbe192aSJason M. Bills                         {"@odata.id",
333adbe192aSJason M. Bills                          "/redfish/v1/Systems/system/PCIeDevices"}};
33449c53ac9SJohnathan Mantey 
33549c53ac9SJohnathan Mantey                     const std::string& connectionName =
33649c53ac9SJohnathan Mantey                         connectionNames[0].first;
3371c8fba97SJames Feist 
33823a21a1cSEd Tanous                     const std::vector<std::string>& interfaces2 =
3391c8fba97SJames Feist                         connectionNames[0].second;
3401c8fba97SJames Feist                     const std::array<const char*, 2> hasIndicatorLed = {
3411c8fba97SJames Feist                         "xyz.openbmc_project.Inventory.Item.Panel",
3421c8fba97SJames Feist                         "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
3431c8fba97SJames Feist 
3441c8fba97SJames Feist                     for (const char* interface : hasIndicatorLed)
3451c8fba97SJames Feist                     {
34623a21a1cSEd Tanous                         if (std::find(interfaces2.begin(), interfaces2.end(),
34723a21a1cSEd Tanous                                       interface) != interfaces2.end())
3481c8fba97SJames Feist                         {
3491c8fba97SJames Feist                             getIndicatorLedState(asyncResp);
3501c8fba97SJames Feist                             break;
3511c8fba97SJames Feist                         }
3521c8fba97SJames Feist                     }
3531c8fba97SJames Feist 
35455c7b7a2SEd Tanous                     crow::connections::systemBus->async_method_call(
35562d5e2e4SEd Tanous                         [asyncResp, chassisId(std::string(chassisId))](
35623a21a1cSEd Tanous                             const boost::system::error_code ec2,
3571abe55efSEd Tanous                             const std::vector<std::pair<
3581abe55efSEd Tanous                                 std::string, VariantType>>& propertiesList) {
359*cb13a392SEd Tanous                             if (ec2)
360*cb13a392SEd Tanous                             {
361*cb13a392SEd Tanous                                 return;
362*cb13a392SEd Tanous                             }
363*cb13a392SEd Tanous 
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(
418adbe192aSJason M. Bills                     asyncResp->res, "#Chassis.v1_10_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 
4281c8fba97SJames Feist     void doPatch(crow::Response& res, const crow::Request& req,
4291c8fba97SJames Feist                  const std::vector<std::string>& params) override
4301c8fba97SJames Feist     {
4311c8fba97SJames Feist         std::optional<std::string> indicatorLed;
4321c8fba97SJames Feist         auto asyncResp = std::make_shared<AsyncResp>(res);
4331c8fba97SJames Feist 
4341c8fba97SJames Feist         if (params.size() != 1)
4351c8fba97SJames Feist         {
4361c8fba97SJames Feist             return;
4371c8fba97SJames Feist         }
4381c8fba97SJames Feist 
4391c8fba97SJames Feist         if (!json_util::readJson(req, res, "IndicatorLED", indicatorLed))
4401c8fba97SJames Feist         {
4411c8fba97SJames Feist             return;
4421c8fba97SJames Feist         }
4431c8fba97SJames Feist 
4441c8fba97SJames Feist         if (!indicatorLed)
4451c8fba97SJames Feist         {
4461c8fba97SJames Feist             return; // delete this when we support more patch properties
4471c8fba97SJames Feist         }
4481c8fba97SJames Feist 
4491c8fba97SJames Feist         const std::array<const char*, 2> interfaces = {
4501c8fba97SJames Feist             "xyz.openbmc_project.Inventory.Item.Board",
4511c8fba97SJames Feist             "xyz.openbmc_project.Inventory.Item.Chassis"};
4521c8fba97SJames Feist 
4531c8fba97SJames Feist         const std::string& chassisId = params[0];
4541c8fba97SJames Feist 
4551c8fba97SJames Feist         crow::connections::systemBus->async_method_call(
4561c8fba97SJames Feist             [asyncResp, chassisId, indicatorLed](
4571c8fba97SJames Feist                 const boost::system::error_code ec,
4581c8fba97SJames Feist                 const crow::openbmc_mapper::GetSubTreeType& subtree) {
4591c8fba97SJames Feist                 if (ec)
4601c8fba97SJames Feist                 {
4611c8fba97SJames Feist                     messages::internalError(asyncResp->res);
4621c8fba97SJames Feist                     return;
4631c8fba97SJames Feist                 }
4641c8fba97SJames Feist 
4651c8fba97SJames Feist                 // Iterate over all retrieved ObjectPaths.
4661c8fba97SJames Feist                 for (const std::pair<
4671c8fba97SJames Feist                          std::string,
4681c8fba97SJames Feist                          std::vector<
4691214b7e7SGunnar Mills                              std::pair<std::string, std::vector<std::string>>>>&
4701214b7e7SGunnar Mills                          object : subtree)
4711c8fba97SJames Feist                 {
4721c8fba97SJames Feist                     const std::string& path = object.first;
4731c8fba97SJames Feist                     const std::vector<
4741214b7e7SGunnar Mills                         std::pair<std::string, std::vector<std::string>>>&
4751214b7e7SGunnar Mills                         connectionNames = object.second;
4761c8fba97SJames Feist 
4771c8fba97SJames Feist                     if (!boost::ends_with(path, chassisId))
4781c8fba97SJames Feist                     {
4791c8fba97SJames Feist                         continue;
4801c8fba97SJames Feist                     }
4811c8fba97SJames Feist 
4821c8fba97SJames Feist                     if (connectionNames.size() < 1)
4831c8fba97SJames Feist                     {
4841c8fba97SJames Feist                         BMCWEB_LOG_ERROR << "Got 0 Connection names";
4851c8fba97SJames Feist                         continue;
4861c8fba97SJames Feist                     }
4871c8fba97SJames Feist 
48823a21a1cSEd Tanous                     const std::vector<std::string>& interfaces3 =
4891c8fba97SJames Feist                         connectionNames[0].second;
4901c8fba97SJames Feist 
4911c8fba97SJames Feist                     if (indicatorLed)
4921c8fba97SJames Feist                     {
4931c8fba97SJames Feist                         const std::array<const char*, 2> hasIndicatorLed = {
4941c8fba97SJames Feist                             "xyz.openbmc_project.Inventory.Item.Panel",
4951c8fba97SJames Feist                             "xyz.openbmc_project.Inventory.Item.Board."
4961c8fba97SJames Feist                             "Motherboard"};
4971c8fba97SJames Feist                         bool indicatorChassis = false;
4981c8fba97SJames Feist                         for (const char* interface : hasIndicatorLed)
4991c8fba97SJames Feist                         {
50023a21a1cSEd Tanous                             if (std::find(interfaces3.begin(),
50123a21a1cSEd Tanous                                           interfaces3.end(),
50223a21a1cSEd Tanous                                           interface) != interfaces3.end())
5031c8fba97SJames Feist                             {
5041c8fba97SJames Feist                                 indicatorChassis = true;
5051c8fba97SJames Feist                                 break;
5061c8fba97SJames Feist                             }
5071c8fba97SJames Feist                         }
5081c8fba97SJames Feist                         if (indicatorChassis)
5091c8fba97SJames Feist                         {
5101c8fba97SJames Feist                             setIndicatorLedState(asyncResp,
5111c8fba97SJames Feist                                                  std::move(*indicatorLed));
5121c8fba97SJames Feist                         }
5131c8fba97SJames Feist                         else
5141c8fba97SJames Feist                         {
5151c8fba97SJames Feist                             messages::propertyUnknown(asyncResp->res,
5161c8fba97SJames Feist                                                       "IndicatorLED");
5171c8fba97SJames Feist                         }
5181c8fba97SJames Feist                     }
5191c8fba97SJames Feist                     return;
5201c8fba97SJames Feist                 }
5211c8fba97SJames Feist 
5221c8fba97SJames Feist                 messages::resourceNotFound(
5231c8fba97SJames Feist                     asyncResp->res, "#Chassis.v1_10_0.Chassis", chassisId);
5241c8fba97SJames Feist             },
5251c8fba97SJames Feist             "xyz.openbmc_project.ObjectMapper",
5261c8fba97SJames Feist             "/xyz/openbmc_project/object_mapper",
5271c8fba97SJames Feist             "xyz.openbmc_project.ObjectMapper", "GetSubTree",
5281c8fba97SJames Feist             "/xyz/openbmc_project/inventory", 0, interfaces);
5291c8fba97SJames Feist     }
53062d5e2e4SEd Tanous };
531dd99e04bSP.K. Lee 
53223a21a1cSEd Tanous inline void doChassisPowerCycle(std::shared_ptr<AsyncResp> asyncResp)
533dd99e04bSP.K. Lee {
534dd99e04bSP.K. Lee     const char* processName = "xyz.openbmc_project.State.Chassis";
535dd99e04bSP.K. Lee     const char* objectPath = "/xyz/openbmc_project/state/chassis0";
536dd99e04bSP.K. Lee     const char* interfaceName = "xyz.openbmc_project.State.Chassis";
537dd99e04bSP.K. Lee     const char* destProperty = "RequestedPowerTransition";
538dd99e04bSP.K. Lee     const std::string propertyValue =
539dd99e04bSP.K. Lee         "xyz.openbmc_project.State.Chassis.Transition.PowerCycle";
540dd99e04bSP.K. Lee 
541dd99e04bSP.K. Lee     crow::connections::systemBus->async_method_call(
542dd99e04bSP.K. Lee         [asyncResp](const boost::system::error_code ec) {
543dd99e04bSP.K. Lee             // Use "Set" method to set the property value.
544dd99e04bSP.K. Lee             if (ec)
545dd99e04bSP.K. Lee             {
546dd99e04bSP.K. Lee                 BMCWEB_LOG_DEBUG << "[Set] Bad D-Bus request error: " << ec;
547dd99e04bSP.K. Lee                 messages::internalError(asyncResp->res);
548dd99e04bSP.K. Lee                 return;
549dd99e04bSP.K. Lee             }
550dd99e04bSP.K. Lee 
551dd99e04bSP.K. Lee             messages::success(asyncResp->res);
552dd99e04bSP.K. Lee         },
553dd99e04bSP.K. Lee         processName, objectPath, "org.freedesktop.DBus.Properties", "Set",
554dd99e04bSP.K. Lee         interfaceName, destProperty, std::variant<std::string>{propertyValue});
555dd99e04bSP.K. Lee }
556dd99e04bSP.K. Lee 
557dd99e04bSP.K. Lee /**
558dd99e04bSP.K. Lee  * ChassisResetAction class supports the POST method for the Reset
559dd99e04bSP.K. Lee  * action.
560dd99e04bSP.K. Lee  */
561dd99e04bSP.K. Lee class ChassisResetAction : public Node
562dd99e04bSP.K. Lee {
563dd99e04bSP.K. Lee   public:
56452cc112dSEd Tanous     ChassisResetAction(App& app) :
565dd99e04bSP.K. Lee         Node(app, "/redfish/v1/Chassis/<str>/Actions/Chassis.Reset/",
566dd99e04bSP.K. Lee              std::string())
567dd99e04bSP.K. Lee     {
568dd99e04bSP.K. Lee         entityPrivileges = {
569dd99e04bSP.K. Lee             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
570dd99e04bSP.K. Lee     }
571dd99e04bSP.K. Lee 
572dd99e04bSP.K. Lee   private:
573dd99e04bSP.K. Lee     /**
574dd99e04bSP.K. Lee      * Function handles POST method request.
575dd99e04bSP.K. Lee      * Analyzes POST body before sending Reset request data to D-Bus.
576dd99e04bSP.K. Lee      */
577dd99e04bSP.K. Lee     void doPost(crow::Response& res, const crow::Request& req,
578*cb13a392SEd Tanous                 const std::vector<std::string>&) override
579dd99e04bSP.K. Lee     {
580dd99e04bSP.K. Lee         BMCWEB_LOG_DEBUG << "Post Chassis Reset.";
581dd99e04bSP.K. Lee 
582dd99e04bSP.K. Lee         std::string resetType;
583dd99e04bSP.K. Lee         auto asyncResp = std::make_shared<AsyncResp>(res);
584dd99e04bSP.K. Lee 
585dd99e04bSP.K. Lee         if (!json_util::readJson(req, asyncResp->res, "ResetType", resetType))
586dd99e04bSP.K. Lee         {
587dd99e04bSP.K. Lee             return;
588dd99e04bSP.K. Lee         }
589dd99e04bSP.K. Lee 
590dd99e04bSP.K. Lee         if (resetType != "PowerCycle")
591dd99e04bSP.K. Lee         {
592dd99e04bSP.K. Lee             BMCWEB_LOG_DEBUG << "Invalid property value for ResetType: "
593dd99e04bSP.K. Lee                              << resetType;
594dd99e04bSP.K. Lee             messages::actionParameterNotSupported(asyncResp->res, resetType,
595dd99e04bSP.K. Lee                                                   "ResetType");
596dd99e04bSP.K. Lee 
597dd99e04bSP.K. Lee             return;
598dd99e04bSP.K. Lee         }
599dd99e04bSP.K. Lee         doChassisPowerCycle(asyncResp);
600dd99e04bSP.K. Lee     }
601dd99e04bSP.K. Lee };
6021cb1a9e6SAppaRao Puli 
6031cb1a9e6SAppaRao Puli /**
6041cb1a9e6SAppaRao Puli  * ChassisResetActionInfo derived class for delivering Chassis
6051cb1a9e6SAppaRao Puli  * ResetType AllowableValues using ResetInfo schema.
6061cb1a9e6SAppaRao Puli  */
6071cb1a9e6SAppaRao Puli class ChassisResetActionInfo : public Node
6081cb1a9e6SAppaRao Puli {
6091cb1a9e6SAppaRao Puli   public:
6101cb1a9e6SAppaRao Puli     /*
6111cb1a9e6SAppaRao Puli      * Default Constructor
6121cb1a9e6SAppaRao Puli      */
61352cc112dSEd Tanous     ChassisResetActionInfo(App& app) :
6141cb1a9e6SAppaRao Puli         Node(app, "/redfish/v1/Chassis/<str>/ResetActionInfo/", std::string())
6151cb1a9e6SAppaRao Puli     {
6161cb1a9e6SAppaRao Puli         entityPrivileges = {
6171cb1a9e6SAppaRao Puli             {boost::beast::http::verb::get, {{"Login"}}},
6181cb1a9e6SAppaRao Puli             {boost::beast::http::verb::head, {{"Login"}}},
6191cb1a9e6SAppaRao Puli             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
6201cb1a9e6SAppaRao Puli             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
6211cb1a9e6SAppaRao Puli             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
6221cb1a9e6SAppaRao Puli             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
6231cb1a9e6SAppaRao Puli     }
6241cb1a9e6SAppaRao Puli 
6251cb1a9e6SAppaRao Puli   private:
6261cb1a9e6SAppaRao Puli     /**
6271cb1a9e6SAppaRao Puli      * Functions triggers appropriate requests on DBus
6281cb1a9e6SAppaRao Puli      */
629*cb13a392SEd Tanous     void doGet(crow::Response& res, const crow::Request&,
6301cb1a9e6SAppaRao Puli                const std::vector<std::string>& params) override
6311cb1a9e6SAppaRao Puli     {
6321cb1a9e6SAppaRao Puli         if (params.size() != 1)
6331cb1a9e6SAppaRao Puli         {
6341cb1a9e6SAppaRao Puli             messages::internalError(res);
6351cb1a9e6SAppaRao Puli             res.end();
6361cb1a9e6SAppaRao Puli             return;
6371cb1a9e6SAppaRao Puli         }
6381cb1a9e6SAppaRao Puli         const std::string& chassisId = params[0];
6391cb1a9e6SAppaRao Puli 
6401cb1a9e6SAppaRao Puli         res.jsonValue = {{"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"},
6411cb1a9e6SAppaRao Puli                          {"@odata.id", "/redfish/v1/Chassis/" + chassisId +
6421cb1a9e6SAppaRao Puli                                            "/ResetActionInfo"},
6431cb1a9e6SAppaRao Puli                          {"Name", "Reset Action Info"},
6441cb1a9e6SAppaRao Puli                          {"Id", "ResetActionInfo"},
6451cb1a9e6SAppaRao Puli                          {"Parameters",
6461cb1a9e6SAppaRao Puli                           {{{"Name", "ResetType"},
6471cb1a9e6SAppaRao Puli                             {"Required", true},
6481cb1a9e6SAppaRao Puli                             {"DataType", "String"},
6491cb1a9e6SAppaRao Puli                             {"AllowableValues", {"PowerCycle"}}}}}};
6501cb1a9e6SAppaRao Puli         res.end();
6511cb1a9e6SAppaRao Puli     }
6521cb1a9e6SAppaRao Puli };
6531cb1a9e6SAppaRao Puli 
654e37f8451SRapkiewicz, Pawel } // namespace redfish
655