xref: /openbmc/bmcweb/features/redfish/lib/chassis.hpp (revision 2474adfaf23ea9409891924662ec36e7217b4535)
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>
21e37f8451SRapkiewicz, Pawel 
221abe55efSEd Tanous namespace redfish
231abe55efSEd Tanous {
24e37f8451SRapkiewicz, Pawel 
25e37f8451SRapkiewicz, Pawel /**
26e37f8451SRapkiewicz, Pawel  * DBus types primitives for several generic DBus interfaces
27e37f8451SRapkiewicz, Pawel  * TODO(Pawel) consider move this to separate file into boost::dbus
28e37f8451SRapkiewicz, Pawel  */
2955c7b7a2SEd Tanous // Note, this is not a very useful Variant, but because it isn't used to get
30aa2e59c1SEd Tanous // values, it should be as simple as possible
31aa2e59c1SEd Tanous // TODO(ed) invent a nullvariant type
3204a258f4SEd Tanous using VariantType = sdbusplus::message::variant<bool, std::string, uint64_t>;
33aa2e59c1SEd Tanous using ManagedObjectsType = std::vector<std::pair<
34aa2e59c1SEd Tanous     sdbusplus::message::object_path,
35aa2e59c1SEd Tanous     std::vector<std::pair<std::string,
36aa2e59c1SEd Tanous                           std::vector<std::pair<std::string, VariantType>>>>>>;
37e37f8451SRapkiewicz, Pawel 
38aa2e59c1SEd Tanous using PropertiesType = boost::container::flat_map<std::string, VariantType>;
39e37f8451SRapkiewicz, Pawel 
40e37f8451SRapkiewicz, Pawel /**
41e37f8451SRapkiewicz, Pawel  * ChassisCollection derived class for delivering Chassis Collection Schema
42e37f8451SRapkiewicz, Pawel  */
431abe55efSEd Tanous class ChassisCollection : public Node
441abe55efSEd Tanous {
45e37f8451SRapkiewicz, Pawel   public:
461abe55efSEd Tanous     ChassisCollection(CrowApp &app) : Node(app, "/redfish/v1/Chassis/")
471abe55efSEd Tanous     {
48e37f8451SRapkiewicz, Pawel         Node::json["@odata.type"] = "#ChassisCollection.ChassisCollection";
49e37f8451SRapkiewicz, Pawel         Node::json["@odata.id"] = "/redfish/v1/Chassis";
50e37f8451SRapkiewicz, Pawel         Node::json["@odata.context"] =
51e37f8451SRapkiewicz, Pawel             "/redfish/v1/$metadata#ChassisCollection.ChassisCollection";
52e37f8451SRapkiewicz, Pawel         Node::json["Name"] = "Chassis Collection";
53e37f8451SRapkiewicz, Pawel 
54e0d918bcSEd Tanous         entityPrivileges = {
55e0d918bcSEd Tanous             {boost::beast::http::verb::get, {{"Login"}}},
56e0d918bcSEd Tanous             {boost::beast::http::verb::head, {{"Login"}}},
57e0d918bcSEd Tanous             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
58e0d918bcSEd Tanous             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
59e0d918bcSEd Tanous             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
60e0d918bcSEd Tanous             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
61e37f8451SRapkiewicz, Pawel     }
62e37f8451SRapkiewicz, Pawel 
63e37f8451SRapkiewicz, Pawel   private:
64e37f8451SRapkiewicz, Pawel     /**
65e37f8451SRapkiewicz, Pawel      * Functions triggers appropriate requests on DBus
66e37f8451SRapkiewicz, Pawel      */
6755c7b7a2SEd Tanous     void doGet(crow::Response &res, const crow::Request &req,
681abe55efSEd Tanous                const std::vector<std::string> &params) override
691abe55efSEd Tanous     {
7062d5e2e4SEd Tanous         const std::array<const char *, 4> interfaces = {
7162d5e2e4SEd Tanous             "xyz.openbmc_project.Inventory.Item.Board",
7262d5e2e4SEd Tanous             "xyz.openbmc_project.Inventory.Item.Chassis",
7362d5e2e4SEd Tanous             "xyz.openbmc_project.Inventory.Item.PowerSupply",
7462d5e2e4SEd Tanous             "xyz.openbmc_project.Inventory.Item.System",
7562d5e2e4SEd Tanous         };
7655c7b7a2SEd Tanous         res.jsonValue = Node::json;
7762d5e2e4SEd Tanous         auto asyncResp = std::make_shared<AsyncResp>(res);
7862d5e2e4SEd Tanous         crow::connections::systemBus->async_method_call(
7962d5e2e4SEd Tanous             [asyncResp](const boost::system::error_code ec,
8062d5e2e4SEd Tanous                         const std::vector<std::string> &chassisList) {
8162d5e2e4SEd Tanous                 if (ec)
821abe55efSEd Tanous                 {
83f12894f8SJason M. Bills                     messages::internalError(asyncResp->res);
8462d5e2e4SEd Tanous                     return;
85e37f8451SRapkiewicz, Pawel                 }
8662d5e2e4SEd Tanous                 nlohmann::json &chassisArray =
8762d5e2e4SEd Tanous                     asyncResp->res.jsonValue["Members"];
8862d5e2e4SEd Tanous                 chassisArray = nlohmann::json::array();
8962d5e2e4SEd Tanous                 for (const std::string &objpath : chassisList)
9062d5e2e4SEd Tanous                 {
9162d5e2e4SEd Tanous                     std::size_t lastPos = objpath.rfind("/");
9262d5e2e4SEd Tanous                     if (lastPos == std::string::npos)
9362d5e2e4SEd Tanous                     {
9462d5e2e4SEd Tanous                         BMCWEB_LOG_ERROR << "Failed to find '/' in " << objpath;
9562d5e2e4SEd Tanous                         continue;
9662d5e2e4SEd Tanous                     }
9762d5e2e4SEd Tanous                     chassisArray.push_back(
9862d5e2e4SEd Tanous                         {{"@odata.id", "/redfish/v1/Chassis/" +
9962d5e2e4SEd Tanous                                            objpath.substr(lastPos + 1)}});
100e37f8451SRapkiewicz, Pawel                 }
101e37f8451SRapkiewicz, Pawel 
10262d5e2e4SEd Tanous                 asyncResp->res.jsonValue["Members@odata.count"] =
10362d5e2e4SEd Tanous                     chassisArray.size();
10462d5e2e4SEd Tanous             },
10562d5e2e4SEd Tanous             "xyz.openbmc_project.ObjectMapper",
10662d5e2e4SEd Tanous             "/xyz/openbmc_project/object_mapper",
10762d5e2e4SEd Tanous             "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
10862d5e2e4SEd Tanous             "/xyz/openbmc_project/inventory", int32_t(3), interfaces);
10962d5e2e4SEd Tanous     }
110e37f8451SRapkiewicz, Pawel };
111e37f8451SRapkiewicz, Pawel 
112e37f8451SRapkiewicz, Pawel /**
113e37f8451SRapkiewicz, Pawel  * Chassis override class for delivering Chassis Schema
114e37f8451SRapkiewicz, Pawel  */
1151abe55efSEd Tanous class Chassis : public Node
1161abe55efSEd Tanous {
117e37f8451SRapkiewicz, Pawel   public:
1181abe55efSEd Tanous     Chassis(CrowApp &app) :
1191abe55efSEd Tanous         Node(app, "/redfish/v1/Chassis/<str>/", std::string())
1201abe55efSEd Tanous     {
121e37f8451SRapkiewicz, Pawel         Node::json["@odata.type"] = "#Chassis.v1_4_0.Chassis";
122e37f8451SRapkiewicz, Pawel         Node::json["@odata.id"] = "/redfish/v1/Chassis";
123e37f8451SRapkiewicz, Pawel         Node::json["@odata.context"] = "/redfish/v1/$metadata#Chassis.Chassis";
124e37f8451SRapkiewicz, Pawel         Node::json["Name"] = "Chassis Collection";
1256c233015SEd Tanous         Node::json["ChassisType"] = "RackMount";
126aef72909SEd Tanous         Node::json["PowerState"] = "On";
127e37f8451SRapkiewicz, Pawel 
128e0d918bcSEd Tanous         entityPrivileges = {
129e0d918bcSEd Tanous             {boost::beast::http::verb::get, {{"Login"}}},
130e0d918bcSEd Tanous             {boost::beast::http::verb::head, {{"Login"}}},
131e0d918bcSEd Tanous             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
132e0d918bcSEd Tanous             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
133e0d918bcSEd Tanous             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
134e0d918bcSEd Tanous             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
135e37f8451SRapkiewicz, Pawel     }
136e37f8451SRapkiewicz, Pawel 
137e37f8451SRapkiewicz, Pawel   private:
138e37f8451SRapkiewicz, Pawel     /**
139e37f8451SRapkiewicz, Pawel      * Functions triggers appropriate requests on DBus
140e37f8451SRapkiewicz, Pawel      */
14155c7b7a2SEd Tanous     void doGet(crow::Response &res, const crow::Request &req,
1421abe55efSEd Tanous                const std::vector<std::string> &params) override
1431abe55efSEd Tanous     {
144e37f8451SRapkiewicz, Pawel         // Check if there is required param, truly entering this shall be
145e37f8451SRapkiewicz, Pawel         // impossible.
1461abe55efSEd Tanous         if (params.size() != 1)
1471abe55efSEd Tanous         {
148f12894f8SJason M. Bills             messages::internalError(res);
149e37f8451SRapkiewicz, Pawel             res.end();
150e37f8451SRapkiewicz, Pawel             return;
151e37f8451SRapkiewicz, Pawel         }
152e37f8451SRapkiewicz, Pawel 
15355c7b7a2SEd Tanous         res.jsonValue = Node::json;
15455c7b7a2SEd Tanous         const std::string &chassisId = params[0];
15562d5e2e4SEd Tanous         auto asyncResp = std::make_shared<AsyncResp>(res);
15655c7b7a2SEd Tanous         crow::connections::systemBus->async_method_call(
15762d5e2e4SEd Tanous             [asyncResp, chassisId(std::string(chassisId))](
15862d5e2e4SEd Tanous                 const boost::system::error_code ec,
159daf36e2eSEd Tanous                 const std::vector<std::pair<
1601abe55efSEd Tanous                     std::string, std::vector<std::pair<
1611abe55efSEd Tanous                                      std::string, std::vector<std::string>>>>>
162daf36e2eSEd Tanous                     &subtree) {
16362d5e2e4SEd Tanous                 if (ec)
1641abe55efSEd Tanous                 {
165f12894f8SJason M. Bills                     messages::internalError(asyncResp->res);
166daf36e2eSEd Tanous                     return;
167daf36e2eSEd Tanous                 }
168daf36e2eSEd Tanous                 // Iterate over all retrieved ObjectPaths.
1691abe55efSEd Tanous                 for (const std::pair<
1701abe55efSEd Tanous                          std::string,
1711abe55efSEd Tanous                          std::vector<
1721abe55efSEd Tanous                              std::pair<std::string, std::vector<std::string>>>>
1731abe55efSEd Tanous                          &object : subtree)
1741abe55efSEd Tanous                 {
175daf36e2eSEd Tanous                     const std::string &path = object.first;
1761abe55efSEd Tanous                     const std::vector<
1771abe55efSEd Tanous                         std::pair<std::string, std::vector<std::string>>>
178daf36e2eSEd Tanous                         &connectionNames = object.second;
179e0d918bcSEd Tanous 
1801abe55efSEd Tanous                     if (!boost::ends_with(path, chassisId))
1811abe55efSEd Tanous                     {
182daf36e2eSEd Tanous                         continue;
183daf36e2eSEd Tanous                     }
1841abe55efSEd Tanous                     if (connectionNames.size() < 1)
1851abe55efSEd Tanous                     {
1861abe55efSEd Tanous                         BMCWEB_LOG_ERROR << "Only got "
1871abe55efSEd Tanous                                          << connectionNames.size()
18855c7b7a2SEd Tanous                                          << " Connection names";
189e0d918bcSEd Tanous                         continue;
190daf36e2eSEd Tanous                     }
191e0d918bcSEd Tanous 
192daf36e2eSEd Tanous                     const std::string connectionName = connectionNames[0].first;
19355c7b7a2SEd Tanous                     crow::connections::systemBus->async_method_call(
19462d5e2e4SEd Tanous                         [asyncResp, chassisId(std::string(chassisId))](
19562d5e2e4SEd Tanous                             const boost::system::error_code ec,
1961abe55efSEd Tanous                             const std::vector<std::pair<
1971abe55efSEd Tanous                                 std::string, VariantType>> &propertiesList) {
1981abe55efSEd Tanous                             for (const std::pair<std::string, VariantType>
1991abe55efSEd Tanous                                      &property : propertiesList)
2001abe55efSEd Tanous                             {
201daf36e2eSEd Tanous                                 const std::string *value =
2021abe55efSEd Tanous                                     mapbox::getPtr<const std::string>(
2031abe55efSEd Tanous                                         property.second);
2041abe55efSEd Tanous                                 if (value != nullptr)
2051abe55efSEd Tanous                                 {
20662d5e2e4SEd Tanous                                     asyncResp->res.jsonValue[property.first] =
20762d5e2e4SEd Tanous                                         *value;
208daf36e2eSEd Tanous                                 }
209daf36e2eSEd Tanous                             }
21062d5e2e4SEd Tanous                             asyncResp->res.jsonValue["Name"] = chassisId;
21162d5e2e4SEd Tanous                             asyncResp->res.jsonValue["Id"] = chassisId;
21262d5e2e4SEd Tanous                             asyncResp->res.jsonValue["Thermal"] = {
2131abe55efSEd Tanous                                 {"@odata.id", "/redfish/v1/Chassis/" +
2141abe55efSEd Tanous                                                   chassisId + "/Thermal"}};
215*2474adfaSEd Tanous                             // Power object
216*2474adfaSEd Tanous                             asyncResp->res.jsonValue["Power"] = {
217*2474adfaSEd Tanous                                 {"@odata.id", "/redfish/v1/Chassis/" +
218*2474adfaSEd Tanous                                                   chassisId + "/Power"}};
219*2474adfaSEd Tanous 
220*2474adfaSEd Tanous                             // TODO: An array of references to computer systems
221*2474adfaSEd Tanous                             // contained in this chassis.
222*2474adfaSEd Tanous                             // res.jsonValue["Links"]["ComputerSystems"]
223*2474adfaSEd Tanous                             // =
224*2474adfaSEd Tanous                             //                          {{{"@odata.id",
225*2474adfaSEd Tanous                             //                          "/redfish/v1/Systems/1"}}};
226*2474adfaSEd Tanous                             // An array of references to the Managers
227*2474adfaSEd Tanous                             // responsible for managing this chassis.
228*2474adfaSEd Tanous                             // res.jsonValue["Links"]["ManagedBy"] =
229*2474adfaSEd Tanous                             //                        {{{"@odata.id",
230*2474adfaSEd Tanous                             //                        "/redfish/v1/Managers/1"}}};
231daf36e2eSEd Tanous                         },
232daf36e2eSEd Tanous                         connectionName, path, "org.freedesktop.DBus.Properties",
2331abe55efSEd Tanous                         "GetAll",
2341abe55efSEd Tanous                         "xyz.openbmc_project.Inventory.Decorator.Asset");
235daf36e2eSEd Tanous                     return;
236daf36e2eSEd Tanous                 }
237e0d918bcSEd Tanous 
238daf36e2eSEd Tanous                 // Couldn't find an object with that name.  return an error
239f12894f8SJason M. Bills                 messages::resourceNotFound(
240f12894f8SJason M. Bills                     asyncResp->res, "#Chassis.v1_4_0.Chassis", chassisId);
241daf36e2eSEd Tanous             },
242daf36e2eSEd Tanous             "xyz.openbmc_project.ObjectMapper",
243daf36e2eSEd Tanous             "/xyz/openbmc_project/object_mapper",
244daf36e2eSEd Tanous             "xyz.openbmc_project.ObjectMapper", "GetSubTree",
245daf36e2eSEd Tanous             "/xyz/openbmc_project/inventory", int32_t(0),
246daf36e2eSEd Tanous             std::array<const char *, 1>{
247daf36e2eSEd Tanous                 "xyz.openbmc_project.Inventory.Decorator.Asset"});
248e37f8451SRapkiewicz, Pawel     }
24962d5e2e4SEd Tanous };
250e37f8451SRapkiewicz, Pawel } // namespace redfish
251