blob: 14e543dc00382934d571138737f5f929ef961e4a [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 2018 Intel Corporation
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +01004#pragma once
5
Ed Tanousd7857202025-01-28 15:32:26 -08006#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"
10#include "dbus_singleton.hpp"
George Liu7a1dbc42022-12-07 16:03:22 +080011#include "dbus_utility.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080012#include "error_messages.hpp"
Ed Tanous539d8c62024-06-19 14:38:27 -070013#include "generated/enums/action_info.hpp"
14#include "generated/enums/chassis.hpp"
15#include "generated/enums/resource.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080016#include "http_request.hpp"
James Feist1c8fba92019-12-20 15:12:07 -080017#include "led.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080018#include "logging.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080019#include "query.hpp"
20#include "registries/privilege_registry.hpp"
21#include "utils/collection.hpp"
22#include "utils/dbus_utils.hpp"
Nan Zhoucf7eba02022-07-21 23:53:20 +000023#include "utils/json_utils.hpp"
Ed Tanous1abe55e2018-09-05 08:30:59 -070024
Ed Tanousd7857202025-01-28 15:32:26 -080025#include <asm-generic/errno.h>
26
27#include <boost/beast/http/field.hpp>
28#include <boost/beast/http/verb.hpp>
George Liue99073f2022-12-09 11:06:16 +080029#include <boost/system/error_code.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070030#include <boost/url/format.hpp>
Ed Tanousd7857202025-01-28 15:32:26 -080031#include <boost/url/url.hpp>
32#include <nlohmann/json.hpp>
Ed Tanousd7857202025-01-28 15:32:26 -080033#include <sdbusplus/message/native_types.hpp>
Krzysztof Grobelny86d89ed2022-08-29 14:49:20 +020034#include <sdbusplus/unpack_properties.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050035
Ed Tanousd7857202025-01-28 15:32:26 -080036#include <algorithm>
George Liu7a1dbc42022-12-07 16:03:22 +080037#include <array>
Ed Tanousd7857202025-01-28 15:32:26 -080038#include <format>
39#include <functional>
Joseph-Jonathan Salzano2952f642024-11-19 12:00:06 -070040#include <memory>
Ed Tanousd7857202025-01-28 15:32:26 -080041#include <optional>
Ed Tanous3544d2a2023-08-06 18:12:20 -070042#include <ranges>
Ed Tanousd7857202025-01-28 15:32:26 -080043#include <string>
George Liu7a1dbc42022-12-07 16:03:22 +080044#include <string_view>
Ed Tanousd7857202025-01-28 15:32:26 -080045#include <utility>
46#include <vector>
George Liu7a1dbc42022-12-07 16:03:22 +080047
Ed Tanous1abe55e2018-09-05 08:30:59 -070048namespace redfish
49{
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010050
Patrick Williams504af5a2025-02-03 14:29:03 -050051inline chassis::ChassisType translateChassisTypeToRedfish(
52 const std::string_view& chassisType)
Joseph-Jonathan Salzano2952f642024-11-19 12:00:06 -070053{
54 if (chassisType ==
55 "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.Blade")
56 {
57 return chassis::ChassisType::Blade;
58 }
59 if (chassisType ==
60 "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.Component")
61 {
62 return chassis::ChassisType::Component;
63 }
64 if (chassisType ==
65 "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.Enclosure")
66 {
67 return chassis::ChassisType::Enclosure;
68 }
69 if (chassisType ==
70 "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.Module")
71 {
72 return chassis::ChassisType::Module;
73 }
74 if (chassisType ==
75 "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.RackMount")
76 {
77 return chassis::ChassisType::RackMount;
78 }
79 if (chassisType ==
80 "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.StandAlone")
81 {
82 return chassis::ChassisType::StandAlone;
83 }
84 if (chassisType ==
85 "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.StorageEnclosure")
86 {
87 return chassis::ChassisType::StorageEnclosure;
88 }
89 if (chassisType ==
90 "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.Zone")
91 {
92 return chassis::ChassisType::Zone;
93 }
94 return chassis::ChassisType::Invalid;
95}
96
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010097/**
Willy Tu5e577bc2022-07-26 00:41:55 +000098 * @brief Retrieves resources over dbus to link to the chassis
99 *
100 * @param[in] asyncResp - Shared pointer for completing asynchronous
101 * calls
102 * @param[in] path - Chassis dbus path to look for the storage.
103 *
104 * Calls the Association endpoints on the path + "/storage" and add the link of
105 * json["Links"]["Storage@odata.count"] =
106 * {"@odata.id", "/redfish/v1/Storage/" + resourceId}
107 *
108 * @return None.
109 */
110inline void getStorageLink(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
111 const sdbusplus::message::object_path& path)
112{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800113 dbus::utility::getProperty<std::vector<std::string>>(
114 "xyz.openbmc_project.ObjectMapper", (path / "storage").str,
115 "xyz.openbmc_project.Association", "endpoints",
Willy Tud4b054c2023-06-12 15:18:45 -0700116 [asyncResp](const boost::system::error_code& ec,
Willy Tu5e577bc2022-07-26 00:41:55 +0000117 const std::vector<std::string>& storageList) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400118 if (ec)
Willy Tu5e577bc2022-07-26 00:41:55 +0000119 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400120 BMCWEB_LOG_DEBUG("getStorageLink got DBUS response error");
121 return;
Willy Tu5e577bc2022-07-26 00:41:55 +0000122 }
123
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400124 nlohmann::json::array_t storages;
125 for (const std::string& storagePath : storageList)
126 {
127 std::string id =
128 sdbusplus::message::object_path(storagePath).filename();
129 if (id.empty())
130 {
131 continue;
132 }
133
134 nlohmann::json::object_t storage;
135 storage["@odata.id"] =
136 boost::urls::format("/redfish/v1/Systems/{}/Storage/{}",
137 BMCWEB_REDFISH_SYSTEM_URI_NAME, id);
138 storages.emplace_back(std::move(storage));
139 }
140 asyncResp->res.jsonValue["Links"]["Storage@odata.count"] =
141 storages.size();
142 asyncResp->res.jsonValue["Links"]["Storage"] = std::move(storages);
143 });
Willy Tu5e577bc2022-07-26 00:41:55 +0000144}
145
146/**
Gunnar Millsbeeca0a2019-02-14 16:30:45 -0600147 * @brief Retrieves chassis state properties over dbus
148 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700149 * @param[in] asyncResp - Shared pointer for completing asynchronous calls.
Gunnar Millsbeeca0a2019-02-14 16:30:45 -0600150 *
151 * @return None.
152 */
Ed Tanousac106bf2023-06-07 09:24:59 -0700153inline void getChassisState(std::shared_ptr<bmcweb::AsyncResp> asyncResp)
Gunnar Millsbeeca0a2019-02-14 16:30:45 -0600154{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700155 // crow::connections::systemBus->async_method_call(
Ed Tanousdeae6a72024-11-11 21:58:57 -0800156 dbus::utility::getProperty<std::string>(
157 "xyz.openbmc_project.State.Chassis",
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700158 "/xyz/openbmc_project/state/chassis0",
159 "xyz.openbmc_project.State.Chassis", "CurrentPowerState",
Ed Tanousac106bf2023-06-07 09:24:59 -0700160 [asyncResp{std::move(asyncResp)}](const boost::system::error_code& ec,
161 const std::string& chassisState) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400162 if (ec)
Gunnar Millsbeeca0a2019-02-14 16:30:45 -0600163 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400164 if (ec == boost::system::errc::host_unreachable)
165 {
166 // Service not available, no error, just don't return
167 // chassis state info
168 BMCWEB_LOG_DEBUG("Service not available {}", ec);
169 return;
170 }
171 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
172 messages::internalError(asyncResp->res);
Gunnar Millsbeeca0a2019-02-14 16:30:45 -0600173 return;
174 }
175
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400176 BMCWEB_LOG_DEBUG("Chassis state: {}", chassisState);
177 // Verify Chassis State
178 if (chassisState ==
179 "xyz.openbmc_project.State.Chassis.PowerState.On")
180 {
181 asyncResp->res.jsonValue["PowerState"] =
182 resource::PowerState::On;
183 asyncResp->res.jsonValue["Status"]["State"] =
184 resource::State::Enabled;
185 }
186 else if (chassisState ==
187 "xyz.openbmc_project.State.Chassis.PowerState.Off")
188 {
189 asyncResp->res.jsonValue["PowerState"] =
190 resource::PowerState::Off;
191 asyncResp->res.jsonValue["Status"]["State"] =
192 resource::State::StandbyOffline;
193 }
194 });
Gunnar Millsbeeca0a2019-02-14 16:30:45 -0600195}
196
Qiang XUc1819422019-02-27 13:51:32 +0800197/**
198 * Retrieves physical security properties over dbus
199 */
Chau Ly7164bc62023-10-15 14:55:30 +0000200inline void handlePhysicalSecurityGetSubTree(
201 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
202 const boost::system::error_code& ec,
203 const dbus::utility::MapperGetSubTreeResponse& subtree)
Qiang XUc1819422019-02-27 13:51:32 +0800204{
Chau Ly7164bc62023-10-15 14:55:30 +0000205 if (ec)
206 {
207 // do not add err msg in redfish response, because this is not
208 // mandatory property
209 BMCWEB_LOG_INFO("DBUS error: no matched iface {}", ec);
210 return;
211 }
212 // Iterate over all retrieved ObjectPaths.
213 for (const auto& object : subtree)
214 {
215 if (!object.second.empty())
Ed Tanous002d39b2022-05-31 08:59:27 -0700216 {
Ed Tanous89144a32024-04-08 17:27:04 -0700217 const auto& service = object.second.front();
Chau Ly7164bc62023-10-15 14:55:30 +0000218
219 BMCWEB_LOG_DEBUG("Get intrusion status by service ");
220
Ed Tanousdeae6a72024-11-11 21:58:57 -0800221 dbus::utility::getProperty<std::string>(
222 service.first, object.first,
Chau Ly7164bc62023-10-15 14:55:30 +0000223 "xyz.openbmc_project.Chassis.Intrusion", "Status",
224 [asyncResp](const boost::system::error_code& ec1,
225 const std::string& value) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400226 if (ec1)
227 {
228 // do not add err msg in redfish response, because this
229 // is not
230 // mandatory property
231 BMCWEB_LOG_ERROR("DBUS response error {}", ec1);
232 return;
233 }
234 asyncResp->res.jsonValue["PhysicalSecurity"]
235 ["IntrusionSensorNumber"] = 1;
236 asyncResp->res
237 .jsonValue["PhysicalSecurity"]["IntrusionSensor"] =
238 value;
239 });
Chau Ly7164bc62023-10-15 14:55:30 +0000240
Ed Tanous002d39b2022-05-31 08:59:27 -0700241 return;
242 }
Chau Ly7164bc62023-10-15 14:55:30 +0000243 }
Qiang XUc1819422019-02-27 13:51:32 +0800244}
245
Nan Zhoucf7eba02022-07-21 23:53:20 +0000246inline void handleChassisCollectionGet(
247 App& app, const crow::Request& req,
248 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
249{
250 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
251 {
252 return;
253 }
254 asyncResp->res.jsonValue["@odata.type"] =
255 "#ChassisCollection.ChassisCollection";
256 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Chassis";
257 asyncResp->res.jsonValue["Name"] = "Chassis Collection";
258
George Liu7a1dbc42022-12-07 16:03:22 +0800259 constexpr std::array<std::string_view, 2> interfaces{
260 "xyz.openbmc_project.Inventory.Item.Board",
261 "xyz.openbmc_project.Inventory.Item.Chassis"};
Nan Zhoucf7eba02022-07-21 23:53:20 +0000262 collection_util::getCollectionMembers(
Lakshmi Yadlapati36b5f1e2023-09-26 23:53:28 -0500263 asyncResp, boost::urls::url("/redfish/v1/Chassis"), interfaces,
264 "/xyz/openbmc_project/inventory");
Nan Zhoucf7eba02022-07-21 23:53:20 +0000265}
266
Jie Yanga5617492021-06-29 12:59:14 -0700267inline void getChassisContainedBy(
268 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
269 const std::string& chassisId, const boost::system::error_code& ec,
Myung Bae28ee5632024-05-24 13:10:04 -0500270 const dbus::utility::MapperGetSubTreePathsResponse& upstreamChassisPaths)
Jie Yanga5617492021-06-29 12:59:14 -0700271{
272 if (ec)
273 {
274 if (ec.value() != EBADR)
275 {
Ed Tanous62598e32023-07-17 17:06:25 -0700276 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Jie Yanga5617492021-06-29 12:59:14 -0700277 messages::internalError(asyncResp->res);
278 }
279 return;
280 }
281 if (upstreamChassisPaths.empty())
282 {
283 return;
284 }
285 if (upstreamChassisPaths.size() > 1)
286 {
Ed Tanous8ece0e42024-01-02 13:16:50 -0800287 BMCWEB_LOG_ERROR("{} is contained by multiple chassis", chassisId);
Jie Yanga5617492021-06-29 12:59:14 -0700288 messages::internalError(asyncResp->res);
289 return;
290 }
291
292 sdbusplus::message::object_path upstreamChassisPath(
293 upstreamChassisPaths[0]);
294 std::string upstreamChassis = upstreamChassisPath.filename();
295 if (upstreamChassis.empty())
296 {
Ed Tanous62598e32023-07-17 17:06:25 -0700297 BMCWEB_LOG_WARNING("Malformed upstream Chassis path {} on {}",
298 upstreamChassisPath.str, chassisId);
Jie Yanga5617492021-06-29 12:59:14 -0700299 return;
300 }
301
302 asyncResp->res.jsonValue["Links"]["ContainedBy"]["@odata.id"] =
303 boost::urls::format("/redfish/v1/Chassis/{}", upstreamChassis);
304}
305
306inline void getChassisContains(
307 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
308 const std::string& chassisId, const boost::system::error_code& ec,
Myung Bae28ee5632024-05-24 13:10:04 -0500309 const dbus::utility::MapperGetSubTreePathsResponse& downstreamChassisPaths)
Jie Yanga5617492021-06-29 12:59:14 -0700310{
311 if (ec)
312 {
313 if (ec.value() != EBADR)
314 {
Ed Tanous62598e32023-07-17 17:06:25 -0700315 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Jie Yanga5617492021-06-29 12:59:14 -0700316 messages::internalError(asyncResp->res);
317 }
318 return;
319 }
320 if (downstreamChassisPaths.empty())
321 {
322 return;
323 }
324 nlohmann::json& jValue = asyncResp->res.jsonValue["Links"]["Contains"];
325 if (!jValue.is_array())
326 {
327 // Create the array if it was empty
328 jValue = nlohmann::json::array();
329 }
330 for (const auto& p : downstreamChassisPaths)
331 {
332 sdbusplus::message::object_path downstreamChassisPath(p);
333 std::string downstreamChassis = downstreamChassisPath.filename();
334 if (downstreamChassis.empty())
335 {
Ed Tanous62598e32023-07-17 17:06:25 -0700336 BMCWEB_LOG_WARNING("Malformed downstream Chassis path {} on {}",
337 downstreamChassisPath.str, chassisId);
Jie Yanga5617492021-06-29 12:59:14 -0700338 continue;
339 }
340 nlohmann::json link;
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400341 link["@odata.id"] =
342 boost::urls::format("/redfish/v1/Chassis/{}", downstreamChassis);
Jie Yanga5617492021-06-29 12:59:14 -0700343 jValue.push_back(std::move(link));
344 }
345 asyncResp->res.jsonValue["Links"]["Contains@odata.count"] = jValue.size();
346}
347
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400348inline void getChassisConnectivity(
349 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
350 const std::string& chassisId, const std::string& chassisPath)
Jie Yanga5617492021-06-29 12:59:14 -0700351{
Ed Tanous62598e32023-07-17 17:06:25 -0700352 BMCWEB_LOG_DEBUG("Get chassis connectivity");
Jie Yanga5617492021-06-29 12:59:14 -0700353
Myung Bae28ee5632024-05-24 13:10:04 -0500354 constexpr std::array<std::string_view, 2> interfaces{
355 "xyz.openbmc_project.Inventory.Item.Board",
356 "xyz.openbmc_project.Inventory.Item.Chassis"};
357
358 dbus::utility::getAssociatedSubTreePaths(
Jie Yanga5617492021-06-29 12:59:14 -0700359 chassisPath + "/contained_by",
Myung Bae28ee5632024-05-24 13:10:04 -0500360 sdbusplus::message::object_path("/xyz/openbmc_project/inventory"), 0,
361 interfaces,
Jie Yanga5617492021-06-29 12:59:14 -0700362 std::bind_front(getChassisContainedBy, asyncResp, chassisId));
363
Myung Bae28ee5632024-05-24 13:10:04 -0500364 dbus::utility::getAssociatedSubTreePaths(
Jie Yanga5617492021-06-29 12:59:14 -0700365 chassisPath + "/containing",
Myung Bae28ee5632024-05-24 13:10:04 -0500366 sdbusplus::message::object_path("/xyz/openbmc_project/inventory"), 0,
367 interfaces, std::bind_front(getChassisContains, asyncResp, chassisId));
Jie Yanga5617492021-06-29 12:59:14 -0700368}
369
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100370/**
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100371 * ChassisCollection derived class for delivering Chassis Collection Schema
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700372 * Functions triggers appropriate requests on DBus
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100373 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700374inline void requestRoutesChassisCollection(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700375{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700376 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/")
Ed Tanoused398212021-06-09 17:05:54 -0700377 .privileges(redfish::privileges::getChassisCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700378 .methods(boost::beast::http::verb::get)(
Nan Zhoucf7eba02022-07-21 23:53:20 +0000379 std::bind_front(handleChassisCollectionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700380}
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100381
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400382inline void getChassisLocationCode(
383 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
384 const std::string& connectionName, const std::string& path)
Willy Tu308f70c2021-09-28 20:24:52 -0700385{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800386 dbus::utility::getProperty<std::string>(
387 connectionName, path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700388 "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800389 [asyncResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700390 const std::string& property) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400391 if (ec)
392 {
393 BMCWEB_LOG_ERROR("DBUS response error for Location");
394 messages::internalError(asyncResp->res);
395 return;
396 }
Willy Tu308f70c2021-09-28 20:24:52 -0700397
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400398 asyncResp->res
399 .jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
400 property;
401 });
Willy Tu308f70c2021-09-28 20:24:52 -0700402}
403
404inline void getChassisUUID(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
405 const std::string& connectionName,
406 const std::string& path)
407{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800408 dbus::utility::getProperty<std::string>(
409 connectionName, path, "xyz.openbmc_project.Common.UUID", "UUID",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800410 [asyncResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700411 const std::string& chassisUUID) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400412 if (ec)
413 {
414 BMCWEB_LOG_ERROR("DBUS response error for UUID");
415 messages::internalError(asyncResp->res);
416 return;
417 }
418 asyncResp->res.jsonValue["UUID"] = chassisUUID;
419 });
Willy Tu308f70c2021-09-28 20:24:52 -0700420}
421
Chau Ly7164bc62023-10-15 14:55:30 +0000422inline void handleDecoratorAssetProperties(
423 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
424 const std::string& chassisId, const std::string& path,
425 const dbus::utility::DBusPropertiesMap& propertiesList)
426{
427 const std::string* partNumber = nullptr;
428 const std::string* serialNumber = nullptr;
429 const std::string* manufacturer = nullptr;
430 const std::string* model = nullptr;
431 const std::string* sparePartNumber = nullptr;
432
433 const bool success = sdbusplus::unpackPropertiesNoThrow(
434 dbus_utils::UnpackErrorPrinter(), propertiesList, "PartNumber",
435 partNumber, "SerialNumber", serialNumber, "Manufacturer", manufacturer,
436 "Model", model, "SparePartNumber", sparePartNumber);
437
438 if (!success)
439 {
440 messages::internalError(asyncResp->res);
441 return;
442 }
443
444 if (partNumber != nullptr)
445 {
446 asyncResp->res.jsonValue["PartNumber"] = *partNumber;
447 }
448
449 if (serialNumber != nullptr)
450 {
451 asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
452 }
453
454 if (manufacturer != nullptr)
455 {
456 asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
457 }
458
459 if (model != nullptr)
460 {
461 asyncResp->res.jsonValue["Model"] = *model;
462 }
463
464 // SparePartNumber is optional on D-Bus
465 // so skip if it is empty
466 if (sparePartNumber != nullptr && !sparePartNumber->empty())
467 {
468 asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber;
469 }
470
471 asyncResp->res.jsonValue["Name"] = chassisId;
472 asyncResp->res.jsonValue["Id"] = chassisId;
Ed Tanous25b54db2024-04-17 15:40:31 -0700473
474 if constexpr (BMCWEB_REDFISH_ALLOW_DEPRECATED_POWER_THERMAL)
475 {
476 asyncResp->res.jsonValue["Thermal"]["@odata.id"] =
477 boost::urls::format("/redfish/v1/Chassis/{}/Thermal", chassisId);
478 // Power object
479 asyncResp->res.jsonValue["Power"]["@odata.id"] =
480 boost::urls::format("/redfish/v1/Chassis/{}/Power", chassisId);
481 }
482
483 if constexpr (BMCWEB_REDFISH_NEW_POWERSUBSYSTEM_THERMALSUBSYSTEM)
484 {
485 asyncResp->res.jsonValue["ThermalSubsystem"]["@odata.id"] =
486 boost::urls::format("/redfish/v1/Chassis/{}/ThermalSubsystem",
487 chassisId);
488 asyncResp->res.jsonValue["PowerSubsystem"]["@odata.id"] =
489 boost::urls::format("/redfish/v1/Chassis/{}/PowerSubsystem",
490 chassisId);
491 asyncResp->res.jsonValue["EnvironmentMetrics"]["@odata.id"] =
492 boost::urls::format("/redfish/v1/Chassis/{}/EnvironmentMetrics",
493 chassisId);
494 }
Chau Ly7164bc62023-10-15 14:55:30 +0000495 // SensorCollection
496 asyncResp->res.jsonValue["Sensors"]["@odata.id"] =
497 boost::urls::format("/redfish/v1/Chassis/{}/Sensors", chassisId);
Ed Tanous539d8c62024-06-19 14:38:27 -0700498 asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
Chau Ly7164bc62023-10-15 14:55:30 +0000499
500 nlohmann::json::array_t computerSystems;
501 nlohmann::json::object_t system;
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400502 system["@odata.id"] =
503 std::format("/redfish/v1/Systems/{}", BMCWEB_REDFISH_SYSTEM_URI_NAME);
Chau Ly7164bc62023-10-15 14:55:30 +0000504 computerSystems.emplace_back(std::move(system));
505 asyncResp->res.jsonValue["Links"]["ComputerSystems"] =
506 std::move(computerSystems);
507
508 nlohmann::json::array_t managedBy;
509 nlohmann::json::object_t manager;
Ed Tanous253f11b2024-05-16 09:38:31 -0700510 manager["@odata.id"] = boost::urls::format("/redfish/v1/Managers/{}",
511 BMCWEB_REDFISH_MANAGER_URI_NAME);
Chau Ly7164bc62023-10-15 14:55:30 +0000512 managedBy.emplace_back(std::move(manager));
513 asyncResp->res.jsonValue["Links"]["ManagedBy"] = std::move(managedBy);
514 getChassisState(asyncResp);
515 getStorageLink(asyncResp, path);
516}
517
Joseph-Jonathan Salzano2952f642024-11-19 12:00:06 -0700518inline void handleChassisProperties(
519 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
520 const dbus::utility::DBusPropertiesMap& propertiesList)
521{
522 const std::string* type = nullptr;
523
524 const bool success = sdbusplus::unpackPropertiesNoThrow(
525 dbus_utils::UnpackErrorPrinter(), propertiesList, "Type", type);
526
527 if (!success)
528 {
529 messages::internalError(asyncResp->res);
530 return;
531 }
532
Gunnar Mills19ea2862024-12-10 09:02:03 -0600533 // Chassis Type is a required property in Redfish
534 // If there is an error or some enum we don't support just sit it to Rack
535 // Mount
536 asyncResp->res.jsonValue["ChassisType"] = chassis::ChassisType::RackMount;
537
Joseph-Jonathan Salzano2952f642024-11-19 12:00:06 -0700538 if (type != nullptr)
539 {
540 auto chassisType = translateChassisTypeToRedfish(*type);
541 if (chassisType != chassis::ChassisType::Invalid)
542 {
543 asyncResp->res.jsonValue["ChassisType"] = chassisType;
544 }
545 }
Joseph-Jonathan Salzano2952f642024-11-19 12:00:06 -0700546}
547
Chau Ly7164bc62023-10-15 14:55:30 +0000548inline void handleChassisGetSubTree(
549 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
550 const std::string& chassisId, const boost::system::error_code& ec,
551 const dbus::utility::MapperGetSubTreeResponse& subtree)
552{
553 if (ec)
554 {
555 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
556 messages::internalError(asyncResp->res);
557 return;
558 }
559 // Iterate over all retrieved ObjectPaths.
560 for (const std::pair<
561 std::string,
562 std::vector<std::pair<std::string, std::vector<std::string>>>>&
563 object : subtree)
564 {
565 const std::string& path = object.first;
566 const std::vector<std::pair<std::string, std::vector<std::string>>>&
567 connectionNames = object.second;
568
569 sdbusplus::message::object_path objPath(path);
570 if (objPath.filename() != chassisId)
571 {
572 continue;
573 }
574
575 getChassisConnectivity(asyncResp, chassisId, path);
576
Chau Ly7164bc62023-10-15 14:55:30 +0000577 if (connectionNames.empty())
578 {
579 BMCWEB_LOG_ERROR("Got 0 Connection names");
580 continue;
581 }
582
583 asyncResp->res.jsonValue["@odata.type"] = "#Chassis.v1_22_0.Chassis";
584 asyncResp->res.jsonValue["@odata.id"] =
585 boost::urls::format("/redfish/v1/Chassis/{}", chassisId);
586 asyncResp->res.jsonValue["Name"] = "Chassis Collection";
Chau Ly7164bc62023-10-15 14:55:30 +0000587 asyncResp->res.jsonValue["Actions"]["#Chassis.Reset"]["target"] =
588 boost::urls::format("/redfish/v1/Chassis/{}/Actions/Chassis.Reset",
589 chassisId);
590 asyncResp->res
591 .jsonValue["Actions"]["#Chassis.Reset"]["@Redfish.ActionInfo"] =
592 boost::urls::format("/redfish/v1/Chassis/{}/ResetActionInfo",
593 chassisId);
Chau Ly7164bc62023-10-15 14:55:30 +0000594 dbus::utility::getAssociationEndPoints(
595 path + "/drive",
596 [asyncResp, chassisId](const boost::system::error_code& ec3,
597 const dbus::utility::MapperEndPoints& resp) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400598 if (ec3 || resp.empty())
599 {
600 return; // no drives = no failures
601 }
Chau Ly7164bc62023-10-15 14:55:30 +0000602
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400603 nlohmann::json reference;
604 reference["@odata.id"] = boost::urls::format(
605 "/redfish/v1/Chassis/{}/Drives", chassisId);
606 asyncResp->res.jsonValue["Drives"] = std::move(reference);
607 });
Chau Ly7164bc62023-10-15 14:55:30 +0000608
609 const std::string& connectionName = connectionNames[0].first;
610
611 const std::vector<std::string>& interfaces2 = connectionNames[0].second;
George Liue5ae9c12021-11-16 10:31:23 +0800612 const std::array<const char*, 3> hasIndicatorLed = {
613 "xyz.openbmc_project.Inventory.Item.Chassis",
Chau Ly7164bc62023-10-15 14:55:30 +0000614 "xyz.openbmc_project.Inventory.Item.Panel",
615 "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
616
617 const std::string assetTagInterface =
618 "xyz.openbmc_project.Inventory.Decorator.AssetTag";
619 const std::string replaceableInterface =
620 "xyz.openbmc_project.Inventory.Decorator.Replaceable";
Carson Labradob4d593f2024-02-16 22:34:32 +0000621 const std::string revisionInterface =
622 "xyz.openbmc_project.Inventory.Decorator.Revision";
Chau Ly7164bc62023-10-15 14:55:30 +0000623 for (const auto& interface : interfaces2)
624 {
625 if (interface == assetTagInterface)
626 {
Ed Tanousdeae6a72024-11-11 21:58:57 -0800627 dbus::utility::getProperty<std::string>(
628 connectionName, path, assetTagInterface, "AssetTag",
Chau Ly7164bc62023-10-15 14:55:30 +0000629 [asyncResp, chassisId](const boost::system::error_code& ec2,
630 const std::string& property) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400631 if (ec2)
632 {
633 BMCWEB_LOG_ERROR(
634 "DBus response error for AssetTag: {}", ec2);
635 messages::internalError(asyncResp->res);
636 return;
637 }
638 asyncResp->res.jsonValue["AssetTag"] = property;
639 });
Chau Ly7164bc62023-10-15 14:55:30 +0000640 }
641 else if (interface == replaceableInterface)
642 {
Ed Tanousdeae6a72024-11-11 21:58:57 -0800643 dbus::utility::getProperty<bool>(
644 connectionName, path, replaceableInterface, "HotPluggable",
Chau Ly7164bc62023-10-15 14:55:30 +0000645 [asyncResp, chassisId](const boost::system::error_code& ec2,
646 const bool property) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400647 if (ec2)
648 {
649 BMCWEB_LOG_ERROR(
650 "DBus response error for HotPluggable: {}",
651 ec2);
652 messages::internalError(asyncResp->res);
653 return;
654 }
655 asyncResp->res.jsonValue["HotPluggable"] = property;
656 });
Chau Ly7164bc62023-10-15 14:55:30 +0000657 }
Carson Labradob4d593f2024-02-16 22:34:32 +0000658 else if (interface == revisionInterface)
659 {
Ed Tanousdeae6a72024-11-11 21:58:57 -0800660 dbus::utility::getProperty<std::string>(
661 connectionName, path, revisionInterface, "Version",
Carson Labradob4d593f2024-02-16 22:34:32 +0000662 [asyncResp, chassisId](const boost::system::error_code& ec2,
663 const std::string& property) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400664 if (ec2)
665 {
666 BMCWEB_LOG_ERROR(
667 "DBus response error for Version: {}", ec2);
668 messages::internalError(asyncResp->res);
669 return;
670 }
671 asyncResp->res.jsonValue["Version"] = property;
672 });
Carson Labradob4d593f2024-02-16 22:34:32 +0000673 }
Chau Ly7164bc62023-10-15 14:55:30 +0000674 }
675
676 for (const char* interface : hasIndicatorLed)
677 {
678 if (std::ranges::find(interfaces2, interface) != interfaces2.end())
679 {
680 getIndicatorLedState(asyncResp);
681 getSystemLocationIndicatorActive(asyncResp);
682 break;
683 }
684 }
685
Ed Tanousdeae6a72024-11-11 21:58:57 -0800686 dbus::utility::getAllProperties(
Chau Ly7164bc62023-10-15 14:55:30 +0000687 *crow::connections::systemBus, connectionName, path,
688 "xyz.openbmc_project.Inventory.Decorator.Asset",
689 [asyncResp, chassisId,
690 path](const boost::system::error_code&,
691 const dbus::utility::DBusPropertiesMap& propertiesList) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400692 handleDecoratorAssetProperties(asyncResp, chassisId, path,
693 propertiesList);
694 });
Chau Ly7164bc62023-10-15 14:55:30 +0000695
Ed Tanous46f780f2025-02-09 09:35:23 -0800696 dbus::utility::getAllProperties(
Joseph-Jonathan Salzano2952f642024-11-19 12:00:06 -0700697 *crow::connections::systemBus, connectionName, path,
698 "xyz.openbmc_project.Inventory.Item.Chassis",
699 [asyncResp](
700 const boost::system::error_code&,
701 const dbus::utility::DBusPropertiesMap& propertiesList) {
702 handleChassisProperties(asyncResp, propertiesList);
703 });
704
Chau Ly7164bc62023-10-15 14:55:30 +0000705 for (const auto& interface : interfaces2)
706 {
707 if (interface == "xyz.openbmc_project.Common.UUID")
708 {
709 getChassisUUID(asyncResp, connectionName, path);
710 }
711 else if (interface ==
712 "xyz.openbmc_project.Inventory.Decorator.LocationCode")
713 {
714 getChassisLocationCode(asyncResp, connectionName, path);
715 }
716 }
717
718 return;
719 }
720
721 // Couldn't find an object with that name. return an error
722 messages::resourceNotFound(asyncResp->res, "Chassis", chassisId);
723}
724
Patrick Williams504af5a2025-02-03 14:29:03 -0500725inline void handleChassisGet(
726 App& app, const crow::Request& req,
727 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
728 const std::string& chassisId)
Nan Zhoucf7eba02022-07-21 23:53:20 +0000729{
730 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
731 {
732 return;
733 }
George Liue99073f2022-12-09 11:06:16 +0800734 constexpr std::array<std::string_view, 2> interfaces = {
Nan Zhoucf7eba02022-07-21 23:53:20 +0000735 "xyz.openbmc_project.Inventory.Item.Board",
736 "xyz.openbmc_project.Inventory.Item.Chassis"};
737
George Liue99073f2022-12-09 11:06:16 +0800738 dbus::utility::getSubTree(
739 "/xyz/openbmc_project/inventory", 0, interfaces,
Chau Ly7164bc62023-10-15 14:55:30 +0000740 std::bind_front(handleChassisGetSubTree, asyncResp, chassisId));
Nan Zhoucf7eba02022-07-21 23:53:20 +0000741
Chau Ly7164bc62023-10-15 14:55:30 +0000742 constexpr std::array<std::string_view, 1> interfaces2 = {
743 "xyz.openbmc_project.Chassis.Intrusion"};
Nan Zhoucf7eba02022-07-21 23:53:20 +0000744
Chau Ly7164bc62023-10-15 14:55:30 +0000745 dbus::utility::getSubTree(
746 "/xyz/openbmc_project", 0, interfaces2,
747 std::bind_front(handlePhysicalSecurityGetSubTree, asyncResp));
Nan Zhoucf7eba02022-07-21 23:53:20 +0000748}
749
Patrick Williams504af5a2025-02-03 14:29:03 -0500750inline void handleChassisPatch(
751 App& app, const crow::Request& req,
752 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
753 const std::string& param)
Nan Zhoucf7eba02022-07-21 23:53:20 +0000754{
755 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
756 {
757 return;
758 }
759 std::optional<bool> locationIndicatorActive;
760 std::optional<std::string> indicatorLed;
761
762 if (param.empty())
763 {
764 return;
765 }
766
Patrick Williams504af5a2025-02-03 14:29:03 -0500767 if (!json_util::readJsonPatch( //
768 req, asyncResp->res, //
769 "IndicatorLED", indicatorLed, //
Myung Baeafc474a2024-10-09 00:53:29 -0700770 "LocationIndicatorActive", locationIndicatorActive //
771 ))
Nan Zhoucf7eba02022-07-21 23:53:20 +0000772 {
773 return;
774 }
775
776 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
777 if (!locationIndicatorActive && !indicatorLed)
778 {
779 return; // delete this when we support more patch properties
780 }
781 if (indicatorLed)
782 {
783 asyncResp->res.addHeader(
784 boost::beast::http::field::warning,
785 "299 - \"IndicatorLED is deprecated. Use LocationIndicatorActive instead.\"");
786 }
787
George Liue99073f2022-12-09 11:06:16 +0800788 constexpr std::array<std::string_view, 2> interfaces = {
Nan Zhoucf7eba02022-07-21 23:53:20 +0000789 "xyz.openbmc_project.Inventory.Item.Board",
790 "xyz.openbmc_project.Inventory.Item.Chassis"};
791
792 const std::string& chassisId = param;
793
George Liue99073f2022-12-09 11:06:16 +0800794 dbus::utility::getSubTree(
795 "/xyz/openbmc_project/inventory", 0, interfaces,
Nan Zhoucf7eba02022-07-21 23:53:20 +0000796 [asyncResp, chassisId, locationIndicatorActive,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800797 indicatorLed](const boost::system::error_code& ec,
Nan Zhoucf7eba02022-07-21 23:53:20 +0000798 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400799 if (ec)
Nan Zhoucf7eba02022-07-21 23:53:20 +0000800 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400801 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
802 messages::internalError(asyncResp->res);
803 return;
Nan Zhoucf7eba02022-07-21 23:53:20 +0000804 }
805
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400806 // Iterate over all retrieved ObjectPaths.
807 for (const std::pair<std::string,
808 std::vector<std::pair<
809 std::string, std::vector<std::string>>>>&
810 object : subtree)
Nan Zhoucf7eba02022-07-21 23:53:20 +0000811 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400812 const std::string& path = object.first;
813 const std::vector<
814 std::pair<std::string, std::vector<std::string>>>&
815 connectionNames = object.second;
816
817 sdbusplus::message::object_path objPath(path);
818 if (objPath.filename() != chassisId)
819 {
820 continue;
821 }
822
823 if (connectionNames.empty())
824 {
825 BMCWEB_LOG_ERROR("Got 0 Connection names");
826 continue;
827 }
828
829 const std::vector<std::string>& interfaces3 =
830 connectionNames[0].second;
831
832 const std::array<const char*, 3> hasIndicatorLed = {
833 "xyz.openbmc_project.Inventory.Item.Chassis",
834 "xyz.openbmc_project.Inventory.Item.Panel",
835 "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
836 bool indicatorChassis = false;
837 for (const char* interface : hasIndicatorLed)
838 {
839 if (std::ranges::find(interfaces3, interface) !=
840 interfaces3.end())
841 {
842 indicatorChassis = true;
843 break;
844 }
845 }
846 if (locationIndicatorActive)
847 {
848 if (indicatorChassis)
849 {
850 setSystemLocationIndicatorActive(
851 asyncResp, *locationIndicatorActive);
852 }
853 else
854 {
855 messages::propertyUnknown(asyncResp->res,
856 "LocationIndicatorActive");
857 }
858 }
859 if (indicatorLed)
860 {
861 if (indicatorChassis)
862 {
863 setIndicatorLedState(asyncResp, *indicatorLed);
864 }
865 else
866 {
867 messages::propertyUnknown(asyncResp->res,
868 "IndicatorLED");
869 }
870 }
871 return;
Nan Zhoucf7eba02022-07-21 23:53:20 +0000872 }
873
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400874 messages::resourceNotFound(asyncResp->res, "Chassis", chassisId);
875 });
Nan Zhoucf7eba02022-07-21 23:53:20 +0000876}
877
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100878/**
879 * Chassis override class for delivering Chassis Schema
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700880 * Functions triggers appropriate requests on DBus
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100881 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700882inline void requestRoutesChassis(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700883{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700884 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700885 .privileges(redfish::privileges::getChassis)
Ed Tanous002d39b2022-05-31 08:59:27 -0700886 .methods(boost::beast::http::verb::get)(
Nan Zhoucf7eba02022-07-21 23:53:20 +0000887 std::bind_front(handleChassisGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700888
889 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700890 .privileges(redfish::privileges::patchChassis)
Ed Tanous002d39b2022-05-31 08:59:27 -0700891 .methods(boost::beast::http::verb::patch)(
Nan Zhoucf7eba02022-07-21 23:53:20 +0000892 std::bind_front(handleChassisPatch, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700893}
P.K. Leedd99e042020-06-17 19:43:16 +0800894
Patrick Williams504af5a2025-02-03 14:29:03 -0500895inline void doChassisPowerCycle(
896 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
P.K. Leedd99e042020-06-17 19:43:16 +0800897{
George Liu7a1dbc42022-12-07 16:03:22 +0800898 constexpr std::array<std::string_view, 1> interfaces = {
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700899 "xyz.openbmc_project.State.Chassis"};
900
901 // Use mapper to get subtree paths.
George Liu7a1dbc42022-12-07 16:03:22 +0800902 dbus::utility::getSubTreePaths(
903 "/", 0, interfaces,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800904 [asyncResp](
George Liu7a1dbc42022-12-07 16:03:22 +0800905 const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800906 const dbus::utility::MapperGetSubTreePathsResponse& chassisList) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400907 if (ec)
908 {
909 BMCWEB_LOG_ERROR("[mapper] Bad D-Bus request error: {}", ec);
910 messages::internalError(asyncResp->res);
911 return;
912 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700913
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400914 const char* processName = "xyz.openbmc_project.State.Chassis";
915 const char* interfaceName = "xyz.openbmc_project.State.Chassis";
916 const char* destProperty = "RequestedPowerTransition";
917 const std::string propertyValue =
918 "xyz.openbmc_project.State.Chassis.Transition.PowerCycle";
919 std::string objectPath =
920 "/xyz/openbmc_project/state/chassis_system0";
Ed Tanous002d39b2022-05-31 08:59:27 -0700921
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400922 /* Look for system reset chassis path */
923 if ((std::ranges::find(chassisList, objectPath)) ==
924 chassisList.end())
925 {
926 /* We prefer to reset the full chassis_system, but if it doesn't
927 * exist on some platforms, fall back to a host-only power reset
928 */
929 objectPath = "/xyz/openbmc_project/state/chassis0";
930 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700931
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400932 setDbusProperty(asyncResp, "ResetType", processName, objectPath,
933 interfaceName, destProperty, propertyValue);
934 });
P.K. Leedd99e042020-06-17 19:43:16 +0800935}
936
Nan Zhoucf7eba02022-07-21 23:53:20 +0000937inline void handleChassisResetActionInfoPost(
938 App& app, const crow::Request& req,
939 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
940 const std::string& /*chassisId*/)
941{
942 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
943 {
944 return;
945 }
Ed Tanous62598e32023-07-17 17:06:25 -0700946 BMCWEB_LOG_DEBUG("Post Chassis Reset.");
Nan Zhoucf7eba02022-07-21 23:53:20 +0000947
948 std::string resetType;
949
950 if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", resetType))
951 {
952 return;
953 }
954
955 if (resetType != "PowerCycle")
956 {
Ed Tanous62598e32023-07-17 17:06:25 -0700957 BMCWEB_LOG_DEBUG("Invalid property value for ResetType: {}", resetType);
Nan Zhoucf7eba02022-07-21 23:53:20 +0000958 messages::actionParameterNotSupported(asyncResp->res, resetType,
959 "ResetType");
960
961 return;
962 }
963 doChassisPowerCycle(asyncResp);
964}
965
P.K. Leedd99e042020-06-17 19:43:16 +0800966/**
967 * ChassisResetAction class supports the POST method for the Reset
968 * action.
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700969 * Function handles POST method request.
970 * Analyzes POST body before sending Reset request data to D-Bus.
P.K. Leedd99e042020-06-17 19:43:16 +0800971 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700972
973inline void requestRoutesChassisResetAction(App& app)
P.K. Leedd99e042020-06-17 19:43:16 +0800974{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700975 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Actions/Chassis.Reset/")
Ed Tanoused398212021-06-09 17:05:54 -0700976 .privileges(redfish::privileges::postChassis)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700977 .methods(boost::beast::http::verb::post)(
Nan Zhoucf7eba02022-07-21 23:53:20 +0000978 std::bind_front(handleChassisResetActionInfoPost, std::ref(app)));
979}
P.K. Leedd99e042020-06-17 19:43:16 +0800980
Nan Zhoucf7eba02022-07-21 23:53:20 +0000981inline void handleChassisResetActionInfoGet(
982 App& app, const crow::Request& req,
983 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
984 const std::string& chassisId)
985{
986 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
987 {
988 return;
989 }
990 asyncResp->res.jsonValue["@odata.type"] = "#ActionInfo.v1_1_2.ActionInfo";
Ed Tanousef4c65b2023-04-24 15:28:50 -0700991 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
992 "/redfish/v1/Chassis/{}/ResetActionInfo", chassisId);
Nan Zhoucf7eba02022-07-21 23:53:20 +0000993 asyncResp->res.jsonValue["Name"] = "Reset Action Info";
P.K. Leedd99e042020-06-17 19:43:16 +0800994
Nan Zhoucf7eba02022-07-21 23:53:20 +0000995 asyncResp->res.jsonValue["Id"] = "ResetActionInfo";
996 nlohmann::json::array_t parameters;
997 nlohmann::json::object_t parameter;
998 parameter["Name"] = "ResetType";
999 parameter["Required"] = true;
Ed Tanous539d8c62024-06-19 14:38:27 -07001000 parameter["DataType"] = action_info::ParameterTypes::String;
Nan Zhoucf7eba02022-07-21 23:53:20 +00001001 nlohmann::json::array_t allowed;
Patrick Williamsad539542023-05-12 10:10:08 -05001002 allowed.emplace_back("PowerCycle");
Nan Zhoucf7eba02022-07-21 23:53:20 +00001003 parameter["AllowableValues"] = std::move(allowed);
Patrick Williamsad539542023-05-12 10:10:08 -05001004 parameters.emplace_back(std::move(parameter));
P.K. Leedd99e042020-06-17 19:43:16 +08001005
Nan Zhoucf7eba02022-07-21 23:53:20 +00001006 asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001007}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05301008
1009/**
1010 * ChassisResetActionInfo derived class for delivering Chassis
1011 * ResetType AllowableValues using ResetInfo schema.
1012 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001013inline void requestRoutesChassisResetActionInfo(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05301014{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001015 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -07001016 .privileges(redfish::privileges::getActionInfo)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001017 .methods(boost::beast::http::verb::get)(
Nan Zhoucf7eba02022-07-21 23:53:20 +00001018 std::bind_front(handleChassisResetActionInfoGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001019}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05301020
Ed Tanous1abe55e2018-09-05 08:30:59 -07001021} // namespace redfish