blob: 47b507005fa1c0f4739ecdaa6906f794d3bf57b8 [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
Qiang XUc1819422019-02-27 13:51:32 +080097 aResp->res.jsonValue["PhysicalSecurity"] = {
Jonathan Doman1e1e5982021-06-11 09:36:17 -070098 {"IntrusionSensorNumber", 1}, {"IntrusionSensor", value}};
99 });
Qiang XUc1819422019-02-27 13:51:32 +0800100}
101
102/**
103 * Retrieves physical security properties over dbus
104 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800105inline void getPhysicalSecurityData(std::shared_ptr<bmcweb::AsyncResp> aResp)
Qiang XUc1819422019-02-27 13:51:32 +0800106{
107 crow::connections::systemBus->async_method_call(
108 [aResp{std::move(aResp)}](
109 const boost::system::error_code ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800110 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Qiang XUc1819422019-02-27 13:51:32 +0800111 if (ec)
112 {
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500113 // do not add err msg in redfish response, because this is not
Qiang XUc1819422019-02-27 13:51:32 +0800114 // mandatory property
Andrew Geissler54fbf172021-11-11 15:59:30 -0600115 BMCWEB_LOG_INFO << "DBUS error: no matched iface " << ec
116 << "\n";
Qiang XUc1819422019-02-27 13:51:32 +0800117 return;
118 }
119 // Iterate over all retrieved ObjectPaths.
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500120 for (const auto& object : subtree)
Qiang XUc1819422019-02-27 13:51:32 +0800121 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500122 for (const auto& service : object.second)
Qiang XUc1819422019-02-27 13:51:32 +0800123 {
124 getIntrusionByService(aResp, service.first, object.first);
125 return;
126 }
127 }
128 },
129 "xyz.openbmc_project.ObjectMapper",
130 "/xyz/openbmc_project/object_mapper",
131 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous271584a2019-07-09 16:24:22 -0700132 "/xyz/openbmc_project/Intrusion", 1,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500133 std::array<const char*, 1>{"xyz.openbmc_project.Chassis.Intrusion"});
Qiang XUc1819422019-02-27 13:51:32 +0800134}
135
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100136/**
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100137 * ChassisCollection derived class for delivering Chassis Collection Schema
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700138 * Functions triggers appropriate requests on DBus
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100139 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700140inline void requestRoutesChassisCollection(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700141{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700142 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/")
Ed Tanoused398212021-06-09 17:05:54 -0700143 .privileges(redfish::privileges::getChassisCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700144 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700145 [&app](const crow::Request& req,
146 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
147 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
148 {
149 return;
150 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700151 asyncResp->res.jsonValue["@odata.type"] =
152 "#ChassisCollection.ChassisCollection";
153 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Chassis";
154 asyncResp->res.jsonValue["Name"] = "Chassis Collection";
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100155
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700156 collection_util::getCollectionMembers(
157 asyncResp, "/redfish/v1/Chassis",
158 {"xyz.openbmc_project.Inventory.Item.Board",
159 "xyz.openbmc_project.Inventory.Item.Chassis"});
160 });
161}
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100162
Willy Tu308f70c2021-09-28 20:24:52 -0700163inline void
164 getChassisLocationCode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
165 const std::string& connectionName,
166 const std::string& path)
167{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700168 sdbusplus::asio::getProperty<std::string>(
169 *crow::connections::systemBus, connectionName, path,
170 "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode",
Willy Tu308f70c2021-09-28 20:24:52 -0700171 [asyncResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700172 const std::string& property) {
Willy Tu308f70c2021-09-28 20:24:52 -0700173 if (ec)
174 {
George Liu0fda0f12021-11-16 10:06:17 +0800175 BMCWEB_LOG_DEBUG << "DBUS response error for Location";
Willy Tu308f70c2021-09-28 20:24:52 -0700176 messages::internalError(asyncResp->res);
177 return;
178 }
179
Willy Tu308f70c2021-09-28 20:24:52 -0700180 asyncResp->res
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700181 .jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
182 property;
183 });
Willy Tu308f70c2021-09-28 20:24:52 -0700184}
185
186inline void getChassisUUID(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
187 const std::string& connectionName,
188 const std::string& path)
189{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700190 sdbusplus::asio::getProperty<std::string>(
191 *crow::connections::systemBus, connectionName, path,
192 "xyz.openbmc_project.Common.UUID", "UUID",
Willy Tu308f70c2021-09-28 20:24:52 -0700193 [asyncResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700194 const std::string& chassisUUID) {
Willy Tu308f70c2021-09-28 20:24:52 -0700195 if (ec)
196 {
George Liu0fda0f12021-11-16 10:06:17 +0800197 BMCWEB_LOG_DEBUG << "DBUS response error for UUID";
Willy Tu308f70c2021-09-28 20:24:52 -0700198 messages::internalError(asyncResp->res);
199 return;
200 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700201 asyncResp->res.jsonValue["UUID"] = chassisUUID;
202 });
Willy Tu308f70c2021-09-28 20:24:52 -0700203}
204
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100205/**
206 * Chassis override class for delivering Chassis Schema
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700207 * Functions triggers appropriate requests on DBus
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100208 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700209inline void requestRoutesChassis(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700210{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700211 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700212 .privileges(redfish::privileges::getChassis)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700213 .methods(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700214 boost::beast::http::verb::
215 get)([&app](const crow::Request& req,
216 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
217 const std::string& chassisId) {
218 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
219 {
220 return;
221 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700222 const std::array<const char*, 2> interfaces = {
223 "xyz.openbmc_project.Inventory.Item.Board",
224 "xyz.openbmc_project.Inventory.Item.Chassis"};
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100225
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700226 crow::connections::systemBus->async_method_call(
227 [asyncResp, chassisId(std::string(chassisId))](
228 const boost::system::error_code ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800229 const dbus::utility::MapperGetSubTreeResponse& subtree) {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700230 if (ec)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700231 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700232 messages::internalError(asyncResp->res);
233 return;
Ed Tanousdaf36e22018-04-20 16:01:36 -0700234 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700235 // Iterate over all retrieved ObjectPaths.
236 for (const std::pair<
237 std::string,
238 std::vector<std::pair<std::string,
239 std::vector<std::string>>>>&
240 object : subtree)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700241 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700242 const std::string& path = object.first;
243 const std::vector<
244 std::pair<std::string, std::vector<std::string>>>&
245 connectionNames = object.second;
Ed Tanouse0d918b2018-03-27 17:41:04 -0700246
George Liu997093e2021-11-17 17:43:45 +0800247 sdbusplus::message::object_path objPath(path);
248 if (objPath.filename() != chassisId)
James Feist1c8fba92019-12-20 15:12:07 -0800249 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700250 continue;
James Feist1c8fba92019-12-20 15:12:07 -0800251 }
James Feist1c8fba92019-12-20 15:12:07 -0800252
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700253 auto health =
254 std::make_shared<HealthPopulate>(asyncResp);
255
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700256 sdbusplus::asio::getProperty<std::vector<std::string>>(
257 *crow::connections::systemBus,
258 "xyz.openbmc_project.ObjectMapper",
259 path + "/all_sensors",
260 "xyz.openbmc_project.Association", "endpoints",
Ed Tanous168e20c2021-12-13 14:39:53 -0800261 [health](const boost::system::error_code ec2,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700262 const std::vector<std::string>& resp) {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700263 if (ec2)
264 {
265 return; // no sensors = no failures
266 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700267 health->inventory = resp;
268 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700269
270 health->populate();
271
Ed Tanous26f69762022-01-25 09:49:11 -0800272 if (connectionNames.empty())
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700273 {
274 BMCWEB_LOG_ERROR << "Got 0 Connection names";
275 continue;
276 }
277
278 asyncResp->res.jsonValue["@odata.type"] =
Gunnar Mills5ac5a2f2022-01-04 12:26:41 -0600279 "#Chassis.v1_16_0.Chassis";
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700280 asyncResp->res.jsonValue["@odata.id"] =
281 "/redfish/v1/Chassis/" + chassisId;
282 asyncResp->res.jsonValue["Name"] = "Chassis Collection";
283 asyncResp->res.jsonValue["ChassisType"] = "RackMount";
284 asyncResp->res.jsonValue["Actions"]["#Chassis.Reset"] =
285 {{"target", "/redfish/v1/Chassis/" + chassisId +
286 "/Actions/Chassis.Reset"},
287 {"@Redfish.ActionInfo", "/redfish/v1/Chassis/" +
288 chassisId +
289 "/ResetActionInfo"}};
290 asyncResp->res.jsonValue["PCIeDevices"] = {
291 {"@odata.id",
292 "/redfish/v1/Systems/system/PCIeDevices"}};
293
294 const std::string& connectionName =
295 connectionNames[0].first;
296
297 const std::vector<std::string>& interfaces2 =
298 connectionNames[0].second;
299 const std::array<const char*, 2> hasIndicatorLed = {
300 "xyz.openbmc_project.Inventory.Item.Panel",
George Liu0fda0f12021-11-16 10:06:17 +0800301 "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700302
Tejas Patil476b9cc2021-06-04 17:09:14 +0530303 const std::string assetTagInterface =
George Liu0fda0f12021-11-16 10:06:17 +0800304 "xyz.openbmc_project.Inventory.Decorator.AssetTag";
Tejas Patil476b9cc2021-06-04 17:09:14 +0530305 if (std::find(interfaces2.begin(), interfaces2.end(),
306 assetTagInterface) != interfaces2.end())
307 {
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700308 sdbusplus::asio::getProperty<std::string>(
309 *crow::connections::systemBus, connectionName,
310 path, assetTagInterface, "AssetTag",
Tejas Patil476b9cc2021-06-04 17:09:14 +0530311 [asyncResp, chassisId(std::string(chassisId))](
312 const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700313 const std::string& property) {
Tejas Patil476b9cc2021-06-04 17:09:14 +0530314 if (ec)
315 {
316 BMCWEB_LOG_DEBUG
George Liu0fda0f12021-11-16 10:06:17 +0800317 << "DBus response error for AssetTag";
Tejas Patil476b9cc2021-06-04 17:09:14 +0530318 messages::internalError(asyncResp->res);
319 return;
320 }
Tejas Patil476b9cc2021-06-04 17:09:14 +0530321 asyncResp->res.jsonValue["AssetTag"] =
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700322 property;
323 });
Tejas Patil476b9cc2021-06-04 17:09:14 +0530324 }
325
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700326 for (const char* interface : hasIndicatorLed)
327 {
328 if (std::find(interfaces2.begin(),
329 interfaces2.end(),
330 interface) != interfaces2.end())
331 {
332 getIndicatorLedState(asyncResp);
333 getLocationIndicatorActive(asyncResp);
334 break;
335 }
336 }
337
SunnySrivastava198488ad7f02020-12-03 10:27:52 -0600338 crow::connections::systemBus->async_method_call(
339 [asyncResp, chassisId(std::string(chassisId))](
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700340 const boost::system::error_code /*ec2*/,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800341 const dbus::utility::DBusPropertiesMap&
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700342 propertiesList) {
Ed Tanous168e20c2021-12-13 14:39:53 -0800343 for (const std::pair<
344 std::string,
345 dbus::utility::DbusVariantType>&
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700346 property : propertiesList)
SunnySrivastava198488ad7f02020-12-03 10:27:52 -0600347 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700348 // Store DBus properties that are also
349 // Redfish properties with same name and a
350 // string value
351 const std::string& propertyName =
352 property.first;
353 if ((propertyName == "PartNumber") ||
354 (propertyName == "SerialNumber") ||
355 (propertyName == "Manufacturer") ||
Alpana Kumaricaa11f72021-11-09 12:16:18 -0600356 (propertyName == "Model") ||
357 (propertyName == "SparePartNumber"))
Shawn McCarney99cffd72019-03-01 10:46:20 -0600358 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700359 const std::string* value =
360 std::get_if<std::string>(
361 &property.second);
Alpana Kumaricaa11f72021-11-09 12:16:18 -0600362 if (value == nullptr)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700363 {
Alpana Kumaricaa11f72021-11-09 12:16:18 -0600364 BMCWEB_LOG_ERROR
365 << "Null value returned for "
366 << propertyName;
367 messages::internalError(
368 asyncResp->res);
369 return;
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700370 }
Alpana Kumaricaa11f72021-11-09 12:16:18 -0600371 // SparePartNumber is optional on D-Bus
372 // so skip if it is empty
373 if (propertyName == "SparePartNumber")
374 {
Ed Tanous26f69762022-01-25 09:49:11 -0800375 if (value->empty())
Alpana Kumaricaa11f72021-11-09 12:16:18 -0600376 {
377 continue;
378 }
379 }
380 asyncResp->res.jsonValue[propertyName] =
381 *value;
Shawn McCarney99cffd72019-03-01 10:46:20 -0600382 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700383 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700384 asyncResp->res.jsonValue["Name"] = chassisId;
385 asyncResp->res.jsonValue["Id"] = chassisId;
zhanghch050256b692021-06-12 10:26:52 +0800386#ifdef BMCWEB_ALLOW_DEPRECATED_POWER_THERMAL
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700387 asyncResp->res.jsonValue["Thermal"] = {
388 {"@odata.id", "/redfish/v1/Chassis/" +
389 chassisId + "/Thermal"}};
390 // Power object
391 asyncResp->res.jsonValue["Power"] = {
392 {"@odata.id", "/redfish/v1/Chassis/" +
393 chassisId + "/Power"}};
zhanghch050256b692021-06-12 10:26:52 +0800394#endif
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700395 // SensorCollection
396 asyncResp->res.jsonValue["Sensors"] = {
397 {"@odata.id", "/redfish/v1/Chassis/" +
398 chassisId + "/Sensors"}};
399 asyncResp->res.jsonValue["Status"] = {
400 {"State", "Enabled"},
401 };
402
403 asyncResp->res
404 .jsonValue["Links"]["ComputerSystems"] = {
405 {{"@odata.id",
406 "/redfish/v1/Systems/system"}}};
407 asyncResp->res.jsonValue["Links"]["ManagedBy"] =
408 {{{"@odata.id",
409 "/redfish/v1/Managers/bmc"}}};
410 getChassisState(asyncResp);
411 },
412 connectionName, path,
413 "org.freedesktop.DBus.Properties", "GetAll",
414 "xyz.openbmc_project.Inventory.Decorator.Asset");
Sharad Yadav2c37b4b2021-05-10 12:53:38 +0530415
Willy Tu308f70c2021-09-28 20:24:52 -0700416 for (const auto& interface : interfaces2)
Sharad Yadav2c37b4b2021-05-10 12:53:38 +0530417 {
Willy Tu308f70c2021-09-28 20:24:52 -0700418 if (interface == "xyz.openbmc_project.Common.UUID")
419 {
420 getChassisUUID(asyncResp, connectionName, path);
421 }
George Liu0fda0f12021-11-16 10:06:17 +0800422 else if (
423 interface ==
424 "xyz.openbmc_project.Inventory.Decorator.LocationCode")
Willy Tu308f70c2021-09-28 20:24:52 -0700425 {
426 getChassisLocationCode(asyncResp,
427 connectionName, path);
428 }
Sharad Yadav2c37b4b2021-05-10 12:53:38 +0530429 }
430
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700431 return;
432 }
433
434 // Couldn't find an object with that name. return an error
435 messages::resourceNotFound(
Gunnar Mills5ac5a2f2022-01-04 12:26:41 -0600436 asyncResp->res, "#Chassis.v1_16_0.Chassis", chassisId);
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700437 },
438 "xyz.openbmc_project.ObjectMapper",
439 "/xyz/openbmc_project/object_mapper",
440 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
441 "/xyz/openbmc_project/inventory", 0, interfaces);
442
443 getPhysicalSecurityData(asyncResp);
444 });
445
446 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700447 .privileges(redfish::privileges::patchChassis)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700448 .methods(
449 boost::beast::http::verb::
Ed Tanous45ca1b82022-03-25 13:07:27 -0700450 patch)([&app](
451 const crow::Request& req,
452 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
453 const std::string& param) {
454 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
455 {
456 return;
457 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700458 std::optional<bool> locationIndicatorActive;
459 std::optional<std::string> indicatorLed;
460
461 if (param.empty())
462 {
463 return;
464 }
465
Willy Tu15ed6782021-12-14 11:03:16 -0800466 if (!json_util::readJsonPatch(
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700467 req, asyncResp->res, "LocationIndicatorActive",
468 locationIndicatorActive, "IndicatorLED", indicatorLed))
469 {
470 return;
471 }
472
473 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
474 if (!locationIndicatorActive && !indicatorLed)
475 {
476 return; // delete this when we support more patch properties
477 }
478 if (indicatorLed)
479 {
480 asyncResp->res.addHeader(
481 boost::beast::http::field::warning,
George Liu0fda0f12021-11-16 10:06:17 +0800482 "299 - \"IndicatorLED is deprecated. Use LocationIndicatorActive instead.\"");
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700483 }
484
485 const std::array<const char*, 2> interfaces = {
486 "xyz.openbmc_project.Inventory.Item.Board",
487 "xyz.openbmc_project.Inventory.Item.Chassis"};
488
489 const std::string& chassisId = param;
490
491 crow::connections::systemBus->async_method_call(
492 [asyncResp, chassisId, locationIndicatorActive, indicatorLed](
493 const boost::system::error_code ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800494 const dbus::utility::MapperGetSubTreeResponse& subtree) {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700495 if (ec)
496 {
497 messages::internalError(asyncResp->res);
498 return;
499 }
500
501 // Iterate over all retrieved ObjectPaths.
502 for (const std::pair<
503 std::string,
504 std::vector<std::pair<std::string,
505 std::vector<std::string>>>>&
506 object : subtree)
507 {
508 const std::string& path = object.first;
509 const std::vector<
510 std::pair<std::string, std::vector<std::string>>>&
511 connectionNames = object.second;
512
George Liu997093e2021-11-17 17:43:45 +0800513 sdbusplus::message::object_path objPath(path);
514 if (objPath.filename() != chassisId)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700515 {
516 continue;
517 }
518
Ed Tanous26f69762022-01-25 09:49:11 -0800519 if (connectionNames.empty())
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700520 {
521 BMCWEB_LOG_ERROR << "Got 0 Connection names";
522 continue;
523 }
524
525 const std::vector<std::string>& interfaces3 =
526 connectionNames[0].second;
527
528 const std::array<const char*, 2> hasIndicatorLed = {
529 "xyz.openbmc_project.Inventory.Item.Panel",
George Liu0fda0f12021-11-16 10:06:17 +0800530 "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700531 bool indicatorChassis = false;
532 for (const char* interface : hasIndicatorLed)
533 {
534 if (std::find(interfaces3.begin(),
535 interfaces3.end(),
536 interface) != interfaces3.end())
537 {
538 indicatorChassis = true;
539 break;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700540 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700541 }
542 if (locationIndicatorActive)
543 {
544 if (indicatorChassis)
545 {
546 setLocationIndicatorActive(
547 asyncResp, *locationIndicatorActive);
548 }
549 else
550 {
551 messages::propertyUnknown(
552 asyncResp->res, "LocationIndicatorActive");
553 }
554 }
555 if (indicatorLed)
556 {
557 if (indicatorChassis)
558 {
559 setIndicatorLedState(asyncResp, *indicatorLed);
560 }
561 else
562 {
563 messages::propertyUnknown(asyncResp->res,
564 "IndicatorLED");
565 }
566 }
567 return;
James Feist1c8fba92019-12-20 15:12:07 -0800568 }
569
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700570 messages::resourceNotFound(
571 asyncResp->res, "#Chassis.v1_14_0.Chassis", chassisId);
572 },
573 "xyz.openbmc_project.ObjectMapper",
574 "/xyz/openbmc_project/object_mapper",
575 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
576 "/xyz/openbmc_project/inventory", 0, interfaces);
577 });
578}
P.K. Leedd99e042020-06-17 19:43:16 +0800579
zhanghch058d1b46d2021-04-01 11:18:24 +0800580inline void
581 doChassisPowerCycle(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
P.K. Leedd99e042020-06-17 19:43:16 +0800582{
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700583 const char* busName = "xyz.openbmc_project.ObjectMapper";
584 const char* path = "/xyz/openbmc_project/object_mapper";
585 const char* interface = "xyz.openbmc_project.ObjectMapper";
586 const char* method = "GetSubTreePaths";
P.K. Leedd99e042020-06-17 19:43:16 +0800587
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700588 const std::array<const char*, 1> interfaces = {
589 "xyz.openbmc_project.State.Chassis"};
590
591 // Use mapper to get subtree paths.
P.K. Leedd99e042020-06-17 19:43:16 +0800592 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -0800593 [asyncResp](
594 const boost::system::error_code ec,
595 const dbus::utility::MapperGetSubTreePathsResponse& chassisList) {
P.K. Leedd99e042020-06-17 19:43:16 +0800596 if (ec)
597 {
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700598 BMCWEB_LOG_DEBUG << "[mapper] Bad D-Bus request error: " << ec;
P.K. Leedd99e042020-06-17 19:43:16 +0800599 messages::internalError(asyncResp->res);
600 return;
601 }
602
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700603 const char* processName = "xyz.openbmc_project.State.Chassis";
604 const char* interfaceName = "xyz.openbmc_project.State.Chassis";
605 const char* destProperty = "RequestedPowerTransition";
606 const std::string propertyValue =
607 "xyz.openbmc_project.State.Chassis.Transition.PowerCycle";
608 std::string objectPath =
609 "/xyz/openbmc_project/state/chassis_system0";
610
611 /* Look for system reset chassis path */
612 if ((std::find(chassisList.begin(), chassisList.end(),
613 objectPath)) == chassisList.end())
614 {
615 /* We prefer to reset the full chassis_system, but if it doesn't
616 * exist on some platforms, fall back to a host-only power reset
617 */
618 objectPath = "/xyz/openbmc_project/state/chassis0";
619 }
620
621 crow::connections::systemBus->async_method_call(
622 [asyncResp](const boost::system::error_code ec) {
623 // Use "Set" method to set the property value.
624 if (ec)
625 {
626 BMCWEB_LOG_DEBUG << "[Set] Bad D-Bus request error: "
627 << ec;
628 messages::internalError(asyncResp->res);
629 return;
630 }
631
632 messages::success(asyncResp->res);
633 },
634 processName, objectPath, "org.freedesktop.DBus.Properties",
635 "Set", interfaceName, destProperty,
Ed Tanous168e20c2021-12-13 14:39:53 -0800636 dbus::utility::DbusVariantType{propertyValue});
P.K. Leedd99e042020-06-17 19:43:16 +0800637 },
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700638 busName, path, interface, method, "/", 0, interfaces);
P.K. Leedd99e042020-06-17 19:43:16 +0800639}
640
641/**
642 * ChassisResetAction class supports the POST method for the Reset
643 * action.
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700644 * Function handles POST method request.
645 * Analyzes POST body before sending Reset request data to D-Bus.
P.K. Leedd99e042020-06-17 19:43:16 +0800646 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700647
648inline void requestRoutesChassisResetAction(App& app)
P.K. Leedd99e042020-06-17 19:43:16 +0800649{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700650 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Actions/Chassis.Reset/")
Ed Tanoused398212021-06-09 17:05:54 -0700651 .privileges(redfish::privileges::postChassis)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700652 .methods(boost::beast::http::verb::post)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700653 [&app](const crow::Request& req,
654 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
655 const std::string&) {
656 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
657 {
658 return;
659 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700660 BMCWEB_LOG_DEBUG << "Post Chassis Reset.";
P.K. Leedd99e042020-06-17 19:43:16 +0800661
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700662 std::string resetType;
P.K. Leedd99e042020-06-17 19:43:16 +0800663
Willy Tu15ed6782021-12-14 11:03:16 -0800664 if (!json_util::readJsonAction(req, asyncResp->res, "ResetType",
665 resetType))
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700666 {
667 return;
668 }
P.K. Leedd99e042020-06-17 19:43:16 +0800669
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700670 if (resetType != "PowerCycle")
671 {
672 BMCWEB_LOG_DEBUG << "Invalid property value for ResetType: "
673 << resetType;
674 messages::actionParameterNotSupported(
675 asyncResp->res, resetType, "ResetType");
P.K. Leedd99e042020-06-17 19:43:16 +0800676
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700677 return;
678 }
679 doChassisPowerCycle(asyncResp);
680 });
681}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530682
683/**
684 * ChassisResetActionInfo derived class for delivering Chassis
685 * ResetType AllowableValues using ResetInfo schema.
686 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700687inline void requestRoutesChassisResetActionInfo(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530688{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700689 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -0700690 .privileges(redfish::privileges::getActionInfo)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700691 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700692 [&app](const crow::Request& req,
693 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
694 const std::string& chassisId) {
695 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
696 {
697 return;
698 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700699 asyncResp->res.jsonValue = {
700 {"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"},
701 {"@odata.id",
702 "/redfish/v1/Chassis/" + chassisId + "/ResetActionInfo"},
703 {"Name", "Reset Action Info"},
704 {"Id", "ResetActionInfo"},
705 {"Parameters",
706 {{{"Name", "ResetType"},
707 {"Required", true},
708 {"DataType", "String"},
709 {"AllowableValues", {"PowerCycle"}}}}}};
710 });
711}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530712
Ed Tanous1abe55e2018-09-05 08:30:59 -0700713} // namespace redfish