xref: /openbmc/bmcweb/features/redfish/lib/chassis.hpp (revision 002d39b4a7a5ed7166e2acad84e0943c3def9492)
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>
2345ca1b86SEd Tanous #include <query.hpp>
24ed398213SEd Tanous #include <registries/privilege_registry.hpp>
251e1e598dSJonathan Doman #include <sdbusplus/asio/property.hpp>
2602f6ff19SGunnar Mills #include <utils/collection.hpp>
271214b7e7SGunnar Mills 
281abe55efSEd Tanous namespace redfish
291abe55efSEd Tanous {
30e37f8451SRapkiewicz, Pawel 
31e37f8451SRapkiewicz, Pawel /**
32beeca0aeSGunnar Mills  * @brief Retrieves chassis state properties over dbus
33beeca0aeSGunnar Mills  *
34beeca0aeSGunnar Mills  * @param[in] aResp - Shared pointer for completing asynchronous calls.
35beeca0aeSGunnar Mills  *
36beeca0aeSGunnar Mills  * @return None.
37beeca0aeSGunnar Mills  */
388d1b46d7Szhanghch05 inline void getChassisState(std::shared_ptr<bmcweb::AsyncResp> aResp)
39beeca0aeSGunnar Mills {
401e1e598dSJonathan Doman     // crow::connections::systemBus->async_method_call(
411e1e598dSJonathan Doman     sdbusplus::asio::getProperty<std::string>(
421e1e598dSJonathan Doman         *crow::connections::systemBus, "xyz.openbmc_project.State.Chassis",
431e1e598dSJonathan Doman         "/xyz/openbmc_project/state/chassis0",
441e1e598dSJonathan Doman         "xyz.openbmc_project.State.Chassis", "CurrentPowerState",
451e1e598dSJonathan Doman         [aResp{std::move(aResp)}](const boost::system::error_code ec,
461e1e598dSJonathan Doman                                   const std::string& chassisState) {
47beeca0aeSGunnar Mills         if (ec)
48beeca0aeSGunnar Mills         {
49a6e5e0abSCarson Labrado             if (ec == boost::system::errc::host_unreachable)
50a6e5e0abSCarson Labrado             {
51a6e5e0abSCarson Labrado                 // Service not available, no error, just don't return
52a6e5e0abSCarson Labrado                 // chassis state info
53a6e5e0abSCarson Labrado                 BMCWEB_LOG_DEBUG << "Service not available " << ec;
54a6e5e0abSCarson Labrado                 return;
55a6e5e0abSCarson Labrado             }
56beeca0aeSGunnar Mills             BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
57beeca0aeSGunnar Mills             messages::internalError(aResp->res);
58beeca0aeSGunnar Mills             return;
59beeca0aeSGunnar Mills         }
60beeca0aeSGunnar Mills 
611e1e598dSJonathan Doman         BMCWEB_LOG_DEBUG << "Chassis state: " << chassisState;
62beeca0aeSGunnar Mills         // Verify Chassis State
63*002d39b4SEd Tanous         if (chassisState == "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 
96*002d39b4SEd Tanous         aResp->res.jsonValue["PhysicalSecurity"]["IntrusionSensorNumber"] = 1;
971476687dSEd Tanous         aResp->res.jsonValue["PhysicalSecurity"]["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,
109b9d36b47SEd 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
114*002d39b4SEd Tanous             BMCWEB_LOG_INFO << "DBUS error: no matched iface " << ec << "\n";
115c181942fSQiang XU             return;
116c181942fSQiang XU         }
117c181942fSQiang XU         // Iterate over all retrieved ObjectPaths.
118c181942fSQiang XU         for (const auto& object : subtree)
119c181942fSQiang XU         {
120c181942fSQiang XU             for (const auto& service : object.second)
121c181942fSQiang XU             {
122c181942fSQiang XU                 getIntrusionByService(aResp, service.first, object.first);
123c181942fSQiang XU                 return;
124c181942fSQiang XU             }
125c181942fSQiang XU         }
126c181942fSQiang XU         },
127c181942fSQiang XU         "xyz.openbmc_project.ObjectMapper",
128c181942fSQiang XU         "/xyz/openbmc_project/object_mapper",
129c181942fSQiang XU         "xyz.openbmc_project.ObjectMapper", "GetSubTree",
130271584abSEd Tanous         "/xyz/openbmc_project/Intrusion", 1,
131c181942fSQiang XU         std::array<const char*, 1>{"xyz.openbmc_project.Chassis.Intrusion"});
132c181942fSQiang XU }
133c181942fSQiang XU 
134e37f8451SRapkiewicz, Pawel /**
135e37f8451SRapkiewicz, Pawel  * ChassisCollection derived class for delivering Chassis Collection Schema
136e37f8451SRapkiewicz, Pawel  *  Functions triggers appropriate requests on DBus
137e37f8451SRapkiewicz, Pawel  */
1387e860f15SJohn Edward Broadbent inline void requestRoutesChassisCollection(App& app)
1391abe55efSEd Tanous {
1407e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Chassis/")
141ed398213SEd Tanous         .privileges(redfish::privileges::getChassisCollection)
1427e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
14345ca1b86SEd Tanous             [&app](const crow::Request& req,
1447e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
14545ca1b86SEd Tanous         if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
14645ca1b86SEd Tanous         {
14745ca1b86SEd Tanous             return;
14845ca1b86SEd Tanous         }
1498d1b46d7Szhanghch05         asyncResp->res.jsonValue["@odata.type"] =
1508d1b46d7Szhanghch05             "#ChassisCollection.ChassisCollection";
1518d1b46d7Szhanghch05         asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Chassis";
1528d1b46d7Szhanghch05         asyncResp->res.jsonValue["Name"] = "Chassis Collection";
153e37f8451SRapkiewicz, Pawel 
15402f6ff19SGunnar Mills         collection_util::getCollectionMembers(
15502f6ff19SGunnar Mills             asyncResp, "/redfish/v1/Chassis",
15602f6ff19SGunnar Mills             {"xyz.openbmc_project.Inventory.Item.Board",
15702f6ff19SGunnar Mills              "xyz.openbmc_project.Inventory.Item.Chassis"});
1587e860f15SJohn Edward Broadbent         });
15962d5e2e4SEd Tanous }
160e37f8451SRapkiewicz, Pawel 
161308f70c7SWilly Tu inline void
162308f70c7SWilly Tu     getChassisLocationCode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
163308f70c7SWilly Tu                            const std::string& connectionName,
164308f70c7SWilly Tu                            const std::string& path)
165308f70c7SWilly Tu {
1661e1e598dSJonathan Doman     sdbusplus::asio::getProperty<std::string>(
1671e1e598dSJonathan Doman         *crow::connections::systemBus, connectionName, path,
1681e1e598dSJonathan Doman         "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode",
169308f70c7SWilly Tu         [asyncResp](const boost::system::error_code ec,
1701e1e598dSJonathan Doman                     const std::string& property) {
171308f70c7SWilly Tu         if (ec)
172308f70c7SWilly Tu         {
1730fda0f12SGeorge Liu             BMCWEB_LOG_DEBUG << "DBUS response error for Location";
174308f70c7SWilly Tu             messages::internalError(asyncResp->res);
175308f70c7SWilly Tu             return;
176308f70c7SWilly Tu         }
177308f70c7SWilly Tu 
178*002d39b4SEd Tanous         asyncResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
1791e1e598dSJonathan Doman             property;
1801e1e598dSJonathan Doman         });
181308f70c7SWilly Tu }
182308f70c7SWilly Tu 
183308f70c7SWilly Tu inline void getChassisUUID(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
184308f70c7SWilly Tu                            const std::string& connectionName,
185308f70c7SWilly Tu                            const std::string& path)
186308f70c7SWilly Tu {
1871e1e598dSJonathan Doman     sdbusplus::asio::getProperty<std::string>(
1881e1e598dSJonathan Doman         *crow::connections::systemBus, connectionName, path,
1891e1e598dSJonathan Doman         "xyz.openbmc_project.Common.UUID", "UUID",
190308f70c7SWilly Tu         [asyncResp](const boost::system::error_code ec,
1911e1e598dSJonathan Doman                     const std::string& chassisUUID) {
192308f70c7SWilly Tu         if (ec)
193308f70c7SWilly Tu         {
1940fda0f12SGeorge Liu             BMCWEB_LOG_DEBUG << "DBUS response error for UUID";
195308f70c7SWilly Tu             messages::internalError(asyncResp->res);
196308f70c7SWilly Tu             return;
197308f70c7SWilly Tu         }
1981e1e598dSJonathan Doman         asyncResp->res.jsonValue["UUID"] = chassisUUID;
1991e1e598dSJonathan Doman         });
200308f70c7SWilly Tu }
201308f70c7SWilly Tu 
202e37f8451SRapkiewicz, Pawel /**
203e37f8451SRapkiewicz, Pawel  * Chassis override class for delivering Chassis Schema
204e37f8451SRapkiewicz, Pawel  * Functions triggers appropriate requests on DBus
205e37f8451SRapkiewicz, Pawel  */
2067e860f15SJohn Edward Broadbent inline void requestRoutesChassis(App& app)
2071abe55efSEd Tanous {
2087e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/")
209ed398213SEd Tanous         .privileges(redfish::privileges::getChassis)
210*002d39b4SEd Tanous         .methods(boost::beast::http::verb::get)(
211*002d39b4SEd Tanous             [&app](const crow::Request& req,
21245ca1b86SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2137e860f15SJohn Edward Broadbent                    const std::string& chassisId) {
21445ca1b86SEd Tanous         if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
21545ca1b86SEd Tanous         {
21645ca1b86SEd Tanous             return;
21745ca1b86SEd Tanous         }
218adc4f0dbSShawn McCarney         const std::array<const char*, 2> interfaces = {
219734bfe90SGunnar Mills             "xyz.openbmc_project.Inventory.Item.Board",
220adc4f0dbSShawn McCarney             "xyz.openbmc_project.Inventory.Item.Chassis"};
221734bfe90SGunnar Mills 
22255c7b7a2SEd Tanous         crow::connections::systemBus->async_method_call(
22362d5e2e4SEd Tanous             [asyncResp, chassisId(std::string(chassisId))](
22462d5e2e4SEd Tanous                 const boost::system::error_code ec,
225b9d36b47SEd Tanous                 const dbus::utility::MapperGetSubTreeResponse& subtree) {
22662d5e2e4SEd Tanous             if (ec)
2271abe55efSEd Tanous             {
228f12894f8SJason M. Bills                 messages::internalError(asyncResp->res);
229daf36e2eSEd Tanous                 return;
230daf36e2eSEd Tanous             }
231daf36e2eSEd Tanous             // Iterate over all retrieved ObjectPaths.
232*002d39b4SEd Tanous             for (const std::pair<std::string,
233*002d39b4SEd Tanous                                  std::vector<std::pair<
234*002d39b4SEd Tanous                                      std::string, std::vector<std::string>>>>&
2351214b7e7SGunnar Mills                      object : subtree)
2361abe55efSEd Tanous             {
237daf36e2eSEd Tanous                 const std::string& path = object.first;
2381abe55efSEd Tanous                 const std::vector<
2391214b7e7SGunnar Mills                     std::pair<std::string, std::vector<std::string>>>&
2401214b7e7SGunnar Mills                     connectionNames = object.second;
2417e860f15SJohn Edward Broadbent 
242997093ebSGeorge Liu                 sdbusplus::message::object_path objPath(path);
243997093ebSGeorge Liu                 if (objPath.filename() != chassisId)
2441abe55efSEd Tanous                 {
245daf36e2eSEd Tanous                     continue;
246daf36e2eSEd Tanous                 }
24726f03899SShawn McCarney 
248*002d39b4SEd Tanous                 auto health = std::make_shared<HealthPopulate>(asyncResp);
249b49ac873SJames Feist 
2501e1e598dSJonathan Doman                 sdbusplus::asio::getProperty<std::vector<std::string>>(
2511e1e598dSJonathan Doman                     *crow::connections::systemBus,
252*002d39b4SEd Tanous                     "xyz.openbmc_project.ObjectMapper", path + "/all_sensors",
2531e1e598dSJonathan Doman                     "xyz.openbmc_project.Association", "endpoints",
254168e20c1SEd Tanous                     [health](const boost::system::error_code ec2,
2551e1e598dSJonathan Doman                              const std::vector<std::string>& resp) {
25623a21a1cSEd Tanous                     if (ec2)
257b49ac873SJames Feist                     {
258b49ac873SJames Feist                         return; // no sensors = no failures
259b49ac873SJames Feist                     }
2601e1e598dSJonathan Doman                     health->inventory = resp;
2611e1e598dSJonathan Doman                     });
262b49ac873SJames Feist 
263b49ac873SJames Feist                 health->populate();
264b49ac873SJames Feist 
26526f6976fSEd Tanous                 if (connectionNames.empty())
2661abe55efSEd Tanous                 {
2671c8fba97SJames Feist                     BMCWEB_LOG_ERROR << "Got 0 Connection names";
268e0d918bcSEd Tanous                     continue;
269daf36e2eSEd Tanous                 }
270e0d918bcSEd Tanous 
27149c53ac9SJohnathan Mantey                 asyncResp->res.jsonValue["@odata.type"] =
2725ac5a2f4SGunnar Mills                     "#Chassis.v1_16_0.Chassis";
27349c53ac9SJohnathan Mantey                 asyncResp->res.jsonValue["@odata.id"] =
27449c53ac9SJohnathan Mantey                     "/redfish/v1/Chassis/" + chassisId;
27549c53ac9SJohnathan Mantey                 asyncResp->res.jsonValue["Name"] = "Chassis Collection";
27649c53ac9SJohnathan Mantey                 asyncResp->res.jsonValue["ChassisType"] = "RackMount";
2771476687dSEd Tanous                 asyncResp->res
2781476687dSEd Tanous                     .jsonValue["Actions"]["#Chassis.Reset"]["target"] =
2791476687dSEd Tanous                     "/redfish/v1/Chassis/" + chassisId +
2801476687dSEd Tanous                     "/Actions/Chassis.Reset";
2811476687dSEd Tanous                 asyncResp->res.jsonValue["Actions"]["#Chassis.Reset"]
2821476687dSEd Tanous                                         ["@Redfish.ActionInfo"] =
283*002d39b4SEd Tanous                     "/redfish/v1/Chassis/" + chassisId + "/ResetActionInfo";
2841476687dSEd Tanous                 asyncResp->res.jsonValue["PCIeDevices"]["@odata.id"] =
2851476687dSEd Tanous                     "/redfish/v1/Systems/system/PCIeDevices";
28649c53ac9SJohnathan Mantey 
287*002d39b4SEd Tanous                 const std::string& connectionName = connectionNames[0].first;
2881c8fba97SJames Feist 
28923a21a1cSEd Tanous                 const std::vector<std::string>& interfaces2 =
2901c8fba97SJames Feist                     connectionNames[0].second;
2911c8fba97SJames Feist                 const std::array<const char*, 2> hasIndicatorLed = {
2921c8fba97SJames Feist                     "xyz.openbmc_project.Inventory.Item.Panel",
2930fda0f12SGeorge Liu                     "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
2941c8fba97SJames Feist 
295476b9cc5STejas Patil                 const std::string assetTagInterface =
2960fda0f12SGeorge Liu                     "xyz.openbmc_project.Inventory.Decorator.AssetTag";
297476b9cc5STejas Patil                 if (std::find(interfaces2.begin(), interfaces2.end(),
298476b9cc5STejas Patil                               assetTagInterface) != interfaces2.end())
299476b9cc5STejas Patil                 {
3001e1e598dSJonathan Doman                     sdbusplus::asio::getProperty<std::string>(
301*002d39b4SEd Tanous                         *crow::connections::systemBus, connectionName, path,
302*002d39b4SEd Tanous                         assetTagInterface, "AssetTag",
303476b9cc5STejas Patil                         [asyncResp, chassisId(std::string(chassisId))](
304476b9cc5STejas Patil                             const boost::system::error_code ec,
3051e1e598dSJonathan Doman                             const std::string& property) {
306476b9cc5STejas Patil                         if (ec)
307476b9cc5STejas Patil                         {
308476b9cc5STejas Patil                             BMCWEB_LOG_DEBUG
3090fda0f12SGeorge Liu                                 << "DBus response error for AssetTag";
310476b9cc5STejas Patil                             messages::internalError(asyncResp->res);
311476b9cc5STejas Patil                             return;
312476b9cc5STejas Patil                         }
313*002d39b4SEd Tanous                         asyncResp->res.jsonValue["AssetTag"] = property;
3141e1e598dSJonathan Doman                         });
315476b9cc5STejas Patil                 }
316476b9cc5STejas Patil 
3171c8fba97SJames Feist                 for (const char* interface : hasIndicatorLed)
3181c8fba97SJames Feist                 {
319*002d39b4SEd Tanous                     if (std::find(interfaces2.begin(), interfaces2.end(),
32023a21a1cSEd Tanous                                   interface) != interfaces2.end())
3211c8fba97SJames Feist                     {
3221c8fba97SJames Feist                         getIndicatorLedState(asyncResp);
3239f8bfa7cSGunnar Mills                         getLocationIndicatorActive(asyncResp);
3241c8fba97SJames Feist                         break;
3251c8fba97SJames Feist                     }
3261c8fba97SJames Feist                 }
3271c8fba97SJames Feist 
32855c7b7a2SEd Tanous                 crow::connections::systemBus->async_method_call(
32962d5e2e4SEd Tanous                     [asyncResp, chassisId(std::string(chassisId))](
33090728b54SEd Tanous                         const boost::system::error_code /*ec2*/,
331b9d36b47SEd Tanous                         const dbus::utility::DBusPropertiesMap&
3327e860f15SJohn Edward Broadbent                             propertiesList) {
333*002d39b4SEd Tanous                     for (const std::pair<std::string,
334168e20c1SEd Tanous                                          dbus::utility::DbusVariantType>&
3351214b7e7SGunnar Mills                              property : propertiesList)
3361abe55efSEd Tanous                     {
3377e860f15SJohn Edward Broadbent                         // Store DBus properties that are also
3387e860f15SJohn Edward Broadbent                         // Redfish properties with same name and a
3397e860f15SJohn Edward Broadbent                         // string value
340*002d39b4SEd Tanous                         const std::string& propertyName = property.first;
34199cffd7fSShawn McCarney                         if ((propertyName == "PartNumber") ||
34299cffd7fSShawn McCarney                             (propertyName == "SerialNumber") ||
34399cffd7fSShawn McCarney                             (propertyName == "Manufacturer") ||
344caa11f7aSAlpana Kumari                             (propertyName == "Model") ||
345caa11f7aSAlpana Kumari                             (propertyName == "SparePartNumber"))
34699cffd7fSShawn McCarney                         {
347daf36e2eSEd Tanous                             const std::string* value =
348*002d39b4SEd Tanous                                 std::get_if<std::string>(&property.second);
349caa11f7aSAlpana Kumari                             if (value == nullptr)
3501abe55efSEd Tanous                             {
351*002d39b4SEd Tanous                                 BMCWEB_LOG_ERROR << "Null value returned for "
352caa11f7aSAlpana Kumari                                                  << propertyName;
353*002d39b4SEd Tanous                                 messages::internalError(asyncResp->res);
354caa11f7aSAlpana Kumari                                 return;
355daf36e2eSEd Tanous                             }
356caa11f7aSAlpana Kumari                             // SparePartNumber is optional on D-Bus
357caa11f7aSAlpana Kumari                             // so skip if it is empty
358caa11f7aSAlpana Kumari                             if (propertyName == "SparePartNumber")
359caa11f7aSAlpana Kumari                             {
36026f6976fSEd Tanous                                 if (value->empty())
361caa11f7aSAlpana Kumari                                 {
362caa11f7aSAlpana Kumari                                     continue;
363caa11f7aSAlpana Kumari                                 }
364caa11f7aSAlpana Kumari                             }
365*002d39b4SEd Tanous                             asyncResp->res.jsonValue[propertyName] = *value;
366daf36e2eSEd Tanous                         }
36799cffd7fSShawn McCarney                     }
36862d5e2e4SEd Tanous                     asyncResp->res.jsonValue["Name"] = chassisId;
36962d5e2e4SEd Tanous                     asyncResp->res.jsonValue["Id"] = chassisId;
3700256b694Szhanghch05 #ifdef BMCWEB_ALLOW_DEPRECATED_POWER_THERMAL
371*002d39b4SEd Tanous                     asyncResp->res.jsonValue["Thermal"]["@odata.id"] =
372*002d39b4SEd Tanous                         "/redfish/v1/Chassis/" + chassisId + "/Thermal";
3732474adfaSEd Tanous                     // Power object
3741476687dSEd Tanous                     asyncResp->res.jsonValue["Power"]["@odata.id"] =
375*002d39b4SEd Tanous                         "/redfish/v1/Chassis/" + chassisId + "/Power";
3760256b694Szhanghch05 #endif
37795a3ecadSAnthony Wilson                     // SensorCollection
378*002d39b4SEd Tanous                     asyncResp->res.jsonValue["Sensors"]["@odata.id"] =
379*002d39b4SEd Tanous                         "/redfish/v1/Chassis/" + chassisId + "/Sensors";
380*002d39b4SEd Tanous                     asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
3811476687dSEd Tanous 
3821476687dSEd Tanous                     nlohmann::json::array_t computerSystems;
3831476687dSEd Tanous                     nlohmann::json::object_t system;
384*002d39b4SEd Tanous                     system["@odata.id"] = "/redfish/v1/Systems/system";
3851476687dSEd Tanous                     computerSystems.push_back(std::move(system));
386*002d39b4SEd Tanous                     asyncResp->res.jsonValue["Links"]["ComputerSystems"] =
3871476687dSEd Tanous                         std::move(computerSystems);
3881476687dSEd Tanous 
3891476687dSEd Tanous                     nlohmann::json::array_t managedBy;
3901476687dSEd Tanous                     nlohmann::json::object_t manager;
391*002d39b4SEd Tanous                     manager["@odata.id"] = "/redfish/v1/Managers/bmc";
3921476687dSEd Tanous                     managedBy.push_back(std::move(manager));
3937e860f15SJohn Edward Broadbent                     asyncResp->res.jsonValue["Links"]["ManagedBy"] =
3941476687dSEd Tanous                         std::move(managedBy);
395beeca0aeSGunnar Mills                     getChassisState(asyncResp);
396daf36e2eSEd Tanous                     },
397*002d39b4SEd Tanous                     connectionName, path, "org.freedesktop.DBus.Properties",
398*002d39b4SEd Tanous                     "GetAll", "xyz.openbmc_project.Inventory.Decorator.Asset");
3992c37b4b0SSharad Yadav 
400308f70c7SWilly Tu                 for (const auto& interface : interfaces2)
4012c37b4b0SSharad Yadav                 {
402308f70c7SWilly Tu                     if (interface == "xyz.openbmc_project.Common.UUID")
4032c37b4b0SSharad Yadav                     {
404308f70c7SWilly Tu                         getChassisUUID(asyncResp, connectionName, path);
4052c37b4b0SSharad Yadav                     }
4060fda0f12SGeorge Liu                     else if (
4070fda0f12SGeorge Liu                         interface ==
4080fda0f12SGeorge Liu                         "xyz.openbmc_project.Inventory.Decorator.LocationCode")
4092c37b4b0SSharad Yadav                     {
410*002d39b4SEd Tanous                         getChassisLocationCode(asyncResp, connectionName, path);
4112c37b4b0SSharad Yadav                     }
4122c37b4b0SSharad Yadav                 }
4132c37b4b0SSharad Yadav 
414daf36e2eSEd Tanous                 return;
415daf36e2eSEd Tanous             }
416e0d918bcSEd Tanous 
417daf36e2eSEd Tanous             // Couldn't find an object with that name.  return an error
418*002d39b4SEd Tanous             messages::resourceNotFound(asyncResp->res,
419*002d39b4SEd Tanous                                        "#Chassis.v1_16_0.Chassis", chassisId);
420daf36e2eSEd Tanous             },
421daf36e2eSEd Tanous             "xyz.openbmc_project.ObjectMapper",
422daf36e2eSEd Tanous             "/xyz/openbmc_project/object_mapper",
423daf36e2eSEd Tanous             "xyz.openbmc_project.ObjectMapper", "GetSubTree",
424271584abSEd Tanous             "/xyz/openbmc_project/inventory", 0, interfaces);
425c181942fSQiang XU 
426c181942fSQiang XU         getPhysicalSecurityData(asyncResp);
4277e860f15SJohn Edward Broadbent         });
4281c8fba97SJames Feist 
4297e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/")
430ed398213SEd Tanous         .privileges(redfish::privileges::patchChassis)
431*002d39b4SEd Tanous         .methods(boost::beast::http::verb::patch)(
432*002d39b4SEd Tanous             [&app](const crow::Request& req,
4337e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
4347e860f15SJohn Edward Broadbent                    const std::string& param) {
43545ca1b86SEd Tanous         if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
43645ca1b86SEd Tanous         {
43745ca1b86SEd Tanous             return;
43845ca1b86SEd Tanous         }
4399f8bfa7cSGunnar Mills         std::optional<bool> locationIndicatorActive;
4401c8fba97SJames Feist         std::optional<std::string> indicatorLed;
4411c8fba97SJames Feist 
4427e860f15SJohn Edward Broadbent         if (param.empty())
4431c8fba97SJames Feist         {
4441c8fba97SJames Feist             return;
4451c8fba97SJames Feist         }
4461c8fba97SJames Feist 
44715ed6780SWilly Tu         if (!json_util::readJsonPatch(
4487e860f15SJohn Edward Broadbent                 req, asyncResp->res, "LocationIndicatorActive",
4497e860f15SJohn Edward Broadbent                 locationIndicatorActive, "IndicatorLED", indicatorLed))
4501c8fba97SJames Feist         {
4511c8fba97SJames Feist             return;
4521c8fba97SJames Feist         }
4531c8fba97SJames Feist 
4549f8bfa7cSGunnar Mills         // TODO (Gunnar): Remove IndicatorLED after enough time has passed
4559f8bfa7cSGunnar Mills         if (!locationIndicatorActive && !indicatorLed)
4561c8fba97SJames Feist         {
4571c8fba97SJames Feist             return; // delete this when we support more patch properties
4581c8fba97SJames Feist         }
459d6aa0093SGunnar Mills         if (indicatorLed)
460d6aa0093SGunnar Mills         {
4617e860f15SJohn Edward Broadbent             asyncResp->res.addHeader(
4627e860f15SJohn Edward Broadbent                 boost::beast::http::field::warning,
4630fda0f12SGeorge Liu                 "299 - \"IndicatorLED is deprecated. Use LocationIndicatorActive instead.\"");
464d6aa0093SGunnar Mills         }
4651c8fba97SJames Feist 
4661c8fba97SJames Feist         const std::array<const char*, 2> interfaces = {
4671c8fba97SJames Feist             "xyz.openbmc_project.Inventory.Item.Board",
4681c8fba97SJames Feist             "xyz.openbmc_project.Inventory.Item.Chassis"};
4691c8fba97SJames Feist 
4707e860f15SJohn Edward Broadbent         const std::string& chassisId = param;
4711c8fba97SJames Feist 
4721c8fba97SJames Feist         crow::connections::systemBus->async_method_call(
4739f8bfa7cSGunnar Mills             [asyncResp, chassisId, locationIndicatorActive, indicatorLed](
4741c8fba97SJames Feist                 const boost::system::error_code ec,
475b9d36b47SEd Tanous                 const dbus::utility::MapperGetSubTreeResponse& subtree) {
4761c8fba97SJames Feist             if (ec)
4771c8fba97SJames Feist             {
4781c8fba97SJames Feist                 messages::internalError(asyncResp->res);
4791c8fba97SJames Feist                 return;
4801c8fba97SJames Feist             }
4811c8fba97SJames Feist 
4821c8fba97SJames Feist             // Iterate over all retrieved ObjectPaths.
483*002d39b4SEd Tanous             for (const std::pair<std::string,
484*002d39b4SEd Tanous                                  std::vector<std::pair<
485*002d39b4SEd Tanous                                      std::string, std::vector<std::string>>>>&
4861214b7e7SGunnar Mills                      object : subtree)
4871c8fba97SJames Feist             {
4881c8fba97SJames Feist                 const std::string& path = object.first;
4891c8fba97SJames Feist                 const std::vector<
4901214b7e7SGunnar Mills                     std::pair<std::string, std::vector<std::string>>>&
4911214b7e7SGunnar Mills                     connectionNames = object.second;
4921c8fba97SJames Feist 
493997093ebSGeorge Liu                 sdbusplus::message::object_path objPath(path);
494997093ebSGeorge Liu                 if (objPath.filename() != chassisId)
4951c8fba97SJames Feist                 {
4961c8fba97SJames Feist                     continue;
4971c8fba97SJames Feist                 }
4981c8fba97SJames Feist 
49926f6976fSEd Tanous                 if (connectionNames.empty())
5001c8fba97SJames Feist                 {
5011c8fba97SJames Feist                     BMCWEB_LOG_ERROR << "Got 0 Connection names";
5021c8fba97SJames Feist                     continue;
5031c8fba97SJames Feist                 }
5041c8fba97SJames Feist 
50523a21a1cSEd Tanous                 const std::vector<std::string>& interfaces3 =
5061c8fba97SJames Feist                     connectionNames[0].second;
5071c8fba97SJames Feist 
5081c8fba97SJames Feist                 const std::array<const char*, 2> hasIndicatorLed = {
5091c8fba97SJames Feist                     "xyz.openbmc_project.Inventory.Item.Panel",
5100fda0f12SGeorge Liu                     "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
5111c8fba97SJames Feist                 bool indicatorChassis = false;
5121c8fba97SJames Feist                 for (const char* interface : hasIndicatorLed)
5131c8fba97SJames Feist                 {
514*002d39b4SEd Tanous                     if (std::find(interfaces3.begin(), interfaces3.end(),
51523a21a1cSEd Tanous                                   interface) != interfaces3.end())
5161c8fba97SJames Feist                     {
5171c8fba97SJames Feist                         indicatorChassis = true;
5181c8fba97SJames Feist                         break;
5191c8fba97SJames Feist                     }
5201c8fba97SJames Feist                 }
5219f8bfa7cSGunnar Mills                 if (locationIndicatorActive)
5229f8bfa7cSGunnar Mills                 {
5239f8bfa7cSGunnar Mills                     if (indicatorChassis)
5249f8bfa7cSGunnar Mills                     {
525*002d39b4SEd Tanous                         setLocationIndicatorActive(asyncResp,
526*002d39b4SEd Tanous                                                    *locationIndicatorActive);
5279f8bfa7cSGunnar Mills                     }
5289f8bfa7cSGunnar Mills                     else
5299f8bfa7cSGunnar Mills                     {
530*002d39b4SEd Tanous                         messages::propertyUnknown(asyncResp->res,
531*002d39b4SEd Tanous                                                   "LocationIndicatorActive");
5329f8bfa7cSGunnar Mills                     }
5339f8bfa7cSGunnar Mills                 }
5349f8bfa7cSGunnar Mills                 if (indicatorLed)
5359f8bfa7cSGunnar Mills                 {
5361c8fba97SJames Feist                     if (indicatorChassis)
5371c8fba97SJames Feist                     {
538f23b7296SEd Tanous                         setIndicatorLedState(asyncResp, *indicatorLed);
5391c8fba97SJames Feist                     }
5401c8fba97SJames Feist                     else
5411c8fba97SJames Feist                     {
5421c8fba97SJames Feist                         messages::propertyUnknown(asyncResp->res,
5431c8fba97SJames Feist                                                   "IndicatorLED");
5441c8fba97SJames Feist                     }
5451c8fba97SJames Feist                 }
5461c8fba97SJames Feist                 return;
5471c8fba97SJames Feist             }
5481c8fba97SJames Feist 
549*002d39b4SEd Tanous             messages::resourceNotFound(asyncResp->res,
550*002d39b4SEd Tanous                                        "#Chassis.v1_14_0.Chassis", chassisId);
5511c8fba97SJames Feist             },
5521c8fba97SJames Feist             "xyz.openbmc_project.ObjectMapper",
5531c8fba97SJames Feist             "/xyz/openbmc_project/object_mapper",
5541c8fba97SJames Feist             "xyz.openbmc_project.ObjectMapper", "GetSubTree",
5551c8fba97SJames Feist             "/xyz/openbmc_project/inventory", 0, interfaces);
5567e860f15SJohn Edward Broadbent         });
5571c8fba97SJames Feist }
558dd99e04bSP.K. Lee 
5598d1b46d7Szhanghch05 inline void
5608d1b46d7Szhanghch05     doChassisPowerCycle(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
561dd99e04bSP.K. Lee {
562c3b3c92aSVijay Khemka     const char* busName = "xyz.openbmc_project.ObjectMapper";
563c3b3c92aSVijay Khemka     const char* path = "/xyz/openbmc_project/object_mapper";
564c3b3c92aSVijay Khemka     const char* interface = "xyz.openbmc_project.ObjectMapper";
565c3b3c92aSVijay Khemka     const char* method = "GetSubTreePaths";
566c3b3c92aSVijay Khemka 
567c3b3c92aSVijay Khemka     const std::array<const char*, 1> interfaces = {
568c3b3c92aSVijay Khemka         "xyz.openbmc_project.State.Chassis"};
569c3b3c92aSVijay Khemka 
570c3b3c92aSVijay Khemka     // Use mapper to get subtree paths.
571c3b3c92aSVijay Khemka     crow::connections::systemBus->async_method_call(
572b9d36b47SEd Tanous         [asyncResp](
573b9d36b47SEd Tanous             const boost::system::error_code ec,
574b9d36b47SEd Tanous             const dbus::utility::MapperGetSubTreePathsResponse& chassisList) {
575c3b3c92aSVijay Khemka         if (ec)
576c3b3c92aSVijay Khemka         {
577c3b3c92aSVijay Khemka             BMCWEB_LOG_DEBUG << "[mapper] Bad D-Bus request error: " << ec;
578c3b3c92aSVijay Khemka             messages::internalError(asyncResp->res);
579c3b3c92aSVijay Khemka             return;
580c3b3c92aSVijay Khemka         }
581c3b3c92aSVijay Khemka 
582dd99e04bSP.K. Lee         const char* processName = "xyz.openbmc_project.State.Chassis";
583dd99e04bSP.K. Lee         const char* interfaceName = "xyz.openbmc_project.State.Chassis";
584dd99e04bSP.K. Lee         const char* destProperty = "RequestedPowerTransition";
585dd99e04bSP.K. Lee         const std::string propertyValue =
586dd99e04bSP.K. Lee             "xyz.openbmc_project.State.Chassis.Transition.PowerCycle";
587*002d39b4SEd Tanous         std::string objectPath = "/xyz/openbmc_project/state/chassis_system0";
588c3b3c92aSVijay Khemka 
589c3b3c92aSVijay Khemka         /* Look for system reset chassis path */
590*002d39b4SEd Tanous         if ((std::find(chassisList.begin(), chassisList.end(), objectPath)) ==
591*002d39b4SEd Tanous             chassisList.end())
592c3b3c92aSVijay Khemka         {
593c3b3c92aSVijay Khemka             /* We prefer to reset the full chassis_system, but if it doesn't
594c3b3c92aSVijay Khemka              * exist on some platforms, fall back to a host-only power reset
595c3b3c92aSVijay Khemka              */
596c3b3c92aSVijay Khemka             objectPath = "/xyz/openbmc_project/state/chassis0";
597c3b3c92aSVijay Khemka         }
598dd99e04bSP.K. Lee 
599dd99e04bSP.K. Lee         crow::connections::systemBus->async_method_call(
600dd99e04bSP.K. Lee             [asyncResp](const boost::system::error_code ec) {
601dd99e04bSP.K. Lee             // Use "Set" method to set the property value.
602dd99e04bSP.K. Lee             if (ec)
603dd99e04bSP.K. Lee             {
604*002d39b4SEd Tanous                 BMCWEB_LOG_DEBUG << "[Set] Bad D-Bus request error: " << ec;
605dd99e04bSP.K. Lee                 messages::internalError(asyncResp->res);
606dd99e04bSP.K. Lee                 return;
607dd99e04bSP.K. Lee             }
608dd99e04bSP.K. Lee 
609dd99e04bSP.K. Lee             messages::success(asyncResp->res);
610dd99e04bSP.K. Lee             },
611*002d39b4SEd Tanous             processName, objectPath, "org.freedesktop.DBus.Properties", "Set",
612*002d39b4SEd Tanous             interfaceName, destProperty,
613168e20c1SEd Tanous             dbus::utility::DbusVariantType{propertyValue});
614c3b3c92aSVijay Khemka         },
615c3b3c92aSVijay Khemka         busName, path, interface, method, "/", 0, interfaces);
616dd99e04bSP.K. Lee }
617dd99e04bSP.K. Lee 
618dd99e04bSP.K. Lee /**
619dd99e04bSP.K. Lee  * ChassisResetAction class supports the POST method for the Reset
620dd99e04bSP.K. Lee  * action.
621dd99e04bSP.K. Lee  * Function handles POST method request.
622dd99e04bSP.K. Lee  * Analyzes POST body before sending Reset request data to D-Bus.
623dd99e04bSP.K. Lee  */
6247e860f15SJohn Edward Broadbent 
6257e860f15SJohn Edward Broadbent inline void requestRoutesChassisResetAction(App& app)
626dd99e04bSP.K. Lee {
6277e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Actions/Chassis.Reset/")
628ed398213SEd Tanous         .privileges(redfish::privileges::postChassis)
6297e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
63045ca1b86SEd Tanous             [&app](const crow::Request& req,
6317e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
6327e860f15SJohn Edward Broadbent                    const std::string&) {
63345ca1b86SEd Tanous         if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
63445ca1b86SEd Tanous         {
63545ca1b86SEd Tanous             return;
63645ca1b86SEd Tanous         }
637dd99e04bSP.K. Lee         BMCWEB_LOG_DEBUG << "Post Chassis Reset.";
638dd99e04bSP.K. Lee 
639dd99e04bSP.K. Lee         std::string resetType;
640dd99e04bSP.K. Lee 
64115ed6780SWilly Tu         if (!json_util::readJsonAction(req, asyncResp->res, "ResetType",
6427e860f15SJohn Edward Broadbent                                        resetType))
643dd99e04bSP.K. Lee         {
644dd99e04bSP.K. Lee             return;
645dd99e04bSP.K. Lee         }
646dd99e04bSP.K. Lee 
647dd99e04bSP.K. Lee         if (resetType != "PowerCycle")
648dd99e04bSP.K. Lee         {
649dd99e04bSP.K. Lee             BMCWEB_LOG_DEBUG << "Invalid property value for ResetType: "
650dd99e04bSP.K. Lee                              << resetType;
651*002d39b4SEd Tanous             messages::actionParameterNotSupported(asyncResp->res, resetType,
652*002d39b4SEd Tanous                                                   "ResetType");
653dd99e04bSP.K. Lee 
654dd99e04bSP.K. Lee             return;
655dd99e04bSP.K. Lee         }
656dd99e04bSP.K. Lee         doChassisPowerCycle(asyncResp);
6577e860f15SJohn Edward Broadbent         });
658dd99e04bSP.K. Lee }
6591cb1a9e6SAppaRao Puli 
6601cb1a9e6SAppaRao Puli /**
6611cb1a9e6SAppaRao Puli  * ChassisResetActionInfo derived class for delivering Chassis
6621cb1a9e6SAppaRao Puli  * ResetType AllowableValues using ResetInfo schema.
6631cb1a9e6SAppaRao Puli  */
6647e860f15SJohn Edward Broadbent inline void requestRoutesChassisResetActionInfo(App& app)
6651cb1a9e6SAppaRao Puli {
6667e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ResetActionInfo/")
667ed398213SEd Tanous         .privileges(redfish::privileges::getActionInfo)
6687e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
66945ca1b86SEd Tanous             [&app](const crow::Request& req,
6707e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
67145ca1b86SEd Tanous                    const std::string& chassisId) {
67245ca1b86SEd Tanous         if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
6731cb1a9e6SAppaRao Puli         {
67445ca1b86SEd Tanous             return;
67545ca1b86SEd Tanous         }
6761476687dSEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
6771476687dSEd Tanous             "#ActionInfo.v1_1_2.ActionInfo";
6781476687dSEd Tanous         asyncResp->res.jsonValue["@odata.id"] =
6791476687dSEd Tanous             "/redfish/v1/Chassis/" + chassisId + "/ResetActionInfo";
6801476687dSEd Tanous         asyncResp->res.jsonValue["Name"] = "Reset Action Info";
6811476687dSEd Tanous 
6821476687dSEd Tanous         asyncResp->res.jsonValue["Id"] = "ResetActionInfo";
6831476687dSEd Tanous         nlohmann::json::object_t parameters;
6841476687dSEd Tanous         parameters["Name"] = "ResetType";
6851476687dSEd Tanous         parameters["Required"] = true;
6861476687dSEd Tanous         parameters["DataType"] = "String";
6871476687dSEd Tanous         nlohmann::json::array_t allowed;
6881476687dSEd Tanous         allowed.push_back("PowerCycle");
6891476687dSEd Tanous         parameters["AllowableValues"] = std::move(allowed);
6901476687dSEd Tanous         asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
6917e860f15SJohn Edward Broadbent         });
6921cb1a9e6SAppaRao Puli }
6931cb1a9e6SAppaRao Puli 
694e37f8451SRapkiewicz, Pawel } // namespace redfish
695