blob: 737867f683e6170a54488bff9af505fe1bd41742 [file] [log] [blame]
Ed Tanous40e9b922024-09-10 13:50:16 -07001// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright OpenBMC Authors
3// SPDX-FileCopyrightText: Copyright 2019 Intel Corporation
Nikhil Potadea25aecc2019-08-23 16:35:26 -07004#pragma once
5
Willy Tu13451e32023-05-24 16:08:18 -07006#include "bmcweb_config.h"
7
Ed Tanous3ccb3ad2023-01-13 17:40:03 -08008#include "app.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -08009#include "async_resp.hpp"
George Liu7a1dbc42022-12-07 16:03:22 +080010#include "dbus_utility.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080011#include "error_messages.hpp"
Ed Tanous539d8c62024-06-19 14:38:27 -070012#include "generated/enums/resource.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080013#include "http_request.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080014#include "logging.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080015#include "query.hpp"
16#include "registries/privilege_registry.hpp"
Christopher Meis7bf29ab2025-10-23 14:46:24 +020017#include "storage_chassis.hpp"
Willy Tu5e577bc2022-07-26 00:41:55 +000018#include "utils/collection.hpp"
James Feist2ad9c2f2019-10-29 16:26:48 -070019
Ed Tanousd7857202025-01-28 15:32:26 -080020#include <boost/beast/http/verb.hpp>
George Liue99073f2022-12-09 11:06:16 +080021#include <boost/system/error_code.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070022#include <boost/url/format.hpp>
Ed Tanousd7857202025-01-28 15:32:26 -080023#include <sdbusplus/message/native_types.hpp>
Krzysztof Grobelnyd1bde9e2022-09-07 10:40:51 +020024#include <sdbusplus/unpack_properties.hpp>
Nikhil Potadea25aecc2019-08-23 16:35:26 -070025
Ed Tanousd7857202025-01-28 15:32:26 -080026#include <algorithm>
George Liu7a1dbc42022-12-07 16:03:22 +080027#include <array>
Ed Tanousd7857202025-01-28 15:32:26 -080028#include <format>
29#include <functional>
30#include <memory>
Ed Tanousd7857202025-01-28 15:32:26 -080031#include <string>
George Liu7a1dbc42022-12-07 16:03:22 +080032#include <string_view>
Ed Tanousd7857202025-01-28 15:32:26 -080033#include <utility>
George Liu7a1dbc42022-12-07 16:03:22 +080034
Nikhil Potadea25aecc2019-08-23 16:35:26 -070035namespace redfish
36{
Ed Tanous36d52332023-06-09 13:18:40 -070037
38inline void handleSystemsStorageCollectionGet(
39 App& app, const crow::Request& req,
40 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
41 const std::string& systemName)
42{
43 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
44 {
45 return;
46 }
Ed Tanous253f11b2024-05-16 09:38:31 -070047 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous36d52332023-06-09 13:18:40 -070048 {
49 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
50 systemName);
51 return;
52 }
53
54 asyncResp->res.jsonValue["@odata.type"] =
55 "#StorageCollection.StorageCollection";
Ed Tanous253f11b2024-05-16 09:38:31 -070056 asyncResp->res.jsonValue["@odata.id"] = std::format(
57 "/redfish/v1/Systems/{}/Storage", BMCWEB_REDFISH_SYSTEM_URI_NAME);
Ed Tanous36d52332023-06-09 13:18:40 -070058 asyncResp->res.jsonValue["Name"] = "Storage Collection";
Willy Tu5e577bc2022-07-26 00:41:55 +000059
Patrick Williams5a39f772023-10-20 11:20:21 -050060 constexpr std::array<std::string_view, 1> interface{
61 "xyz.openbmc_project.Inventory.Item.Storage"};
Willy Tu5e577bc2022-07-26 00:41:55 +000062 collection_util::getCollectionMembers(
Ed Tanous253f11b2024-05-16 09:38:31 -070063 asyncResp,
64 boost::urls::format("/redfish/v1/Systems/{}/Storage",
65 BMCWEB_REDFISH_SYSTEM_URI_NAME),
Lakshmi Yadlapati36b5f1e2023-09-26 23:53:28 -050066 interface, "/xyz/openbmc_project/inventory");
Willy Tu5e577bc2022-07-26 00:41:55 +000067}
68
69inline void handleStorageCollectionGet(
70 App& app, const crow::Request& req,
71 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
72{
73 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
74 {
75 return;
76 }
77 asyncResp->res.jsonValue["@odata.type"] =
78 "#StorageCollection.StorageCollection";
79 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Storage";
80 asyncResp->res.jsonValue["Name"] = "Storage Collection";
Patrick Williams5a39f772023-10-20 11:20:21 -050081 constexpr std::array<std::string_view, 1> interface{
82 "xyz.openbmc_project.Inventory.Item.Storage"};
Willy Tu5e577bc2022-07-26 00:41:55 +000083 collection_util::getCollectionMembers(
Lakshmi Yadlapati36b5f1e2023-09-26 23:53:28 -050084 asyncResp, boost::urls::format("/redfish/v1/Storage"), interface,
85 "/xyz/openbmc_project/inventory");
Ed Tanous36d52332023-06-09 13:18:40 -070086}
87
Ed Tanous36d52332023-06-09 13:18:40 -070088inline void afterChassisDriveCollectionSubtree(
89 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous36d52332023-06-09 13:18:40 -070090 const boost::system::error_code& ec,
91 const dbus::utility::MapperGetSubTreePathsResponse& driveList)
92{
93 if (ec)
94 {
Ed Tanous62598e32023-07-17 17:06:25 -070095 BMCWEB_LOG_ERROR("Drive mapper call error");
Ed Tanous36d52332023-06-09 13:18:40 -070096 messages::internalError(asyncResp->res);
97 return;
98 }
99
100 nlohmann::json& driveArray = asyncResp->res.jsonValue["Drives"];
101 driveArray = nlohmann::json::array();
102 auto& count = asyncResp->res.jsonValue["Drives@odata.count"];
103 count = 0;
104
Ed Tanous36d52332023-06-09 13:18:40 -0700105 for (const std::string& drive : driveList)
106 {
107 sdbusplus::message::object_path object(drive);
108 if (object.filename().empty())
109 {
Ed Tanous62598e32023-07-17 17:06:25 -0700110 BMCWEB_LOG_ERROR("Failed to find filename in {}", drive);
Ed Tanous36d52332023-06-09 13:18:40 -0700111 return;
112 }
113
114 nlohmann::json::object_t driveJson;
115 driveJson["@odata.id"] = boost::urls::format(
Ed Tanous253f11b2024-05-16 09:38:31 -0700116 "/redfish/v1/Systems/{}/Storage/1/Drives/{}",
117 BMCWEB_REDFISH_SYSTEM_URI_NAME, object.filename());
Ed Tanous36d52332023-06-09 13:18:40 -0700118 driveArray.emplace_back(std::move(driveJson));
119 }
120
121 count = driveArray.size();
122}
Gunnar Mills7ac13cc2024-04-01 16:05:21 -0500123inline void getDrives(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Willy Tua85afbe2021-12-28 14:43:47 -0800124{
George Liu7a1dbc42022-12-07 16:03:22 +0800125 const std::array<std::string_view, 1> interfaces = {
126 "xyz.openbmc_project.Inventory.Item.Drive"};
127 dbus::utility::getSubTreePaths(
128 "/xyz/openbmc_project/inventory", 0, interfaces,
Gunnar Mills7ac13cc2024-04-01 16:05:21 -0500129 std::bind_front(afterChassisDriveCollectionSubtree, asyncResp));
Ed Tanous36d52332023-06-09 13:18:40 -0700130}
Willy Tua85afbe2021-12-28 14:43:47 -0800131
Willy Tu5e577bc2022-07-26 00:41:55 +0000132inline void afterSystemsStorageGetSubtree(
133 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
134 const std::string& storageId, const boost::system::error_code& ec,
135 const dbus::utility::MapperGetSubTreeResponse& subtree)
Ed Tanous36d52332023-06-09 13:18:40 -0700136{
Willy Tu5e577bc2022-07-26 00:41:55 +0000137 if (ec)
Ed Tanous36d52332023-06-09 13:18:40 -0700138 {
Ed Tanous62598e32023-07-17 17:06:25 -0700139 BMCWEB_LOG_DEBUG("requestRoutesStorage DBUS response error");
Willy Tu5e577bc2022-07-26 00:41:55 +0000140 messages::resourceNotFound(asyncResp->res, "#Storage.v1_13_0.Storage",
141 storageId);
Ed Tanous36d52332023-06-09 13:18:40 -0700142 return;
143 }
Ed Tanous3544d2a2023-08-06 18:12:20 -0700144 auto storage = std::ranges::find_if(
145 subtree,
Willy Tu5e577bc2022-07-26 00:41:55 +0000146 [&storageId](const std::pair<std::string,
147 dbus::utility::MapperServiceMap>& object) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400148 return sdbusplus::message::object_path(object.first).filename() ==
149 storageId;
150 });
Willy Tu5e577bc2022-07-26 00:41:55 +0000151 if (storage == subtree.end())
152 {
153 messages::resourceNotFound(asyncResp->res, "#Storage.v1_13_0.Storage",
154 storageId);
155 return;
156 }
157
Ed Tanous36d52332023-06-09 13:18:40 -0700158 asyncResp->res.jsonValue["@odata.type"] = "#Storage.v1_13_0.Storage";
159 asyncResp->res.jsonValue["@odata.id"] =
Ed Tanous253f11b2024-05-16 09:38:31 -0700160 boost::urls::format("/redfish/v1/Systems/{}/Storage/{}",
161 BMCWEB_REDFISH_SYSTEM_URI_NAME, storageId);
Ed Tanous36d52332023-06-09 13:18:40 -0700162 asyncResp->res.jsonValue["Name"] = "Storage";
Willy Tu5e577bc2022-07-26 00:41:55 +0000163 asyncResp->res.jsonValue["Id"] = storageId;
Ed Tanous539d8c62024-06-19 14:38:27 -0700164 asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
Willy Tua85afbe2021-12-28 14:43:47 -0800165
Gunnar Mills7ac13cc2024-04-01 16:05:21 -0500166 getDrives(asyncResp);
Ed Tanous253f11b2024-05-16 09:38:31 -0700167 asyncResp->res.jsonValue["Controllers"]["@odata.id"] =
168 boost::urls::format("/redfish/v1/Systems/{}/Storage/{}/Controllers",
169 BMCWEB_REDFISH_SYSTEM_URI_NAME, storageId);
Willy Tu5e577bc2022-07-26 00:41:55 +0000170}
171
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400172inline void handleSystemsStorageGet(
173 App& app, const crow::Request& req,
174 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
175 const std::string& systemName, const std::string& storageId)
Willy Tu5e577bc2022-07-26 00:41:55 +0000176{
177 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
178 {
179 return;
180 }
Ed Tanous25b54db2024-04-17 15:40:31 -0700181 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800182 {
183 // Option currently returns no systems. TBD
184 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
185 systemName);
186 return;
187 }
Willy Tu5e577bc2022-07-26 00:41:55 +0000188
189 constexpr std::array<std::string_view, 1> interfaces = {
190 "xyz.openbmc_project.Inventory.Item.Storage"};
191 dbus::utility::getSubTree(
192 "/xyz/openbmc_project/inventory", 0, interfaces,
193 std::bind_front(afterSystemsStorageGetSubtree, asyncResp, storageId));
194}
195
196inline void afterSubtree(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
197 const std::string& storageId,
198 const boost::system::error_code& ec,
199 const dbus::utility::MapperGetSubTreeResponse& subtree)
200{
201 if (ec)
202 {
Ed Tanous62598e32023-07-17 17:06:25 -0700203 BMCWEB_LOG_DEBUG("requestRoutesStorage DBUS response error");
Willy Tu5e577bc2022-07-26 00:41:55 +0000204 messages::resourceNotFound(asyncResp->res, "#Storage.v1_13_0.Storage",
205 storageId);
206 return;
207 }
Ed Tanous3544d2a2023-08-06 18:12:20 -0700208 auto storage = std::ranges::find_if(
209 subtree,
Willy Tu5e577bc2022-07-26 00:41:55 +0000210 [&storageId](const std::pair<std::string,
211 dbus::utility::MapperServiceMap>& object) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400212 return sdbusplus::message::object_path(object.first).filename() ==
213 storageId;
214 });
Willy Tu5e577bc2022-07-26 00:41:55 +0000215 if (storage == subtree.end())
216 {
217 messages::resourceNotFound(asyncResp->res, "#Storage.v1_13_0.Storage",
218 storageId);
219 return;
220 }
221
222 asyncResp->res.jsonValue["@odata.type"] = "#Storage.v1_13_0.Storage";
223 asyncResp->res.jsonValue["@odata.id"] =
224 boost::urls::format("/redfish/v1/Storage/{}", storageId);
225 asyncResp->res.jsonValue["Name"] = "Storage";
226 asyncResp->res.jsonValue["Id"] = storageId;
Ed Tanous539d8c62024-06-19 14:38:27 -0700227 asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
Willy Tu5e577bc2022-07-26 00:41:55 +0000228
229 // Storage subsystem to Storage link.
230 nlohmann::json::array_t storageServices;
231 nlohmann::json::object_t storageService;
232 storageService["@odata.id"] =
Ed Tanous253f11b2024-05-16 09:38:31 -0700233 boost::urls::format("/redfish/v1/Systems/{}/Storage/{}",
234 BMCWEB_REDFISH_SYSTEM_URI_NAME, storageId);
Willy Tu5e577bc2022-07-26 00:41:55 +0000235 storageServices.emplace_back(storageService);
236 asyncResp->res.jsonValue["Links"]["StorageServices"] =
237 std::move(storageServices);
238 asyncResp->res.jsonValue["Links"]["StorageServices@odata.count"] = 1;
239}
240
Patrick Williams504af5a2025-02-03 14:29:03 -0500241inline void handleStorageGet(
242 App& app, const crow::Request& req,
243 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
244 const std::string& storageId)
Willy Tu5e577bc2022-07-26 00:41:55 +0000245{
246 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
247 {
Ed Tanous62598e32023-07-17 17:06:25 -0700248 BMCWEB_LOG_DEBUG("requestRoutesStorage setUpRedfishRoute failed");
Willy Tu5e577bc2022-07-26 00:41:55 +0000249 return;
250 }
251
252 constexpr std::array<std::string_view, 1> interfaces = {
253 "xyz.openbmc_project.Inventory.Item.Storage"};
254 dbus::utility::getSubTree(
255 "/xyz/openbmc_project/inventory", 0, interfaces,
256 std::bind_front(afterSubtree, asyncResp, storageId));
Willy Tua85afbe2021-12-28 14:43:47 -0800257}
258
Ed Tanous36d52332023-06-09 13:18:40 -0700259inline void handleSystemsStorageDriveGet(
260 App& app, const crow::Request& req,
261 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
262 const std::string& systemName, const std::string& driveId)
263{
264 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
265 {
266 return;
267 }
Ed Tanous25b54db2024-04-17 15:40:31 -0700268 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800269 {
270 // Option currently returns no systems. TBD
271 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
272 systemName);
273 return;
274 }
275
Ed Tanous253f11b2024-05-16 09:38:31 -0700276 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
Ed Tanous36d52332023-06-09 13:18:40 -0700277 {
278 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
279 systemName);
280 return;
281 }
282
283 constexpr std::array<std::string_view, 1> interfaces = {
284 "xyz.openbmc_project.Inventory.Item.Drive"};
285 dbus::utility::getSubTree(
286 "/xyz/openbmc_project/inventory", 0, interfaces,
287 std::bind_front(afterGetSubtreeSystemsStorageDrive, asyncResp,
288 driveId));
289}
290
Christopher Meis7bf29ab2025-10-23 14:46:24 +0200291inline void requestRoutesStorage(App& app)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700292{
Christopher Meis7bf29ab2025-10-23 14:46:24 +0200293 BMCWEB_ROUTE(app, "/redfish/v1/Storage/")
294 .privileges(redfish::privileges::getStorageCollection)
295 .methods(boost::beast::http::verb::get)(
296 std::bind_front(handleStorageCollectionGet, std::ref(app)));
297
298 BMCWEB_ROUTE(app, "/redfish/v1/Storage/<str>/")
299 .privileges(redfish::privileges::getStorage)
300 .methods(boost::beast::http::verb::get)(
301 std::bind_front(handleStorageGet, std::ref(app)));
302
303 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Storage/")
304 .privileges(redfish::privileges::getStorageCollection)
305 .methods(boost::beast::http::verb::get)(
306 std::bind_front(handleSystemsStorageCollectionGet, std::ref(app)));
307
308 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Storage/<str>/")
309 .privileges(redfish::privileges::getStorage)
310 .methods(boost::beast::http::verb::get)(
311 std::bind_front(handleSystemsStorageGet, std::ref(app)));
312
Ed Tanous22d268c2022-05-19 09:39:07 -0700313 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Storage/1/Drives/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700314 .privileges(redfish::privileges::getDrive)
Ed Tanous002d39b2022-05-31 08:59:27 -0700315 .methods(boost::beast::http::verb::get)(
Ed Tanous36d52332023-06-09 13:18:40 -0700316 std::bind_front(handleSystemsStorageDriveGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700317}
John Edward Broadbent92903bd2022-04-26 13:40:59 -0700318
Nikhil Potadea25aecc2019-08-23 16:35:26 -0700319} // namespace redfish