blob: 1aa7b40bb664eb563778f8aed2f4564d0373c8c0 [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
James Feistb49ac872019-05-21 15:12:01 -070018#include "health.hpp"
James Feist1c8fba92019-12-20 15:12:07 -080019#include "led.hpp"
Ed Tanous1abe55e2018-09-05 08:30:59 -070020
John Edward Broadbent7e860f12021-04-08 15:57:16 -070021#include <app.hpp>
Ed Tanous168e20c2021-12-13 14:39:53 -080022#include <dbus_utility.hpp>
Ed Tanous45ca1b82022-03-25 13:07:27 -070023#include <query.hpp>
Ed Tanoused398212021-06-09 17:05:54 -070024#include <registries/privilege_registry.hpp>
Jonathan Doman1e1e5982021-06-11 09:36:17 -070025#include <sdbusplus/asio/property.hpp>
Gunnar Mills02f6ff12020-10-14 15:59:58 -050026#include <utils/collection.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050027
Ed Tanous1abe55e2018-09-05 08:30:59 -070028namespace redfish
29{
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010030
31/**
Gunnar Millsbeeca0a2019-02-14 16:30:45 -060032 * @brief Retrieves chassis state properties over dbus
33 *
34 * @param[in] aResp - Shared pointer for completing asynchronous calls.
35 *
36 * @return None.
37 */
zhanghch058d1b46d2021-04-01 11:18:24 +080038inline void getChassisState(std::shared_ptr<bmcweb::AsyncResp> aResp)
Gunnar Millsbeeca0a2019-02-14 16:30:45 -060039{
Jonathan Doman1e1e5982021-06-11 09:36:17 -070040 // crow::connections::systemBus->async_method_call(
41 sdbusplus::asio::getProperty<std::string>(
42 *crow::connections::systemBus, "xyz.openbmc_project.State.Chassis",
43 "/xyz/openbmc_project/state/chassis0",
44 "xyz.openbmc_project.State.Chassis", "CurrentPowerState",
45 [aResp{std::move(aResp)}](const boost::system::error_code ec,
46 const std::string& chassisState) {
Gunnar Millsbeeca0a2019-02-14 16:30:45 -060047 if (ec)
48 {
Carson Labradoa6e5e0a2022-02-15 00:26:03 +000049 if (ec == boost::system::errc::host_unreachable)
50 {
51 // Service not available, no error, just don't return
52 // chassis state info
53 BMCWEB_LOG_DEBUG << "Service not available " << ec;
54 return;
55 }
Gunnar Millsbeeca0a2019-02-14 16:30:45 -060056 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
57 messages::internalError(aResp->res);
58 return;
59 }
60
Jonathan Doman1e1e5982021-06-11 09:36:17 -070061 BMCWEB_LOG_DEBUG << "Chassis state: " << chassisState;
62 // Verify Chassis State
63 if (chassisState ==
64 "xyz.openbmc_project.State.Chassis.PowerState.On")
Gunnar Millsbeeca0a2019-02-14 16:30:45 -060065 {
Jonathan Doman1e1e5982021-06-11 09:36:17 -070066 aResp->res.jsonValue["PowerState"] = "On";
67 aResp->res.jsonValue["Status"]["State"] = "Enabled";
Gunnar Millsbeeca0a2019-02-14 16:30:45 -060068 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -070069 else if (chassisState ==
70 "xyz.openbmc_project.State.Chassis.PowerState.Off")
71 {
72 aResp->res.jsonValue["PowerState"] = "Off";
73 aResp->res.jsonValue["Status"]["State"] = "StandbyOffline";
74 }
75 });
Gunnar Millsbeeca0a2019-02-14 16:30:45 -060076}
77
zhanghch058d1b46d2021-04-01 11:18:24 +080078inline void getIntrusionByService(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous23a21a12020-07-25 04:45:05 +000079 const std::string& service,
80 const std::string& objPath)
Qiang XUc1819422019-02-27 13:51:32 +080081{
82 BMCWEB_LOG_DEBUG << "Get intrusion status by service \n";
83
Jonathan Doman1e1e5982021-06-11 09:36:17 -070084 sdbusplus::asio::getProperty<std::string>(
85 *crow::connections::systemBus, service, objPath,
86 "xyz.openbmc_project.Chassis.Intrusion", "Status",
Qiang XUc1819422019-02-27 13:51:32 +080087 [aResp{std::move(aResp)}](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -070088 const std::string& value) {
Qiang XUc1819422019-02-27 13:51:32 +080089 if (ec)
90 {
Gunnar Mills4e0453b2020-07-08 14:00:30 -050091 // do not add err msg in redfish response, because this is not
Qiang XUc1819422019-02-27 13:51:32 +080092 // mandatory property
93 BMCWEB_LOG_ERROR << "DBUS response error " << ec << "\n";
94 return;
95 }
96
Ed Tanous14766872022-03-15 10:44:42 -070097 aResp->res.jsonValue["PhysicalSecurity"]["IntrusionSensorNumber"] =
98 1;
99 aResp->res.jsonValue["PhysicalSecurity"]["IntrusionSensor"] = value;
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700100 });
Qiang XUc1819422019-02-27 13:51:32 +0800101}
102
103/**
104 * Retrieves physical security properties over dbus
105 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800106inline void getPhysicalSecurityData(std::shared_ptr<bmcweb::AsyncResp> aResp)
Qiang XUc1819422019-02-27 13:51:32 +0800107{
108 crow::connections::systemBus->async_method_call(
109 [aResp{std::move(aResp)}](
110 const boost::system::error_code ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800111 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Qiang XUc1819422019-02-27 13:51:32 +0800112 if (ec)
113 {
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500114 // do not add err msg in redfish response, because this is not
Qiang XUc1819422019-02-27 13:51:32 +0800115 // mandatory property
Andrew Geissler54fbf172021-11-11 15:59:30 -0600116 BMCWEB_LOG_INFO << "DBUS error: no matched iface " << ec
117 << "\n";
Qiang XUc1819422019-02-27 13:51:32 +0800118 return;
119 }
120 // Iterate over all retrieved ObjectPaths.
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500121 for (const auto& object : subtree)
Qiang XUc1819422019-02-27 13:51:32 +0800122 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500123 for (const auto& service : object.second)
Qiang XUc1819422019-02-27 13:51:32 +0800124 {
125 getIntrusionByService(aResp, service.first, object.first);
126 return;
127 }
128 }
129 },
130 "xyz.openbmc_project.ObjectMapper",
131 "/xyz/openbmc_project/object_mapper",
132 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous271584a2019-07-09 16:24:22 -0700133 "/xyz/openbmc_project/Intrusion", 1,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500134 std::array<const char*, 1>{"xyz.openbmc_project.Chassis.Intrusion"});
Qiang XUc1819422019-02-27 13:51:32 +0800135}
136
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100137/**
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100138 * ChassisCollection derived class for delivering Chassis Collection Schema
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700139 * Functions triggers appropriate requests on DBus
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100140 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700141inline void requestRoutesChassisCollection(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700142{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700143 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/")
Ed Tanoused398212021-06-09 17:05:54 -0700144 .privileges(redfish::privileges::getChassisCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700145 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700146 [&app](const crow::Request& req,
147 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
148 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
149 {
150 return;
151 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700152 asyncResp->res.jsonValue["@odata.type"] =
153 "#ChassisCollection.ChassisCollection";
154 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Chassis";
155 asyncResp->res.jsonValue["Name"] = "Chassis Collection";
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100156
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700157 collection_util::getCollectionMembers(
158 asyncResp, "/redfish/v1/Chassis",
159 {"xyz.openbmc_project.Inventory.Item.Board",
160 "xyz.openbmc_project.Inventory.Item.Chassis"});
161 });
162}
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100163
Willy Tu308f70c2021-09-28 20:24:52 -0700164inline void
165 getChassisLocationCode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
166 const std::string& connectionName,
167 const std::string& path)
168{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700169 sdbusplus::asio::getProperty<std::string>(
170 *crow::connections::systemBus, connectionName, path,
171 "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode",
Willy Tu308f70c2021-09-28 20:24:52 -0700172 [asyncResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700173 const std::string& property) {
Willy Tu308f70c2021-09-28 20:24:52 -0700174 if (ec)
175 {
George Liu0fda0f12021-11-16 10:06:17 +0800176 BMCWEB_LOG_DEBUG << "DBUS response error for Location";
Willy Tu308f70c2021-09-28 20:24:52 -0700177 messages::internalError(asyncResp->res);
178 return;
179 }
180
Willy Tu308f70c2021-09-28 20:24:52 -0700181 asyncResp->res
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700182 .jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
183 property;
184 });
Willy Tu308f70c2021-09-28 20:24:52 -0700185}
186
187inline void getChassisUUID(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
188 const std::string& connectionName,
189 const std::string& path)
190{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700191 sdbusplus::asio::getProperty<std::string>(
192 *crow::connections::systemBus, connectionName, path,
193 "xyz.openbmc_project.Common.UUID", "UUID",
Willy Tu308f70c2021-09-28 20:24:52 -0700194 [asyncResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700195 const std::string& chassisUUID) {
Willy Tu308f70c2021-09-28 20:24:52 -0700196 if (ec)
197 {
George Liu0fda0f12021-11-16 10:06:17 +0800198 BMCWEB_LOG_DEBUG << "DBUS response error for UUID";
Willy Tu308f70c2021-09-28 20:24:52 -0700199 messages::internalError(asyncResp->res);
200 return;
201 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700202 asyncResp->res.jsonValue["UUID"] = chassisUUID;
203 });
Willy Tu308f70c2021-09-28 20:24:52 -0700204}
205
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100206/**
207 * Chassis override class for delivering Chassis Schema
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700208 * Functions triggers appropriate requests on DBus
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100209 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700210inline void requestRoutesChassis(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700211{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700212 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700213 .privileges(redfish::privileges::getChassis)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700214 .methods(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700215 boost::beast::http::verb::
216 get)([&app](const crow::Request& req,
217 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
218 const std::string& chassisId) {
219 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
220 {
221 return;
222 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700223 const std::array<const char*, 2> interfaces = {
224 "xyz.openbmc_project.Inventory.Item.Board",
225 "xyz.openbmc_project.Inventory.Item.Chassis"};
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100226
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700227 crow::connections::systemBus->async_method_call(
228 [asyncResp, chassisId(std::string(chassisId))](
229 const boost::system::error_code ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800230 const dbus::utility::MapperGetSubTreeResponse& subtree) {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700231 if (ec)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700232 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700233 messages::internalError(asyncResp->res);
234 return;
Ed Tanousdaf36e22018-04-20 16:01:36 -0700235 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700236 // Iterate over all retrieved ObjectPaths.
237 for (const std::pair<
238 std::string,
239 std::vector<std::pair<std::string,
240 std::vector<std::string>>>>&
241 object : subtree)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700242 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700243 const std::string& path = object.first;
244 const std::vector<
245 std::pair<std::string, std::vector<std::string>>>&
246 connectionNames = object.second;
Ed Tanouse0d918b2018-03-27 17:41:04 -0700247
George Liu997093e2021-11-17 17:43:45 +0800248 sdbusplus::message::object_path objPath(path);
249 if (objPath.filename() != chassisId)
James Feist1c8fba92019-12-20 15:12:07 -0800250 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700251 continue;
James Feist1c8fba92019-12-20 15:12:07 -0800252 }
James Feist1c8fba92019-12-20 15:12:07 -0800253
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700254 auto health =
255 std::make_shared<HealthPopulate>(asyncResp);
256
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700257 sdbusplus::asio::getProperty<std::vector<std::string>>(
258 *crow::connections::systemBus,
259 "xyz.openbmc_project.ObjectMapper",
260 path + "/all_sensors",
261 "xyz.openbmc_project.Association", "endpoints",
Ed Tanous168e20c2021-12-13 14:39:53 -0800262 [health](const boost::system::error_code ec2,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700263 const std::vector<std::string>& resp) {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700264 if (ec2)
265 {
266 return; // no sensors = no failures
267 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700268 health->inventory = resp;
269 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700270
271 health->populate();
272
Ed Tanous26f69762022-01-25 09:49:11 -0800273 if (connectionNames.empty())
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700274 {
275 BMCWEB_LOG_ERROR << "Got 0 Connection names";
276 continue;
277 }
278
279 asyncResp->res.jsonValue["@odata.type"] =
Gunnar Mills5ac5a2f2022-01-04 12:26:41 -0600280 "#Chassis.v1_16_0.Chassis";
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700281 asyncResp->res.jsonValue["@odata.id"] =
282 "/redfish/v1/Chassis/" + chassisId;
283 asyncResp->res.jsonValue["Name"] = "Chassis Collection";
284 asyncResp->res.jsonValue["ChassisType"] = "RackMount";
Ed Tanous14766872022-03-15 10:44:42 -0700285 asyncResp->res
286 .jsonValue["Actions"]["#Chassis.Reset"]["target"] =
287 "/redfish/v1/Chassis/" + chassisId +
288 "/Actions/Chassis.Reset";
289 asyncResp->res.jsonValue["Actions"]["#Chassis.Reset"]
290 ["@Redfish.ActionInfo"] =
291 "/redfish/v1/Chassis/" + chassisId +
292 "/ResetActionInfo";
293 asyncResp->res.jsonValue["PCIeDevices"]["@odata.id"] =
294 "/redfish/v1/Systems/system/PCIeDevices";
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700295
296 const std::string& connectionName =
297 connectionNames[0].first;
298
299 const std::vector<std::string>& interfaces2 =
300 connectionNames[0].second;
301 const std::array<const char*, 2> hasIndicatorLed = {
302 "xyz.openbmc_project.Inventory.Item.Panel",
George Liu0fda0f12021-11-16 10:06:17 +0800303 "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700304
Tejas Patil476b9cc2021-06-04 17:09:14 +0530305 const std::string assetTagInterface =
George Liu0fda0f12021-11-16 10:06:17 +0800306 "xyz.openbmc_project.Inventory.Decorator.AssetTag";
Tejas Patil476b9cc2021-06-04 17:09:14 +0530307 if (std::find(interfaces2.begin(), interfaces2.end(),
308 assetTagInterface) != interfaces2.end())
309 {
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700310 sdbusplus::asio::getProperty<std::string>(
311 *crow::connections::systemBus, connectionName,
312 path, assetTagInterface, "AssetTag",
Tejas Patil476b9cc2021-06-04 17:09:14 +0530313 [asyncResp, chassisId(std::string(chassisId))](
314 const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700315 const std::string& property) {
Tejas Patil476b9cc2021-06-04 17:09:14 +0530316 if (ec)
317 {
318 BMCWEB_LOG_DEBUG
George Liu0fda0f12021-11-16 10:06:17 +0800319 << "DBus response error for AssetTag";
Tejas Patil476b9cc2021-06-04 17:09:14 +0530320 messages::internalError(asyncResp->res);
321 return;
322 }
Tejas Patil476b9cc2021-06-04 17:09:14 +0530323 asyncResp->res.jsonValue["AssetTag"] =
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700324 property;
325 });
Tejas Patil476b9cc2021-06-04 17:09:14 +0530326 }
327
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700328 for (const char* interface : hasIndicatorLed)
329 {
330 if (std::find(interfaces2.begin(),
331 interfaces2.end(),
332 interface) != interfaces2.end())
333 {
334 getIndicatorLedState(asyncResp);
335 getLocationIndicatorActive(asyncResp);
336 break;
337 }
338 }
339
SunnySrivastava198488ad7f02020-12-03 10:27:52 -0600340 crow::connections::systemBus->async_method_call(
341 [asyncResp, chassisId(std::string(chassisId))](
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700342 const boost::system::error_code /*ec2*/,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800343 const dbus::utility::DBusPropertiesMap&
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700344 propertiesList) {
Ed Tanous168e20c2021-12-13 14:39:53 -0800345 for (const std::pair<
346 std::string,
347 dbus::utility::DbusVariantType>&
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700348 property : propertiesList)
SunnySrivastava198488ad7f02020-12-03 10:27:52 -0600349 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700350 // Store DBus properties that are also
351 // Redfish properties with same name and a
352 // string value
353 const std::string& propertyName =
354 property.first;
355 if ((propertyName == "PartNumber") ||
356 (propertyName == "SerialNumber") ||
357 (propertyName == "Manufacturer") ||
Alpana Kumaricaa11f72021-11-09 12:16:18 -0600358 (propertyName == "Model") ||
359 (propertyName == "SparePartNumber"))
Shawn McCarney99cffd72019-03-01 10:46:20 -0600360 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700361 const std::string* value =
362 std::get_if<std::string>(
363 &property.second);
Alpana Kumaricaa11f72021-11-09 12:16:18 -0600364 if (value == nullptr)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700365 {
Alpana Kumaricaa11f72021-11-09 12:16:18 -0600366 BMCWEB_LOG_ERROR
367 << "Null value returned for "
368 << propertyName;
369 messages::internalError(
370 asyncResp->res);
371 return;
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700372 }
Alpana Kumaricaa11f72021-11-09 12:16:18 -0600373 // SparePartNumber is optional on D-Bus
374 // so skip if it is empty
375 if (propertyName == "SparePartNumber")
376 {
Ed Tanous26f69762022-01-25 09:49:11 -0800377 if (value->empty())
Alpana Kumaricaa11f72021-11-09 12:16:18 -0600378 {
379 continue;
380 }
381 }
382 asyncResp->res.jsonValue[propertyName] =
383 *value;
Shawn McCarney99cffd72019-03-01 10:46:20 -0600384 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700385 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700386 asyncResp->res.jsonValue["Name"] = chassisId;
387 asyncResp->res.jsonValue["Id"] = chassisId;
zhanghch050256b692021-06-12 10:26:52 +0800388#ifdef BMCWEB_ALLOW_DEPRECATED_POWER_THERMAL
Ed Tanous14766872022-03-15 10:44:42 -0700389 asyncResp->res
390 .jsonValue["Thermal"]["@odata.id"] =
391 "/redfish/v1/Chassis/" + chassisId +
392 "/Thermal";
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700393 // Power object
Ed Tanous14766872022-03-15 10:44:42 -0700394 asyncResp->res.jsonValue["Power"]["@odata.id"] =
395 "/redfish/v1/Chassis/" + chassisId +
396 "/Power";
zhanghch050256b692021-06-12 10:26:52 +0800397#endif
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700398 // SensorCollection
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700399 asyncResp->res
Ed Tanous14766872022-03-15 10:44:42 -0700400 .jsonValue["Sensors"]["@odata.id"] =
401 "/redfish/v1/Chassis/" + chassisId +
402 "/Sensors";
403 asyncResp->res.jsonValue["Status"]["State"] =
404 "Enabled";
405
406 nlohmann::json::array_t computerSystems;
407 nlohmann::json::object_t system;
408 system["@odata.id"] =
409 "/redfish/v1/Systems/system";
410 computerSystems.push_back(std::move(system));
411 asyncResp->res
412 .jsonValue["Links"]["ComputerSystems"] =
413 std::move(computerSystems);
414
415 nlohmann::json::array_t managedBy;
416 nlohmann::json::object_t manager;
417 manager["@odata.id"] =
418 "/redfish/v1/Managers/bmc";
419 managedBy.push_back(std::move(manager));
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700420 asyncResp->res.jsonValue["Links"]["ManagedBy"] =
Ed Tanous14766872022-03-15 10:44:42 -0700421 std::move(managedBy);
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700422 getChassisState(asyncResp);
423 },
424 connectionName, path,
425 "org.freedesktop.DBus.Properties", "GetAll",
426 "xyz.openbmc_project.Inventory.Decorator.Asset");
Sharad Yadav2c37b4b2021-05-10 12:53:38 +0530427
Willy Tu308f70c2021-09-28 20:24:52 -0700428 for (const auto& interface : interfaces2)
Sharad Yadav2c37b4b2021-05-10 12:53:38 +0530429 {
Willy Tu308f70c2021-09-28 20:24:52 -0700430 if (interface == "xyz.openbmc_project.Common.UUID")
431 {
432 getChassisUUID(asyncResp, connectionName, path);
433 }
George Liu0fda0f12021-11-16 10:06:17 +0800434 else if (
435 interface ==
436 "xyz.openbmc_project.Inventory.Decorator.LocationCode")
Willy Tu308f70c2021-09-28 20:24:52 -0700437 {
438 getChassisLocationCode(asyncResp,
439 connectionName, path);
440 }
Sharad Yadav2c37b4b2021-05-10 12:53:38 +0530441 }
442
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700443 return;
444 }
445
446 // Couldn't find an object with that name. return an error
447 messages::resourceNotFound(
Gunnar Mills5ac5a2f2022-01-04 12:26:41 -0600448 asyncResp->res, "#Chassis.v1_16_0.Chassis", chassisId);
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700449 },
450 "xyz.openbmc_project.ObjectMapper",
451 "/xyz/openbmc_project/object_mapper",
452 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
453 "/xyz/openbmc_project/inventory", 0, interfaces);
454
455 getPhysicalSecurityData(asyncResp);
456 });
457
458 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700459 .privileges(redfish::privileges::patchChassis)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700460 .methods(
461 boost::beast::http::verb::
Ed Tanous45ca1b82022-03-25 13:07:27 -0700462 patch)([&app](
463 const crow::Request& req,
464 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
465 const std::string& param) {
466 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
467 {
468 return;
469 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700470 std::optional<bool> locationIndicatorActive;
471 std::optional<std::string> indicatorLed;
472
473 if (param.empty())
474 {
475 return;
476 }
477
Willy Tu15ed6782021-12-14 11:03:16 -0800478 if (!json_util::readJsonPatch(
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700479 req, asyncResp->res, "LocationIndicatorActive",
480 locationIndicatorActive, "IndicatorLED", indicatorLed))
481 {
482 return;
483 }
484
485 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
486 if (!locationIndicatorActive && !indicatorLed)
487 {
488 return; // delete this when we support more patch properties
489 }
490 if (indicatorLed)
491 {
492 asyncResp->res.addHeader(
493 boost::beast::http::field::warning,
George Liu0fda0f12021-11-16 10:06:17 +0800494 "299 - \"IndicatorLED is deprecated. Use LocationIndicatorActive instead.\"");
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700495 }
496
497 const std::array<const char*, 2> interfaces = {
498 "xyz.openbmc_project.Inventory.Item.Board",
499 "xyz.openbmc_project.Inventory.Item.Chassis"};
500
501 const std::string& chassisId = param;
502
503 crow::connections::systemBus->async_method_call(
504 [asyncResp, chassisId, locationIndicatorActive, indicatorLed](
505 const boost::system::error_code ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800506 const dbus::utility::MapperGetSubTreeResponse& subtree) {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700507 if (ec)
508 {
509 messages::internalError(asyncResp->res);
510 return;
511 }
512
513 // Iterate over all retrieved ObjectPaths.
514 for (const std::pair<
515 std::string,
516 std::vector<std::pair<std::string,
517 std::vector<std::string>>>>&
518 object : subtree)
519 {
520 const std::string& path = object.first;
521 const std::vector<
522 std::pair<std::string, std::vector<std::string>>>&
523 connectionNames = object.second;
524
George Liu997093e2021-11-17 17:43:45 +0800525 sdbusplus::message::object_path objPath(path);
526 if (objPath.filename() != chassisId)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700527 {
528 continue;
529 }
530
Ed Tanous26f69762022-01-25 09:49:11 -0800531 if (connectionNames.empty())
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700532 {
533 BMCWEB_LOG_ERROR << "Got 0 Connection names";
534 continue;
535 }
536
537 const std::vector<std::string>& interfaces3 =
538 connectionNames[0].second;
539
540 const std::array<const char*, 2> hasIndicatorLed = {
541 "xyz.openbmc_project.Inventory.Item.Panel",
George Liu0fda0f12021-11-16 10:06:17 +0800542 "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700543 bool indicatorChassis = false;
544 for (const char* interface : hasIndicatorLed)
545 {
546 if (std::find(interfaces3.begin(),
547 interfaces3.end(),
548 interface) != interfaces3.end())
549 {
550 indicatorChassis = true;
551 break;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700552 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700553 }
554 if (locationIndicatorActive)
555 {
556 if (indicatorChassis)
557 {
558 setLocationIndicatorActive(
559 asyncResp, *locationIndicatorActive);
560 }
561 else
562 {
563 messages::propertyUnknown(
564 asyncResp->res, "LocationIndicatorActive");
565 }
566 }
567 if (indicatorLed)
568 {
569 if (indicatorChassis)
570 {
571 setIndicatorLedState(asyncResp, *indicatorLed);
572 }
573 else
574 {
575 messages::propertyUnknown(asyncResp->res,
576 "IndicatorLED");
577 }
578 }
579 return;
James Feist1c8fba92019-12-20 15:12:07 -0800580 }
581
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700582 messages::resourceNotFound(
583 asyncResp->res, "#Chassis.v1_14_0.Chassis", chassisId);
584 },
585 "xyz.openbmc_project.ObjectMapper",
586 "/xyz/openbmc_project/object_mapper",
587 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
588 "/xyz/openbmc_project/inventory", 0, interfaces);
589 });
590}
P.K. Leedd99e042020-06-17 19:43:16 +0800591
zhanghch058d1b46d2021-04-01 11:18:24 +0800592inline void
593 doChassisPowerCycle(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
P.K. Leedd99e042020-06-17 19:43:16 +0800594{
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700595 const char* busName = "xyz.openbmc_project.ObjectMapper";
596 const char* path = "/xyz/openbmc_project/object_mapper";
597 const char* interface = "xyz.openbmc_project.ObjectMapper";
598 const char* method = "GetSubTreePaths";
P.K. Leedd99e042020-06-17 19:43:16 +0800599
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700600 const std::array<const char*, 1> interfaces = {
601 "xyz.openbmc_project.State.Chassis"};
602
603 // Use mapper to get subtree paths.
P.K. Leedd99e042020-06-17 19:43:16 +0800604 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -0800605 [asyncResp](
606 const boost::system::error_code ec,
607 const dbus::utility::MapperGetSubTreePathsResponse& chassisList) {
P.K. Leedd99e042020-06-17 19:43:16 +0800608 if (ec)
609 {
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700610 BMCWEB_LOG_DEBUG << "[mapper] Bad D-Bus request error: " << ec;
P.K. Leedd99e042020-06-17 19:43:16 +0800611 messages::internalError(asyncResp->res);
612 return;
613 }
614
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700615 const char* processName = "xyz.openbmc_project.State.Chassis";
616 const char* interfaceName = "xyz.openbmc_project.State.Chassis";
617 const char* destProperty = "RequestedPowerTransition";
618 const std::string propertyValue =
619 "xyz.openbmc_project.State.Chassis.Transition.PowerCycle";
620 std::string objectPath =
621 "/xyz/openbmc_project/state/chassis_system0";
622
623 /* Look for system reset chassis path */
624 if ((std::find(chassisList.begin(), chassisList.end(),
625 objectPath)) == chassisList.end())
626 {
627 /* We prefer to reset the full chassis_system, but if it doesn't
628 * exist on some platforms, fall back to a host-only power reset
629 */
630 objectPath = "/xyz/openbmc_project/state/chassis0";
631 }
632
633 crow::connections::systemBus->async_method_call(
634 [asyncResp](const boost::system::error_code ec) {
635 // Use "Set" method to set the property value.
636 if (ec)
637 {
638 BMCWEB_LOG_DEBUG << "[Set] Bad D-Bus request error: "
639 << ec;
640 messages::internalError(asyncResp->res);
641 return;
642 }
643
644 messages::success(asyncResp->res);
645 },
646 processName, objectPath, "org.freedesktop.DBus.Properties",
647 "Set", interfaceName, destProperty,
Ed Tanous168e20c2021-12-13 14:39:53 -0800648 dbus::utility::DbusVariantType{propertyValue});
P.K. Leedd99e042020-06-17 19:43:16 +0800649 },
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700650 busName, path, interface, method, "/", 0, interfaces);
P.K. Leedd99e042020-06-17 19:43:16 +0800651}
652
653/**
654 * ChassisResetAction class supports the POST method for the Reset
655 * action.
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700656 * Function handles POST method request.
657 * Analyzes POST body before sending Reset request data to D-Bus.
P.K. Leedd99e042020-06-17 19:43:16 +0800658 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700659
660inline void requestRoutesChassisResetAction(App& app)
P.K. Leedd99e042020-06-17 19:43:16 +0800661{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700662 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Actions/Chassis.Reset/")
Ed Tanoused398212021-06-09 17:05:54 -0700663 .privileges(redfish::privileges::postChassis)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700664 .methods(boost::beast::http::verb::post)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700665 [&app](const crow::Request& req,
666 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
667 const std::string&) {
668 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
669 {
670 return;
671 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700672 BMCWEB_LOG_DEBUG << "Post Chassis Reset.";
P.K. Leedd99e042020-06-17 19:43:16 +0800673
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700674 std::string resetType;
P.K. Leedd99e042020-06-17 19:43:16 +0800675
Willy Tu15ed6782021-12-14 11:03:16 -0800676 if (!json_util::readJsonAction(req, asyncResp->res, "ResetType",
677 resetType))
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700678 {
679 return;
680 }
P.K. Leedd99e042020-06-17 19:43:16 +0800681
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700682 if (resetType != "PowerCycle")
683 {
684 BMCWEB_LOG_DEBUG << "Invalid property value for ResetType: "
685 << resetType;
686 messages::actionParameterNotSupported(
687 asyncResp->res, resetType, "ResetType");
P.K. Leedd99e042020-06-17 19:43:16 +0800688
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700689 return;
690 }
691 doChassisPowerCycle(asyncResp);
692 });
693}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530694
695/**
696 * ChassisResetActionInfo derived class for delivering Chassis
697 * ResetType AllowableValues using ResetInfo schema.
698 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700699inline void requestRoutesChassisResetActionInfo(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530700{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700701 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -0700702 .privileges(redfish::privileges::getActionInfo)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700703 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700704 [&app](const crow::Request& req,
705 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
706 const std::string& chassisId) {
707 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
708 {
709 return;
710 }
Ed Tanous14766872022-03-15 10:44:42 -0700711 asyncResp->res.jsonValue["@odata.type"] =
712 "#ActionInfo.v1_1_2.ActionInfo";
713 asyncResp->res.jsonValue["@odata.id"] =
714 "/redfish/v1/Chassis/" + chassisId + "/ResetActionInfo";
715 asyncResp->res.jsonValue["Name"] = "Reset Action Info";
716
717 asyncResp->res.jsonValue["Id"] = "ResetActionInfo";
718 nlohmann::json::object_t parameters;
719 parameters["Name"] = "ResetType";
720 parameters["Required"] = true;
721 parameters["DataType"] = "String";
722 nlohmann::json::array_t allowed;
723 allowed.push_back("PowerCycle");
724 parameters["AllowableValues"] = std::move(allowed);
725 asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700726 });
727}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530728
Ed Tanous1abe55e2018-09-05 08:30:59 -0700729} // namespace redfish