blob: 32eb29b138db62151d09a3b9eb5a5f2c851f19cd [file] [log] [blame]
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +01001/*
2// Copyright (c) 2018 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16#pragma once
17
Willy Tu13451e32023-05-24 16:08:18 -070018#include "bmcweb_config.h"
19
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080020#include "app.hpp"
George Liu7a1dbc42022-12-07 16:03:22 +080021#include "dbus_utility.hpp"
James Feistb49ac872019-05-21 15:12:01 -070022#include "health.hpp"
James Feist1c8fba92019-12-20 15:12:07 -080023#include "led.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080024#include "query.hpp"
25#include "registries/privilege_registry.hpp"
26#include "utils/collection.hpp"
27#include "utils/dbus_utils.hpp"
Nan Zhoucf7eba02022-07-21 23:53:20 +000028#include "utils/json_utils.hpp"
Ed Tanous1abe55e2018-09-05 08:30:59 -070029
George Liue99073f2022-12-09 11:06:16 +080030#include <boost/system/error_code.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070031#include <boost/url/format.hpp>
Jonathan Doman1e1e5982021-06-11 09:36:17 -070032#include <sdbusplus/asio/property.hpp>
Krzysztof Grobelny86d89ed2022-08-29 14:49:20 +020033#include <sdbusplus/unpack_properties.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050034
George Liu7a1dbc42022-12-07 16:03:22 +080035#include <array>
36#include <string_view>
37
Ed Tanous1abe55e2018-09-05 08:30:59 -070038namespace redfish
39{
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010040
41/**
Gunnar Millsbeeca0a2019-02-14 16:30:45 -060042 * @brief Retrieves chassis state properties over dbus
43 *
44 * @param[in] aResp - Shared pointer for completing asynchronous calls.
45 *
46 * @return None.
47 */
zhanghch058d1b46d2021-04-01 11:18:24 +080048inline void getChassisState(std::shared_ptr<bmcweb::AsyncResp> aResp)
Gunnar Millsbeeca0a2019-02-14 16:30:45 -060049{
Jonathan Doman1e1e5982021-06-11 09:36:17 -070050 // crow::connections::systemBus->async_method_call(
51 sdbusplus::asio::getProperty<std::string>(
52 *crow::connections::systemBus, "xyz.openbmc_project.State.Chassis",
53 "/xyz/openbmc_project/state/chassis0",
54 "xyz.openbmc_project.State.Chassis", "CurrentPowerState",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -080055 [aResp{std::move(aResp)}](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -070056 const std::string& chassisState) {
Ed Tanous002d39b2022-05-31 08:59:27 -070057 if (ec)
58 {
59 if (ec == boost::system::errc::host_unreachable)
Gunnar Millsbeeca0a2019-02-14 16:30:45 -060060 {
Ed Tanous002d39b2022-05-31 08:59:27 -070061 // Service not available, no error, just don't return
62 // chassis state info
63 BMCWEB_LOG_DEBUG << "Service not available " << ec;
Gunnar Millsbeeca0a2019-02-14 16:30:45 -060064 return;
65 }
Ed Tanous002d39b2022-05-31 08:59:27 -070066 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
67 messages::internalError(aResp->res);
68 return;
69 }
Gunnar Millsbeeca0a2019-02-14 16:30:45 -060070
Ed Tanous002d39b2022-05-31 08:59:27 -070071 BMCWEB_LOG_DEBUG << "Chassis state: " << chassisState;
72 // Verify Chassis State
73 if (chassisState == "xyz.openbmc_project.State.Chassis.PowerState.On")
74 {
75 aResp->res.jsonValue["PowerState"] = "On";
76 aResp->res.jsonValue["Status"]["State"] = "Enabled";
77 }
78 else if (chassisState ==
79 "xyz.openbmc_project.State.Chassis.PowerState.Off")
80 {
81 aResp->res.jsonValue["PowerState"] = "Off";
82 aResp->res.jsonValue["Status"]["State"] = "StandbyOffline";
83 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -070084 });
Gunnar Millsbeeca0a2019-02-14 16:30:45 -060085}
86
zhanghch058d1b46d2021-04-01 11:18:24 +080087inline void getIntrusionByService(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous23a21a12020-07-25 04:45:05 +000088 const std::string& service,
89 const std::string& objPath)
Qiang XUc1819422019-02-27 13:51:32 +080090{
91 BMCWEB_LOG_DEBUG << "Get intrusion status by service \n";
92
Jonathan Doman1e1e5982021-06-11 09:36:17 -070093 sdbusplus::asio::getProperty<std::string>(
94 *crow::connections::systemBus, service, objPath,
95 "xyz.openbmc_project.Chassis.Intrusion", "Status",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -080096 [aResp{std::move(aResp)}](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -070097 const std::string& value) {
Ed Tanous002d39b2022-05-31 08:59:27 -070098 if (ec)
99 {
100 // do not add err msg in redfish response, because this is not
101 // mandatory property
102 BMCWEB_LOG_ERROR << "DBUS response error " << ec << "\n";
103 return;
104 }
Qiang XUc1819422019-02-27 13:51:32 +0800105
Ed Tanous002d39b2022-05-31 08:59:27 -0700106 aResp->res.jsonValue["PhysicalSecurity"]["IntrusionSensorNumber"] = 1;
107 aResp->res.jsonValue["PhysicalSecurity"]["IntrusionSensor"] = value;
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700108 });
Qiang XUc1819422019-02-27 13:51:32 +0800109}
110
111/**
112 * Retrieves physical security properties over dbus
113 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800114inline void getPhysicalSecurityData(std::shared_ptr<bmcweb::AsyncResp> aResp)
Qiang XUc1819422019-02-27 13:51:32 +0800115{
George Liue99073f2022-12-09 11:06:16 +0800116 constexpr std::array<std::string_view, 1> interfaces = {
117 "xyz.openbmc_project.Chassis.Intrusion"};
118 dbus::utility::getSubTree(
119 "/xyz/openbmc_project/Intrusion", 1, interfaces,
Qiang XUc1819422019-02-27 13:51:32 +0800120 [aResp{std::move(aResp)}](
George Liue99073f2022-12-09 11:06:16 +0800121 const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800122 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700123 if (ec)
124 {
125 // do not add err msg in redfish response, because this is not
126 // mandatory property
127 BMCWEB_LOG_INFO << "DBUS error: no matched iface " << ec << "\n";
128 return;
129 }
130 // Iterate over all retrieved ObjectPaths.
131 for (const auto& object : subtree)
132 {
Patrick Williams840a9ff2023-05-12 10:18:43 -0500133 if (!object.second.empty())
Qiang XUc1819422019-02-27 13:51:32 +0800134 {
Patrick Williams840a9ff2023-05-12 10:18:43 -0500135 const auto service = object.second.front();
Ed Tanous002d39b2022-05-31 08:59:27 -0700136 getIntrusionByService(aResp, service.first, object.first);
Qiang XUc1819422019-02-27 13:51:32 +0800137 return;
138 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700139 }
George Liue99073f2022-12-09 11:06:16 +0800140 });
Qiang XUc1819422019-02-27 13:51:32 +0800141}
142
Nan Zhoucf7eba02022-07-21 23:53:20 +0000143inline void handleChassisCollectionGet(
144 App& app, const crow::Request& req,
145 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
146{
147 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
148 {
149 return;
150 }
151 asyncResp->res.jsonValue["@odata.type"] =
152 "#ChassisCollection.ChassisCollection";
153 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Chassis";
154 asyncResp->res.jsonValue["Name"] = "Chassis Collection";
155
George Liu7a1dbc42022-12-07 16:03:22 +0800156 constexpr std::array<std::string_view, 2> interfaces{
157 "xyz.openbmc_project.Inventory.Item.Board",
158 "xyz.openbmc_project.Inventory.Item.Chassis"};
Nan Zhoucf7eba02022-07-21 23:53:20 +0000159 collection_util::getCollectionMembers(
George Liu7a1dbc42022-12-07 16:03:22 +0800160 asyncResp, boost::urls::url("/redfish/v1/Chassis"), interfaces);
Nan Zhoucf7eba02022-07-21 23:53:20 +0000161}
162
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100163/**
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100164 * ChassisCollection derived class for delivering Chassis Collection Schema
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700165 * Functions triggers appropriate requests on DBus
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100166 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700167inline void requestRoutesChassisCollection(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700168{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700169 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/")
Ed Tanoused398212021-06-09 17:05:54 -0700170 .privileges(redfish::privileges::getChassisCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700171 .methods(boost::beast::http::verb::get)(
Nan Zhoucf7eba02022-07-21 23:53:20 +0000172 std::bind_front(handleChassisCollectionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700173}
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100174
Willy Tu308f70c2021-09-28 20:24:52 -0700175inline void
176 getChassisLocationCode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
177 const std::string& connectionName,
178 const std::string& path)
179{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700180 sdbusplus::asio::getProperty<std::string>(
181 *crow::connections::systemBus, connectionName, path,
182 "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800183 [asyncResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700184 const std::string& property) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700185 if (ec)
186 {
187 BMCWEB_LOG_DEBUG << "DBUS response error for Location";
188 messages::internalError(asyncResp->res);
189 return;
190 }
Willy Tu308f70c2021-09-28 20:24:52 -0700191
Ed Tanous002d39b2022-05-31 08:59:27 -0700192 asyncResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
193 property;
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700194 });
Willy Tu308f70c2021-09-28 20:24:52 -0700195}
196
197inline void getChassisUUID(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
198 const std::string& connectionName,
199 const std::string& path)
200{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700201 sdbusplus::asio::getProperty<std::string>(
202 *crow::connections::systemBus, connectionName, path,
203 "xyz.openbmc_project.Common.UUID", "UUID",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800204 [asyncResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700205 const std::string& chassisUUID) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700206 if (ec)
207 {
208 BMCWEB_LOG_DEBUG << "DBUS response error for UUID";
209 messages::internalError(asyncResp->res);
210 return;
211 }
212 asyncResp->res.jsonValue["UUID"] = chassisUUID;
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700213 });
Willy Tu308f70c2021-09-28 20:24:52 -0700214}
215
Nan Zhoucf7eba02022-07-21 23:53:20 +0000216inline void
217 handleChassisGet(App& app, const crow::Request& req,
218 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
219 const std::string& chassisId)
220{
221 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
222 {
223 return;
224 }
George Liue99073f2022-12-09 11:06:16 +0800225 constexpr std::array<std::string_view, 2> interfaces = {
Nan Zhoucf7eba02022-07-21 23:53:20 +0000226 "xyz.openbmc_project.Inventory.Item.Board",
227 "xyz.openbmc_project.Inventory.Item.Chassis"};
228
George Liue99073f2022-12-09 11:06:16 +0800229 dbus::utility::getSubTree(
230 "/xyz/openbmc_project/inventory", 0, interfaces,
Nan Zhoucf7eba02022-07-21 23:53:20 +0000231 [asyncResp, chassisId(std::string(chassisId))](
George Liue99073f2022-12-09 11:06:16 +0800232 const boost::system::error_code& ec,
Nan Zhoucf7eba02022-07-21 23:53:20 +0000233 const dbus::utility::MapperGetSubTreeResponse& subtree) {
234 if (ec)
235 {
236 messages::internalError(asyncResp->res);
237 return;
238 }
239 // Iterate over all retrieved ObjectPaths.
240 for (const std::pair<
241 std::string,
242 std::vector<std::pair<std::string, std::vector<std::string>>>>&
243 object : subtree)
244 {
245 const std::string& path = object.first;
246 const std::vector<std::pair<std::string, std::vector<std::string>>>&
247 connectionNames = object.second;
248
249 sdbusplus::message::object_path objPath(path);
250 if (objPath.filename() != chassisId)
251 {
252 continue;
253 }
254
255 auto health = std::make_shared<HealthPopulate>(asyncResp);
256
Willy Tu13451e32023-05-24 16:08:18 -0700257 if constexpr (bmcwebEnableHealthPopulate)
258 {
259 dbus::utility::getAssociationEndPoints(
260 path + "/all_sensors",
261 [health](const boost::system::error_code& ec2,
262 const dbus::utility::MapperEndPoints& resp) {
263 if (ec2)
264 {
265 return; // no sensors = no failures
266 }
267 health->inventory = resp;
268 });
Nan Zhoucf7eba02022-07-21 23:53:20 +0000269
Willy Tu13451e32023-05-24 16:08:18 -0700270 health->populate();
271 }
Nan Zhoucf7eba02022-07-21 23:53:20 +0000272
273 if (connectionNames.empty())
274 {
275 BMCWEB_LOG_ERROR << "Got 0 Connection names";
276 continue;
277 }
278
279 asyncResp->res.jsonValue["@odata.type"] =
Logananth Sundararaj523d4862023-01-24 11:56:28 +0530280 "#Chassis.v1_22_0.Chassis";
Nan Zhoucf7eba02022-07-21 23:53:20 +0000281 asyncResp->res.jsonValue["@odata.id"] =
Ed Tanousef4c65b2023-04-24 15:28:50 -0700282 boost::urls::format("/redfish/v1/Chassis/{}", chassisId);
Nan Zhoucf7eba02022-07-21 23:53:20 +0000283 asyncResp->res.jsonValue["Name"] = "Chassis Collection";
284 asyncResp->res.jsonValue["ChassisType"] = "RackMount";
285 asyncResp->res.jsonValue["Actions"]["#Chassis.Reset"]["target"] =
Ed Tanousef4c65b2023-04-24 15:28:50 -0700286 boost::urls::format(
287 "/redfish/v1/Chassis/{}/Actions/Chassis.Reset", chassisId);
Nan Zhoucf7eba02022-07-21 23:53:20 +0000288 asyncResp->res
289 .jsonValue["Actions"]["#Chassis.Reset"]["@Redfish.ActionInfo"] =
Ed Tanousef4c65b2023-04-24 15:28:50 -0700290 boost::urls::format("/redfish/v1/Chassis/{}/ResetActionInfo",
291 chassisId);
Nan Zhoucf7eba02022-07-21 23:53:20 +0000292 asyncResp->res.jsonValue["PCIeDevices"]["@odata.id"] =
Ed Tanousef4c65b2023-04-24 15:28:50 -0700293 "/redfish/v1/Systems/system/PCIeDevices";
Nan Zhoucf7eba02022-07-21 23:53:20 +0000294
George Liu6c3e9452023-03-03 13:55:29 +0800295 dbus::utility::getAssociationEndPoints(
296 path + "/drive",
297 [asyncResp,
298 chassisId](const boost::system::error_code& ec3,
299 const dbus::utility::MapperEndPoints& resp) {
Nan Zhoucf7eba02022-07-21 23:53:20 +0000300 if (ec3 || resp.empty())
301 {
302 return; // no drives = no failures
303 }
304
305 nlohmann::json reference;
Ed Tanousef4c65b2023-04-24 15:28:50 -0700306 reference["@odata.id"] = boost::urls::format(
307 "/redfish/v1/Chassis/{}/Drives", chassisId);
Nan Zhoucf7eba02022-07-21 23:53:20 +0000308 asyncResp->res.jsonValue["Drives"] = std::move(reference);
309 });
310
311 const std::string& connectionName = connectionNames[0].first;
312
313 const std::vector<std::string>& interfaces2 =
314 connectionNames[0].second;
315 const std::array<const char*, 2> hasIndicatorLed = {
316 "xyz.openbmc_project.Inventory.Item.Panel",
317 "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
318
319 const std::string assetTagInterface =
320 "xyz.openbmc_project.Inventory.Decorator.AssetTag";
Logananth Sundararaj523d4862023-01-24 11:56:28 +0530321 const std::string replaceableInterface =
322 "xyz.openbmc_project.Inventory.Decorator.Replaceable";
323 for (const auto& interface : interfaces2)
Nan Zhoucf7eba02022-07-21 23:53:20 +0000324 {
Logananth Sundararaj523d4862023-01-24 11:56:28 +0530325 if (interface == assetTagInterface)
326 {
327 sdbusplus::asio::getProperty<std::string>(
328 *crow::connections::systemBus, connectionName, path,
329 assetTagInterface, "AssetTag",
330 [asyncResp,
331 chassisId](const boost::system::error_code& ec2,
332 const std::string& property) {
333 if (ec2)
334 {
335 BMCWEB_LOG_ERROR
336 << "DBus response error for AssetTag: " << ec2;
337 messages::internalError(asyncResp->res);
338 return;
339 }
340 asyncResp->res.jsonValue["AssetTag"] = property;
341 });
342 }
343 else if (interface == replaceableInterface)
344 {
345 sdbusplus::asio::getProperty<bool>(
346 *crow::connections::systemBus, connectionName, path,
347 replaceableInterface, "HotPluggable",
348 [asyncResp,
349 chassisId](const boost::system::error_code& ec2,
350 const bool property) {
351 if (ec2)
352 {
353 BMCWEB_LOG_ERROR
354 << "DBus response error for HotPluggable: "
355 << ec2;
356 messages::internalError(asyncResp->res);
357 return;
358 }
359 asyncResp->res.jsonValue["HotPluggable"] = property;
360 });
361 }
Nan Zhoucf7eba02022-07-21 23:53:20 +0000362 }
363
364 for (const char* interface : hasIndicatorLed)
365 {
366 if (std::find(interfaces2.begin(), interfaces2.end(),
367 interface) != interfaces2.end())
368 {
369 getIndicatorLedState(asyncResp);
370 getLocationIndicatorActive(asyncResp);
371 break;
372 }
373 }
374
Krzysztof Grobelny86d89ed2022-08-29 14:49:20 +0200375 sdbusplus::asio::getAllProperties(
376 *crow::connections::systemBus, connectionName, path,
377 "xyz.openbmc_project.Inventory.Decorator.Asset",
Nan Zhoucf7eba02022-07-21 23:53:20 +0000378 [asyncResp, chassisId(std::string(chassisId))](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800379 const boost::system::error_code& /*ec2*/,
Nan Zhoucf7eba02022-07-21 23:53:20 +0000380 const dbus::utility::DBusPropertiesMap& propertiesList) {
Krzysztof Grobelny86d89ed2022-08-29 14:49:20 +0200381 const std::string* partNumber = nullptr;
382 const std::string* serialNumber = nullptr;
383 const std::string* manufacturer = nullptr;
384 const std::string* model = nullptr;
385 const std::string* sparePartNumber = nullptr;
386
387 const bool success = sdbusplus::unpackPropertiesNoThrow(
388 dbus_utils::UnpackErrorPrinter(), propertiesList,
389 "PartNumber", partNumber, "SerialNumber", serialNumber,
390 "Manufacturer", manufacturer, "Model", model,
391 "SparePartNumber", sparePartNumber);
392
393 if (!success)
Nan Zhoucf7eba02022-07-21 23:53:20 +0000394 {
Krzysztof Grobelny86d89ed2022-08-29 14:49:20 +0200395 messages::internalError(asyncResp->res);
396 return;
Nan Zhoucf7eba02022-07-21 23:53:20 +0000397 }
Krzysztof Grobelny86d89ed2022-08-29 14:49:20 +0200398
399 if (partNumber != nullptr)
400 {
401 asyncResp->res.jsonValue["PartNumber"] = *partNumber;
402 }
403
404 if (serialNumber != nullptr)
405 {
406 asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
407 }
408
409 if (manufacturer != nullptr)
410 {
411 asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
412 }
413
414 if (model != nullptr)
415 {
416 asyncResp->res.jsonValue["Model"] = *model;
417 }
418
419 // SparePartNumber is optional on D-Bus
420 // so skip if it is empty
421 if (sparePartNumber != nullptr && !sparePartNumber->empty())
422 {
423 asyncResp->res.jsonValue["SparePartNumber"] =
424 *sparePartNumber;
425 }
426
Nan Zhoucf7eba02022-07-21 23:53:20 +0000427 asyncResp->res.jsonValue["Name"] = chassisId;
428 asyncResp->res.jsonValue["Id"] = chassisId;
429#ifdef BMCWEB_ALLOW_DEPRECATED_POWER_THERMAL
430 asyncResp->res.jsonValue["Thermal"]["@odata.id"] =
Ed Tanousef4c65b2023-04-24 15:28:50 -0700431 boost::urls::format("/redfish/v1/Chassis/{}/Thermal",
432 chassisId);
Nan Zhoucf7eba02022-07-21 23:53:20 +0000433 // Power object
434 asyncResp->res.jsonValue["Power"]["@odata.id"] =
Ed Tanousef4c65b2023-04-24 15:28:50 -0700435 boost::urls::format("/redfish/v1/Chassis/{}/Power",
436 chassisId);
Nan Zhoucf7eba02022-07-21 23:53:20 +0000437#endif
Xiaochao Ma29739632021-03-02 15:53:13 +0800438#ifdef BMCWEB_NEW_POWERSUBSYSTEM_THERMALSUBSYSTEM
439 asyncResp->res.jsonValue["ThermalSubsystem"]["@odata.id"] =
Ed Tanousef4c65b2023-04-24 15:28:50 -0700440 boost::urls::format(
441 "/redfish/v1/Chassis/{}/ThermalSubsystem", chassisId);
Chicago Duan77b36432021-02-05 15:48:26 +0800442 asyncResp->res.jsonValue["PowerSubsystem"]["@odata.id"] =
Ed Tanousef4c65b2023-04-24 15:28:50 -0700443 boost::urls::format("/redfish/v1/Chassis/{}/PowerSubsystem",
444 chassisId);
Albert Zhang4ca3ec32021-06-13 14:39:38 +0800445 asyncResp->res.jsonValue["EnvironmentMetrics"]["@odata.id"] =
Ed Tanousef4c65b2023-04-24 15:28:50 -0700446 boost::urls::format(
447 "/redfish/v1/Chassis/{}/EnvironmentMetrics", chassisId);
Xiaochao Ma29739632021-03-02 15:53:13 +0800448#endif
Nan Zhoucf7eba02022-07-21 23:53:20 +0000449 // SensorCollection
450 asyncResp->res.jsonValue["Sensors"]["@odata.id"] =
Ed Tanousef4c65b2023-04-24 15:28:50 -0700451 boost::urls::format("/redfish/v1/Chassis/{}/Sensors",
452 chassisId);
Nan Zhoucf7eba02022-07-21 23:53:20 +0000453 asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
454
455 nlohmann::json::array_t computerSystems;
456 nlohmann::json::object_t system;
457 system["@odata.id"] = "/redfish/v1/Systems/system";
Patrick Williamsad539542023-05-12 10:10:08 -0500458 computerSystems.emplace_back(std::move(system));
Nan Zhoucf7eba02022-07-21 23:53:20 +0000459 asyncResp->res.jsonValue["Links"]["ComputerSystems"] =
460 std::move(computerSystems);
461
462 nlohmann::json::array_t managedBy;
463 nlohmann::json::object_t manager;
464 manager["@odata.id"] = "/redfish/v1/Managers/bmc";
Patrick Williamsad539542023-05-12 10:10:08 -0500465 managedBy.emplace_back(std::move(manager));
Nan Zhoucf7eba02022-07-21 23:53:20 +0000466 asyncResp->res.jsonValue["Links"]["ManagedBy"] =
467 std::move(managedBy);
468 getChassisState(asyncResp);
Krzysztof Grobelny86d89ed2022-08-29 14:49:20 +0200469 });
Nan Zhoucf7eba02022-07-21 23:53:20 +0000470
471 for (const auto& interface : interfaces2)
472 {
473 if (interface == "xyz.openbmc_project.Common.UUID")
474 {
475 getChassisUUID(asyncResp, connectionName, path);
476 }
477 else if (interface ==
478 "xyz.openbmc_project.Inventory.Decorator.LocationCode")
479 {
480 getChassisLocationCode(asyncResp, connectionName, path);
481 }
482 }
483
484 return;
485 }
486
487 // Couldn't find an object with that name. return an error
Jiaqing Zhaod8a5d5d2022-08-05 16:21:51 +0800488 messages::resourceNotFound(asyncResp->res, "Chassis", chassisId);
George Liue99073f2022-12-09 11:06:16 +0800489 });
Nan Zhoucf7eba02022-07-21 23:53:20 +0000490
491 getPhysicalSecurityData(asyncResp);
492}
493
494inline void
495 handleChassisPatch(App& app, const crow::Request& req,
496 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
497 const std::string& param)
498{
499 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
500 {
501 return;
502 }
503 std::optional<bool> locationIndicatorActive;
504 std::optional<std::string> indicatorLed;
505
506 if (param.empty())
507 {
508 return;
509 }
510
511 if (!json_util::readJsonPatch(
512 req, asyncResp->res, "LocationIndicatorActive",
513 locationIndicatorActive, "IndicatorLED", indicatorLed))
514 {
515 return;
516 }
517
518 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
519 if (!locationIndicatorActive && !indicatorLed)
520 {
521 return; // delete this when we support more patch properties
522 }
523 if (indicatorLed)
524 {
525 asyncResp->res.addHeader(
526 boost::beast::http::field::warning,
527 "299 - \"IndicatorLED is deprecated. Use LocationIndicatorActive instead.\"");
528 }
529
George Liue99073f2022-12-09 11:06:16 +0800530 constexpr std::array<std::string_view, 2> interfaces = {
Nan Zhoucf7eba02022-07-21 23:53:20 +0000531 "xyz.openbmc_project.Inventory.Item.Board",
532 "xyz.openbmc_project.Inventory.Item.Chassis"};
533
534 const std::string& chassisId = param;
535
George Liue99073f2022-12-09 11:06:16 +0800536 dbus::utility::getSubTree(
537 "/xyz/openbmc_project/inventory", 0, interfaces,
Nan Zhoucf7eba02022-07-21 23:53:20 +0000538 [asyncResp, chassisId, locationIndicatorActive,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800539 indicatorLed](const boost::system::error_code& ec,
Nan Zhoucf7eba02022-07-21 23:53:20 +0000540 const dbus::utility::MapperGetSubTreeResponse& subtree) {
541 if (ec)
542 {
543 messages::internalError(asyncResp->res);
544 return;
545 }
546
547 // Iterate over all retrieved ObjectPaths.
548 for (const std::pair<
549 std::string,
550 std::vector<std::pair<std::string, std::vector<std::string>>>>&
551 object : subtree)
552 {
553 const std::string& path = object.first;
554 const std::vector<std::pair<std::string, std::vector<std::string>>>&
555 connectionNames = object.second;
556
557 sdbusplus::message::object_path objPath(path);
558 if (objPath.filename() != chassisId)
559 {
560 continue;
561 }
562
563 if (connectionNames.empty())
564 {
565 BMCWEB_LOG_ERROR << "Got 0 Connection names";
566 continue;
567 }
568
569 const std::vector<std::string>& interfaces3 =
570 connectionNames[0].second;
571
572 const std::array<const char*, 2> hasIndicatorLed = {
573 "xyz.openbmc_project.Inventory.Item.Panel",
574 "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
575 bool indicatorChassis = false;
576 for (const char* interface : hasIndicatorLed)
577 {
578 if (std::find(interfaces3.begin(), interfaces3.end(),
579 interface) != interfaces3.end())
580 {
581 indicatorChassis = true;
582 break;
583 }
584 }
585 if (locationIndicatorActive)
586 {
587 if (indicatorChassis)
588 {
589 setLocationIndicatorActive(asyncResp,
590 *locationIndicatorActive);
591 }
592 else
593 {
594 messages::propertyUnknown(asyncResp->res,
595 "LocationIndicatorActive");
596 }
597 }
598 if (indicatorLed)
599 {
600 if (indicatorChassis)
601 {
602 setIndicatorLedState(asyncResp, *indicatorLed);
603 }
604 else
605 {
606 messages::propertyUnknown(asyncResp->res, "IndicatorLED");
607 }
608 }
609 return;
610 }
611
Jiaqing Zhaod8a5d5d2022-08-05 16:21:51 +0800612 messages::resourceNotFound(asyncResp->res, "Chassis", chassisId);
George Liue99073f2022-12-09 11:06:16 +0800613 });
Nan Zhoucf7eba02022-07-21 23:53:20 +0000614}
615
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100616/**
617 * Chassis override class for delivering Chassis Schema
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700618 * Functions triggers appropriate requests on DBus
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100619 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700620inline void requestRoutesChassis(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700621{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700622 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700623 .privileges(redfish::privileges::getChassis)
Ed Tanous002d39b2022-05-31 08:59:27 -0700624 .methods(boost::beast::http::verb::get)(
Nan Zhoucf7eba02022-07-21 23:53:20 +0000625 std::bind_front(handleChassisGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700626
627 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700628 .privileges(redfish::privileges::patchChassis)
Ed Tanous002d39b2022-05-31 08:59:27 -0700629 .methods(boost::beast::http::verb::patch)(
Nan Zhoucf7eba02022-07-21 23:53:20 +0000630 std::bind_front(handleChassisPatch, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700631}
P.K. Leedd99e042020-06-17 19:43:16 +0800632
zhanghch058d1b46d2021-04-01 11:18:24 +0800633inline void
634 doChassisPowerCycle(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
P.K. Leedd99e042020-06-17 19:43:16 +0800635{
George Liu7a1dbc42022-12-07 16:03:22 +0800636 constexpr std::array<std::string_view, 1> interfaces = {
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700637 "xyz.openbmc_project.State.Chassis"};
638
639 // Use mapper to get subtree paths.
George Liu7a1dbc42022-12-07 16:03:22 +0800640 dbus::utility::getSubTreePaths(
641 "/", 0, interfaces,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800642 [asyncResp](
George Liu7a1dbc42022-12-07 16:03:22 +0800643 const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800644 const dbus::utility::MapperGetSubTreePathsResponse& chassisList) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700645 if (ec)
646 {
647 BMCWEB_LOG_DEBUG << "[mapper] Bad D-Bus request error: " << ec;
648 messages::internalError(asyncResp->res);
649 return;
650 }
651
652 const char* processName = "xyz.openbmc_project.State.Chassis";
653 const char* interfaceName = "xyz.openbmc_project.State.Chassis";
654 const char* destProperty = "RequestedPowerTransition";
655 const std::string propertyValue =
656 "xyz.openbmc_project.State.Chassis.Transition.PowerCycle";
657 std::string objectPath = "/xyz/openbmc_project/state/chassis_system0";
658
659 /* Look for system reset chassis path */
660 if ((std::find(chassisList.begin(), chassisList.end(), objectPath)) ==
661 chassisList.end())
662 {
663 /* We prefer to reset the full chassis_system, but if it doesn't
664 * exist on some platforms, fall back to a host-only power reset
665 */
666 objectPath = "/xyz/openbmc_project/state/chassis0";
667 }
668
669 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800670 [asyncResp](const boost::system::error_code& ec2) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700671 // Use "Set" method to set the property value.
Ed Tanous8a592812022-06-04 09:06:59 -0700672 if (ec2)
P.K. Leedd99e042020-06-17 19:43:16 +0800673 {
Ed Tanous8a592812022-06-04 09:06:59 -0700674 BMCWEB_LOG_DEBUG << "[Set] Bad D-Bus request error: " << ec2;
P.K. Leedd99e042020-06-17 19:43:16 +0800675 messages::internalError(asyncResp->res);
676 return;
677 }
678
Ed Tanous002d39b2022-05-31 08:59:27 -0700679 messages::success(asyncResp->res);
680 },
681 processName, objectPath, "org.freedesktop.DBus.Properties", "Set",
682 interfaceName, destProperty,
683 dbus::utility::DbusVariantType{propertyValue});
George Liu7a1dbc42022-12-07 16:03:22 +0800684 });
P.K. Leedd99e042020-06-17 19:43:16 +0800685}
686
Nan Zhoucf7eba02022-07-21 23:53:20 +0000687inline void handleChassisResetActionInfoPost(
688 App& app, const crow::Request& req,
689 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
690 const std::string& /*chassisId*/)
691{
692 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
693 {
694 return;
695 }
696 BMCWEB_LOG_DEBUG << "Post Chassis Reset.";
697
698 std::string resetType;
699
700 if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", resetType))
701 {
702 return;
703 }
704
705 if (resetType != "PowerCycle")
706 {
707 BMCWEB_LOG_DEBUG << "Invalid property value for ResetType: "
708 << resetType;
709 messages::actionParameterNotSupported(asyncResp->res, resetType,
710 "ResetType");
711
712 return;
713 }
714 doChassisPowerCycle(asyncResp);
715}
716
P.K. Leedd99e042020-06-17 19:43:16 +0800717/**
718 * ChassisResetAction class supports the POST method for the Reset
719 * action.
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700720 * Function handles POST method request.
721 * Analyzes POST body before sending Reset request data to D-Bus.
P.K. Leedd99e042020-06-17 19:43:16 +0800722 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700723
724inline void requestRoutesChassisResetAction(App& app)
P.K. Leedd99e042020-06-17 19:43:16 +0800725{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700726 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Actions/Chassis.Reset/")
Ed Tanoused398212021-06-09 17:05:54 -0700727 .privileges(redfish::privileges::postChassis)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700728 .methods(boost::beast::http::verb::post)(
Nan Zhoucf7eba02022-07-21 23:53:20 +0000729 std::bind_front(handleChassisResetActionInfoPost, std::ref(app)));
730}
P.K. Leedd99e042020-06-17 19:43:16 +0800731
Nan Zhoucf7eba02022-07-21 23:53:20 +0000732inline void handleChassisResetActionInfoGet(
733 App& app, const crow::Request& req,
734 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
735 const std::string& chassisId)
736{
737 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
738 {
739 return;
740 }
741 asyncResp->res.jsonValue["@odata.type"] = "#ActionInfo.v1_1_2.ActionInfo";
Ed Tanousef4c65b2023-04-24 15:28:50 -0700742 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
743 "/redfish/v1/Chassis/{}/ResetActionInfo", chassisId);
Nan Zhoucf7eba02022-07-21 23:53:20 +0000744 asyncResp->res.jsonValue["Name"] = "Reset Action Info";
P.K. Leedd99e042020-06-17 19:43:16 +0800745
Nan Zhoucf7eba02022-07-21 23:53:20 +0000746 asyncResp->res.jsonValue["Id"] = "ResetActionInfo";
747 nlohmann::json::array_t parameters;
748 nlohmann::json::object_t parameter;
749 parameter["Name"] = "ResetType";
750 parameter["Required"] = true;
751 parameter["DataType"] = "String";
752 nlohmann::json::array_t allowed;
Patrick Williamsad539542023-05-12 10:10:08 -0500753 allowed.emplace_back("PowerCycle");
Nan Zhoucf7eba02022-07-21 23:53:20 +0000754 parameter["AllowableValues"] = std::move(allowed);
Patrick Williamsad539542023-05-12 10:10:08 -0500755 parameters.emplace_back(std::move(parameter));
P.K. Leedd99e042020-06-17 19:43:16 +0800756
Nan Zhoucf7eba02022-07-21 23:53:20 +0000757 asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700758}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530759
760/**
761 * ChassisResetActionInfo derived class for delivering Chassis
762 * ResetType AllowableValues using ResetInfo schema.
763 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700764inline void requestRoutesChassisResetActionInfo(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530765{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700766 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -0700767 .privileges(redfish::privileges::getActionInfo)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700768 .methods(boost::beast::http::verb::get)(
Nan Zhoucf7eba02022-07-21 23:53:20 +0000769 std::bind_front(handleChassisResetActionInfoGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700770}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530771
Ed Tanous1abe55e2018-09-05 08:30:59 -0700772} // namespace redfish