xref: /openbmc/bmcweb/features/redfish/lib/chassis.hpp (revision 7e860f1550c8686eec42f7a75bc5f2ef51e756ad)
1e37f8451SRapkiewicz, Pawel /*
2e37f8451SRapkiewicz, Pawel // Copyright (c) 2018 Intel Corporation
3e37f8451SRapkiewicz, Pawel //
4e37f8451SRapkiewicz, Pawel // Licensed under the Apache License, Version 2.0 (the "License");
5e37f8451SRapkiewicz, Pawel // you may not use this file except in compliance with the License.
6e37f8451SRapkiewicz, Pawel // You may obtain a copy of the License at
7e37f8451SRapkiewicz, Pawel //
8e37f8451SRapkiewicz, Pawel //      http://www.apache.org/licenses/LICENSE-2.0
9e37f8451SRapkiewicz, Pawel //
10e37f8451SRapkiewicz, Pawel // Unless required by applicable law or agreed to in writing, software
11e37f8451SRapkiewicz, Pawel // distributed under the License is distributed on an "AS IS" BASIS,
12e37f8451SRapkiewicz, Pawel // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e37f8451SRapkiewicz, Pawel // See the License for the specific language governing permissions and
14e37f8451SRapkiewicz, Pawel // limitations under the License.
15e37f8451SRapkiewicz, Pawel */
16e37f8451SRapkiewicz, Pawel #pragma once
17e37f8451SRapkiewicz, Pawel 
18b49ac873SJames Feist #include "health.hpp"
191c8fba97SJames Feist #include "led.hpp"
201abe55efSEd Tanous 
21*7e860f15SJohn Edward Broadbent #include <app.hpp>
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  */
378d1b46d7Szhanghch05 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 
898d1b46d7Szhanghch05 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  */
1248d1b46d7Szhanghch05 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  *  Functions triggers appropriate requests on DBus
161e37f8451SRapkiewicz, Pawel  */
162*7e860f15SJohn Edward Broadbent inline void requestRoutesChassisCollection(App& app)
1631abe55efSEd Tanous {
164*7e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Chassis/")
165*7e860f15SJohn Edward Broadbent         .privileges({"Login"})
166*7e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
167*7e860f15SJohn Edward Broadbent             [](const crow::Request&,
168*7e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
1698d1b46d7Szhanghch05                 asyncResp->res.jsonValue["@odata.type"] =
1708d1b46d7Szhanghch05                     "#ChassisCollection.ChassisCollection";
1718d1b46d7Szhanghch05                 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Chassis";
1728d1b46d7Szhanghch05                 asyncResp->res.jsonValue["Name"] = "Chassis Collection";
173e37f8451SRapkiewicz, Pawel 
17402f6ff19SGunnar Mills                 collection_util::getCollectionMembers(
17502f6ff19SGunnar Mills                     asyncResp, "/redfish/v1/Chassis",
17602f6ff19SGunnar Mills                     {"xyz.openbmc_project.Inventory.Item.Board",
17702f6ff19SGunnar Mills                      "xyz.openbmc_project.Inventory.Item.Chassis"});
178*7e860f15SJohn Edward Broadbent             });
17962d5e2e4SEd Tanous }
180e37f8451SRapkiewicz, Pawel 
181e37f8451SRapkiewicz, Pawel /**
182e37f8451SRapkiewicz, Pawel  * Chassis override class for delivering Chassis Schema
183e37f8451SRapkiewicz, Pawel  * Functions triggers appropriate requests on DBus
184e37f8451SRapkiewicz, Pawel  */
185*7e860f15SJohn Edward Broadbent inline void requestRoutesChassis(App& app)
1861abe55efSEd Tanous {
187*7e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/")
188*7e860f15SJohn Edward Broadbent         .privileges({"Login"})
189*7e860f15SJohn Edward Broadbent         .methods(
190*7e860f15SJohn Edward Broadbent             boost::beast::http::verb::get)([](const crow::Request&,
191*7e860f15SJohn Edward Broadbent                                               const std::shared_ptr<
192*7e860f15SJohn Edward Broadbent                                                   bmcweb::AsyncResp>& asyncResp,
193*7e860f15SJohn Edward Broadbent                                               const std::string& chassisId) {
194adc4f0dbSShawn McCarney             const std::array<const char*, 2> interfaces = {
195734bfe90SGunnar Mills                 "xyz.openbmc_project.Inventory.Item.Board",
196adc4f0dbSShawn McCarney                 "xyz.openbmc_project.Inventory.Item.Chassis"};
197734bfe90SGunnar Mills 
19855c7b7a2SEd Tanous             crow::connections::systemBus->async_method_call(
19962d5e2e4SEd Tanous                 [asyncResp, chassisId(std::string(chassisId))](
20062d5e2e4SEd Tanous                     const boost::system::error_code ec,
2011c8fba97SJames Feist                     const crow::openbmc_mapper::GetSubTreeType& subtree) {
20262d5e2e4SEd Tanous                     if (ec)
2031abe55efSEd Tanous                     {
204f12894f8SJason M. Bills                         messages::internalError(asyncResp->res);
205daf36e2eSEd Tanous                         return;
206daf36e2eSEd Tanous                     }
207daf36e2eSEd Tanous                     // Iterate over all retrieved ObjectPaths.
2081abe55efSEd Tanous                     for (const std::pair<
2091abe55efSEd Tanous                              std::string,
210*7e860f15SJohn Edward Broadbent                              std::vector<std::pair<std::string,
211*7e860f15SJohn Edward Broadbent                                                    std::vector<std::string>>>>&
2121214b7e7SGunnar Mills                              object : subtree)
2131abe55efSEd Tanous                     {
214daf36e2eSEd Tanous                         const std::string& path = object.first;
2151abe55efSEd Tanous                         const std::vector<
2161214b7e7SGunnar Mills                             std::pair<std::string, std::vector<std::string>>>&
2171214b7e7SGunnar Mills                             connectionNames = object.second;
218*7e860f15SJohn Edward Broadbent 
219*7e860f15SJohn Edward Broadbent                         if (!boost::ends_with(path, chassisId))
2201abe55efSEd Tanous                         {
221daf36e2eSEd Tanous                             continue;
222daf36e2eSEd Tanous                         }
22326f03899SShawn McCarney 
224*7e860f15SJohn Edward Broadbent                         auto health =
225*7e860f15SJohn Edward Broadbent                             std::make_shared<HealthPopulate>(asyncResp);
226b49ac873SJames Feist 
227b49ac873SJames Feist                         crow::connections::systemBus->async_method_call(
228*7e860f15SJohn Edward Broadbent                             [health](
229*7e860f15SJohn Edward Broadbent                                 const boost::system::error_code ec2,
230b49ac873SJames Feist                                 std::variant<std::vector<std::string>>& resp) {
23123a21a1cSEd Tanous                                 if (ec2)
232b49ac873SJames Feist                                 {
233b49ac873SJames Feist                                     return; // no sensors = no failures
234b49ac873SJames Feist                                 }
235b49ac873SJames Feist                                 std::vector<std::string>* data =
236*7e860f15SJohn Edward Broadbent                                     std::get_if<std::vector<std::string>>(
237*7e860f15SJohn Edward Broadbent                                         &resp);
238b49ac873SJames Feist                                 if (data == nullptr)
239b49ac873SJames Feist                                 {
240b49ac873SJames Feist                                     return;
241b49ac873SJames Feist                                 }
242b49ac873SJames Feist                                 health->inventory = std::move(*data);
243b49ac873SJames Feist                             },
244b49ac873SJames Feist                             "xyz.openbmc_project.ObjectMapper",
245b49ac873SJames Feist                             path + "/all_sensors",
246b49ac873SJames Feist                             "org.freedesktop.DBus.Properties", "Get",
247b49ac873SJames Feist                             "xyz.openbmc_project.Association", "endpoints");
248b49ac873SJames Feist 
249b49ac873SJames Feist                         health->populate();
250b49ac873SJames Feist 
2511abe55efSEd Tanous                         if (connectionNames.size() < 1)
2521abe55efSEd Tanous                         {
2531c8fba97SJames Feist                             BMCWEB_LOG_ERROR << "Got 0 Connection names";
254e0d918bcSEd Tanous                             continue;
255daf36e2eSEd Tanous                         }
256e0d918bcSEd Tanous 
25749c53ac9SJohnathan Mantey                         asyncResp->res.jsonValue["@odata.type"] =
2589f8bfa7cSGunnar Mills                             "#Chassis.v1_14_0.Chassis";
25949c53ac9SJohnathan Mantey                         asyncResp->res.jsonValue["@odata.id"] =
26049c53ac9SJohnathan Mantey                             "/redfish/v1/Chassis/" + chassisId;
26149c53ac9SJohnathan Mantey                         asyncResp->res.jsonValue["Name"] = "Chassis Collection";
26249c53ac9SJohnathan Mantey                         asyncResp->res.jsonValue["ChassisType"] = "RackMount";
263*7e860f15SJohn Edward Broadbent                         asyncResp->res.jsonValue["Actions"]["#Chassis.Reset"] =
264*7e860f15SJohn Edward Broadbent                             {{"target", "/redfish/v1/Chassis/" + chassisId +
265dd99e04bSP.K. Lee                                             "/Actions/Chassis.Reset"},
2661cb1a9e6SAppaRao Puli                              {"@Redfish.ActionInfo", "/redfish/v1/Chassis/" +
2671cb1a9e6SAppaRao Puli                                                          chassisId +
2681cb1a9e6SAppaRao Puli                                                          "/ResetActionInfo"}};
269adbe192aSJason M. Bills                         asyncResp->res.jsonValue["PCIeDevices"] = {
270adbe192aSJason M. Bills                             {"@odata.id",
271adbe192aSJason M. Bills                              "/redfish/v1/Systems/system/PCIeDevices"}};
27249c53ac9SJohnathan Mantey 
27349c53ac9SJohnathan Mantey                         const std::string& connectionName =
27449c53ac9SJohnathan Mantey                             connectionNames[0].first;
2751c8fba97SJames Feist 
27623a21a1cSEd Tanous                         const std::vector<std::string>& interfaces2 =
2771c8fba97SJames Feist                             connectionNames[0].second;
2781c8fba97SJames Feist                         const std::array<const char*, 2> hasIndicatorLed = {
2791c8fba97SJames Feist                             "xyz.openbmc_project.Inventory.Item.Panel",
280*7e860f15SJohn Edward Broadbent                             "xyz.openbmc_project.Inventory.Item.Board."
281*7e860f15SJohn Edward Broadbent                             "Motherboard"};
2821c8fba97SJames Feist 
2831c8fba97SJames Feist                         for (const char* interface : hasIndicatorLed)
2841c8fba97SJames Feist                         {
285*7e860f15SJohn Edward Broadbent                             if (std::find(interfaces2.begin(),
286*7e860f15SJohn Edward Broadbent                                           interfaces2.end(),
28723a21a1cSEd Tanous                                           interface) != interfaces2.end())
2881c8fba97SJames Feist                             {
2891c8fba97SJames Feist                                 getIndicatorLedState(asyncResp);
2909f8bfa7cSGunnar Mills                                 getLocationIndicatorActive(asyncResp);
2911c8fba97SJames Feist                                 break;
2921c8fba97SJames Feist                             }
2931c8fba97SJames Feist                         }
2941c8fba97SJames Feist 
29588ad7f03SSunnySrivastava1984                         const std::string locationInterface =
296*7e860f15SJohn Edward Broadbent                             "xyz.openbmc_project.Inventory.Decorator."
297*7e860f15SJohn Edward Broadbent                             "LocationCode";
29888ad7f03SSunnySrivastava1984                         if (std::find(interfaces2.begin(), interfaces2.end(),
29988ad7f03SSunnySrivastava1984                                       locationInterface) != interfaces2.end())
30088ad7f03SSunnySrivastava1984                         {
30188ad7f03SSunnySrivastava1984                             crow::connections::systemBus->async_method_call(
30288ad7f03SSunnySrivastava1984                                 [asyncResp, chassisId(std::string(chassisId))](
30388ad7f03SSunnySrivastava1984                                     const boost::system::error_code ec,
30488ad7f03SSunnySrivastava1984                                     const std::variant<std::string>& property) {
30588ad7f03SSunnySrivastava1984                                     if (ec)
30688ad7f03SSunnySrivastava1984                                     {
30788ad7f03SSunnySrivastava1984                                         BMCWEB_LOG_DEBUG
308*7e860f15SJohn Edward Broadbent                                             << "DBUS response error for "
309*7e860f15SJohn Edward Broadbent                                                "Location";
31088ad7f03SSunnySrivastava1984                                         messages::internalError(asyncResp->res);
31188ad7f03SSunnySrivastava1984                                         return;
31288ad7f03SSunnySrivastava1984                                     }
31388ad7f03SSunnySrivastava1984 
31488ad7f03SSunnySrivastava1984                                     const std::string* value =
31588ad7f03SSunnySrivastava1984                                         std::get_if<std::string>(&property);
31688ad7f03SSunnySrivastava1984                                     if (value == nullptr)
31788ad7f03SSunnySrivastava1984                                     {
318*7e860f15SJohn Edward Broadbent                                         BMCWEB_LOG_DEBUG
319*7e860f15SJohn Edward Broadbent                                             << "Null value returned "
32088ad7f03SSunnySrivastava1984                                                "for locaton code";
32188ad7f03SSunnySrivastava1984                                         messages::internalError(asyncResp->res);
32288ad7f03SSunnySrivastava1984                                         return;
32388ad7f03SSunnySrivastava1984                                     }
32488ad7f03SSunnySrivastava1984                                     asyncResp->res
32588ad7f03SSunnySrivastava1984                                         .jsonValue["Location"]["PartLocation"]
32688ad7f03SSunnySrivastava1984                                                   ["ServiceLabel"] = *value;
32788ad7f03SSunnySrivastava1984                                 },
32888ad7f03SSunnySrivastava1984                                 connectionName, path,
32988ad7f03SSunnySrivastava1984                                 "org.freedesktop.DBus.Properties", "Get",
33088ad7f03SSunnySrivastava1984                                 locationInterface, "LocationCode");
33188ad7f03SSunnySrivastava1984                         }
33288ad7f03SSunnySrivastava1984 
33355c7b7a2SEd Tanous                         crow::connections::systemBus->async_method_call(
33462d5e2e4SEd Tanous                             [asyncResp, chassisId(std::string(chassisId))](
33590728b54SEd Tanous                                 const boost::system::error_code /*ec2*/,
336*7e860f15SJohn Edward Broadbent                                 const std::vector<
337*7e860f15SJohn Edward Broadbent                                     std::pair<std::string, VariantType>>&
338*7e860f15SJohn Edward Broadbent                                     propertiesList) {
3391214b7e7SGunnar Mills                                 for (const std::pair<std::string, VariantType>&
3401214b7e7SGunnar Mills                                          property : propertiesList)
3411abe55efSEd Tanous                                 {
342*7e860f15SJohn Edward Broadbent                                     // Store DBus properties that are also
343*7e860f15SJohn Edward Broadbent                                     // Redfish properties with same name and a
344*7e860f15SJohn Edward Broadbent                                     // string value
34599cffd7fSShawn McCarney                                     const std::string& propertyName =
34699cffd7fSShawn McCarney                                         property.first;
34799cffd7fSShawn McCarney                                     if ((propertyName == "PartNumber") ||
34899cffd7fSShawn McCarney                                         (propertyName == "SerialNumber") ||
34999cffd7fSShawn McCarney                                         (propertyName == "Manufacturer") ||
35099cffd7fSShawn McCarney                                         (propertyName == "Model"))
35199cffd7fSShawn McCarney                                     {
352daf36e2eSEd Tanous                                         const std::string* value =
35399cffd7fSShawn McCarney                                             std::get_if<std::string>(
35499cffd7fSShawn McCarney                                                 &property.second);
3551abe55efSEd Tanous                                         if (value != nullptr)
3561abe55efSEd Tanous                                         {
357*7e860f15SJohn Edward Broadbent                                             asyncResp->res
358*7e860f15SJohn Edward Broadbent                                                 .jsonValue[propertyName] =
35962d5e2e4SEd Tanous                                                 *value;
360daf36e2eSEd Tanous                                         }
361daf36e2eSEd Tanous                                     }
36299cffd7fSShawn McCarney                                 }
36362d5e2e4SEd Tanous                                 asyncResp->res.jsonValue["Name"] = chassisId;
36462d5e2e4SEd Tanous                                 asyncResp->res.jsonValue["Id"] = chassisId;
36562d5e2e4SEd Tanous                                 asyncResp->res.jsonValue["Thermal"] = {
3661abe55efSEd Tanous                                     {"@odata.id", "/redfish/v1/Chassis/" +
3671abe55efSEd Tanous                                                       chassisId + "/Thermal"}};
3682474adfaSEd Tanous                                 // Power object
3692474adfaSEd Tanous                                 asyncResp->res.jsonValue["Power"] = {
3702474adfaSEd Tanous                                     {"@odata.id", "/redfish/v1/Chassis/" +
3712474adfaSEd Tanous                                                       chassisId + "/Power"}};
37295a3ecadSAnthony Wilson                                 // SensorCollection
37395a3ecadSAnthony Wilson                                 asyncResp->res.jsonValue["Sensors"] = {
37495a3ecadSAnthony Wilson                                     {"@odata.id", "/redfish/v1/Chassis/" +
37595a3ecadSAnthony Wilson                                                       chassisId + "/Sensors"}};
376029573d4SEd Tanous                                 asyncResp->res.jsonValue["Status"] = {
377029573d4SEd Tanous                                     {"State", "Enabled"},
378029573d4SEd Tanous                                 };
3792474adfaSEd Tanous 
380029573d4SEd Tanous                                 asyncResp->res
381029573d4SEd Tanous                                     .jsonValue["Links"]["ComputerSystems"] = {
382*7e860f15SJohn Edward Broadbent                                     {{"@odata.id",
383*7e860f15SJohn Edward Broadbent                                       "/redfish/v1/Systems/system"}}};
384*7e860f15SJohn Edward Broadbent                                 asyncResp->res.jsonValue["Links"]["ManagedBy"] =
385*7e860f15SJohn Edward Broadbent                                     {{{"@odata.id",
386*7e860f15SJohn Edward Broadbent                                        "/redfish/v1/Managers/bmc"}}};
387beeca0aeSGunnar Mills                                 getChassisState(asyncResp);
388daf36e2eSEd Tanous                             },
389*7e860f15SJohn Edward Broadbent                             connectionName, path,
390*7e860f15SJohn Edward Broadbent                             "org.freedesktop.DBus.Properties", "GetAll",
3911abe55efSEd Tanous                             "xyz.openbmc_project.Inventory.Decorator.Asset");
392daf36e2eSEd Tanous                         return;
393daf36e2eSEd Tanous                     }
394e0d918bcSEd Tanous 
395daf36e2eSEd Tanous                     // Couldn't find an object with that name.  return an error
396f12894f8SJason M. Bills                     messages::resourceNotFound(
3979f8bfa7cSGunnar Mills                         asyncResp->res, "#Chassis.v1_14_0.Chassis", chassisId);
398daf36e2eSEd Tanous                 },
399daf36e2eSEd Tanous                 "xyz.openbmc_project.ObjectMapper",
400daf36e2eSEd Tanous                 "/xyz/openbmc_project/object_mapper",
401daf36e2eSEd Tanous                 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
402271584abSEd Tanous                 "/xyz/openbmc_project/inventory", 0, interfaces);
403c181942fSQiang XU 
404c181942fSQiang XU             getPhysicalSecurityData(asyncResp);
405*7e860f15SJohn Edward Broadbent         });
4061c8fba97SJames Feist 
407*7e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/")
408*7e860f15SJohn Edward Broadbent         .privileges({"ConfigureComponents"})
409*7e860f15SJohn Edward Broadbent         .methods(
410*7e860f15SJohn Edward Broadbent             boost::beast::http::verb::
411*7e860f15SJohn Edward Broadbent                 patch)([](const crow::Request& req,
412*7e860f15SJohn Edward Broadbent                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
413*7e860f15SJohn Edward Broadbent                           const std::string& param) {
4149f8bfa7cSGunnar Mills             std::optional<bool> locationIndicatorActive;
4151c8fba97SJames Feist             std::optional<std::string> indicatorLed;
4161c8fba97SJames Feist 
417*7e860f15SJohn Edward Broadbent             if (param.empty())
4181c8fba97SJames Feist             {
4191c8fba97SJames Feist                 return;
4201c8fba97SJames Feist             }
4211c8fba97SJames Feist 
422*7e860f15SJohn Edward Broadbent             if (!json_util::readJson(
423*7e860f15SJohn Edward Broadbent                     req, asyncResp->res, "LocationIndicatorActive",
424*7e860f15SJohn Edward Broadbent                     locationIndicatorActive, "IndicatorLED", indicatorLed))
4251c8fba97SJames Feist             {
4261c8fba97SJames Feist                 return;
4271c8fba97SJames Feist             }
4281c8fba97SJames Feist 
4299f8bfa7cSGunnar Mills             // TODO (Gunnar): Remove IndicatorLED after enough time has passed
4309f8bfa7cSGunnar Mills             if (!locationIndicatorActive && !indicatorLed)
4311c8fba97SJames Feist             {
4321c8fba97SJames Feist                 return; // delete this when we support more patch properties
4331c8fba97SJames Feist             }
434d6aa0093SGunnar Mills             if (indicatorLed)
435d6aa0093SGunnar Mills             {
436*7e860f15SJohn Edward Broadbent                 asyncResp->res.addHeader(
437*7e860f15SJohn Edward Broadbent                     boost::beast::http::field::warning,
438d6aa0093SGunnar Mills                     "299 - \"IndicatorLED is deprecated. Use "
439d6aa0093SGunnar Mills                     "LocationIndicatorActive instead.\"");
440d6aa0093SGunnar Mills             }
4411c8fba97SJames Feist 
4421c8fba97SJames Feist             const std::array<const char*, 2> interfaces = {
4431c8fba97SJames Feist                 "xyz.openbmc_project.Inventory.Item.Board",
4441c8fba97SJames Feist                 "xyz.openbmc_project.Inventory.Item.Chassis"};
4451c8fba97SJames Feist 
446*7e860f15SJohn Edward Broadbent             const std::string& chassisId = param;
4471c8fba97SJames Feist 
4481c8fba97SJames Feist             crow::connections::systemBus->async_method_call(
4499f8bfa7cSGunnar Mills                 [asyncResp, chassisId, locationIndicatorActive, indicatorLed](
4501c8fba97SJames Feist                     const boost::system::error_code ec,
4511c8fba97SJames Feist                     const crow::openbmc_mapper::GetSubTreeType& subtree) {
4521c8fba97SJames Feist                     if (ec)
4531c8fba97SJames Feist                     {
4541c8fba97SJames Feist                         messages::internalError(asyncResp->res);
4551c8fba97SJames Feist                         return;
4561c8fba97SJames Feist                     }
4571c8fba97SJames Feist 
4581c8fba97SJames Feist                     // Iterate over all retrieved ObjectPaths.
4591c8fba97SJames Feist                     for (const std::pair<
4601c8fba97SJames Feist                              std::string,
461*7e860f15SJohn Edward Broadbent                              std::vector<std::pair<std::string,
462*7e860f15SJohn Edward Broadbent                                                    std::vector<std::string>>>>&
4631214b7e7SGunnar Mills                              object : subtree)
4641c8fba97SJames Feist                     {
4651c8fba97SJames Feist                         const std::string& path = object.first;
4661c8fba97SJames Feist                         const std::vector<
4671214b7e7SGunnar Mills                             std::pair<std::string, std::vector<std::string>>>&
4681214b7e7SGunnar Mills                             connectionNames = object.second;
4691c8fba97SJames Feist 
4701c8fba97SJames Feist                         if (!boost::ends_with(path, chassisId))
4711c8fba97SJames Feist                         {
4721c8fba97SJames Feist                             continue;
4731c8fba97SJames Feist                         }
4741c8fba97SJames Feist 
4751c8fba97SJames Feist                         if (connectionNames.size() < 1)
4761c8fba97SJames Feist                         {
4771c8fba97SJames Feist                             BMCWEB_LOG_ERROR << "Got 0 Connection names";
4781c8fba97SJames Feist                             continue;
4791c8fba97SJames Feist                         }
4801c8fba97SJames Feist 
48123a21a1cSEd Tanous                         const std::vector<std::string>& interfaces3 =
4821c8fba97SJames Feist                             connectionNames[0].second;
4831c8fba97SJames Feist 
4841c8fba97SJames Feist                         const std::array<const char*, 2> hasIndicatorLed = {
4851c8fba97SJames Feist                             "xyz.openbmc_project.Inventory.Item.Panel",
4861c8fba97SJames Feist                             "xyz.openbmc_project.Inventory.Item.Board."
4871c8fba97SJames Feist                             "Motherboard"};
4881c8fba97SJames Feist                         bool indicatorChassis = false;
4891c8fba97SJames Feist                         for (const char* interface : hasIndicatorLed)
4901c8fba97SJames Feist                         {
491*7e860f15SJohn Edward Broadbent                             if (std::find(interfaces3.begin(),
492*7e860f15SJohn Edward Broadbent                                           interfaces3.end(),
49323a21a1cSEd Tanous                                           interface) != interfaces3.end())
4941c8fba97SJames Feist                             {
4951c8fba97SJames Feist                                 indicatorChassis = true;
4961c8fba97SJames Feist                                 break;
4971c8fba97SJames Feist                             }
4981c8fba97SJames Feist                         }
4999f8bfa7cSGunnar Mills                         if (locationIndicatorActive)
5009f8bfa7cSGunnar Mills                         {
5019f8bfa7cSGunnar Mills                             if (indicatorChassis)
5029f8bfa7cSGunnar Mills                             {
5039f8bfa7cSGunnar Mills                                 setLocationIndicatorActive(
5049f8bfa7cSGunnar Mills                                     asyncResp, *locationIndicatorActive);
5059f8bfa7cSGunnar Mills                             }
5069f8bfa7cSGunnar Mills                             else
5079f8bfa7cSGunnar Mills                             {
5089f8bfa7cSGunnar Mills                                 messages::propertyUnknown(
5099f8bfa7cSGunnar Mills                                     asyncResp->res, "LocationIndicatorActive");
5109f8bfa7cSGunnar Mills                             }
5119f8bfa7cSGunnar Mills                         }
5129f8bfa7cSGunnar Mills                         if (indicatorLed)
5139f8bfa7cSGunnar Mills                         {
5141c8fba97SJames Feist                             if (indicatorChassis)
5151c8fba97SJames Feist                             {
516f23b7296SEd Tanous                                 setIndicatorLedState(asyncResp, *indicatorLed);
5171c8fba97SJames Feist                             }
5181c8fba97SJames Feist                             else
5191c8fba97SJames Feist                             {
5201c8fba97SJames Feist                                 messages::propertyUnknown(asyncResp->res,
5211c8fba97SJames Feist                                                           "IndicatorLED");
5221c8fba97SJames Feist                             }
5231c8fba97SJames Feist                         }
5241c8fba97SJames Feist                         return;
5251c8fba97SJames Feist                     }
5261c8fba97SJames Feist 
5271c8fba97SJames Feist                     messages::resourceNotFound(
5289f8bfa7cSGunnar Mills                         asyncResp->res, "#Chassis.v1_14_0.Chassis", chassisId);
5291c8fba97SJames Feist                 },
5301c8fba97SJames Feist                 "xyz.openbmc_project.ObjectMapper",
5311c8fba97SJames Feist                 "/xyz/openbmc_project/object_mapper",
5321c8fba97SJames Feist                 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
5331c8fba97SJames Feist                 "/xyz/openbmc_project/inventory", 0, interfaces);
534*7e860f15SJohn Edward Broadbent         });
5351c8fba97SJames Feist }
536dd99e04bSP.K. Lee 
5378d1b46d7Szhanghch05 inline void
5388d1b46d7Szhanghch05     doChassisPowerCycle(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
539dd99e04bSP.K. Lee {
540c3b3c92aSVijay Khemka     const char* busName = "xyz.openbmc_project.ObjectMapper";
541c3b3c92aSVijay Khemka     const char* path = "/xyz/openbmc_project/object_mapper";
542c3b3c92aSVijay Khemka     const char* interface = "xyz.openbmc_project.ObjectMapper";
543c3b3c92aSVijay Khemka     const char* method = "GetSubTreePaths";
544c3b3c92aSVijay Khemka 
545c3b3c92aSVijay Khemka     const std::array<const char*, 1> interfaces = {
546c3b3c92aSVijay Khemka         "xyz.openbmc_project.State.Chassis"};
547c3b3c92aSVijay Khemka 
548c3b3c92aSVijay Khemka     // Use mapper to get subtree paths.
549c3b3c92aSVijay Khemka     crow::connections::systemBus->async_method_call(
550c3b3c92aSVijay Khemka         [asyncResp](const boost::system::error_code ec,
551c3b3c92aSVijay Khemka                     const std::vector<std::string>& chassisList) {
552c3b3c92aSVijay Khemka             if (ec)
553c3b3c92aSVijay Khemka             {
554c3b3c92aSVijay Khemka                 BMCWEB_LOG_DEBUG << "[mapper] Bad D-Bus request error: " << ec;
555c3b3c92aSVijay Khemka                 messages::internalError(asyncResp->res);
556c3b3c92aSVijay Khemka                 return;
557c3b3c92aSVijay Khemka             }
558c3b3c92aSVijay Khemka 
559dd99e04bSP.K. Lee             const char* processName = "xyz.openbmc_project.State.Chassis";
560dd99e04bSP.K. Lee             const char* interfaceName = "xyz.openbmc_project.State.Chassis";
561dd99e04bSP.K. Lee             const char* destProperty = "RequestedPowerTransition";
562dd99e04bSP.K. Lee             const std::string propertyValue =
563dd99e04bSP.K. Lee                 "xyz.openbmc_project.State.Chassis.Transition.PowerCycle";
564c3b3c92aSVijay Khemka             std::string objectPath =
565c3b3c92aSVijay Khemka                 "/xyz/openbmc_project/state/chassis_system0";
566c3b3c92aSVijay Khemka 
567c3b3c92aSVijay Khemka             /* Look for system reset chassis path */
568c3b3c92aSVijay Khemka             if ((std::find(chassisList.begin(), chassisList.end(),
569c3b3c92aSVijay Khemka                            objectPath)) == chassisList.end())
570c3b3c92aSVijay Khemka             {
571c3b3c92aSVijay Khemka                 /* We prefer to reset the full chassis_system, but if it doesn't
572c3b3c92aSVijay Khemka                  * exist on some platforms, fall back to a host-only power reset
573c3b3c92aSVijay Khemka                  */
574c3b3c92aSVijay Khemka                 objectPath = "/xyz/openbmc_project/state/chassis0";
575c3b3c92aSVijay Khemka             }
576dd99e04bSP.K. Lee 
577dd99e04bSP.K. Lee             crow::connections::systemBus->async_method_call(
578dd99e04bSP.K. Lee                 [asyncResp](const boost::system::error_code ec) {
579dd99e04bSP.K. Lee                     // Use "Set" method to set the property value.
580dd99e04bSP.K. Lee                     if (ec)
581dd99e04bSP.K. Lee                     {
582c3b3c92aSVijay Khemka                         BMCWEB_LOG_DEBUG << "[Set] Bad D-Bus request error: "
583c3b3c92aSVijay Khemka                                          << ec;
584dd99e04bSP.K. Lee                         messages::internalError(asyncResp->res);
585dd99e04bSP.K. Lee                         return;
586dd99e04bSP.K. Lee                     }
587dd99e04bSP.K. Lee 
588dd99e04bSP.K. Lee                     messages::success(asyncResp->res);
589dd99e04bSP.K. Lee                 },
590c3b3c92aSVijay Khemka                 processName, objectPath, "org.freedesktop.DBus.Properties",
591c3b3c92aSVijay Khemka                 "Set", interfaceName, destProperty,
592c3b3c92aSVijay Khemka                 std::variant<std::string>{propertyValue});
593c3b3c92aSVijay Khemka         },
594c3b3c92aSVijay Khemka         busName, path, interface, method, "/", 0, interfaces);
595dd99e04bSP.K. Lee }
596dd99e04bSP.K. Lee 
597dd99e04bSP.K. Lee /**
598dd99e04bSP.K. Lee  * ChassisResetAction class supports the POST method for the Reset
599dd99e04bSP.K. Lee  * action.
600dd99e04bSP.K. Lee  * Function handles POST method request.
601dd99e04bSP.K. Lee  * Analyzes POST body before sending Reset request data to D-Bus.
602dd99e04bSP.K. Lee  */
603*7e860f15SJohn Edward Broadbent 
604*7e860f15SJohn Edward Broadbent inline void requestRoutesChassisResetAction(App& app)
605dd99e04bSP.K. Lee {
606*7e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Actions/Chassis.Reset/")
607*7e860f15SJohn Edward Broadbent         .privileges({"ConfigureComponents"})
608*7e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
609*7e860f15SJohn Edward Broadbent             [](const crow::Request& req,
610*7e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
611*7e860f15SJohn Edward Broadbent                const std::string&) {
612dd99e04bSP.K. Lee                 BMCWEB_LOG_DEBUG << "Post Chassis Reset.";
613dd99e04bSP.K. Lee 
614dd99e04bSP.K. Lee                 std::string resetType;
615dd99e04bSP.K. Lee 
616*7e860f15SJohn Edward Broadbent                 if (!json_util::readJson(req, asyncResp->res, "ResetType",
617*7e860f15SJohn Edward Broadbent                                          resetType))
618dd99e04bSP.K. Lee                 {
619dd99e04bSP.K. Lee                     return;
620dd99e04bSP.K. Lee                 }
621dd99e04bSP.K. Lee 
622dd99e04bSP.K. Lee                 if (resetType != "PowerCycle")
623dd99e04bSP.K. Lee                 {
624dd99e04bSP.K. Lee                     BMCWEB_LOG_DEBUG << "Invalid property value for ResetType: "
625dd99e04bSP.K. Lee                                      << resetType;
626*7e860f15SJohn Edward Broadbent                     messages::actionParameterNotSupported(
627*7e860f15SJohn Edward Broadbent                         asyncResp->res, resetType, "ResetType");
628dd99e04bSP.K. Lee 
629dd99e04bSP.K. Lee                     return;
630dd99e04bSP.K. Lee                 }
631dd99e04bSP.K. Lee                 doChassisPowerCycle(asyncResp);
632*7e860f15SJohn Edward Broadbent             });
633dd99e04bSP.K. Lee }
6341cb1a9e6SAppaRao Puli 
6351cb1a9e6SAppaRao Puli /**
6361cb1a9e6SAppaRao Puli  * ChassisResetActionInfo derived class for delivering Chassis
6371cb1a9e6SAppaRao Puli  * ResetType AllowableValues using ResetInfo schema.
6381cb1a9e6SAppaRao Puli  */
639*7e860f15SJohn Edward Broadbent inline void requestRoutesChassisResetActionInfo(App& app)
6401cb1a9e6SAppaRao Puli {
641*7e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ResetActionInfo/")
642*7e860f15SJohn Edward Broadbent         .privileges({"Login"})
643*7e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
644*7e860f15SJohn Edward Broadbent             [](const crow::Request&,
645*7e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
646*7e860f15SJohn Edward Broadbent                const std::string& chassisId)
6471cb1a9e6SAppaRao Puli 
6481cb1a9e6SAppaRao Puli             {
6498d1b46d7Szhanghch05                 asyncResp->res.jsonValue = {
6508d1b46d7Szhanghch05                     {"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"},
6518d1b46d7Szhanghch05                     {"@odata.id",
6528d1b46d7Szhanghch05                      "/redfish/v1/Chassis/" + chassisId + "/ResetActionInfo"},
6531cb1a9e6SAppaRao Puli                     {"Name", "Reset Action Info"},
6541cb1a9e6SAppaRao Puli                     {"Id", "ResetActionInfo"},
6551cb1a9e6SAppaRao Puli                     {"Parameters",
6561cb1a9e6SAppaRao Puli                      {{{"Name", "ResetType"},
6571cb1a9e6SAppaRao Puli                        {"Required", true},
6581cb1a9e6SAppaRao Puli                        {"DataType", "String"},
6591cb1a9e6SAppaRao Puli                        {"AllowableValues", {"PowerCycle"}}}}}};
660*7e860f15SJohn Edward Broadbent             });
6611cb1a9e6SAppaRao Puli }
6621cb1a9e6SAppaRao Puli 
663e37f8451SRapkiewicz, Pawel } // namespace redfish
664