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