xref: /openbmc/bmcweb/redfish-core/lib/storage_controller.hpp (revision 7bf29ab37ad696aed3f0580ef0f6cb90864c89ee)
1*7bf29ab3SChristopher Meis // SPDX-License-Identifier: Apache-2.0
2*7bf29ab3SChristopher Meis // SPDX-FileCopyrightText: Copyright OpenBMC Authors
3*7bf29ab3SChristopher Meis // SPDX-FileCopyrightText: Copyright 2019 Intel Corporation
4*7bf29ab3SChristopher Meis #pragma once
5*7bf29ab3SChristopher Meis 
6*7bf29ab3SChristopher Meis #include "app.hpp"
7*7bf29ab3SChristopher Meis #include "async_resp.hpp"
8*7bf29ab3SChristopher Meis #include "generated/enums/resource.hpp"
9*7bf29ab3SChristopher Meis #include "http_request.hpp"
10*7bf29ab3SChristopher Meis #include "query.hpp"
11*7bf29ab3SChristopher Meis #include "registries/privilege_registry.hpp"
12*7bf29ab3SChristopher Meis 
13*7bf29ab3SChristopher Meis namespace redfish
14*7bf29ab3SChristopher Meis {
15*7bf29ab3SChristopher Meis 
populateStorageController(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & controllerId,const std::string & connectionName,const std::string & path)16*7bf29ab3SChristopher Meis inline void populateStorageController(
17*7bf29ab3SChristopher Meis     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
18*7bf29ab3SChristopher Meis     const std::string& controllerId, const std::string& connectionName,
19*7bf29ab3SChristopher Meis     const std::string& path)
20*7bf29ab3SChristopher Meis {
21*7bf29ab3SChristopher Meis     asyncResp->res.jsonValue["@odata.type"] =
22*7bf29ab3SChristopher Meis         "#StorageController.v1_6_0.StorageController";
23*7bf29ab3SChristopher Meis     asyncResp->res.jsonValue["@odata.id"] =
24*7bf29ab3SChristopher Meis         boost::urls::format("/redfish/v1/Systems/{}/Storage/1/Controllers/{}",
25*7bf29ab3SChristopher Meis                             BMCWEB_REDFISH_SYSTEM_URI_NAME, controllerId);
26*7bf29ab3SChristopher Meis     asyncResp->res.jsonValue["Name"] = controllerId;
27*7bf29ab3SChristopher Meis     asyncResp->res.jsonValue["Id"] = controllerId;
28*7bf29ab3SChristopher Meis     asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
29*7bf29ab3SChristopher Meis 
30*7bf29ab3SChristopher Meis     dbus::utility::getProperty<bool>(
31*7bf29ab3SChristopher Meis         connectionName, path, "xyz.openbmc_project.Inventory.Item", "Present",
32*7bf29ab3SChristopher Meis         [asyncResp](const boost::system::error_code& ec, bool isPresent) {
33*7bf29ab3SChristopher Meis             // this interface isn't necessary, only check it
34*7bf29ab3SChristopher Meis             // if we get a good return
35*7bf29ab3SChristopher Meis             if (ec)
36*7bf29ab3SChristopher Meis             {
37*7bf29ab3SChristopher Meis                 BMCWEB_LOG_DEBUG("Failed to get Present property");
38*7bf29ab3SChristopher Meis                 return;
39*7bf29ab3SChristopher Meis             }
40*7bf29ab3SChristopher Meis             if (!isPresent)
41*7bf29ab3SChristopher Meis             {
42*7bf29ab3SChristopher Meis                 asyncResp->res.jsonValue["Status"]["State"] =
43*7bf29ab3SChristopher Meis                     resource::State::Absent;
44*7bf29ab3SChristopher Meis             }
45*7bf29ab3SChristopher Meis         });
46*7bf29ab3SChristopher Meis 
47*7bf29ab3SChristopher Meis     asset_utils::getAssetInfo(asyncResp, connectionName, path, ""_json_pointer,
48*7bf29ab3SChristopher Meis                               false);
49*7bf29ab3SChristopher Meis }
50*7bf29ab3SChristopher Meis 
getStorageControllerHandler(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & controllerId,const boost::system::error_code & ec,const dbus::utility::MapperGetSubTreeResponse & subtree)51*7bf29ab3SChristopher Meis inline void getStorageControllerHandler(
52*7bf29ab3SChristopher Meis     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
53*7bf29ab3SChristopher Meis     const std::string& controllerId, const boost::system::error_code& ec,
54*7bf29ab3SChristopher Meis     const dbus::utility::MapperGetSubTreeResponse& subtree)
55*7bf29ab3SChristopher Meis {
56*7bf29ab3SChristopher Meis     if (ec || subtree.empty())
57*7bf29ab3SChristopher Meis     {
58*7bf29ab3SChristopher Meis         // doesn't have to be there
59*7bf29ab3SChristopher Meis         BMCWEB_LOG_DEBUG("Failed to handle StorageController");
60*7bf29ab3SChristopher Meis         return;
61*7bf29ab3SChristopher Meis     }
62*7bf29ab3SChristopher Meis 
63*7bf29ab3SChristopher Meis     for (const auto& [path, interfaceDict] : subtree)
64*7bf29ab3SChristopher Meis     {
65*7bf29ab3SChristopher Meis         sdbusplus::message::object_path object(path);
66*7bf29ab3SChristopher Meis         std::string id = object.filename();
67*7bf29ab3SChristopher Meis         if (id.empty())
68*7bf29ab3SChristopher Meis         {
69*7bf29ab3SChristopher Meis             BMCWEB_LOG_ERROR("Failed to find filename in {}", path);
70*7bf29ab3SChristopher Meis             return;
71*7bf29ab3SChristopher Meis         }
72*7bf29ab3SChristopher Meis         if (id != controllerId)
73*7bf29ab3SChristopher Meis         {
74*7bf29ab3SChristopher Meis             continue;
75*7bf29ab3SChristopher Meis         }
76*7bf29ab3SChristopher Meis 
77*7bf29ab3SChristopher Meis         if (interfaceDict.size() != 1)
78*7bf29ab3SChristopher Meis         {
79*7bf29ab3SChristopher Meis             BMCWEB_LOG_ERROR("Connection size {}, greater than 1",
80*7bf29ab3SChristopher Meis                              interfaceDict.size());
81*7bf29ab3SChristopher Meis             messages::internalError(asyncResp->res);
82*7bf29ab3SChristopher Meis             return;
83*7bf29ab3SChristopher Meis         }
84*7bf29ab3SChristopher Meis 
85*7bf29ab3SChristopher Meis         const std::string& connectionName = interfaceDict.front().first;
86*7bf29ab3SChristopher Meis         populateStorageController(asyncResp, controllerId, connectionName,
87*7bf29ab3SChristopher Meis                                   path);
88*7bf29ab3SChristopher Meis     }
89*7bf29ab3SChristopher Meis }
90*7bf29ab3SChristopher Meis 
populateStorageControllerCollection(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const boost::system::error_code & ec,const dbus::utility::MapperGetSubTreePathsResponse & controllerList)91*7bf29ab3SChristopher Meis inline void populateStorageControllerCollection(
92*7bf29ab3SChristopher Meis     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
93*7bf29ab3SChristopher Meis     const boost::system::error_code& ec,
94*7bf29ab3SChristopher Meis     const dbus::utility::MapperGetSubTreePathsResponse& controllerList)
95*7bf29ab3SChristopher Meis {
96*7bf29ab3SChristopher Meis     nlohmann::json::array_t members;
97*7bf29ab3SChristopher Meis     if (ec || controllerList.empty())
98*7bf29ab3SChristopher Meis     {
99*7bf29ab3SChristopher Meis         asyncResp->res.jsonValue["Members"] = std::move(members);
100*7bf29ab3SChristopher Meis         asyncResp->res.jsonValue["Members@odata.count"] = 0;
101*7bf29ab3SChristopher Meis         BMCWEB_LOG_DEBUG("Failed to find any StorageController");
102*7bf29ab3SChristopher Meis         return;
103*7bf29ab3SChristopher Meis     }
104*7bf29ab3SChristopher Meis 
105*7bf29ab3SChristopher Meis     for (const std::string& path : controllerList)
106*7bf29ab3SChristopher Meis     {
107*7bf29ab3SChristopher Meis         std::string id = sdbusplus::message::object_path(path).filename();
108*7bf29ab3SChristopher Meis         if (id.empty())
109*7bf29ab3SChristopher Meis         {
110*7bf29ab3SChristopher Meis             BMCWEB_LOG_ERROR("Failed to find filename in {}", path);
111*7bf29ab3SChristopher Meis             return;
112*7bf29ab3SChristopher Meis         }
113*7bf29ab3SChristopher Meis         nlohmann::json::object_t member;
114*7bf29ab3SChristopher Meis         member["@odata.id"] = boost::urls::format(
115*7bf29ab3SChristopher Meis             "/redfish/v1/Systems/{}/Storage/1/Controllers/{}",
116*7bf29ab3SChristopher Meis             BMCWEB_REDFISH_SYSTEM_URI_NAME, id);
117*7bf29ab3SChristopher Meis         members.emplace_back(member);
118*7bf29ab3SChristopher Meis     }
119*7bf29ab3SChristopher Meis     asyncResp->res.jsonValue["Members@odata.count"] = members.size();
120*7bf29ab3SChristopher Meis     asyncResp->res.jsonValue["Members"] = std::move(members);
121*7bf29ab3SChristopher Meis }
122*7bf29ab3SChristopher Meis 
handleSystemsStorageControllerGet(App & app,const crow::Request & req,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & systemName,const std::string & controllerId)123*7bf29ab3SChristopher Meis inline void handleSystemsStorageControllerGet(
124*7bf29ab3SChristopher Meis     App& app, const crow::Request& req,
125*7bf29ab3SChristopher Meis     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
126*7bf29ab3SChristopher Meis     const std::string& systemName, const std::string& controllerId)
127*7bf29ab3SChristopher Meis {
128*7bf29ab3SChristopher Meis     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
129*7bf29ab3SChristopher Meis     {
130*7bf29ab3SChristopher Meis         BMCWEB_LOG_DEBUG("Failed to setup Redfish Route for StorageController");
131*7bf29ab3SChristopher Meis         return;
132*7bf29ab3SChristopher Meis     }
133*7bf29ab3SChristopher Meis     if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
134*7bf29ab3SChristopher Meis     {
135*7bf29ab3SChristopher Meis         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
136*7bf29ab3SChristopher Meis                                    systemName);
137*7bf29ab3SChristopher Meis         BMCWEB_LOG_DEBUG("Failed to find ComputerSystem of {}", systemName);
138*7bf29ab3SChristopher Meis         return;
139*7bf29ab3SChristopher Meis     }
140*7bf29ab3SChristopher Meis     constexpr std::array<std::string_view, 1> interfaces = {
141*7bf29ab3SChristopher Meis         "xyz.openbmc_project.Inventory.Item.StorageController"};
142*7bf29ab3SChristopher Meis     dbus::utility::getSubTree(
143*7bf29ab3SChristopher Meis         "/xyz/openbmc_project/inventory", 0, interfaces,
144*7bf29ab3SChristopher Meis         [asyncResp,
145*7bf29ab3SChristopher Meis          controllerId](const boost::system::error_code& ec,
146*7bf29ab3SChristopher Meis                        const dbus::utility::MapperGetSubTreeResponse& subtree) {
147*7bf29ab3SChristopher Meis             getStorageControllerHandler(asyncResp, controllerId, ec, subtree);
148*7bf29ab3SChristopher Meis         });
149*7bf29ab3SChristopher Meis }
150*7bf29ab3SChristopher Meis 
handleSystemsStorageControllerCollectionGet(App & app,const crow::Request & req,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & systemName)151*7bf29ab3SChristopher Meis inline void handleSystemsStorageControllerCollectionGet(
152*7bf29ab3SChristopher Meis     App& app, const crow::Request& req,
153*7bf29ab3SChristopher Meis     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
154*7bf29ab3SChristopher Meis     const std::string& systemName)
155*7bf29ab3SChristopher Meis {
156*7bf29ab3SChristopher Meis     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
157*7bf29ab3SChristopher Meis     {
158*7bf29ab3SChristopher Meis         BMCWEB_LOG_DEBUG(
159*7bf29ab3SChristopher Meis             "Failed to setup Redfish Route for StorageController Collection");
160*7bf29ab3SChristopher Meis         return;
161*7bf29ab3SChristopher Meis     }
162*7bf29ab3SChristopher Meis     if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
163*7bf29ab3SChristopher Meis     {
164*7bf29ab3SChristopher Meis         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
165*7bf29ab3SChristopher Meis                                    systemName);
166*7bf29ab3SChristopher Meis         BMCWEB_LOG_DEBUG("Failed to find ComputerSystem of {}", systemName);
167*7bf29ab3SChristopher Meis         return;
168*7bf29ab3SChristopher Meis     }
169*7bf29ab3SChristopher Meis 
170*7bf29ab3SChristopher Meis     asyncResp->res.jsonValue["@odata.type"] =
171*7bf29ab3SChristopher Meis         "#StorageControllerCollection.StorageControllerCollection";
172*7bf29ab3SChristopher Meis     asyncResp->res.jsonValue["@odata.id"] =
173*7bf29ab3SChristopher Meis         std::format("/redfish/v1/Systems/{}/Storage/1/Controllers",
174*7bf29ab3SChristopher Meis                     BMCWEB_REDFISH_SYSTEM_URI_NAME);
175*7bf29ab3SChristopher Meis     asyncResp->res.jsonValue["Name"] = "Storage Controller Collection";
176*7bf29ab3SChristopher Meis 
177*7bf29ab3SChristopher Meis     constexpr std::array<std::string_view, 1> interfaces = {
178*7bf29ab3SChristopher Meis         "xyz.openbmc_project.Inventory.Item.StorageController"};
179*7bf29ab3SChristopher Meis     dbus::utility::getSubTreePaths(
180*7bf29ab3SChristopher Meis         "/xyz/openbmc_project/inventory", 0, interfaces,
181*7bf29ab3SChristopher Meis         [asyncResp](const boost::system::error_code& ec,
182*7bf29ab3SChristopher Meis                     const dbus::utility::MapperGetSubTreePathsResponse&
183*7bf29ab3SChristopher Meis                         controllerList) {
184*7bf29ab3SChristopher Meis             populateStorageControllerCollection(asyncResp, ec, controllerList);
185*7bf29ab3SChristopher Meis         });
186*7bf29ab3SChristopher Meis }
187*7bf29ab3SChristopher Meis 
requestRoutesStorageController(App & app)188*7bf29ab3SChristopher Meis inline void requestRoutesStorageController(App& app)
189*7bf29ab3SChristopher Meis {
190*7bf29ab3SChristopher Meis     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Storage/1/Controllers/")
191*7bf29ab3SChristopher Meis         .privileges(redfish::privileges::getStorageControllerCollection)
192*7bf29ab3SChristopher Meis         .methods(boost::beast::http::verb::get)(std::bind_front(
193*7bf29ab3SChristopher Meis             handleSystemsStorageControllerCollectionGet, std::ref(app)));
194*7bf29ab3SChristopher Meis 
195*7bf29ab3SChristopher Meis     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Storage/1/Controllers/<str>")
196*7bf29ab3SChristopher Meis         .privileges(redfish::privileges::getStorageController)
197*7bf29ab3SChristopher Meis         .methods(boost::beast::http::verb::get)(
198*7bf29ab3SChristopher Meis             std::bind_front(handleSystemsStorageControllerGet, std::ref(app)));
199*7bf29ab3SChristopher Meis }
200*7bf29ab3SChristopher Meis 
201*7bf29ab3SChristopher Meis } // namespace redfish
202