xref: /openbmc/bmcweb/redfish-core/lib/chassis.hpp (revision 603a6640)
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 
18e37f8451SRapkiewicz, Pawel #include "node.hpp"
191abe55efSEd Tanous 
20e37f8451SRapkiewicz, Pawel #include <boost/container/flat_map.hpp>
21abf2add6SEd Tanous #include <variant>
22e37f8451SRapkiewicz, Pawel 
231abe55efSEd Tanous namespace redfish
241abe55efSEd Tanous {
25e37f8451SRapkiewicz, Pawel 
26e37f8451SRapkiewicz, Pawel /**
27e37f8451SRapkiewicz, Pawel  * DBus types primitives for several generic DBus interfaces
28e37f8451SRapkiewicz, Pawel  * TODO(Pawel) consider move this to separate file into boost::dbus
29e37f8451SRapkiewicz, Pawel  */
3055c7b7a2SEd Tanous // Note, this is not a very useful Variant, but because it isn't used to get
31aa2e59c1SEd Tanous // values, it should be as simple as possible
32aa2e59c1SEd Tanous // TODO(ed) invent a nullvariant type
33abf2add6SEd Tanous using VariantType = std::variant<bool, std::string, uint64_t>;
34aa2e59c1SEd Tanous using ManagedObjectsType = std::vector<std::pair<
35aa2e59c1SEd Tanous     sdbusplus::message::object_path,
36aa2e59c1SEd Tanous     std::vector<std::pair<std::string,
37aa2e59c1SEd Tanous                           std::vector<std::pair<std::string, VariantType>>>>>>;
38e37f8451SRapkiewicz, Pawel 
39aa2e59c1SEd Tanous using PropertiesType = boost::container::flat_map<std::string, VariantType>;
40e37f8451SRapkiewicz, Pawel 
41c181942fSQiang XU void getIntrusionByService(std::shared_ptr<AsyncResp> aResp,
42c181942fSQiang XU                            const std::string &service,
43c181942fSQiang XU                            const std::string &objPath)
44c181942fSQiang XU {
45c181942fSQiang XU     BMCWEB_LOG_DEBUG << "Get intrusion status by service \n";
46c181942fSQiang XU 
47c181942fSQiang XU     crow::connections::systemBus->async_method_call(
48c181942fSQiang XU         [aResp{std::move(aResp)}](const boost::system::error_code ec,
49c181942fSQiang XU                                   const std::variant<std::string> &value) {
50c181942fSQiang XU             if (ec)
51c181942fSQiang XU             {
52c181942fSQiang XU                 // do not add err msg in redfish response, becaues this is not
53c181942fSQiang XU                 //     mandatory property
54c181942fSQiang XU                 BMCWEB_LOG_ERROR << "DBUS response error " << ec << "\n";
55c181942fSQiang XU                 return;
56c181942fSQiang XU             }
57c181942fSQiang XU 
58c181942fSQiang XU             const std::string *status = std::get_if<std::string>(&value);
59c181942fSQiang XU 
60c181942fSQiang XU             if (status == nullptr)
61c181942fSQiang XU             {
62c181942fSQiang XU                 BMCWEB_LOG_ERROR << "intrusion status read error \n";
63c181942fSQiang XU                 return;
64c181942fSQiang XU             }
65c181942fSQiang XU 
66c181942fSQiang XU             aResp->res.jsonValue["PhysicalSecurity"] = {
67c181942fSQiang XU                 {"IntrusionSensorNumber", 1}, {"IntrusionSensor", *status}};
68c181942fSQiang XU         },
69c181942fSQiang XU         service, objPath, "org.freedesktop.DBus.Properties", "Get",
70c181942fSQiang XU         "xyz.openbmc_project.Chassis.Intrusion", "Status");
71c181942fSQiang XU }
72c181942fSQiang XU 
73c181942fSQiang XU /**
74c181942fSQiang XU  * Retrieves physical security properties over dbus
75c181942fSQiang XU  */
76c181942fSQiang XU void getPhysicalSecurityData(std::shared_ptr<AsyncResp> aResp)
77c181942fSQiang XU {
78c181942fSQiang XU     crow::connections::systemBus->async_method_call(
79c181942fSQiang XU         [aResp{std::move(aResp)}](
80c181942fSQiang XU             const boost::system::error_code ec,
81c181942fSQiang XU             const std::vector<std::pair<
82c181942fSQiang XU                 std::string,
83c181942fSQiang XU                 std::vector<std::pair<std::string, std::vector<std::string>>>>>
84c181942fSQiang XU                 &subtree) {
85c181942fSQiang XU             if (ec)
86c181942fSQiang XU             {
87c181942fSQiang XU                 // do not add err msg in redfish response, becaues this is not
88c181942fSQiang XU                 //     mandatory property
89c181942fSQiang XU                 BMCWEB_LOG_ERROR << "DBUS error: no matched iface " << ec
90c181942fSQiang XU                                  << "\n";
91c181942fSQiang XU                 return;
92c181942fSQiang XU             }
93c181942fSQiang XU             // Iterate over all retrieved ObjectPaths.
94c181942fSQiang XU             for (const auto &object : subtree)
95c181942fSQiang XU             {
96c181942fSQiang XU                 for (const auto &service : object.second)
97c181942fSQiang XU                 {
98c181942fSQiang XU                     getIntrusionByService(aResp, service.first, object.first);
99c181942fSQiang XU                     return;
100c181942fSQiang XU                 }
101c181942fSQiang XU             }
102c181942fSQiang XU         },
103c181942fSQiang XU         "xyz.openbmc_project.ObjectMapper",
104c181942fSQiang XU         "/xyz/openbmc_project/object_mapper",
105c181942fSQiang XU         "xyz.openbmc_project.ObjectMapper", "GetSubTree",
106c181942fSQiang XU         "/xyz/openbmc_project/Intrusion", int32_t(1),
107c181942fSQiang XU         std::array<const char *, 1>{"xyz.openbmc_project.Chassis.Intrusion"});
108c181942fSQiang XU }
109c181942fSQiang XU 
110e37f8451SRapkiewicz, Pawel /**
111e37f8451SRapkiewicz, Pawel  * ChassisCollection derived class for delivering Chassis Collection Schema
112e37f8451SRapkiewicz, Pawel  */
1131abe55efSEd Tanous class ChassisCollection : public Node
1141abe55efSEd Tanous {
115e37f8451SRapkiewicz, Pawel   public:
1161abe55efSEd Tanous     ChassisCollection(CrowApp &app) : Node(app, "/redfish/v1/Chassis/")
1171abe55efSEd Tanous     {
118e0d918bcSEd Tanous         entityPrivileges = {
119e0d918bcSEd Tanous             {boost::beast::http::verb::get, {{"Login"}}},
120e0d918bcSEd Tanous             {boost::beast::http::verb::head, {{"Login"}}},
121e0d918bcSEd Tanous             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
122e0d918bcSEd Tanous             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
123e0d918bcSEd Tanous             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
124e0d918bcSEd Tanous             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
125e37f8451SRapkiewicz, Pawel     }
126e37f8451SRapkiewicz, Pawel 
127e37f8451SRapkiewicz, Pawel   private:
128e37f8451SRapkiewicz, Pawel     /**
129e37f8451SRapkiewicz, Pawel      * Functions triggers appropriate requests on DBus
130e37f8451SRapkiewicz, Pawel      */
13155c7b7a2SEd Tanous     void doGet(crow::Response &res, const crow::Request &req,
1321abe55efSEd Tanous                const std::vector<std::string> &params) override
1331abe55efSEd Tanous     {
1340f74e643SEd Tanous         res.jsonValue["@odata.type"] = "#ChassisCollection.ChassisCollection";
1350f74e643SEd Tanous         res.jsonValue["@odata.id"] = "/redfish/v1/Chassis";
1360f74e643SEd Tanous         res.jsonValue["@odata.context"] =
1370f74e643SEd Tanous             "/redfish/v1/$metadata#ChassisCollection.ChassisCollection";
1380f74e643SEd Tanous         res.jsonValue["Name"] = "Chassis Collection";
1390f74e643SEd Tanous 
140*603a6640SGunnar Mills #ifdef BMCWEB_ENABLE_REDFISH_ONE_CHASSIS
141*603a6640SGunnar Mills         // Assume one Chassis named "chassis"
142*603a6640SGunnar Mills         res.jsonValue["Members@odata.count"] = 1;
143*603a6640SGunnar Mills         res.jsonValue["Members"] = {
144*603a6640SGunnar Mills             {{"@odata.id", "/redfish/v1/Chassis/chassis"}}};
145*603a6640SGunnar Mills         res.end();
146*603a6640SGunnar Mills         return;
147*603a6640SGunnar Mills #endif
148*603a6640SGunnar Mills         const std::array<const char *, 3> interfaces = {
149*603a6640SGunnar Mills             "xyz.openbmc_project.Inventory.Item.Board",
150*603a6640SGunnar Mills             "xyz.openbmc_project.Inventory.Item.Chassis",
151*603a6640SGunnar Mills             "xyz.openbmc_project.Inventory.Item.PowerSupply"};
152*603a6640SGunnar Mills 
15362d5e2e4SEd Tanous         auto asyncResp = std::make_shared<AsyncResp>(res);
15462d5e2e4SEd Tanous         crow::connections::systemBus->async_method_call(
15562d5e2e4SEd Tanous             [asyncResp](const boost::system::error_code ec,
15662d5e2e4SEd Tanous                         const std::vector<std::string> &chassisList) {
15762d5e2e4SEd Tanous                 if (ec)
1581abe55efSEd Tanous                 {
159f12894f8SJason M. Bills                     messages::internalError(asyncResp->res);
16062d5e2e4SEd Tanous                     return;
161e37f8451SRapkiewicz, Pawel                 }
16262d5e2e4SEd Tanous                 nlohmann::json &chassisArray =
16362d5e2e4SEd Tanous                     asyncResp->res.jsonValue["Members"];
16462d5e2e4SEd Tanous                 chassisArray = nlohmann::json::array();
16562d5e2e4SEd Tanous                 for (const std::string &objpath : chassisList)
16662d5e2e4SEd Tanous                 {
16762d5e2e4SEd Tanous                     std::size_t lastPos = objpath.rfind("/");
16862d5e2e4SEd Tanous                     if (lastPos == std::string::npos)
16962d5e2e4SEd Tanous                     {
17062d5e2e4SEd Tanous                         BMCWEB_LOG_ERROR << "Failed to find '/' in " << objpath;
17162d5e2e4SEd Tanous                         continue;
17262d5e2e4SEd Tanous                     }
17362d5e2e4SEd Tanous                     chassisArray.push_back(
17462d5e2e4SEd Tanous                         {{"@odata.id", "/redfish/v1/Chassis/" +
17562d5e2e4SEd Tanous                                            objpath.substr(lastPos + 1)}});
176e37f8451SRapkiewicz, Pawel                 }
177e37f8451SRapkiewicz, Pawel 
17862d5e2e4SEd Tanous                 asyncResp->res.jsonValue["Members@odata.count"] =
17962d5e2e4SEd Tanous                     chassisArray.size();
18062d5e2e4SEd Tanous             },
18162d5e2e4SEd Tanous             "xyz.openbmc_project.ObjectMapper",
18262d5e2e4SEd Tanous             "/xyz/openbmc_project/object_mapper",
18362d5e2e4SEd Tanous             "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
184734bfe90SGunnar Mills             "/xyz/openbmc_project/inventory", int32_t(0), interfaces);
18562d5e2e4SEd Tanous     }
186e37f8451SRapkiewicz, Pawel };
187e37f8451SRapkiewicz, Pawel 
188e37f8451SRapkiewicz, Pawel /**
189e37f8451SRapkiewicz, Pawel  * Chassis override class for delivering Chassis Schema
190e37f8451SRapkiewicz, Pawel  */
1911abe55efSEd Tanous class Chassis : public Node
1921abe55efSEd Tanous {
193e37f8451SRapkiewicz, Pawel   public:
1941abe55efSEd Tanous     Chassis(CrowApp &app) :
1951abe55efSEd Tanous         Node(app, "/redfish/v1/Chassis/<str>/", std::string())
1961abe55efSEd Tanous     {
197e0d918bcSEd Tanous         entityPrivileges = {
198e0d918bcSEd Tanous             {boost::beast::http::verb::get, {{"Login"}}},
199e0d918bcSEd Tanous             {boost::beast::http::verb::head, {{"Login"}}},
200e0d918bcSEd Tanous             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
201e0d918bcSEd Tanous             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
202e0d918bcSEd Tanous             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
203e0d918bcSEd Tanous             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
204e37f8451SRapkiewicz, Pawel     }
205e37f8451SRapkiewicz, Pawel 
206e37f8451SRapkiewicz, Pawel   private:
207e37f8451SRapkiewicz, Pawel     /**
208e37f8451SRapkiewicz, Pawel      * Functions triggers appropriate requests on DBus
209e37f8451SRapkiewicz, Pawel      */
21055c7b7a2SEd Tanous     void doGet(crow::Response &res, const crow::Request &req,
2111abe55efSEd Tanous                const std::vector<std::string> &params) override
2121abe55efSEd Tanous     {
213734bfe90SGunnar Mills         const std::array<const char *, 3> interfaces = {
214734bfe90SGunnar Mills             "xyz.openbmc_project.Inventory.Item.Board",
215734bfe90SGunnar Mills             "xyz.openbmc_project.Inventory.Item.Chassis",
216734bfe90SGunnar Mills             "xyz.openbmc_project.Inventory.Item.PowerSupply"};
217734bfe90SGunnar Mills 
218e37f8451SRapkiewicz, Pawel         // Check if there is required param, truly entering this shall be
219e37f8451SRapkiewicz, Pawel         // impossible.
2201abe55efSEd Tanous         if (params.size() != 1)
2211abe55efSEd Tanous         {
222f12894f8SJason M. Bills             messages::internalError(res);
223e37f8451SRapkiewicz, Pawel             res.end();
224e37f8451SRapkiewicz, Pawel             return;
225e37f8451SRapkiewicz, Pawel         }
22699cffd7fSShawn McCarney         const std::string &chassisId = params[0];
227*603a6640SGunnar Mills #ifdef BMCWEB_ENABLE_REDFISH_ONE_CHASSIS
228*603a6640SGunnar Mills         // In a one chassis system the only supported name is "chassis"
229*603a6640SGunnar Mills         if (chassisId != "chassis")
230*603a6640SGunnar Mills         {
231*603a6640SGunnar Mills             messages::resourceNotFound(res, "#Chassis.v1_4_0.Chassis",
232*603a6640SGunnar Mills                                        chassisId);
233*603a6640SGunnar Mills             res.end();
234*603a6640SGunnar Mills             return;
235*603a6640SGunnar Mills         }
236*603a6640SGunnar Mills #endif
237e37f8451SRapkiewicz, Pawel 
2380f74e643SEd Tanous         res.jsonValue["@odata.type"] = "#Chassis.v1_4_0.Chassis";
23999cffd7fSShawn McCarney         res.jsonValue["@odata.id"] = "/redfish/v1/Chassis/" + chassisId;
2400f74e643SEd Tanous         res.jsonValue["@odata.context"] =
2410f74e643SEd Tanous             "/redfish/v1/$metadata#Chassis.Chassis";
2420f74e643SEd Tanous         res.jsonValue["Name"] = "Chassis Collection";
2430f74e643SEd Tanous         res.jsonValue["ChassisType"] = "RackMount";
2440f74e643SEd Tanous         res.jsonValue["PowerState"] = "On";
2450f74e643SEd Tanous 
24662d5e2e4SEd Tanous         auto asyncResp = std::make_shared<AsyncResp>(res);
24755c7b7a2SEd Tanous         crow::connections::systemBus->async_method_call(
24862d5e2e4SEd Tanous             [asyncResp, chassisId(std::string(chassisId))](
24962d5e2e4SEd Tanous                 const boost::system::error_code ec,
250daf36e2eSEd Tanous                 const std::vector<std::pair<
2511abe55efSEd Tanous                     std::string, std::vector<std::pair<
2521abe55efSEd Tanous                                      std::string, std::vector<std::string>>>>>
253daf36e2eSEd Tanous                     &subtree) {
25462d5e2e4SEd Tanous                 if (ec)
2551abe55efSEd Tanous                 {
256f12894f8SJason M. Bills                     messages::internalError(asyncResp->res);
257daf36e2eSEd Tanous                     return;
258daf36e2eSEd Tanous                 }
259daf36e2eSEd Tanous                 // Iterate over all retrieved ObjectPaths.
2601abe55efSEd Tanous                 for (const std::pair<
2611abe55efSEd Tanous                          std::string,
2621abe55efSEd Tanous                          std::vector<
2631abe55efSEd Tanous                              std::pair<std::string, std::vector<std::string>>>>
2641abe55efSEd Tanous                          &object : subtree)
2651abe55efSEd Tanous                 {
266daf36e2eSEd Tanous                     const std::string &path = object.first;
2671abe55efSEd Tanous                     const std::vector<
2681abe55efSEd Tanous                         std::pair<std::string, std::vector<std::string>>>
269daf36e2eSEd Tanous                         &connectionNames = object.second;
270e0d918bcSEd Tanous 
271*603a6640SGunnar Mills // If only one chassis, just select the first one
272*603a6640SGunnar Mills #ifndef BMCWEB_ENABLE_REDFISH_ONE_CHASSIS
2731abe55efSEd Tanous                     if (!boost::ends_with(path, chassisId))
2741abe55efSEd Tanous                     {
275daf36e2eSEd Tanous                         continue;
276daf36e2eSEd Tanous                     }
277*603a6640SGunnar Mills #endif
2781abe55efSEd Tanous                     if (connectionNames.size() < 1)
2791abe55efSEd Tanous                     {
2801abe55efSEd Tanous                         BMCWEB_LOG_ERROR << "Only got "
2811abe55efSEd Tanous                                          << connectionNames.size()
28255c7b7a2SEd Tanous                                          << " Connection names";
283e0d918bcSEd Tanous                         continue;
284daf36e2eSEd Tanous                     }
285e0d918bcSEd Tanous 
286daf36e2eSEd Tanous                     const std::string connectionName = connectionNames[0].first;
28755c7b7a2SEd Tanous                     crow::connections::systemBus->async_method_call(
28862d5e2e4SEd Tanous                         [asyncResp, chassisId(std::string(chassisId))](
28962d5e2e4SEd Tanous                             const boost::system::error_code ec,
2901abe55efSEd Tanous                             const std::vector<std::pair<
2911abe55efSEd Tanous                                 std::string, VariantType>> &propertiesList) {
2921abe55efSEd Tanous                             for (const std::pair<std::string, VariantType>
2931abe55efSEd Tanous                                      &property : propertiesList)
2941abe55efSEd Tanous                             {
29599cffd7fSShawn McCarney                                 // Store DBus properties that are also Redfish
29699cffd7fSShawn McCarney                                 // properties with same name and a string value
29799cffd7fSShawn McCarney                                 const std::string &propertyName =
29899cffd7fSShawn McCarney                                     property.first;
29999cffd7fSShawn McCarney                                 if ((propertyName == "PartNumber") ||
30099cffd7fSShawn McCarney                                     (propertyName == "SerialNumber") ||
30199cffd7fSShawn McCarney                                     (propertyName == "Manufacturer") ||
30299cffd7fSShawn McCarney                                     (propertyName == "Model"))
30399cffd7fSShawn McCarney                                 {
304daf36e2eSEd Tanous                                     const std::string *value =
30599cffd7fSShawn McCarney                                         std::get_if<std::string>(
30699cffd7fSShawn McCarney                                             &property.second);
3071abe55efSEd Tanous                                     if (value != nullptr)
3081abe55efSEd Tanous                                     {
30999cffd7fSShawn McCarney                                         asyncResp->res.jsonValue[propertyName] =
31062d5e2e4SEd Tanous                                             *value;
311daf36e2eSEd Tanous                                     }
312daf36e2eSEd Tanous                                 }
31399cffd7fSShawn McCarney                             }
31462d5e2e4SEd Tanous                             asyncResp->res.jsonValue["Name"] = chassisId;
31562d5e2e4SEd Tanous                             asyncResp->res.jsonValue["Id"] = chassisId;
31662d5e2e4SEd Tanous                             asyncResp->res.jsonValue["Thermal"] = {
3171abe55efSEd Tanous                                 {"@odata.id", "/redfish/v1/Chassis/" +
3181abe55efSEd Tanous                                                   chassisId + "/Thermal"}};
3192474adfaSEd Tanous                             // Power object
3202474adfaSEd Tanous                             asyncResp->res.jsonValue["Power"] = {
3212474adfaSEd Tanous                                 {"@odata.id", "/redfish/v1/Chassis/" +
3222474adfaSEd Tanous                                                   chassisId + "/Power"}};
323029573d4SEd Tanous                             asyncResp->res.jsonValue["Status"] = {
324029573d4SEd Tanous                                 {"Health", "OK"},
325029573d4SEd Tanous                                 {"State", "Enabled"},
326029573d4SEd Tanous                             };
3272474adfaSEd Tanous 
328029573d4SEd Tanous                             asyncResp->res
329029573d4SEd Tanous                                 .jsonValue["Links"]["ComputerSystems"] = {
330029573d4SEd Tanous                                 {{"@odata.id", "/redfish/v1/Systems/system"}}};
331029573d4SEd Tanous                             asyncResp->res.jsonValue["Links"]["ManagedBy"] = {
332029573d4SEd Tanous                                 {{"@odata.id", "/redfish/v1/Managers/bmc"}}};
333daf36e2eSEd Tanous                         },
334daf36e2eSEd Tanous                         connectionName, path, "org.freedesktop.DBus.Properties",
3351abe55efSEd Tanous                         "GetAll",
3361abe55efSEd Tanous                         "xyz.openbmc_project.Inventory.Decorator.Asset");
337daf36e2eSEd Tanous                     return;
338daf36e2eSEd Tanous                 }
339e0d918bcSEd Tanous 
340daf36e2eSEd Tanous                 // Couldn't find an object with that name.  return an error
341f12894f8SJason M. Bills                 messages::resourceNotFound(
342f12894f8SJason M. Bills                     asyncResp->res, "#Chassis.v1_4_0.Chassis", chassisId);
343daf36e2eSEd Tanous             },
344daf36e2eSEd Tanous             "xyz.openbmc_project.ObjectMapper",
345daf36e2eSEd Tanous             "/xyz/openbmc_project/object_mapper",
346daf36e2eSEd Tanous             "xyz.openbmc_project.ObjectMapper", "GetSubTree",
347734bfe90SGunnar Mills             "/xyz/openbmc_project/inventory", int32_t(0), interfaces);
348c181942fSQiang XU 
349c181942fSQiang XU         getPhysicalSecurityData(asyncResp);
350e37f8451SRapkiewicz, Pawel     }
35162d5e2e4SEd Tanous };
352e37f8451SRapkiewicz, Pawel } // namespace redfish
353