blob: d405e755489ea2c14b425dd4714d380f30b7f94e [file] [log] [blame]
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +01001/*
Ed Tanous6be832e2024-09-10 11:44:48 -07002Copyright (c) 2018 Intel Corporation
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010015*/
16#pragma once
17
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080018#include "app.hpp"
George Liu7a1dbc42022-12-07 16:03:22 +080019#include "dbus_utility.hpp"
Ed Tanous539d8c62024-06-19 14:38:27 -070020#include "generated/enums/action_info.hpp"
21#include "generated/enums/chassis.hpp"
22#include "generated/enums/resource.hpp"
James Feist1c8fba92019-12-20 15:12:07 -080023#include "led.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080024#include "query.hpp"
Chau Ly7164bc62023-10-15 14:55:30 +000025#include "redfish_util.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080026#include "registries/privilege_registry.hpp"
27#include "utils/collection.hpp"
28#include "utils/dbus_utils.hpp"
Nan Zhoucf7eba02022-07-21 23:53:20 +000029#include "utils/json_utils.hpp"
Ed Tanous1abe55e2018-09-05 08:30:59 -070030
George Liue99073f2022-12-09 11:06:16 +080031#include <boost/system/error_code.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070032#include <boost/url/format.hpp>
Jonathan Doman1e1e5982021-06-11 09:36:17 -070033#include <sdbusplus/asio/property.hpp>
Andrew Geisslerfc903b32023-05-31 14:15:42 -040034#include <sdbusplus/message.hpp>
Krzysztof Grobelny86d89ed2022-08-29 14:49:20 +020035#include <sdbusplus/unpack_properties.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050036
George Liu7a1dbc42022-12-07 16:03:22 +080037#include <array>
Joseph-Jonathan Salzano2952f642024-11-19 12:00:06 -070038#include <memory>
Ed Tanous3544d2a2023-08-06 18:12:20 -070039#include <ranges>
George Liu7a1dbc42022-12-07 16:03:22 +080040#include <string_view>
41
Ed Tanous1abe55e2018-09-05 08:30:59 -070042namespace redfish
43{
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010044
Joseph-Jonathan Salzano2952f642024-11-19 12:00:06 -070045inline chassis::ChassisType
46 translateChassisTypeToRedfish(const std::string_view& chassisType)
47{
48 if (chassisType ==
49 "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.Blade")
50 {
51 return chassis::ChassisType::Blade;
52 }
53 if (chassisType ==
54 "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.Component")
55 {
56 return chassis::ChassisType::Component;
57 }
58 if (chassisType ==
59 "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.Enclosure")
60 {
61 return chassis::ChassisType::Enclosure;
62 }
63 if (chassisType ==
64 "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.Module")
65 {
66 return chassis::ChassisType::Module;
67 }
68 if (chassisType ==
69 "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.RackMount")
70 {
71 return chassis::ChassisType::RackMount;
72 }
73 if (chassisType ==
74 "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.StandAlone")
75 {
76 return chassis::ChassisType::StandAlone;
77 }
78 if (chassisType ==
79 "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.StorageEnclosure")
80 {
81 return chassis::ChassisType::StorageEnclosure;
82 }
83 if (chassisType ==
84 "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.Zone")
85 {
86 return chassis::ChassisType::Zone;
87 }
88 return chassis::ChassisType::Invalid;
89}
90
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010091/**
Willy Tu5e577bc2022-07-26 00:41:55 +000092 * @brief Retrieves resources over dbus to link to the chassis
93 *
94 * @param[in] asyncResp - Shared pointer for completing asynchronous
95 * calls
96 * @param[in] path - Chassis dbus path to look for the storage.
97 *
98 * Calls the Association endpoints on the path + "/storage" and add the link of
99 * json["Links"]["Storage@odata.count"] =
100 * {"@odata.id", "/redfish/v1/Storage/" + resourceId}
101 *
102 * @return None.
103 */
104inline void getStorageLink(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
105 const sdbusplus::message::object_path& path)
106{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800107 dbus::utility::getProperty<std::vector<std::string>>(
108 "xyz.openbmc_project.ObjectMapper", (path / "storage").str,
109 "xyz.openbmc_project.Association", "endpoints",
Willy Tud4b054c2023-06-12 15:18:45 -0700110 [asyncResp](const boost::system::error_code& ec,
Willy Tu5e577bc2022-07-26 00:41:55 +0000111 const std::vector<std::string>& storageList) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400112 if (ec)
Willy Tu5e577bc2022-07-26 00:41:55 +0000113 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400114 BMCWEB_LOG_DEBUG("getStorageLink got DBUS response error");
115 return;
Willy Tu5e577bc2022-07-26 00:41:55 +0000116 }
117
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400118 nlohmann::json::array_t storages;
119 for (const std::string& storagePath : storageList)
120 {
121 std::string id =
122 sdbusplus::message::object_path(storagePath).filename();
123 if (id.empty())
124 {
125 continue;
126 }
127
128 nlohmann::json::object_t storage;
129 storage["@odata.id"] =
130 boost::urls::format("/redfish/v1/Systems/{}/Storage/{}",
131 BMCWEB_REDFISH_SYSTEM_URI_NAME, id);
132 storages.emplace_back(std::move(storage));
133 }
134 asyncResp->res.jsonValue["Links"]["Storage@odata.count"] =
135 storages.size();
136 asyncResp->res.jsonValue["Links"]["Storage"] = std::move(storages);
137 });
Willy Tu5e577bc2022-07-26 00:41:55 +0000138}
139
140/**
Gunnar Millsbeeca0a2019-02-14 16:30:45 -0600141 * @brief Retrieves chassis state properties over dbus
142 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700143 * @param[in] asyncResp - Shared pointer for completing asynchronous calls.
Gunnar Millsbeeca0a2019-02-14 16:30:45 -0600144 *
145 * @return None.
146 */
Ed Tanousac106bf2023-06-07 09:24:59 -0700147inline void getChassisState(std::shared_ptr<bmcweb::AsyncResp> asyncResp)
Gunnar Millsbeeca0a2019-02-14 16:30:45 -0600148{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700149 // crow::connections::systemBus->async_method_call(
Ed Tanousdeae6a72024-11-11 21:58:57 -0800150 dbus::utility::getProperty<std::string>(
151 "xyz.openbmc_project.State.Chassis",
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700152 "/xyz/openbmc_project/state/chassis0",
153 "xyz.openbmc_project.State.Chassis", "CurrentPowerState",
Ed Tanousac106bf2023-06-07 09:24:59 -0700154 [asyncResp{std::move(asyncResp)}](const boost::system::error_code& ec,
155 const std::string& chassisState) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400156 if (ec)
Gunnar Millsbeeca0a2019-02-14 16:30:45 -0600157 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400158 if (ec == boost::system::errc::host_unreachable)
159 {
160 // Service not available, no error, just don't return
161 // chassis state info
162 BMCWEB_LOG_DEBUG("Service not available {}", ec);
163 return;
164 }
165 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
166 messages::internalError(asyncResp->res);
Gunnar Millsbeeca0a2019-02-14 16:30:45 -0600167 return;
168 }
169
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400170 BMCWEB_LOG_DEBUG("Chassis state: {}", chassisState);
171 // Verify Chassis State
172 if (chassisState ==
173 "xyz.openbmc_project.State.Chassis.PowerState.On")
174 {
175 asyncResp->res.jsonValue["PowerState"] =
176 resource::PowerState::On;
177 asyncResp->res.jsonValue["Status"]["State"] =
178 resource::State::Enabled;
179 }
180 else if (chassisState ==
181 "xyz.openbmc_project.State.Chassis.PowerState.Off")
182 {
183 asyncResp->res.jsonValue["PowerState"] =
184 resource::PowerState::Off;
185 asyncResp->res.jsonValue["Status"]["State"] =
186 resource::State::StandbyOffline;
187 }
188 });
Gunnar Millsbeeca0a2019-02-14 16:30:45 -0600189}
190
Qiang XUc1819422019-02-27 13:51:32 +0800191/**
192 * Retrieves physical security properties over dbus
193 */
Chau Ly7164bc62023-10-15 14:55:30 +0000194inline void handlePhysicalSecurityGetSubTree(
195 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
196 const boost::system::error_code& ec,
197 const dbus::utility::MapperGetSubTreeResponse& subtree)
Qiang XUc1819422019-02-27 13:51:32 +0800198{
Chau Ly7164bc62023-10-15 14:55:30 +0000199 if (ec)
200 {
201 // do not add err msg in redfish response, because this is not
202 // mandatory property
203 BMCWEB_LOG_INFO("DBUS error: no matched iface {}", ec);
204 return;
205 }
206 // Iterate over all retrieved ObjectPaths.
207 for (const auto& object : subtree)
208 {
209 if (!object.second.empty())
Ed Tanous002d39b2022-05-31 08:59:27 -0700210 {
Ed Tanous89144a32024-04-08 17:27:04 -0700211 const auto& service = object.second.front();
Chau Ly7164bc62023-10-15 14:55:30 +0000212
213 BMCWEB_LOG_DEBUG("Get intrusion status by service ");
214
Ed Tanousdeae6a72024-11-11 21:58:57 -0800215 dbus::utility::getProperty<std::string>(
216 service.first, object.first,
Chau Ly7164bc62023-10-15 14:55:30 +0000217 "xyz.openbmc_project.Chassis.Intrusion", "Status",
218 [asyncResp](const boost::system::error_code& ec1,
219 const std::string& value) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400220 if (ec1)
221 {
222 // do not add err msg in redfish response, because this
223 // is not
224 // mandatory property
225 BMCWEB_LOG_ERROR("DBUS response error {}", ec1);
226 return;
227 }
228 asyncResp->res.jsonValue["PhysicalSecurity"]
229 ["IntrusionSensorNumber"] = 1;
230 asyncResp->res
231 .jsonValue["PhysicalSecurity"]["IntrusionSensor"] =
232 value;
233 });
Chau Ly7164bc62023-10-15 14:55:30 +0000234
Ed Tanous002d39b2022-05-31 08:59:27 -0700235 return;
236 }
Chau Ly7164bc62023-10-15 14:55:30 +0000237 }
Qiang XUc1819422019-02-27 13:51:32 +0800238}
239
Nan Zhoucf7eba02022-07-21 23:53:20 +0000240inline void handleChassisCollectionGet(
241 App& app, const crow::Request& req,
242 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
243{
244 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
245 {
246 return;
247 }
248 asyncResp->res.jsonValue["@odata.type"] =
249 "#ChassisCollection.ChassisCollection";
250 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Chassis";
251 asyncResp->res.jsonValue["Name"] = "Chassis Collection";
252
George Liu7a1dbc42022-12-07 16:03:22 +0800253 constexpr std::array<std::string_view, 2> interfaces{
254 "xyz.openbmc_project.Inventory.Item.Board",
255 "xyz.openbmc_project.Inventory.Item.Chassis"};
Nan Zhoucf7eba02022-07-21 23:53:20 +0000256 collection_util::getCollectionMembers(
Lakshmi Yadlapati36b5f1e2023-09-26 23:53:28 -0500257 asyncResp, boost::urls::url("/redfish/v1/Chassis"), interfaces,
258 "/xyz/openbmc_project/inventory");
Nan Zhoucf7eba02022-07-21 23:53:20 +0000259}
260
Jie Yanga5617492021-06-29 12:59:14 -0700261inline void getChassisContainedBy(
262 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
263 const std::string& chassisId, const boost::system::error_code& ec,
Myung Bae28ee5632024-05-24 13:10:04 -0500264 const dbus::utility::MapperGetSubTreePathsResponse& upstreamChassisPaths)
Jie Yanga5617492021-06-29 12:59:14 -0700265{
266 if (ec)
267 {
268 if (ec.value() != EBADR)
269 {
Ed Tanous62598e32023-07-17 17:06:25 -0700270 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Jie Yanga5617492021-06-29 12:59:14 -0700271 messages::internalError(asyncResp->res);
272 }
273 return;
274 }
275 if (upstreamChassisPaths.empty())
276 {
277 return;
278 }
279 if (upstreamChassisPaths.size() > 1)
280 {
Ed Tanous8ece0e42024-01-02 13:16:50 -0800281 BMCWEB_LOG_ERROR("{} is contained by multiple chassis", chassisId);
Jie Yanga5617492021-06-29 12:59:14 -0700282 messages::internalError(asyncResp->res);
283 return;
284 }
285
286 sdbusplus::message::object_path upstreamChassisPath(
287 upstreamChassisPaths[0]);
288 std::string upstreamChassis = upstreamChassisPath.filename();
289 if (upstreamChassis.empty())
290 {
Ed Tanous62598e32023-07-17 17:06:25 -0700291 BMCWEB_LOG_WARNING("Malformed upstream Chassis path {} on {}",
292 upstreamChassisPath.str, chassisId);
Jie Yanga5617492021-06-29 12:59:14 -0700293 return;
294 }
295
296 asyncResp->res.jsonValue["Links"]["ContainedBy"]["@odata.id"] =
297 boost::urls::format("/redfish/v1/Chassis/{}", upstreamChassis);
298}
299
300inline void getChassisContains(
301 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
302 const std::string& chassisId, const boost::system::error_code& ec,
Myung Bae28ee5632024-05-24 13:10:04 -0500303 const dbus::utility::MapperGetSubTreePathsResponse& downstreamChassisPaths)
Jie Yanga5617492021-06-29 12:59:14 -0700304{
305 if (ec)
306 {
307 if (ec.value() != EBADR)
308 {
Ed Tanous62598e32023-07-17 17:06:25 -0700309 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Jie Yanga5617492021-06-29 12:59:14 -0700310 messages::internalError(asyncResp->res);
311 }
312 return;
313 }
314 if (downstreamChassisPaths.empty())
315 {
316 return;
317 }
318 nlohmann::json& jValue = asyncResp->res.jsonValue["Links"]["Contains"];
319 if (!jValue.is_array())
320 {
321 // Create the array if it was empty
322 jValue = nlohmann::json::array();
323 }
324 for (const auto& p : downstreamChassisPaths)
325 {
326 sdbusplus::message::object_path downstreamChassisPath(p);
327 std::string downstreamChassis = downstreamChassisPath.filename();
328 if (downstreamChassis.empty())
329 {
Ed Tanous62598e32023-07-17 17:06:25 -0700330 BMCWEB_LOG_WARNING("Malformed downstream Chassis path {} on {}",
331 downstreamChassisPath.str, chassisId);
Jie Yanga5617492021-06-29 12:59:14 -0700332 continue;
333 }
334 nlohmann::json link;
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400335 link["@odata.id"] =
336 boost::urls::format("/redfish/v1/Chassis/{}", downstreamChassis);
Jie Yanga5617492021-06-29 12:59:14 -0700337 jValue.push_back(std::move(link));
338 }
339 asyncResp->res.jsonValue["Links"]["Contains@odata.count"] = jValue.size();
340}
341
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400342inline void getChassisConnectivity(
343 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
344 const std::string& chassisId, const std::string& chassisPath)
Jie Yanga5617492021-06-29 12:59:14 -0700345{
Ed Tanous62598e32023-07-17 17:06:25 -0700346 BMCWEB_LOG_DEBUG("Get chassis connectivity");
Jie Yanga5617492021-06-29 12:59:14 -0700347
Myung Bae28ee5632024-05-24 13:10:04 -0500348 constexpr std::array<std::string_view, 2> interfaces{
349 "xyz.openbmc_project.Inventory.Item.Board",
350 "xyz.openbmc_project.Inventory.Item.Chassis"};
351
352 dbus::utility::getAssociatedSubTreePaths(
Jie Yanga5617492021-06-29 12:59:14 -0700353 chassisPath + "/contained_by",
Myung Bae28ee5632024-05-24 13:10:04 -0500354 sdbusplus::message::object_path("/xyz/openbmc_project/inventory"), 0,
355 interfaces,
Jie Yanga5617492021-06-29 12:59:14 -0700356 std::bind_front(getChassisContainedBy, asyncResp, chassisId));
357
Myung Bae28ee5632024-05-24 13:10:04 -0500358 dbus::utility::getAssociatedSubTreePaths(
Jie Yanga5617492021-06-29 12:59:14 -0700359 chassisPath + "/containing",
Myung Bae28ee5632024-05-24 13:10:04 -0500360 sdbusplus::message::object_path("/xyz/openbmc_project/inventory"), 0,
361 interfaces, std::bind_front(getChassisContains, asyncResp, chassisId));
Jie Yanga5617492021-06-29 12:59:14 -0700362}
363
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100364/**
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100365 * ChassisCollection derived class for delivering Chassis Collection Schema
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700366 * Functions triggers appropriate requests on DBus
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100367 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700368inline void requestRoutesChassisCollection(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700369{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700370 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/")
Ed Tanoused398212021-06-09 17:05:54 -0700371 .privileges(redfish::privileges::getChassisCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700372 .methods(boost::beast::http::verb::get)(
Nan Zhoucf7eba02022-07-21 23:53:20 +0000373 std::bind_front(handleChassisCollectionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700374}
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100375
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400376inline void getChassisLocationCode(
377 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
378 const std::string& connectionName, const std::string& path)
Willy Tu308f70c2021-09-28 20:24:52 -0700379{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800380 dbus::utility::getProperty<std::string>(
381 connectionName, path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700382 "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800383 [asyncResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700384 const std::string& property) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400385 if (ec)
386 {
387 BMCWEB_LOG_ERROR("DBUS response error for Location");
388 messages::internalError(asyncResp->res);
389 return;
390 }
Willy Tu308f70c2021-09-28 20:24:52 -0700391
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400392 asyncResp->res
393 .jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
394 property;
395 });
Willy Tu308f70c2021-09-28 20:24:52 -0700396}
397
398inline void getChassisUUID(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
399 const std::string& connectionName,
400 const std::string& path)
401{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800402 dbus::utility::getProperty<std::string>(
403 connectionName, path, "xyz.openbmc_project.Common.UUID", "UUID",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800404 [asyncResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700405 const std::string& chassisUUID) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400406 if (ec)
407 {
408 BMCWEB_LOG_ERROR("DBUS response error for UUID");
409 messages::internalError(asyncResp->res);
410 return;
411 }
412 asyncResp->res.jsonValue["UUID"] = chassisUUID;
413 });
Willy Tu308f70c2021-09-28 20:24:52 -0700414}
415
Chau Ly7164bc62023-10-15 14:55:30 +0000416inline void handleDecoratorAssetProperties(
417 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
418 const std::string& chassisId, const std::string& path,
419 const dbus::utility::DBusPropertiesMap& propertiesList)
420{
421 const std::string* partNumber = nullptr;
422 const std::string* serialNumber = nullptr;
423 const std::string* manufacturer = nullptr;
424 const std::string* model = nullptr;
425 const std::string* sparePartNumber = nullptr;
426
427 const bool success = sdbusplus::unpackPropertiesNoThrow(
428 dbus_utils::UnpackErrorPrinter(), propertiesList, "PartNumber",
429 partNumber, "SerialNumber", serialNumber, "Manufacturer", manufacturer,
430 "Model", model, "SparePartNumber", sparePartNumber);
431
432 if (!success)
433 {
434 messages::internalError(asyncResp->res);
435 return;
436 }
437
438 if (partNumber != nullptr)
439 {
440 asyncResp->res.jsonValue["PartNumber"] = *partNumber;
441 }
442
443 if (serialNumber != nullptr)
444 {
445 asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
446 }
447
448 if (manufacturer != nullptr)
449 {
450 asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
451 }
452
453 if (model != nullptr)
454 {
455 asyncResp->res.jsonValue["Model"] = *model;
456 }
457
458 // SparePartNumber is optional on D-Bus
459 // so skip if it is empty
460 if (sparePartNumber != nullptr && !sparePartNumber->empty())
461 {
462 asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber;
463 }
464
465 asyncResp->res.jsonValue["Name"] = chassisId;
466 asyncResp->res.jsonValue["Id"] = chassisId;
Ed Tanous25b54db2024-04-17 15:40:31 -0700467
468 if constexpr (BMCWEB_REDFISH_ALLOW_DEPRECATED_POWER_THERMAL)
469 {
470 asyncResp->res.jsonValue["Thermal"]["@odata.id"] =
471 boost::urls::format("/redfish/v1/Chassis/{}/Thermal", chassisId);
472 // Power object
473 asyncResp->res.jsonValue["Power"]["@odata.id"] =
474 boost::urls::format("/redfish/v1/Chassis/{}/Power", chassisId);
475 }
476
477 if constexpr (BMCWEB_REDFISH_NEW_POWERSUBSYSTEM_THERMALSUBSYSTEM)
478 {
479 asyncResp->res.jsonValue["ThermalSubsystem"]["@odata.id"] =
480 boost::urls::format("/redfish/v1/Chassis/{}/ThermalSubsystem",
481 chassisId);
482 asyncResp->res.jsonValue["PowerSubsystem"]["@odata.id"] =
483 boost::urls::format("/redfish/v1/Chassis/{}/PowerSubsystem",
484 chassisId);
485 asyncResp->res.jsonValue["EnvironmentMetrics"]["@odata.id"] =
486 boost::urls::format("/redfish/v1/Chassis/{}/EnvironmentMetrics",
487 chassisId);
488 }
Chau Ly7164bc62023-10-15 14:55:30 +0000489 // SensorCollection
490 asyncResp->res.jsonValue["Sensors"]["@odata.id"] =
491 boost::urls::format("/redfish/v1/Chassis/{}/Sensors", chassisId);
Ed Tanous539d8c62024-06-19 14:38:27 -0700492 asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
Chau Ly7164bc62023-10-15 14:55:30 +0000493
494 nlohmann::json::array_t computerSystems;
495 nlohmann::json::object_t system;
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400496 system["@odata.id"] =
497 std::format("/redfish/v1/Systems/{}", BMCWEB_REDFISH_SYSTEM_URI_NAME);
Chau Ly7164bc62023-10-15 14:55:30 +0000498 computerSystems.emplace_back(std::move(system));
499 asyncResp->res.jsonValue["Links"]["ComputerSystems"] =
500 std::move(computerSystems);
501
502 nlohmann::json::array_t managedBy;
503 nlohmann::json::object_t manager;
Ed Tanous253f11b2024-05-16 09:38:31 -0700504 manager["@odata.id"] = boost::urls::format("/redfish/v1/Managers/{}",
505 BMCWEB_REDFISH_MANAGER_URI_NAME);
Chau Ly7164bc62023-10-15 14:55:30 +0000506 managedBy.emplace_back(std::move(manager));
507 asyncResp->res.jsonValue["Links"]["ManagedBy"] = std::move(managedBy);
508 getChassisState(asyncResp);
509 getStorageLink(asyncResp, path);
510}
511
Joseph-Jonathan Salzano2952f642024-11-19 12:00:06 -0700512inline void handleChassisProperties(
513 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
514 const dbus::utility::DBusPropertiesMap& propertiesList)
515{
516 const std::string* type = nullptr;
517
518 const bool success = sdbusplus::unpackPropertiesNoThrow(
519 dbus_utils::UnpackErrorPrinter(), propertiesList, "Type", type);
520
521 if (!success)
522 {
523 messages::internalError(asyncResp->res);
524 return;
525 }
526
Gunnar Mills19ea2862024-12-10 09:02:03 -0600527 // Chassis Type is a required property in Redfish
528 // If there is an error or some enum we don't support just sit it to Rack
529 // Mount
530 asyncResp->res.jsonValue["ChassisType"] = chassis::ChassisType::RackMount;
531
Joseph-Jonathan Salzano2952f642024-11-19 12:00:06 -0700532 if (type != nullptr)
533 {
534 auto chassisType = translateChassisTypeToRedfish(*type);
535 if (chassisType != chassis::ChassisType::Invalid)
536 {
537 asyncResp->res.jsonValue["ChassisType"] = chassisType;
538 }
539 }
Joseph-Jonathan Salzano2952f642024-11-19 12:00:06 -0700540}
541
Chau Ly7164bc62023-10-15 14:55:30 +0000542inline void handleChassisGetSubTree(
543 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
544 const std::string& chassisId, const boost::system::error_code& ec,
545 const dbus::utility::MapperGetSubTreeResponse& subtree)
546{
547 if (ec)
548 {
549 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
550 messages::internalError(asyncResp->res);
551 return;
552 }
553 // Iterate over all retrieved ObjectPaths.
554 for (const std::pair<
555 std::string,
556 std::vector<std::pair<std::string, std::vector<std::string>>>>&
557 object : subtree)
558 {
559 const std::string& path = object.first;
560 const std::vector<std::pair<std::string, std::vector<std::string>>>&
561 connectionNames = object.second;
562
563 sdbusplus::message::object_path objPath(path);
564 if (objPath.filename() != chassisId)
565 {
566 continue;
567 }
568
569 getChassisConnectivity(asyncResp, chassisId, path);
570
Chau Ly7164bc62023-10-15 14:55:30 +0000571 if (connectionNames.empty())
572 {
573 BMCWEB_LOG_ERROR("Got 0 Connection names");
574 continue;
575 }
576
577 asyncResp->res.jsonValue["@odata.type"] = "#Chassis.v1_22_0.Chassis";
578 asyncResp->res.jsonValue["@odata.id"] =
579 boost::urls::format("/redfish/v1/Chassis/{}", chassisId);
580 asyncResp->res.jsonValue["Name"] = "Chassis Collection";
Chau Ly7164bc62023-10-15 14:55:30 +0000581 asyncResp->res.jsonValue["Actions"]["#Chassis.Reset"]["target"] =
582 boost::urls::format("/redfish/v1/Chassis/{}/Actions/Chassis.Reset",
583 chassisId);
584 asyncResp->res
585 .jsonValue["Actions"]["#Chassis.Reset"]["@Redfish.ActionInfo"] =
586 boost::urls::format("/redfish/v1/Chassis/{}/ResetActionInfo",
587 chassisId);
Chau Ly7164bc62023-10-15 14:55:30 +0000588 dbus::utility::getAssociationEndPoints(
589 path + "/drive",
590 [asyncResp, chassisId](const boost::system::error_code& ec3,
591 const dbus::utility::MapperEndPoints& resp) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400592 if (ec3 || resp.empty())
593 {
594 return; // no drives = no failures
595 }
Chau Ly7164bc62023-10-15 14:55:30 +0000596
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400597 nlohmann::json reference;
598 reference["@odata.id"] = boost::urls::format(
599 "/redfish/v1/Chassis/{}/Drives", chassisId);
600 asyncResp->res.jsonValue["Drives"] = std::move(reference);
601 });
Chau Ly7164bc62023-10-15 14:55:30 +0000602
603 const std::string& connectionName = connectionNames[0].first;
604
605 const std::vector<std::string>& interfaces2 = connectionNames[0].second;
George Liue5ae9c12021-11-16 10:31:23 +0800606 const std::array<const char*, 3> hasIndicatorLed = {
607 "xyz.openbmc_project.Inventory.Item.Chassis",
Chau Ly7164bc62023-10-15 14:55:30 +0000608 "xyz.openbmc_project.Inventory.Item.Panel",
609 "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
610
611 const std::string assetTagInterface =
612 "xyz.openbmc_project.Inventory.Decorator.AssetTag";
613 const std::string replaceableInterface =
614 "xyz.openbmc_project.Inventory.Decorator.Replaceable";
Carson Labradob4d593f2024-02-16 22:34:32 +0000615 const std::string revisionInterface =
616 "xyz.openbmc_project.Inventory.Decorator.Revision";
Chau Ly7164bc62023-10-15 14:55:30 +0000617 for (const auto& interface : interfaces2)
618 {
619 if (interface == assetTagInterface)
620 {
Ed Tanousdeae6a72024-11-11 21:58:57 -0800621 dbus::utility::getProperty<std::string>(
622 connectionName, path, assetTagInterface, "AssetTag",
Chau Ly7164bc62023-10-15 14:55:30 +0000623 [asyncResp, chassisId](const boost::system::error_code& ec2,
624 const std::string& property) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400625 if (ec2)
626 {
627 BMCWEB_LOG_ERROR(
628 "DBus response error for AssetTag: {}", ec2);
629 messages::internalError(asyncResp->res);
630 return;
631 }
632 asyncResp->res.jsonValue["AssetTag"] = property;
633 });
Chau Ly7164bc62023-10-15 14:55:30 +0000634 }
635 else if (interface == replaceableInterface)
636 {
Ed Tanousdeae6a72024-11-11 21:58:57 -0800637 dbus::utility::getProperty<bool>(
638 connectionName, path, replaceableInterface, "HotPluggable",
Chau Ly7164bc62023-10-15 14:55:30 +0000639 [asyncResp, chassisId](const boost::system::error_code& ec2,
640 const bool property) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400641 if (ec2)
642 {
643 BMCWEB_LOG_ERROR(
644 "DBus response error for HotPluggable: {}",
645 ec2);
646 messages::internalError(asyncResp->res);
647 return;
648 }
649 asyncResp->res.jsonValue["HotPluggable"] = property;
650 });
Chau Ly7164bc62023-10-15 14:55:30 +0000651 }
Carson Labradob4d593f2024-02-16 22:34:32 +0000652 else if (interface == revisionInterface)
653 {
Ed Tanousdeae6a72024-11-11 21:58:57 -0800654 dbus::utility::getProperty<std::string>(
655 connectionName, path, revisionInterface, "Version",
Carson Labradob4d593f2024-02-16 22:34:32 +0000656 [asyncResp, chassisId](const boost::system::error_code& ec2,
657 const std::string& property) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400658 if (ec2)
659 {
660 BMCWEB_LOG_ERROR(
661 "DBus response error for Version: {}", ec2);
662 messages::internalError(asyncResp->res);
663 return;
664 }
665 asyncResp->res.jsonValue["Version"] = property;
666 });
Carson Labradob4d593f2024-02-16 22:34:32 +0000667 }
Chau Ly7164bc62023-10-15 14:55:30 +0000668 }
669
670 for (const char* interface : hasIndicatorLed)
671 {
672 if (std::ranges::find(interfaces2, interface) != interfaces2.end())
673 {
674 getIndicatorLedState(asyncResp);
675 getSystemLocationIndicatorActive(asyncResp);
676 break;
677 }
678 }
679
Ed Tanousdeae6a72024-11-11 21:58:57 -0800680 dbus::utility::getAllProperties(
Chau Ly7164bc62023-10-15 14:55:30 +0000681 *crow::connections::systemBus, connectionName, path,
682 "xyz.openbmc_project.Inventory.Decorator.Asset",
683 [asyncResp, chassisId,
684 path](const boost::system::error_code&,
685 const dbus::utility::DBusPropertiesMap& propertiesList) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400686 handleDecoratorAssetProperties(asyncResp, chassisId, path,
687 propertiesList);
688 });
Chau Ly7164bc62023-10-15 14:55:30 +0000689
Joseph-Jonathan Salzano2952f642024-11-19 12:00:06 -0700690 sdbusplus::asio::getAllProperties(
691 *crow::connections::systemBus, connectionName, path,
692 "xyz.openbmc_project.Inventory.Item.Chassis",
693 [asyncResp](
694 const boost::system::error_code&,
695 const dbus::utility::DBusPropertiesMap& propertiesList) {
696 handleChassisProperties(asyncResp, propertiesList);
697 });
698
Chau Ly7164bc62023-10-15 14:55:30 +0000699 for (const auto& interface : interfaces2)
700 {
701 if (interface == "xyz.openbmc_project.Common.UUID")
702 {
703 getChassisUUID(asyncResp, connectionName, path);
704 }
705 else if (interface ==
706 "xyz.openbmc_project.Inventory.Decorator.LocationCode")
707 {
708 getChassisLocationCode(asyncResp, connectionName, path);
709 }
710 }
711
712 return;
713 }
714
715 // Couldn't find an object with that name. return an error
716 messages::resourceNotFound(asyncResp->res, "Chassis", chassisId);
717}
718
Nan Zhoucf7eba02022-07-21 23:53:20 +0000719inline void
720 handleChassisGet(App& app, const crow::Request& req,
721 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
722 const std::string& chassisId)
723{
724 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
725 {
726 return;
727 }
George Liue99073f2022-12-09 11:06:16 +0800728 constexpr std::array<std::string_view, 2> interfaces = {
Nan Zhoucf7eba02022-07-21 23:53:20 +0000729 "xyz.openbmc_project.Inventory.Item.Board",
730 "xyz.openbmc_project.Inventory.Item.Chassis"};
731
George Liue99073f2022-12-09 11:06:16 +0800732 dbus::utility::getSubTree(
733 "/xyz/openbmc_project/inventory", 0, interfaces,
Chau Ly7164bc62023-10-15 14:55:30 +0000734 std::bind_front(handleChassisGetSubTree, asyncResp, chassisId));
Nan Zhoucf7eba02022-07-21 23:53:20 +0000735
Chau Ly7164bc62023-10-15 14:55:30 +0000736 constexpr std::array<std::string_view, 1> interfaces2 = {
737 "xyz.openbmc_project.Chassis.Intrusion"};
Nan Zhoucf7eba02022-07-21 23:53:20 +0000738
Chau Ly7164bc62023-10-15 14:55:30 +0000739 dbus::utility::getSubTree(
740 "/xyz/openbmc_project", 0, interfaces2,
741 std::bind_front(handlePhysicalSecurityGetSubTree, asyncResp));
Nan Zhoucf7eba02022-07-21 23:53:20 +0000742}
743
744inline void
745 handleChassisPatch(App& app, const crow::Request& req,
746 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
747 const std::string& param)
748{
749 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
750 {
751 return;
752 }
753 std::optional<bool> locationIndicatorActive;
754 std::optional<std::string> indicatorLed;
755
756 if (param.empty())
757 {
758 return;
759 }
760
Myung Baeafc474a2024-10-09 00:53:29 -0700761 if (!json_util::readJsonPatch( //
762 req, asyncResp->res, //
763 "IndicatorLED", indicatorLed, //
764 "LocationIndicatorActive", locationIndicatorActive //
765 ))
Nan Zhoucf7eba02022-07-21 23:53:20 +0000766 {
767 return;
768 }
769
770 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
771 if (!locationIndicatorActive && !indicatorLed)
772 {
773 return; // delete this when we support more patch properties
774 }
775 if (indicatorLed)
776 {
777 asyncResp->res.addHeader(
778 boost::beast::http::field::warning,
779 "299 - \"IndicatorLED is deprecated. Use LocationIndicatorActive instead.\"");
780 }
781
George Liue99073f2022-12-09 11:06:16 +0800782 constexpr std::array<std::string_view, 2> interfaces = {
Nan Zhoucf7eba02022-07-21 23:53:20 +0000783 "xyz.openbmc_project.Inventory.Item.Board",
784 "xyz.openbmc_project.Inventory.Item.Chassis"};
785
786 const std::string& chassisId = param;
787
George Liue99073f2022-12-09 11:06:16 +0800788 dbus::utility::getSubTree(
789 "/xyz/openbmc_project/inventory", 0, interfaces,
Nan Zhoucf7eba02022-07-21 23:53:20 +0000790 [asyncResp, chassisId, locationIndicatorActive,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800791 indicatorLed](const boost::system::error_code& ec,
Nan Zhoucf7eba02022-07-21 23:53:20 +0000792 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400793 if (ec)
Nan Zhoucf7eba02022-07-21 23:53:20 +0000794 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400795 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
796 messages::internalError(asyncResp->res);
797 return;
Nan Zhoucf7eba02022-07-21 23:53:20 +0000798 }
799
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400800 // Iterate over all retrieved ObjectPaths.
801 for (const std::pair<std::string,
802 std::vector<std::pair<
803 std::string, std::vector<std::string>>>>&
804 object : subtree)
Nan Zhoucf7eba02022-07-21 23:53:20 +0000805 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400806 const std::string& path = object.first;
807 const std::vector<
808 std::pair<std::string, std::vector<std::string>>>&
809 connectionNames = object.second;
810
811 sdbusplus::message::object_path objPath(path);
812 if (objPath.filename() != chassisId)
813 {
814 continue;
815 }
816
817 if (connectionNames.empty())
818 {
819 BMCWEB_LOG_ERROR("Got 0 Connection names");
820 continue;
821 }
822
823 const std::vector<std::string>& interfaces3 =
824 connectionNames[0].second;
825
826 const std::array<const char*, 3> hasIndicatorLed = {
827 "xyz.openbmc_project.Inventory.Item.Chassis",
828 "xyz.openbmc_project.Inventory.Item.Panel",
829 "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
830 bool indicatorChassis = false;
831 for (const char* interface : hasIndicatorLed)
832 {
833 if (std::ranges::find(interfaces3, interface) !=
834 interfaces3.end())
835 {
836 indicatorChassis = true;
837 break;
838 }
839 }
840 if (locationIndicatorActive)
841 {
842 if (indicatorChassis)
843 {
844 setSystemLocationIndicatorActive(
845 asyncResp, *locationIndicatorActive);
846 }
847 else
848 {
849 messages::propertyUnknown(asyncResp->res,
850 "LocationIndicatorActive");
851 }
852 }
853 if (indicatorLed)
854 {
855 if (indicatorChassis)
856 {
857 setIndicatorLedState(asyncResp, *indicatorLed);
858 }
859 else
860 {
861 messages::propertyUnknown(asyncResp->res,
862 "IndicatorLED");
863 }
864 }
865 return;
Nan Zhoucf7eba02022-07-21 23:53:20 +0000866 }
867
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400868 messages::resourceNotFound(asyncResp->res, "Chassis", chassisId);
869 });
Nan Zhoucf7eba02022-07-21 23:53:20 +0000870}
871
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100872/**
873 * Chassis override class for delivering Chassis Schema
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700874 * Functions triggers appropriate requests on DBus
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100875 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700876inline void requestRoutesChassis(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700877{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700878 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700879 .privileges(redfish::privileges::getChassis)
Ed Tanous002d39b2022-05-31 08:59:27 -0700880 .methods(boost::beast::http::verb::get)(
Nan Zhoucf7eba02022-07-21 23:53:20 +0000881 std::bind_front(handleChassisGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700882
883 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700884 .privileges(redfish::privileges::patchChassis)
Ed Tanous002d39b2022-05-31 08:59:27 -0700885 .methods(boost::beast::http::verb::patch)(
Nan Zhoucf7eba02022-07-21 23:53:20 +0000886 std::bind_front(handleChassisPatch, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700887}
P.K. Leedd99e042020-06-17 19:43:16 +0800888
zhanghch058d1b46d2021-04-01 11:18:24 +0800889inline void
890 doChassisPowerCycle(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
P.K. Leedd99e042020-06-17 19:43:16 +0800891{
George Liu7a1dbc42022-12-07 16:03:22 +0800892 constexpr std::array<std::string_view, 1> interfaces = {
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700893 "xyz.openbmc_project.State.Chassis"};
894
895 // Use mapper to get subtree paths.
George Liu7a1dbc42022-12-07 16:03:22 +0800896 dbus::utility::getSubTreePaths(
897 "/", 0, interfaces,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800898 [asyncResp](
George Liu7a1dbc42022-12-07 16:03:22 +0800899 const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800900 const dbus::utility::MapperGetSubTreePathsResponse& chassisList) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400901 if (ec)
902 {
903 BMCWEB_LOG_ERROR("[mapper] Bad D-Bus request error: {}", ec);
904 messages::internalError(asyncResp->res);
905 return;
906 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700907
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400908 const char* processName = "xyz.openbmc_project.State.Chassis";
909 const char* interfaceName = "xyz.openbmc_project.State.Chassis";
910 const char* destProperty = "RequestedPowerTransition";
911 const std::string propertyValue =
912 "xyz.openbmc_project.State.Chassis.Transition.PowerCycle";
913 std::string objectPath =
914 "/xyz/openbmc_project/state/chassis_system0";
Ed Tanous002d39b2022-05-31 08:59:27 -0700915
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400916 /* Look for system reset chassis path */
917 if ((std::ranges::find(chassisList, objectPath)) ==
918 chassisList.end())
919 {
920 /* We prefer to reset the full chassis_system, but if it doesn't
921 * exist on some platforms, fall back to a host-only power reset
922 */
923 objectPath = "/xyz/openbmc_project/state/chassis0";
924 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700925
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400926 setDbusProperty(asyncResp, "ResetType", processName, objectPath,
927 interfaceName, destProperty, propertyValue);
928 });
P.K. Leedd99e042020-06-17 19:43:16 +0800929}
930
Nan Zhoucf7eba02022-07-21 23:53:20 +0000931inline void handleChassisResetActionInfoPost(
932 App& app, const crow::Request& req,
933 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
934 const std::string& /*chassisId*/)
935{
936 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
937 {
938 return;
939 }
Ed Tanous62598e32023-07-17 17:06:25 -0700940 BMCWEB_LOG_DEBUG("Post Chassis Reset.");
Nan Zhoucf7eba02022-07-21 23:53:20 +0000941
942 std::string resetType;
943
944 if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", resetType))
945 {
946 return;
947 }
948
949 if (resetType != "PowerCycle")
950 {
Ed Tanous62598e32023-07-17 17:06:25 -0700951 BMCWEB_LOG_DEBUG("Invalid property value for ResetType: {}", resetType);
Nan Zhoucf7eba02022-07-21 23:53:20 +0000952 messages::actionParameterNotSupported(asyncResp->res, resetType,
953 "ResetType");
954
955 return;
956 }
957 doChassisPowerCycle(asyncResp);
958}
959
P.K. Leedd99e042020-06-17 19:43:16 +0800960/**
961 * ChassisResetAction class supports the POST method for the Reset
962 * action.
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700963 * Function handles POST method request.
964 * Analyzes POST body before sending Reset request data to D-Bus.
P.K. Leedd99e042020-06-17 19:43:16 +0800965 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700966
967inline void requestRoutesChassisResetAction(App& app)
P.K. Leedd99e042020-06-17 19:43:16 +0800968{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700969 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Actions/Chassis.Reset/")
Ed Tanoused398212021-06-09 17:05:54 -0700970 .privileges(redfish::privileges::postChassis)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700971 .methods(boost::beast::http::verb::post)(
Nan Zhoucf7eba02022-07-21 23:53:20 +0000972 std::bind_front(handleChassisResetActionInfoPost, std::ref(app)));
973}
P.K. Leedd99e042020-06-17 19:43:16 +0800974
Nan Zhoucf7eba02022-07-21 23:53:20 +0000975inline void handleChassisResetActionInfoGet(
976 App& app, const crow::Request& req,
977 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
978 const std::string& chassisId)
979{
980 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
981 {
982 return;
983 }
984 asyncResp->res.jsonValue["@odata.type"] = "#ActionInfo.v1_1_2.ActionInfo";
Ed Tanousef4c65b2023-04-24 15:28:50 -0700985 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
986 "/redfish/v1/Chassis/{}/ResetActionInfo", chassisId);
Nan Zhoucf7eba02022-07-21 23:53:20 +0000987 asyncResp->res.jsonValue["Name"] = "Reset Action Info";
P.K. Leedd99e042020-06-17 19:43:16 +0800988
Nan Zhoucf7eba02022-07-21 23:53:20 +0000989 asyncResp->res.jsonValue["Id"] = "ResetActionInfo";
990 nlohmann::json::array_t parameters;
991 nlohmann::json::object_t parameter;
992 parameter["Name"] = "ResetType";
993 parameter["Required"] = true;
Ed Tanous539d8c62024-06-19 14:38:27 -0700994 parameter["DataType"] = action_info::ParameterTypes::String;
Nan Zhoucf7eba02022-07-21 23:53:20 +0000995 nlohmann::json::array_t allowed;
Patrick Williamsad539542023-05-12 10:10:08 -0500996 allowed.emplace_back("PowerCycle");
Nan Zhoucf7eba02022-07-21 23:53:20 +0000997 parameter["AllowableValues"] = std::move(allowed);
Patrick Williamsad539542023-05-12 10:10:08 -0500998 parameters.emplace_back(std::move(parameter));
P.K. Leedd99e042020-06-17 19:43:16 +0800999
Nan Zhoucf7eba02022-07-21 23:53:20 +00001000 asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001001}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05301002
1003/**
1004 * ChassisResetActionInfo derived class for delivering Chassis
1005 * ResetType AllowableValues using ResetInfo schema.
1006 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001007inline void requestRoutesChassisResetActionInfo(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05301008{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001009 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -07001010 .privileges(redfish::privileges::getActionInfo)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001011 .methods(boost::beast::http::verb::get)(
Nan Zhoucf7eba02022-07-21 23:53:20 +00001012 std::bind_front(handleChassisResetActionInfoGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07001013}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05301014
Ed Tanous1abe55e2018-09-05 08:30:59 -07001015} // namespace redfish