xref: /openbmc/bmcweb/features/redfish/lib/chassis.hpp (revision b9d36b4791d77a47e1f3c5c4564fcdf7cc68c115)
1e37f8451SRapkiewicz, Pawel /*
2e37f8451SRapkiewicz, Pawel // Copyright (c) 2018 Intel Corporation
3e37f8451SRapkiewicz, Pawel //
4e37f8451SRapkiewicz, Pawel // Licensed under the Apache License, Version 2.0 (the "License");
5e37f8451SRapkiewicz, Pawel // you may not use this file except in compliance with the License.
6e37f8451SRapkiewicz, Pawel // You may obtain a copy of the License at
7e37f8451SRapkiewicz, Pawel //
8e37f8451SRapkiewicz, Pawel //      http://www.apache.org/licenses/LICENSE-2.0
9e37f8451SRapkiewicz, Pawel //
10e37f8451SRapkiewicz, Pawel // Unless required by applicable law or agreed to in writing, software
11e37f8451SRapkiewicz, Pawel // distributed under the License is distributed on an "AS IS" BASIS,
12e37f8451SRapkiewicz, Pawel // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e37f8451SRapkiewicz, Pawel // See the License for the specific language governing permissions and
14e37f8451SRapkiewicz, Pawel // limitations under the License.
15e37f8451SRapkiewicz, Pawel */
16e37f8451SRapkiewicz, Pawel #pragma once
17e37f8451SRapkiewicz, Pawel 
18b49ac873SJames Feist #include "health.hpp"
191c8fba97SJames Feist #include "led.hpp"
201abe55efSEd Tanous 
217e860f15SJohn Edward Broadbent #include <app.hpp>
22168e20c1SEd Tanous #include <dbus_utility.hpp>
23ed398213SEd Tanous #include <registries/privilege_registry.hpp>
241e1e598dSJonathan Doman #include <sdbusplus/asio/property.hpp>
2502f6ff19SGunnar Mills #include <utils/collection.hpp>
261214b7e7SGunnar Mills 
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 {
391e1e598dSJonathan Doman     // crow::connections::systemBus->async_method_call(
401e1e598dSJonathan Doman     sdbusplus::asio::getProperty<std::string>(
411e1e598dSJonathan Doman         *crow::connections::systemBus, "xyz.openbmc_project.State.Chassis",
421e1e598dSJonathan Doman         "/xyz/openbmc_project/state/chassis0",
431e1e598dSJonathan Doman         "xyz.openbmc_project.State.Chassis", "CurrentPowerState",
441e1e598dSJonathan Doman         [aResp{std::move(aResp)}](const boost::system::error_code ec,
451e1e598dSJonathan Doman                                   const std::string& chassisState) {
46beeca0aeSGunnar Mills             if (ec)
47beeca0aeSGunnar Mills             {
48a6e5e0abSCarson Labrado                 if (ec == boost::system::errc::host_unreachable)
49a6e5e0abSCarson Labrado                 {
50a6e5e0abSCarson Labrado                     // Service not available, no error, just don't return
51a6e5e0abSCarson Labrado                     // chassis state info
52a6e5e0abSCarson Labrado                     BMCWEB_LOG_DEBUG << "Service not available " << ec;
53a6e5e0abSCarson Labrado                     return;
54a6e5e0abSCarson Labrado                 }
55beeca0aeSGunnar Mills                 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
56beeca0aeSGunnar Mills                 messages::internalError(aResp->res);
57beeca0aeSGunnar Mills                 return;
58beeca0aeSGunnar Mills             }
59beeca0aeSGunnar Mills 
601e1e598dSJonathan Doman             BMCWEB_LOG_DEBUG << "Chassis state: " << chassisState;
61beeca0aeSGunnar Mills             // Verify Chassis State
621e1e598dSJonathan Doman             if (chassisState ==
631e1e598dSJonathan Doman                 "xyz.openbmc_project.State.Chassis.PowerState.On")
64beeca0aeSGunnar Mills             {
65beeca0aeSGunnar Mills                 aResp->res.jsonValue["PowerState"] = "On";
66beeca0aeSGunnar Mills                 aResp->res.jsonValue["Status"]["State"] = "Enabled";
67beeca0aeSGunnar Mills             }
681e1e598dSJonathan Doman             else if (chassisState ==
69beeca0aeSGunnar Mills                      "xyz.openbmc_project.State.Chassis.PowerState.Off")
70beeca0aeSGunnar Mills             {
71beeca0aeSGunnar Mills                 aResp->res.jsonValue["PowerState"] = "Off";
72beeca0aeSGunnar Mills                 aResp->res.jsonValue["Status"]["State"] = "StandbyOffline";
73beeca0aeSGunnar Mills             }
741e1e598dSJonathan Doman         });
75beeca0aeSGunnar Mills }
76beeca0aeSGunnar Mills 
778d1b46d7Szhanghch05 inline void getIntrusionByService(std::shared_ptr<bmcweb::AsyncResp> aResp,
78c181942fSQiang XU                                   const std::string& service,
79c181942fSQiang XU                                   const std::string& objPath)
80c181942fSQiang XU {
81c181942fSQiang XU     BMCWEB_LOG_DEBUG << "Get intrusion status by service \n";
82c181942fSQiang XU 
831e1e598dSJonathan Doman     sdbusplus::asio::getProperty<std::string>(
841e1e598dSJonathan Doman         *crow::connections::systemBus, service, objPath,
851e1e598dSJonathan Doman         "xyz.openbmc_project.Chassis.Intrusion", "Status",
86c181942fSQiang XU         [aResp{std::move(aResp)}](const boost::system::error_code ec,
871e1e598dSJonathan Doman                                   const std::string& value) {
88c181942fSQiang XU             if (ec)
89c181942fSQiang XU             {
904e0453b1SGunnar Mills                 // do not add err msg in redfish response, because this is not
91c181942fSQiang XU                 //     mandatory property
92c181942fSQiang XU                 BMCWEB_LOG_ERROR << "DBUS response error " << ec << "\n";
93c181942fSQiang XU                 return;
94c181942fSQiang XU             }
95c181942fSQiang XU 
96c181942fSQiang XU             aResp->res.jsonValue["PhysicalSecurity"] = {
971e1e598dSJonathan Doman                 {"IntrusionSensorNumber", 1}, {"IntrusionSensor", value}};
981e1e598dSJonathan Doman         });
99c181942fSQiang XU }
100c181942fSQiang XU 
101c181942fSQiang XU /**
102c181942fSQiang XU  * Retrieves physical security properties over dbus
103c181942fSQiang XU  */
1048d1b46d7Szhanghch05 inline void getPhysicalSecurityData(std::shared_ptr<bmcweb::AsyncResp> aResp)
105c181942fSQiang XU {
106c181942fSQiang XU     crow::connections::systemBus->async_method_call(
107c181942fSQiang XU         [aResp{std::move(aResp)}](
108c181942fSQiang XU             const boost::system::error_code ec,
109*b9d36b47SEd Tanous             const dbus::utility::MapperGetSubTreeResponse& subtree) {
110c181942fSQiang XU             if (ec)
111c181942fSQiang XU             {
1124e0453b1SGunnar Mills                 // do not add err msg in redfish response, because this is not
113c181942fSQiang XU                 //     mandatory property
11454fbf177SAndrew Geissler                 BMCWEB_LOG_INFO << "DBUS error: no matched iface " << ec
115c181942fSQiang XU                                 << "\n";
116c181942fSQiang XU                 return;
117c181942fSQiang XU             }
118c181942fSQiang XU             // Iterate over all retrieved ObjectPaths.
119c181942fSQiang XU             for (const auto& object : subtree)
120c181942fSQiang XU             {
121c181942fSQiang XU                 for (const auto& service : object.second)
122c181942fSQiang XU                 {
123c181942fSQiang XU                     getIntrusionByService(aResp, service.first, object.first);
124c181942fSQiang XU                     return;
125c181942fSQiang XU                 }
126c181942fSQiang XU             }
127c181942fSQiang XU         },
128c181942fSQiang XU         "xyz.openbmc_project.ObjectMapper",
129c181942fSQiang XU         "/xyz/openbmc_project/object_mapper",
130c181942fSQiang XU         "xyz.openbmc_project.ObjectMapper", "GetSubTree",
131271584abSEd Tanous         "/xyz/openbmc_project/Intrusion", 1,
132c181942fSQiang XU         std::array<const char*, 1>{"xyz.openbmc_project.Chassis.Intrusion"});
133c181942fSQiang XU }
134c181942fSQiang XU 
135e37f8451SRapkiewicz, Pawel /**
136e37f8451SRapkiewicz, Pawel  * ChassisCollection derived class for delivering Chassis Collection Schema
137e37f8451SRapkiewicz, Pawel  *  Functions triggers appropriate requests on DBus
138e37f8451SRapkiewicz, Pawel  */
1397e860f15SJohn Edward Broadbent inline void requestRoutesChassisCollection(App& app)
1401abe55efSEd Tanous {
1417e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Chassis/")
142ed398213SEd Tanous         .privileges(redfish::privileges::getChassisCollection)
1437e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
1447e860f15SJohn Edward Broadbent             [](const crow::Request&,
1457e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
1468d1b46d7Szhanghch05                 asyncResp->res.jsonValue["@odata.type"] =
1478d1b46d7Szhanghch05                     "#ChassisCollection.ChassisCollection";
1488d1b46d7Szhanghch05                 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Chassis";
1498d1b46d7Szhanghch05                 asyncResp->res.jsonValue["Name"] = "Chassis Collection";
150e37f8451SRapkiewicz, Pawel 
15102f6ff19SGunnar Mills                 collection_util::getCollectionMembers(
15202f6ff19SGunnar Mills                     asyncResp, "/redfish/v1/Chassis",
15302f6ff19SGunnar Mills                     {"xyz.openbmc_project.Inventory.Item.Board",
15402f6ff19SGunnar Mills                      "xyz.openbmc_project.Inventory.Item.Chassis"});
1557e860f15SJohn Edward Broadbent             });
15662d5e2e4SEd Tanous }
157e37f8451SRapkiewicz, Pawel 
158308f70c7SWilly Tu inline void
159308f70c7SWilly Tu     getChassisLocationCode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
160308f70c7SWilly Tu                            const std::string& connectionName,
161308f70c7SWilly Tu                            const std::string& path)
162308f70c7SWilly Tu {
1631e1e598dSJonathan Doman     sdbusplus::asio::getProperty<std::string>(
1641e1e598dSJonathan Doman         *crow::connections::systemBus, connectionName, path,
1651e1e598dSJonathan Doman         "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode",
166308f70c7SWilly Tu         [asyncResp](const boost::system::error_code ec,
1671e1e598dSJonathan Doman                     const std::string& property) {
168308f70c7SWilly Tu             if (ec)
169308f70c7SWilly Tu             {
1700fda0f12SGeorge Liu                 BMCWEB_LOG_DEBUG << "DBUS response error for Location";
171308f70c7SWilly Tu                 messages::internalError(asyncResp->res);
172308f70c7SWilly Tu                 return;
173308f70c7SWilly Tu             }
174308f70c7SWilly Tu 
175308f70c7SWilly Tu             asyncResp->res
1761e1e598dSJonathan Doman                 .jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
1771e1e598dSJonathan Doman                 property;
1781e1e598dSJonathan Doman         });
179308f70c7SWilly Tu }
180308f70c7SWilly Tu 
181308f70c7SWilly Tu inline void getChassisUUID(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
182308f70c7SWilly Tu                            const std::string& connectionName,
183308f70c7SWilly Tu                            const std::string& path)
184308f70c7SWilly Tu {
1851e1e598dSJonathan Doman     sdbusplus::asio::getProperty<std::string>(
1861e1e598dSJonathan Doman         *crow::connections::systemBus, connectionName, path,
1871e1e598dSJonathan Doman         "xyz.openbmc_project.Common.UUID", "UUID",
188308f70c7SWilly Tu         [asyncResp](const boost::system::error_code ec,
1891e1e598dSJonathan Doman                     const std::string& chassisUUID) {
190308f70c7SWilly Tu             if (ec)
191308f70c7SWilly Tu             {
1920fda0f12SGeorge Liu                 BMCWEB_LOG_DEBUG << "DBUS response error for UUID";
193308f70c7SWilly Tu                 messages::internalError(asyncResp->res);
194308f70c7SWilly Tu                 return;
195308f70c7SWilly Tu             }
1961e1e598dSJonathan Doman             asyncResp->res.jsonValue["UUID"] = chassisUUID;
1971e1e598dSJonathan Doman         });
198308f70c7SWilly Tu }
199308f70c7SWilly Tu 
200e37f8451SRapkiewicz, Pawel /**
201e37f8451SRapkiewicz, Pawel  * Chassis override class for delivering Chassis Schema
202e37f8451SRapkiewicz, Pawel  * Functions triggers appropriate requests on DBus
203e37f8451SRapkiewicz, Pawel  */
2047e860f15SJohn Edward Broadbent inline void requestRoutesChassis(App& app)
2051abe55efSEd Tanous {
2067e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/")
207ed398213SEd Tanous         .privileges(redfish::privileges::getChassis)
2087e860f15SJohn Edward Broadbent         .methods(
2097e860f15SJohn Edward Broadbent             boost::beast::http::verb::get)([](const crow::Request&,
2107e860f15SJohn Edward Broadbent                                               const std::shared_ptr<
2117e860f15SJohn Edward Broadbent                                                   bmcweb::AsyncResp>& asyncResp,
2127e860f15SJohn Edward Broadbent                                               const std::string& chassisId) {
213adc4f0dbSShawn McCarney             const std::array<const char*, 2> interfaces = {
214734bfe90SGunnar Mills                 "xyz.openbmc_project.Inventory.Item.Board",
215adc4f0dbSShawn McCarney                 "xyz.openbmc_project.Inventory.Item.Chassis"};
216734bfe90SGunnar Mills 
21755c7b7a2SEd Tanous             crow::connections::systemBus->async_method_call(
21862d5e2e4SEd Tanous                 [asyncResp, chassisId(std::string(chassisId))](
21962d5e2e4SEd Tanous                     const boost::system::error_code ec,
220*b9d36b47SEd Tanous                     const dbus::utility::MapperGetSubTreeResponse& subtree) {
22162d5e2e4SEd Tanous                     if (ec)
2221abe55efSEd Tanous                     {
223f12894f8SJason M. Bills                         messages::internalError(asyncResp->res);
224daf36e2eSEd Tanous                         return;
225daf36e2eSEd Tanous                     }
226daf36e2eSEd Tanous                     // Iterate over all retrieved ObjectPaths.
2271abe55efSEd Tanous                     for (const std::pair<
2281abe55efSEd Tanous                              std::string,
2297e860f15SJohn Edward Broadbent                              std::vector<std::pair<std::string,
2307e860f15SJohn Edward Broadbent                                                    std::vector<std::string>>>>&
2311214b7e7SGunnar Mills                              object : subtree)
2321abe55efSEd Tanous                     {
233daf36e2eSEd Tanous                         const std::string& path = object.first;
2341abe55efSEd Tanous                         const std::vector<
2351214b7e7SGunnar Mills                             std::pair<std::string, std::vector<std::string>>>&
2361214b7e7SGunnar Mills                             connectionNames = object.second;
2377e860f15SJohn Edward Broadbent 
238997093ebSGeorge Liu                         sdbusplus::message::object_path objPath(path);
239997093ebSGeorge Liu                         if (objPath.filename() != chassisId)
2401abe55efSEd Tanous                         {
241daf36e2eSEd Tanous                             continue;
242daf36e2eSEd Tanous                         }
24326f03899SShawn McCarney 
2447e860f15SJohn Edward Broadbent                         auto health =
2457e860f15SJohn Edward Broadbent                             std::make_shared<HealthPopulate>(asyncResp);
246b49ac873SJames Feist 
2471e1e598dSJonathan Doman                         sdbusplus::asio::getProperty<std::vector<std::string>>(
2481e1e598dSJonathan Doman                             *crow::connections::systemBus,
2491e1e598dSJonathan Doman                             "xyz.openbmc_project.ObjectMapper",
2501e1e598dSJonathan Doman                             path + "/all_sensors",
2511e1e598dSJonathan Doman                             "xyz.openbmc_project.Association", "endpoints",
252168e20c1SEd Tanous                             [health](const boost::system::error_code ec2,
2531e1e598dSJonathan Doman                                      const std::vector<std::string>& resp) {
25423a21a1cSEd Tanous                                 if (ec2)
255b49ac873SJames Feist                                 {
256b49ac873SJames Feist                                     return; // no sensors = no failures
257b49ac873SJames Feist                                 }
2581e1e598dSJonathan Doman                                 health->inventory = resp;
2591e1e598dSJonathan Doman                             });
260b49ac873SJames Feist 
261b49ac873SJames Feist                         health->populate();
262b49ac873SJames Feist 
26326f6976fSEd Tanous                         if (connectionNames.empty())
2641abe55efSEd Tanous                         {
2651c8fba97SJames Feist                             BMCWEB_LOG_ERROR << "Got 0 Connection names";
266e0d918bcSEd Tanous                             continue;
267daf36e2eSEd Tanous                         }
268e0d918bcSEd Tanous 
26949c53ac9SJohnathan Mantey                         asyncResp->res.jsonValue["@odata.type"] =
2705ac5a2f4SGunnar Mills                             "#Chassis.v1_16_0.Chassis";
27149c53ac9SJohnathan Mantey                         asyncResp->res.jsonValue["@odata.id"] =
27249c53ac9SJohnathan Mantey                             "/redfish/v1/Chassis/" + chassisId;
27349c53ac9SJohnathan Mantey                         asyncResp->res.jsonValue["Name"] = "Chassis Collection";
27449c53ac9SJohnathan Mantey                         asyncResp->res.jsonValue["ChassisType"] = "RackMount";
2757e860f15SJohn Edward Broadbent                         asyncResp->res.jsonValue["Actions"]["#Chassis.Reset"] =
2767e860f15SJohn Edward Broadbent                             {{"target", "/redfish/v1/Chassis/" + chassisId +
277dd99e04bSP.K. Lee                                             "/Actions/Chassis.Reset"},
2781cb1a9e6SAppaRao Puli                              {"@Redfish.ActionInfo", "/redfish/v1/Chassis/" +
2791cb1a9e6SAppaRao Puli                                                          chassisId +
2801cb1a9e6SAppaRao Puli                                                          "/ResetActionInfo"}};
281adbe192aSJason M. Bills                         asyncResp->res.jsonValue["PCIeDevices"] = {
282adbe192aSJason M. Bills                             {"@odata.id",
283adbe192aSJason M. Bills                              "/redfish/v1/Systems/system/PCIeDevices"}};
28449c53ac9SJohnathan Mantey 
28549c53ac9SJohnathan Mantey                         const std::string& connectionName =
28649c53ac9SJohnathan Mantey                             connectionNames[0].first;
2871c8fba97SJames Feist 
28823a21a1cSEd Tanous                         const std::vector<std::string>& interfaces2 =
2891c8fba97SJames Feist                             connectionNames[0].second;
2901c8fba97SJames Feist                         const std::array<const char*, 2> hasIndicatorLed = {
2911c8fba97SJames Feist                             "xyz.openbmc_project.Inventory.Item.Panel",
2920fda0f12SGeorge Liu                             "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
2931c8fba97SJames Feist 
294476b9cc5STejas Patil                         const std::string assetTagInterface =
2950fda0f12SGeorge Liu                             "xyz.openbmc_project.Inventory.Decorator.AssetTag";
296476b9cc5STejas Patil                         if (std::find(interfaces2.begin(), interfaces2.end(),
297476b9cc5STejas Patil                                       assetTagInterface) != interfaces2.end())
298476b9cc5STejas Patil                         {
2991e1e598dSJonathan Doman                             sdbusplus::asio::getProperty<std::string>(
3001e1e598dSJonathan Doman                                 *crow::connections::systemBus, connectionName,
3011e1e598dSJonathan Doman                                 path, assetTagInterface, "AssetTag",
302476b9cc5STejas Patil                                 [asyncResp, chassisId(std::string(chassisId))](
303476b9cc5STejas Patil                                     const boost::system::error_code ec,
3041e1e598dSJonathan Doman                                     const std::string& property) {
305476b9cc5STejas Patil                                     if (ec)
306476b9cc5STejas Patil                                     {
307476b9cc5STejas Patil                                         BMCWEB_LOG_DEBUG
3080fda0f12SGeorge Liu                                             << "DBus response error for AssetTag";
309476b9cc5STejas Patil                                         messages::internalError(asyncResp->res);
310476b9cc5STejas Patil                                         return;
311476b9cc5STejas Patil                                     }
312476b9cc5STejas Patil                                     asyncResp->res.jsonValue["AssetTag"] =
3131e1e598dSJonathan Doman                                         property;
3141e1e598dSJonathan Doman                                 });
315476b9cc5STejas Patil                         }
316476b9cc5STejas Patil 
3171c8fba97SJames Feist                         for (const char* interface : hasIndicatorLed)
3181c8fba97SJames Feist                         {
3197e860f15SJohn Edward Broadbent                             if (std::find(interfaces2.begin(),
3207e860f15SJohn Edward Broadbent                                           interfaces2.end(),
32123a21a1cSEd Tanous                                           interface) != interfaces2.end())
3221c8fba97SJames Feist                             {
3231c8fba97SJames Feist                                 getIndicatorLedState(asyncResp);
3249f8bfa7cSGunnar Mills                                 getLocationIndicatorActive(asyncResp);
3251c8fba97SJames Feist                                 break;
3261c8fba97SJames Feist                             }
3271c8fba97SJames Feist                         }
3281c8fba97SJames Feist 
32955c7b7a2SEd Tanous                         crow::connections::systemBus->async_method_call(
33062d5e2e4SEd Tanous                             [asyncResp, chassisId(std::string(chassisId))](
33190728b54SEd Tanous                                 const boost::system::error_code /*ec2*/,
332*b9d36b47SEd Tanous                                 const dbus::utility::DBusPropertiesMap&
3337e860f15SJohn Edward Broadbent                                     propertiesList) {
334168e20c1SEd Tanous                                 for (const std::pair<
335168e20c1SEd Tanous                                          std::string,
336168e20c1SEd Tanous                                          dbus::utility::DbusVariantType>&
3371214b7e7SGunnar Mills                                          property : propertiesList)
3381abe55efSEd Tanous                                 {
3397e860f15SJohn Edward Broadbent                                     // Store DBus properties that are also
3407e860f15SJohn Edward Broadbent                                     // Redfish properties with same name and a
3417e860f15SJohn Edward Broadbent                                     // string value
34299cffd7fSShawn McCarney                                     const std::string& propertyName =
34399cffd7fSShawn McCarney                                         property.first;
34499cffd7fSShawn McCarney                                     if ((propertyName == "PartNumber") ||
34599cffd7fSShawn McCarney                                         (propertyName == "SerialNumber") ||
34699cffd7fSShawn McCarney                                         (propertyName == "Manufacturer") ||
347caa11f7aSAlpana Kumari                                         (propertyName == "Model") ||
348caa11f7aSAlpana Kumari                                         (propertyName == "SparePartNumber"))
34999cffd7fSShawn McCarney                                     {
350daf36e2eSEd Tanous                                         const std::string* value =
35199cffd7fSShawn McCarney                                             std::get_if<std::string>(
35299cffd7fSShawn McCarney                                                 &property.second);
353caa11f7aSAlpana Kumari                                         if (value == nullptr)
3541abe55efSEd Tanous                                         {
355caa11f7aSAlpana Kumari                                             BMCWEB_LOG_ERROR
356caa11f7aSAlpana Kumari                                                 << "Null value returned for "
357caa11f7aSAlpana Kumari                                                 << propertyName;
358caa11f7aSAlpana Kumari                                             messages::internalError(
359caa11f7aSAlpana Kumari                                                 asyncResp->res);
360caa11f7aSAlpana Kumari                                             return;
361daf36e2eSEd Tanous                                         }
362caa11f7aSAlpana Kumari                                         // SparePartNumber is optional on D-Bus
363caa11f7aSAlpana Kumari                                         // so skip if it is empty
364caa11f7aSAlpana Kumari                                         if (propertyName == "SparePartNumber")
365caa11f7aSAlpana Kumari                                         {
36626f6976fSEd Tanous                                             if (value->empty())
367caa11f7aSAlpana Kumari                                             {
368caa11f7aSAlpana Kumari                                                 continue;
369caa11f7aSAlpana Kumari                                             }
370caa11f7aSAlpana Kumari                                         }
371caa11f7aSAlpana Kumari                                         asyncResp->res.jsonValue[propertyName] =
372caa11f7aSAlpana Kumari                                             *value;
373daf36e2eSEd Tanous                                     }
37499cffd7fSShawn McCarney                                 }
37562d5e2e4SEd Tanous                                 asyncResp->res.jsonValue["Name"] = chassisId;
37662d5e2e4SEd Tanous                                 asyncResp->res.jsonValue["Id"] = chassisId;
3770256b694Szhanghch05 #ifdef BMCWEB_ALLOW_DEPRECATED_POWER_THERMAL
37862d5e2e4SEd Tanous                                 asyncResp->res.jsonValue["Thermal"] = {
3791abe55efSEd Tanous                                     {"@odata.id", "/redfish/v1/Chassis/" +
3801abe55efSEd Tanous                                                       chassisId + "/Thermal"}};
3812474adfaSEd Tanous                                 // Power object
3822474adfaSEd Tanous                                 asyncResp->res.jsonValue["Power"] = {
3832474adfaSEd Tanous                                     {"@odata.id", "/redfish/v1/Chassis/" +
3842474adfaSEd Tanous                                                       chassisId + "/Power"}};
3850256b694Szhanghch05 #endif
38695a3ecadSAnthony Wilson                                 // SensorCollection
38795a3ecadSAnthony Wilson                                 asyncResp->res.jsonValue["Sensors"] = {
38895a3ecadSAnthony Wilson                                     {"@odata.id", "/redfish/v1/Chassis/" +
38995a3ecadSAnthony Wilson                                                       chassisId + "/Sensors"}};
390029573d4SEd Tanous                                 asyncResp->res.jsonValue["Status"] = {
391029573d4SEd Tanous                                     {"State", "Enabled"},
392029573d4SEd Tanous                                 };
3932474adfaSEd Tanous 
394029573d4SEd Tanous                                 asyncResp->res
395029573d4SEd Tanous                                     .jsonValue["Links"]["ComputerSystems"] = {
3967e860f15SJohn Edward Broadbent                                     {{"@odata.id",
3977e860f15SJohn Edward Broadbent                                       "/redfish/v1/Systems/system"}}};
3987e860f15SJohn Edward Broadbent                                 asyncResp->res.jsonValue["Links"]["ManagedBy"] =
3997e860f15SJohn Edward Broadbent                                     {{{"@odata.id",
4007e860f15SJohn Edward Broadbent                                        "/redfish/v1/Managers/bmc"}}};
401beeca0aeSGunnar Mills                                 getChassisState(asyncResp);
402daf36e2eSEd Tanous                             },
4037e860f15SJohn Edward Broadbent                             connectionName, path,
4047e860f15SJohn Edward Broadbent                             "org.freedesktop.DBus.Properties", "GetAll",
4051abe55efSEd Tanous                             "xyz.openbmc_project.Inventory.Decorator.Asset");
4062c37b4b0SSharad Yadav 
407308f70c7SWilly Tu                         for (const auto& interface : interfaces2)
4082c37b4b0SSharad Yadav                         {
409308f70c7SWilly Tu                             if (interface == "xyz.openbmc_project.Common.UUID")
4102c37b4b0SSharad Yadav                             {
411308f70c7SWilly Tu                                 getChassisUUID(asyncResp, connectionName, path);
4122c37b4b0SSharad Yadav                             }
4130fda0f12SGeorge Liu                             else if (
4140fda0f12SGeorge Liu                                 interface ==
4150fda0f12SGeorge Liu                                 "xyz.openbmc_project.Inventory.Decorator.LocationCode")
4162c37b4b0SSharad Yadav                             {
417308f70c7SWilly Tu                                 getChassisLocationCode(asyncResp,
418308f70c7SWilly Tu                                                        connectionName, path);
4192c37b4b0SSharad Yadav                             }
4202c37b4b0SSharad Yadav                         }
4212c37b4b0SSharad Yadav 
422daf36e2eSEd Tanous                         return;
423daf36e2eSEd Tanous                     }
424e0d918bcSEd Tanous 
425daf36e2eSEd Tanous                     // Couldn't find an object with that name.  return an error
426f12894f8SJason M. Bills                     messages::resourceNotFound(
4275ac5a2f4SGunnar Mills                         asyncResp->res, "#Chassis.v1_16_0.Chassis", chassisId);
428daf36e2eSEd Tanous                 },
429daf36e2eSEd Tanous                 "xyz.openbmc_project.ObjectMapper",
430daf36e2eSEd Tanous                 "/xyz/openbmc_project/object_mapper",
431daf36e2eSEd Tanous                 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
432271584abSEd Tanous                 "/xyz/openbmc_project/inventory", 0, interfaces);
433c181942fSQiang XU 
434c181942fSQiang XU             getPhysicalSecurityData(asyncResp);
4357e860f15SJohn Edward Broadbent         });
4361c8fba97SJames Feist 
4377e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/")
438ed398213SEd Tanous         .privileges(redfish::privileges::patchChassis)
4397e860f15SJohn Edward Broadbent         .methods(
4407e860f15SJohn Edward Broadbent             boost::beast::http::verb::
4417e860f15SJohn Edward Broadbent                 patch)([](const crow::Request& req,
4427e860f15SJohn Edward Broadbent                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
4437e860f15SJohn Edward Broadbent                           const std::string& param) {
4449f8bfa7cSGunnar Mills             std::optional<bool> locationIndicatorActive;
4451c8fba97SJames Feist             std::optional<std::string> indicatorLed;
4461c8fba97SJames Feist 
4477e860f15SJohn Edward Broadbent             if (param.empty())
4481c8fba97SJames Feist             {
4491c8fba97SJames Feist                 return;
4501c8fba97SJames Feist             }
4511c8fba97SJames Feist 
45215ed6780SWilly Tu             if (!json_util::readJsonPatch(
4537e860f15SJohn Edward Broadbent                     req, asyncResp->res, "LocationIndicatorActive",
4547e860f15SJohn Edward Broadbent                     locationIndicatorActive, "IndicatorLED", indicatorLed))
4551c8fba97SJames Feist             {
4561c8fba97SJames Feist                 return;
4571c8fba97SJames Feist             }
4581c8fba97SJames Feist 
4599f8bfa7cSGunnar Mills             // TODO (Gunnar): Remove IndicatorLED after enough time has passed
4609f8bfa7cSGunnar Mills             if (!locationIndicatorActive && !indicatorLed)
4611c8fba97SJames Feist             {
4621c8fba97SJames Feist                 return; // delete this when we support more patch properties
4631c8fba97SJames Feist             }
464d6aa0093SGunnar Mills             if (indicatorLed)
465d6aa0093SGunnar Mills             {
4667e860f15SJohn Edward Broadbent                 asyncResp->res.addHeader(
4677e860f15SJohn Edward Broadbent                     boost::beast::http::field::warning,
4680fda0f12SGeorge Liu                     "299 - \"IndicatorLED is deprecated. Use LocationIndicatorActive instead.\"");
469d6aa0093SGunnar Mills             }
4701c8fba97SJames Feist 
4711c8fba97SJames Feist             const std::array<const char*, 2> interfaces = {
4721c8fba97SJames Feist                 "xyz.openbmc_project.Inventory.Item.Board",
4731c8fba97SJames Feist                 "xyz.openbmc_project.Inventory.Item.Chassis"};
4741c8fba97SJames Feist 
4757e860f15SJohn Edward Broadbent             const std::string& chassisId = param;
4761c8fba97SJames Feist 
4771c8fba97SJames Feist             crow::connections::systemBus->async_method_call(
4789f8bfa7cSGunnar Mills                 [asyncResp, chassisId, locationIndicatorActive, indicatorLed](
4791c8fba97SJames Feist                     const boost::system::error_code ec,
480*b9d36b47SEd Tanous                     const dbus::utility::MapperGetSubTreeResponse& subtree) {
4811c8fba97SJames Feist                     if (ec)
4821c8fba97SJames Feist                     {
4831c8fba97SJames Feist                         messages::internalError(asyncResp->res);
4841c8fba97SJames Feist                         return;
4851c8fba97SJames Feist                     }
4861c8fba97SJames Feist 
4871c8fba97SJames Feist                     // Iterate over all retrieved ObjectPaths.
4881c8fba97SJames Feist                     for (const std::pair<
4891c8fba97SJames Feist                              std::string,
4907e860f15SJohn Edward Broadbent                              std::vector<std::pair<std::string,
4917e860f15SJohn Edward Broadbent                                                    std::vector<std::string>>>>&
4921214b7e7SGunnar Mills                              object : subtree)
4931c8fba97SJames Feist                     {
4941c8fba97SJames Feist                         const std::string& path = object.first;
4951c8fba97SJames Feist                         const std::vector<
4961214b7e7SGunnar Mills                             std::pair<std::string, std::vector<std::string>>>&
4971214b7e7SGunnar Mills                             connectionNames = object.second;
4981c8fba97SJames Feist 
499997093ebSGeorge Liu                         sdbusplus::message::object_path objPath(path);
500997093ebSGeorge Liu                         if (objPath.filename() != chassisId)
5011c8fba97SJames Feist                         {
5021c8fba97SJames Feist                             continue;
5031c8fba97SJames Feist                         }
5041c8fba97SJames Feist 
50526f6976fSEd Tanous                         if (connectionNames.empty())
5061c8fba97SJames Feist                         {
5071c8fba97SJames Feist                             BMCWEB_LOG_ERROR << "Got 0 Connection names";
5081c8fba97SJames Feist                             continue;
5091c8fba97SJames Feist                         }
5101c8fba97SJames Feist 
51123a21a1cSEd Tanous                         const std::vector<std::string>& interfaces3 =
5121c8fba97SJames Feist                             connectionNames[0].second;
5131c8fba97SJames Feist 
5141c8fba97SJames Feist                         const std::array<const char*, 2> hasIndicatorLed = {
5151c8fba97SJames Feist                             "xyz.openbmc_project.Inventory.Item.Panel",
5160fda0f12SGeorge Liu                             "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
5171c8fba97SJames Feist                         bool indicatorChassis = false;
5181c8fba97SJames Feist                         for (const char* interface : hasIndicatorLed)
5191c8fba97SJames Feist                         {
5207e860f15SJohn Edward Broadbent                             if (std::find(interfaces3.begin(),
5217e860f15SJohn Edward Broadbent                                           interfaces3.end(),
52223a21a1cSEd Tanous                                           interface) != interfaces3.end())
5231c8fba97SJames Feist                             {
5241c8fba97SJames Feist                                 indicatorChassis = true;
5251c8fba97SJames Feist                                 break;
5261c8fba97SJames Feist                             }
5271c8fba97SJames Feist                         }
5289f8bfa7cSGunnar Mills                         if (locationIndicatorActive)
5299f8bfa7cSGunnar Mills                         {
5309f8bfa7cSGunnar Mills                             if (indicatorChassis)
5319f8bfa7cSGunnar Mills                             {
5329f8bfa7cSGunnar Mills                                 setLocationIndicatorActive(
5339f8bfa7cSGunnar Mills                                     asyncResp, *locationIndicatorActive);
5349f8bfa7cSGunnar Mills                             }
5359f8bfa7cSGunnar Mills                             else
5369f8bfa7cSGunnar Mills                             {
5379f8bfa7cSGunnar Mills                                 messages::propertyUnknown(
5389f8bfa7cSGunnar Mills                                     asyncResp->res, "LocationIndicatorActive");
5399f8bfa7cSGunnar Mills                             }
5409f8bfa7cSGunnar Mills                         }
5419f8bfa7cSGunnar Mills                         if (indicatorLed)
5429f8bfa7cSGunnar Mills                         {
5431c8fba97SJames Feist                             if (indicatorChassis)
5441c8fba97SJames Feist                             {
545f23b7296SEd Tanous                                 setIndicatorLedState(asyncResp, *indicatorLed);
5461c8fba97SJames Feist                             }
5471c8fba97SJames Feist                             else
5481c8fba97SJames Feist                             {
5491c8fba97SJames Feist                                 messages::propertyUnknown(asyncResp->res,
5501c8fba97SJames Feist                                                           "IndicatorLED");
5511c8fba97SJames Feist                             }
5521c8fba97SJames Feist                         }
5531c8fba97SJames Feist                         return;
5541c8fba97SJames Feist                     }
5551c8fba97SJames Feist 
5561c8fba97SJames Feist                     messages::resourceNotFound(
5579f8bfa7cSGunnar Mills                         asyncResp->res, "#Chassis.v1_14_0.Chassis", chassisId);
5581c8fba97SJames Feist                 },
5591c8fba97SJames Feist                 "xyz.openbmc_project.ObjectMapper",
5601c8fba97SJames Feist                 "/xyz/openbmc_project/object_mapper",
5611c8fba97SJames Feist                 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
5621c8fba97SJames Feist                 "/xyz/openbmc_project/inventory", 0, interfaces);
5637e860f15SJohn Edward Broadbent         });
5641c8fba97SJames Feist }
565dd99e04bSP.K. Lee 
5668d1b46d7Szhanghch05 inline void
5678d1b46d7Szhanghch05     doChassisPowerCycle(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
568dd99e04bSP.K. Lee {
569c3b3c92aSVijay Khemka     const char* busName = "xyz.openbmc_project.ObjectMapper";
570c3b3c92aSVijay Khemka     const char* path = "/xyz/openbmc_project/object_mapper";
571c3b3c92aSVijay Khemka     const char* interface = "xyz.openbmc_project.ObjectMapper";
572c3b3c92aSVijay Khemka     const char* method = "GetSubTreePaths";
573c3b3c92aSVijay Khemka 
574c3b3c92aSVijay Khemka     const std::array<const char*, 1> interfaces = {
575c3b3c92aSVijay Khemka         "xyz.openbmc_project.State.Chassis"};
576c3b3c92aSVijay Khemka 
577c3b3c92aSVijay Khemka     // Use mapper to get subtree paths.
578c3b3c92aSVijay Khemka     crow::connections::systemBus->async_method_call(
579*b9d36b47SEd Tanous         [asyncResp](
580*b9d36b47SEd Tanous             const boost::system::error_code ec,
581*b9d36b47SEd Tanous             const dbus::utility::MapperGetSubTreePathsResponse& chassisList) {
582c3b3c92aSVijay Khemka             if (ec)
583c3b3c92aSVijay Khemka             {
584c3b3c92aSVijay Khemka                 BMCWEB_LOG_DEBUG << "[mapper] Bad D-Bus request error: " << ec;
585c3b3c92aSVijay Khemka                 messages::internalError(asyncResp->res);
586c3b3c92aSVijay Khemka                 return;
587c3b3c92aSVijay Khemka             }
588c3b3c92aSVijay Khemka 
589dd99e04bSP.K. Lee             const char* processName = "xyz.openbmc_project.State.Chassis";
590dd99e04bSP.K. Lee             const char* interfaceName = "xyz.openbmc_project.State.Chassis";
591dd99e04bSP.K. Lee             const char* destProperty = "RequestedPowerTransition";
592dd99e04bSP.K. Lee             const std::string propertyValue =
593dd99e04bSP.K. Lee                 "xyz.openbmc_project.State.Chassis.Transition.PowerCycle";
594c3b3c92aSVijay Khemka             std::string objectPath =
595c3b3c92aSVijay Khemka                 "/xyz/openbmc_project/state/chassis_system0";
596c3b3c92aSVijay Khemka 
597c3b3c92aSVijay Khemka             /* Look for system reset chassis path */
598c3b3c92aSVijay Khemka             if ((std::find(chassisList.begin(), chassisList.end(),
599c3b3c92aSVijay Khemka                            objectPath)) == chassisList.end())
600c3b3c92aSVijay Khemka             {
601c3b3c92aSVijay Khemka                 /* We prefer to reset the full chassis_system, but if it doesn't
602c3b3c92aSVijay Khemka                  * exist on some platforms, fall back to a host-only power reset
603c3b3c92aSVijay Khemka                  */
604c3b3c92aSVijay Khemka                 objectPath = "/xyz/openbmc_project/state/chassis0";
605c3b3c92aSVijay Khemka             }
606dd99e04bSP.K. Lee 
607dd99e04bSP.K. Lee             crow::connections::systemBus->async_method_call(
608dd99e04bSP.K. Lee                 [asyncResp](const boost::system::error_code ec) {
609dd99e04bSP.K. Lee                     // Use "Set" method to set the property value.
610dd99e04bSP.K. Lee                     if (ec)
611dd99e04bSP.K. Lee                     {
612c3b3c92aSVijay Khemka                         BMCWEB_LOG_DEBUG << "[Set] Bad D-Bus request error: "
613c3b3c92aSVijay Khemka                                          << ec;
614dd99e04bSP.K. Lee                         messages::internalError(asyncResp->res);
615dd99e04bSP.K. Lee                         return;
616dd99e04bSP.K. Lee                     }
617dd99e04bSP.K. Lee 
618dd99e04bSP.K. Lee                     messages::success(asyncResp->res);
619dd99e04bSP.K. Lee                 },
620c3b3c92aSVijay Khemka                 processName, objectPath, "org.freedesktop.DBus.Properties",
621c3b3c92aSVijay Khemka                 "Set", interfaceName, destProperty,
622168e20c1SEd Tanous                 dbus::utility::DbusVariantType{propertyValue});
623c3b3c92aSVijay Khemka         },
624c3b3c92aSVijay Khemka         busName, path, interface, method, "/", 0, interfaces);
625dd99e04bSP.K. Lee }
626dd99e04bSP.K. Lee 
627dd99e04bSP.K. Lee /**
628dd99e04bSP.K. Lee  * ChassisResetAction class supports the POST method for the Reset
629dd99e04bSP.K. Lee  * action.
630dd99e04bSP.K. Lee  * Function handles POST method request.
631dd99e04bSP.K. Lee  * Analyzes POST body before sending Reset request data to D-Bus.
632dd99e04bSP.K. Lee  */
6337e860f15SJohn Edward Broadbent 
6347e860f15SJohn Edward Broadbent inline void requestRoutesChassisResetAction(App& app)
635dd99e04bSP.K. Lee {
6367e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Actions/Chassis.Reset/")
637ed398213SEd Tanous         .privileges(redfish::privileges::postChassis)
6387e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
6397e860f15SJohn Edward Broadbent             [](const crow::Request& req,
6407e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
6417e860f15SJohn Edward Broadbent                const std::string&) {
642dd99e04bSP.K. Lee                 BMCWEB_LOG_DEBUG << "Post Chassis Reset.";
643dd99e04bSP.K. Lee 
644dd99e04bSP.K. Lee                 std::string resetType;
645dd99e04bSP.K. Lee 
64615ed6780SWilly Tu                 if (!json_util::readJsonAction(req, asyncResp->res, "ResetType",
6477e860f15SJohn Edward Broadbent                                                resetType))
648dd99e04bSP.K. Lee                 {
649dd99e04bSP.K. Lee                     return;
650dd99e04bSP.K. Lee                 }
651dd99e04bSP.K. Lee 
652dd99e04bSP.K. Lee                 if (resetType != "PowerCycle")
653dd99e04bSP.K. Lee                 {
654dd99e04bSP.K. Lee                     BMCWEB_LOG_DEBUG << "Invalid property value for ResetType: "
655dd99e04bSP.K. Lee                                      << resetType;
6567e860f15SJohn Edward Broadbent                     messages::actionParameterNotSupported(
6577e860f15SJohn Edward Broadbent                         asyncResp->res, resetType, "ResetType");
658dd99e04bSP.K. Lee 
659dd99e04bSP.K. Lee                     return;
660dd99e04bSP.K. Lee                 }
661dd99e04bSP.K. Lee                 doChassisPowerCycle(asyncResp);
6627e860f15SJohn Edward Broadbent             });
663dd99e04bSP.K. Lee }
6641cb1a9e6SAppaRao Puli 
6651cb1a9e6SAppaRao Puli /**
6661cb1a9e6SAppaRao Puli  * ChassisResetActionInfo derived class for delivering Chassis
6671cb1a9e6SAppaRao Puli  * ResetType AllowableValues using ResetInfo schema.
6681cb1a9e6SAppaRao Puli  */
6697e860f15SJohn Edward Broadbent inline void requestRoutesChassisResetActionInfo(App& app)
6701cb1a9e6SAppaRao Puli {
6717e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ResetActionInfo/")
672ed398213SEd Tanous         .privileges(redfish::privileges::getActionInfo)
6737e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
6747e860f15SJohn Edward Broadbent             [](const crow::Request&,
6757e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
6767e860f15SJohn Edward Broadbent                const std::string& chassisId)
6771cb1a9e6SAppaRao Puli 
6781cb1a9e6SAppaRao Puli             {
6798d1b46d7Szhanghch05                 asyncResp->res.jsonValue = {
6808d1b46d7Szhanghch05                     {"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"},
6818d1b46d7Szhanghch05                     {"@odata.id",
6828d1b46d7Szhanghch05                      "/redfish/v1/Chassis/" + chassisId + "/ResetActionInfo"},
6831cb1a9e6SAppaRao Puli                     {"Name", "Reset Action Info"},
6841cb1a9e6SAppaRao Puli                     {"Id", "ResetActionInfo"},
6851cb1a9e6SAppaRao Puli                     {"Parameters",
6861cb1a9e6SAppaRao Puli                      {{{"Name", "ResetType"},
6871cb1a9e6SAppaRao Puli                        {"Required", true},
6881cb1a9e6SAppaRao Puli                        {"DataType", "String"},
6891cb1a9e6SAppaRao Puli                        {"AllowableValues", {"PowerCycle"}}}}}};
6907e860f15SJohn Edward Broadbent             });
6911cb1a9e6SAppaRao Puli }
6921cb1a9e6SAppaRao Puli 
693e37f8451SRapkiewicz, Pawel } // namespace redfish
694