blob: c10288df7efd76b3816e36f7d25641f20f9675e2 [file] [log] [blame]
Ed Tanous40e9b922024-09-10 13:50:16 -07001// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright OpenBMC Authors
George Liu9516f412022-09-29 17:21:41 +08003#pragma once
4
5#include "app.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -08006#include "async_resp.hpp"
George Liu9516f412022-09-29 17:21:41 +08007#include "dbus_utility.hpp"
8#include "error_messages.hpp"
Ed Tanous539d8c62024-06-19 14:38:27 -07009#include "generated/enums/resource.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080010#include "http_request.hpp"
Myung Bae1da1ff52024-08-20 11:34:59 -050011#include "led.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080012#include "logging.hpp"
George Liu9516f412022-09-29 17:21:41 +080013#include "query.hpp"
14#include "registries/privilege_registry.hpp"
15#include "utils/chassis_utils.hpp"
Ed Tanous177612a2025-02-14 15:16:09 -080016#include "utils/dbus_utils.hpp"
Myung Bae1da1ff52024-08-20 11:34:59 -050017#include "utils/json_utils.hpp"
George Liu9516f412022-09-29 17:21:41 +080018
Ed Tanousd7857202025-01-28 15:32:26 -080019#include <asm-generic/errno.h>
20
21#include <boost/beast/http/field.hpp>
22#include <boost/beast/http/verb.hpp>
Albert Zhang9f1ae5a2021-06-10 14:41:48 +080023#include <boost/system/error_code.hpp>
George Liu9516f412022-09-29 17:21:41 +080024#include <boost/url/format.hpp>
Ed Tanousd7857202025-01-28 15:32:26 -080025#include <nlohmann/json.hpp>
26#include <sdbusplus/unpack_properties.hpp>
George Liu9516f412022-09-29 17:21:41 +080027
Ed Tanousd7857202025-01-28 15:32:26 -080028#include <array>
George Liu9516f412022-09-29 17:21:41 +080029#include <functional>
30#include <memory>
31#include <optional>
32#include <string>
33#include <string_view>
Ed Tanousd7857202025-01-28 15:32:26 -080034#include <utility>
George Liu9516f412022-09-29 17:21:41 +080035
36namespace redfish
37{
38constexpr std::array<std::string_view, 1> fanInterface = {
39 "xyz.openbmc_project.Inventory.Item.Fan"};
40
Patrick Williams504af5a2025-02-03 14:29:03 -050041inline void updateFanList(
42 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
43 const std::string& chassisId,
44 const dbus::utility::MapperGetSubTreePathsResponse& fanPaths)
George Liu9516f412022-09-29 17:21:41 +080045{
46 nlohmann::json& fanList = asyncResp->res.jsonValue["Members"];
47 for (const std::string& fanPath : fanPaths)
48 {
49 std::string fanName =
50 sdbusplus::message::object_path(fanPath).filename();
51 if (fanName.empty())
52 {
53 continue;
54 }
55
56 nlohmann::json item = nlohmann::json::object();
57 item["@odata.id"] = boost::urls::format(
58 "/redfish/v1/Chassis/{}/ThermalSubsystem/Fans/{}", chassisId,
59 fanName);
60
61 fanList.emplace_back(std::move(item));
62 }
63 asyncResp->res.jsonValue["Members@odata.count"] = fanList.size();
64}
65
66inline void getFanPaths(
67 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanousd547d8d2024-03-16 18:04:41 -070068 const std::string& validChassisPath,
George Liu9516f412022-09-29 17:21:41 +080069 const std::function<void(const dbus::utility::MapperGetSubTreePathsResponse&
70 fanPaths)>& callback)
71{
Ed Tanousd547d8d2024-03-16 18:04:41 -070072 sdbusplus::message::object_path endpointPath{validChassisPath};
George Liu9516f412022-09-29 17:21:41 +080073 endpointPath /= "cooled_by";
74
75 dbus::utility::getAssociatedSubTreePaths(
76 endpointPath,
77 sdbusplus::message::object_path("/xyz/openbmc_project/inventory"), 0,
78 fanInterface,
79 [asyncResp, callback](
80 const boost::system::error_code& ec,
81 const dbus::utility::MapperGetSubTreePathsResponse& subtreePaths) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -040082 if (ec)
George Liu9516f412022-09-29 17:21:41 +080083 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -040084 if (ec.value() != EBADR)
85 {
86 BMCWEB_LOG_ERROR(
87 "DBUS response error for getAssociatedSubTreePaths {}",
88 ec.value());
89 messages::internalError(asyncResp->res);
90 }
91 return;
George Liu9516f412022-09-29 17:21:41 +080092 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -040093 callback(subtreePaths);
94 });
George Liu9516f412022-09-29 17:21:41 +080095}
96
97inline void doFanCollection(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
98 const std::string& chassisId,
99 const std::optional<std::string>& validChassisPath)
100{
101 if (!validChassisPath)
102 {
103 messages::resourceNotFound(asyncResp->res, "Chassis", chassisId);
104 return;
105 }
106
107 asyncResp->res.addHeader(
108 boost::beast::http::field::link,
109 "</redfish/v1/JsonSchemas/FanCollection/FanCollection.json>; rel=describedby");
110 asyncResp->res.jsonValue["@odata.type"] = "#FanCollection.FanCollection";
111 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
112 "/redfish/v1/Chassis/{}/ThermalSubsystem/Fans", chassisId);
113 asyncResp->res.jsonValue["Name"] = "Fan Collection";
114 asyncResp->res.jsonValue["Description"] =
115 "The collection of Fan resource instances " + chassisId;
116 asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
117 asyncResp->res.jsonValue["Members@odata.count"] = 0;
118
Ed Tanousd547d8d2024-03-16 18:04:41 -0700119 getFanPaths(asyncResp, *validChassisPath,
George Liu9516f412022-09-29 17:21:41 +0800120 std::bind_front(updateFanList, asyncResp, chassisId));
121}
122
Patrick Williams504af5a2025-02-03 14:29:03 -0500123inline void handleFanCollectionHead(
124 App& app, const crow::Request& req,
125 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
126 const std::string& chassisId)
George Liu9516f412022-09-29 17:21:41 +0800127{
128 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
129 {
130 return;
131 }
132
133 redfish::chassis_utils::getValidChassisPath(
134 asyncResp, chassisId,
135 [asyncResp,
136 chassisId](const std::optional<std::string>& validChassisPath) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400137 if (!validChassisPath)
138 {
139 messages::resourceNotFound(asyncResp->res, "Chassis",
140 chassisId);
141 return;
142 }
143 asyncResp->res.addHeader(
144 boost::beast::http::field::link,
145 "</redfish/v1/JsonSchemas/FanCollection/FanCollection.json>; rel=describedby");
146 });
George Liu9516f412022-09-29 17:21:41 +0800147}
148
Patrick Williams504af5a2025-02-03 14:29:03 -0500149inline void handleFanCollectionGet(
150 App& app, const crow::Request& req,
151 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
152 const std::string& chassisId)
George Liu9516f412022-09-29 17:21:41 +0800153{
154 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
155 {
156 return;
157 }
158
159 redfish::chassis_utils::getValidChassisPath(
160 asyncResp, chassisId,
161 std::bind_front(doFanCollection, asyncResp, chassisId));
162}
163
164inline void requestRoutesFanCollection(App& app)
165{
166 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ThermalSubsystem/Fans/")
167 .privileges(redfish::privileges::headFanCollection)
168 .methods(boost::beast::http::verb::head)(
169 std::bind_front(handleFanCollectionHead, std::ref(app)));
170
171 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ThermalSubsystem/Fans/")
172 .privileges(redfish::privileges::getFanCollection)
173 .methods(boost::beast::http::verb::get)(
174 std::bind_front(handleFanCollectionGet, std::ref(app)));
175}
176
George Liue4e54232022-09-30 09:08:11 +0800177inline bool checkFanId(const std::string& fanPath, const std::string& fanId)
178{
179 std::string fanName = sdbusplus::message::object_path(fanPath).filename();
180
181 return !(fanName.empty() || fanName != fanId);
182}
183
Ed Tanous4ff0f1f2024-09-04 17:27:37 -0700184inline void handleFanPath(
George Liue4e54232022-09-30 09:08:11 +0800185 const std::string& fanId,
186 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
187 const dbus::utility::MapperGetSubTreePathsResponse& fanPaths,
188 const std::function<void(const std::string& fanPath,
189 const std::string& service)>& callback)
190{
191 for (const auto& fanPath : fanPaths)
192 {
193 if (!checkFanId(fanPath, fanId))
194 {
195 continue;
196 }
197 dbus::utility::getDbusObject(
198 fanPath, fanInterface,
199 [fanPath, asyncResp,
200 callback](const boost::system::error_code& ec,
201 const dbus::utility::MapperGetObject& object) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400202 if (ec || object.empty())
203 {
204 BMCWEB_LOG_ERROR("DBUS response error on getDbusObject {}",
205 ec.value());
206 messages::internalError(asyncResp->res);
207 return;
208 }
209 callback(fanPath, object.begin()->first);
210 });
George Liue4e54232022-09-30 09:08:11 +0800211
212 return;
213 }
Ed Tanous62598e32023-07-17 17:06:25 -0700214 BMCWEB_LOG_WARNING("Fan not found {}", fanId);
George Liue4e54232022-09-30 09:08:11 +0800215 messages::resourceNotFound(asyncResp->res, "Fan", fanId);
216}
217
Myung Bae1da1ff52024-08-20 11:34:59 -0500218inline void getValidFanObject(
George Liue4e54232022-09-30 09:08:11 +0800219 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
220 const std::string& validChassisPath, const std::string& fanId,
221 const std::function<void(const std::string& fanPath,
222 const std::string& service)>& callback)
223{
224 getFanPaths(
225 asyncResp, validChassisPath,
226 [fanId, asyncResp, callback](
227 const dbus::utility::MapperGetSubTreePathsResponse& fanPaths) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400228 handleFanPath(fanId, asyncResp, fanPaths, callback);
229 });
George Liue4e54232022-09-30 09:08:11 +0800230}
231
232inline void addFanCommonProperties(crow::Response& resp,
233 const std::string& chassisId,
234 const std::string& fanId)
235{
236 resp.addHeader(boost::beast::http::field::link,
237 "</redfish/v1/JsonSchemas/Fan/Fan.json>; rel=describedby");
238 resp.jsonValue["@odata.type"] = "#Fan.v1_3_0.Fan";
239 resp.jsonValue["Name"] = "Fan";
240 resp.jsonValue["Id"] = fanId;
241 resp.jsonValue["@odata.id"] = boost::urls::format(
242 "/redfish/v1/Chassis/{}/ThermalSubsystem/Fans/{}", chassisId, fanId);
Ed Tanous539d8c62024-06-19 14:38:27 -0700243 resp.jsonValue["Status"]["State"] = resource::State::Enabled;
244 resp.jsonValue["Status"]["Health"] = resource::Health::OK;
Albert Zhang9f1ae5a2021-06-10 14:41:48 +0800245}
246
247inline void getFanHealth(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
248 const std::string& fanPath, const std::string& service)
249{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800250 dbus::utility::getProperty<bool>(
251 service, fanPath,
Albert Zhang9f1ae5a2021-06-10 14:41:48 +0800252 "xyz.openbmc_project.State.Decorator.OperationalStatus", "Functional",
253 [asyncResp](const boost::system::error_code& ec, const bool value) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400254 if (ec)
Albert Zhang9f1ae5a2021-06-10 14:41:48 +0800255 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400256 if (ec.value() != EBADR)
257 {
258 BMCWEB_LOG_ERROR("DBUS response error for Health {}",
259 ec.value());
260 messages::internalError(asyncResp->res);
261 }
262 return;
Albert Zhang9f1ae5a2021-06-10 14:41:48 +0800263 }
Albert Zhang9f1ae5a2021-06-10 14:41:48 +0800264
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400265 if (!value)
266 {
267 asyncResp->res.jsonValue["Status"]["Health"] =
268 resource::Health::Critical;
269 }
270 });
Albert Zhang9f1ae5a2021-06-10 14:41:48 +0800271}
272
273inline void getFanState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
274 const std::string& fanPath, const std::string& service)
275{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800276 dbus::utility::getProperty<bool>(
277 service, fanPath, "xyz.openbmc_project.Inventory.Item", "Present",
Albert Zhang9f1ae5a2021-06-10 14:41:48 +0800278 [asyncResp](const boost::system::error_code& ec, const bool value) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400279 if (ec)
Albert Zhang9f1ae5a2021-06-10 14:41:48 +0800280 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400281 if (ec.value() != EBADR)
282 {
283 BMCWEB_LOG_ERROR("DBUS response error for State {}",
284 ec.value());
285 messages::internalError(asyncResp->res);
286 }
287 return;
Albert Zhang9f1ae5a2021-06-10 14:41:48 +0800288 }
Albert Zhang9f1ae5a2021-06-10 14:41:48 +0800289
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400290 if (!value)
291 {
292 asyncResp->res.jsonValue["Status"]["State"] =
293 resource::State::Absent;
294 }
295 });
George Liue4e54232022-09-30 09:08:11 +0800296}
297
George Liu090ae7b2022-10-04 15:45:25 +0800298inline void getFanAsset(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
299 const std::string& fanPath, const std::string& service)
300{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800301 dbus::utility::getAllProperties(
302 service, fanPath, "xyz.openbmc_project.Inventory.Decorator.Asset",
George Liu090ae7b2022-10-04 15:45:25 +0800303 [fanPath, asyncResp{asyncResp}](
304 const boost::system::error_code& ec,
305 const dbus::utility::DBusPropertiesMap& assetList) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400306 if (ec)
George Liu090ae7b2022-10-04 15:45:25 +0800307 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400308 if (ec.value() != EBADR)
309 {
310 BMCWEB_LOG_ERROR("DBUS response error for Properties{}",
311 ec.value());
312 messages::internalError(asyncResp->res);
313 }
314 return;
George Liu090ae7b2022-10-04 15:45:25 +0800315 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400316 const std::string* manufacturer = nullptr;
317 const std::string* model = nullptr;
318 const std::string* partNumber = nullptr;
319 const std::string* serialNumber = nullptr;
320 const std::string* sparePartNumber = nullptr;
George Liu090ae7b2022-10-04 15:45:25 +0800321
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400322 const bool success = sdbusplus::unpackPropertiesNoThrow(
323 dbus_utils::UnpackErrorPrinter(), assetList, "Manufacturer",
324 manufacturer, "Model", model, "PartNumber", partNumber,
325 "SerialNumber", serialNumber, "SparePartNumber",
326 sparePartNumber);
327 if (!success)
328 {
329 messages::internalError(asyncResp->res);
330 return;
331 }
332 if (manufacturer != nullptr)
333 {
334 asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
335 }
336 if (model != nullptr)
337 {
338 asyncResp->res.jsonValue["Model"] = *model;
339 }
340 if (partNumber != nullptr)
341 {
342 asyncResp->res.jsonValue["PartNumber"] = *partNumber;
343 }
344 if (serialNumber != nullptr)
345 {
346 asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
347 }
348 if (sparePartNumber != nullptr && !sparePartNumber->empty())
349 {
350 asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber;
351 }
352 });
George Liu090ae7b2022-10-04 15:45:25 +0800353}
354
Ed Tanousfc3edfd2023-07-20 12:41:30 -0700355inline void getFanLocation(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
George Liu4a2e4852022-10-04 16:13:44 +0800356 const std::string& fanPath,
357 const std::string& service)
358{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800359 dbus::utility::getProperty<std::string>(
360 service, fanPath,
George Liu4a2e4852022-10-04 16:13:44 +0800361 "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode",
Ed Tanousfc3edfd2023-07-20 12:41:30 -0700362 [asyncResp](const boost::system::error_code& ec,
363 const std::string& property) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400364 if (ec)
George Liu4a2e4852022-10-04 16:13:44 +0800365 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400366 if (ec.value() != EBADR)
367 {
368 BMCWEB_LOG_ERROR("DBUS response error for Location{}",
369 ec.value());
370 messages::internalError(asyncResp->res);
371 }
372 return;
George Liu4a2e4852022-10-04 16:13:44 +0800373 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400374 asyncResp->res
375 .jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
376 property;
377 });
George Liu4a2e4852022-10-04 16:13:44 +0800378}
379
Myung Bae1da1ff52024-08-20 11:34:59 -0500380inline void afterGetValidFanObject(
Patrick Williams504af5a2025-02-03 14:29:03 -0500381 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
382 const std::string& chassisId, const std::string& fanId,
383 const std::string& fanPath, const std::string& service)
George Liue4e54232022-09-30 09:08:11 +0800384{
George Liue4e54232022-09-30 09:08:11 +0800385 addFanCommonProperties(asyncResp->res, chassisId, fanId);
Albert Zhang9f1ae5a2021-06-10 14:41:48 +0800386 getFanState(asyncResp, fanPath, service);
387 getFanHealth(asyncResp, fanPath, service);
George Liu090ae7b2022-10-04 15:45:25 +0800388 getFanAsset(asyncResp, fanPath, service);
George Liu4a2e4852022-10-04 16:13:44 +0800389 getFanLocation(asyncResp, fanPath, service);
Myung Bae1da1ff52024-08-20 11:34:59 -0500390 getLocationIndicatorActive(asyncResp, fanPath);
George Liue4e54232022-09-30 09:08:11 +0800391}
392
393inline void doFanGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
394 const std::string& chassisId, const std::string& fanId,
395 const std::optional<std::string>& validChassisPath)
396{
397 if (!validChassisPath)
398 {
399 messages::resourceNotFound(asyncResp->res, "Chassis", chassisId);
400 return;
401 }
402
Myung Bae1da1ff52024-08-20 11:34:59 -0500403 getValidFanObject(
George Liue4e54232022-09-30 09:08:11 +0800404 asyncResp, *validChassisPath, fanId,
Myung Bae1da1ff52024-08-20 11:34:59 -0500405 std::bind_front(afterGetValidFanObject, asyncResp, chassisId, fanId));
George Liue4e54232022-09-30 09:08:11 +0800406}
407
408inline void handleFanHead(App& app, const crow::Request& req,
409 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
410 const std::string& chassisId,
411 const std::string& fanId)
412{
413 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
414 {
415 return;
416 }
417
418 redfish::chassis_utils::getValidChassisPath(
419 asyncResp, chassisId,
420 [asyncResp, chassisId,
421 fanId](const std::optional<std::string>& validChassisPath) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400422 if (!validChassisPath)
423 {
424 messages::resourceNotFound(asyncResp->res, "Chassis",
425 chassisId);
426 return;
427 }
Myung Bae1da1ff52024-08-20 11:34:59 -0500428 getValidFanObject(
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400429 asyncResp, *validChassisPath, fanId,
430 [asyncResp](const std::string&, const std::string&) {
431 asyncResp->res.addHeader(
432 boost::beast::http::field::link,
433 "</redfish/v1/JsonSchemas/Fan/Fan.json>; rel=describedby");
434 });
George Liue4e54232022-09-30 09:08:11 +0800435 });
George Liue4e54232022-09-30 09:08:11 +0800436}
437
438inline void handleFanGet(App& app, const crow::Request& req,
439 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
440 const std::string& chassisId, const std::string& fanId)
441{
442 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
443 {
444 return;
445 }
446
447 redfish::chassis_utils::getValidChassisPath(
448 asyncResp, chassisId,
449 std::bind_front(doFanGet, asyncResp, chassisId, fanId));
450}
451
Myung Bae1da1ff52024-08-20 11:34:59 -0500452inline void handleSetFanPathById(
453 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
454 const std::string& chassisId, const std::string& fanId,
455 bool locationIndicatorActive, const boost::system::error_code& ec,
456 const dbus::utility::MapperGetSubTreePathsResponse& fanPaths)
457{
458 if (ec)
459 {
460 if (ec.value() == boost::system::errc::io_error)
461 {
462 BMCWEB_LOG_WARNING("Chassis {} not found", chassisId);
463 messages::resourceNotFound(asyncResp->res, "Chassis", chassisId);
464 return;
465 }
466
467 BMCWEB_LOG_ERROR("DBUS response error {}", ec.value());
468 messages::internalError(asyncResp->res);
469 return;
470 }
471
472 for (const auto& fanPath : fanPaths)
473 {
474 if (checkFanId(fanPath, fanId))
475 {
476 setLocationIndicatorActive(asyncResp, fanPath,
477 locationIndicatorActive);
478 return;
479 }
480 }
481 BMCWEB_LOG_WARNING("Fan {} not found", fanId);
482 messages::resourceNotFound(asyncResp->res, "Fan", fanId);
483}
484
485inline void handleFanPatch(App& app, const crow::Request& req,
486 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
487 const std::string& chassisId,
488 const std::string& fanId)
489{
490 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
491 {
492 return;
493 }
494
495 std::optional<bool> locationIndicatorActive;
496 if (!json_util::readJsonPatch(req, asyncResp->res,
497 "LocationIndicatorActive",
498 locationIndicatorActive))
499 {
500 return;
501 }
502
503 if (locationIndicatorActive)
504 {
505 dbus::utility::getAssociatedSubTreePathsById(
506 chassisId, "/xyz/openbmc_project/inventory", chassisInterfaces,
507 "cooled_by", fanInterface,
508 [asyncResp, chassisId, fanId, locationIndicatorActive](
509 const boost::system::error_code& ec,
510 const dbus::utility::MapperGetSubTreePathsResponse&
511 subtreePaths) {
512 handleSetFanPathById(asyncResp, chassisId, fanId,
513 *locationIndicatorActive, ec,
514 subtreePaths);
515 });
516 }
517}
518
George Liue4e54232022-09-30 09:08:11 +0800519inline void requestRoutesFan(App& app)
520{
521 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ThermalSubsystem/Fans/<str>/")
522 .privileges(redfish::privileges::headFan)
523 .methods(boost::beast::http::verb::head)(
524 std::bind_front(handleFanHead, std::ref(app)));
525
526 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ThermalSubsystem/Fans/<str>/")
527 .privileges(redfish::privileges::getFan)
528 .methods(boost::beast::http::verb::get)(
529 std::bind_front(handleFanGet, std::ref(app)));
Myung Bae1da1ff52024-08-20 11:34:59 -0500530
531 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ThermalSubsystem/Fans/<str>/")
532 .privileges(redfish::privileges::patchFan)
533 .methods(boost::beast::http::verb::patch)(
534 std::bind_front(handleFanPatch, std::ref(app)));
George Liue4e54232022-09-30 09:08:11 +0800535}
536
George Liu9516f412022-09-29 17:21:41 +0800537} // namespace redfish