blob: 45348dbca361e3bac4dc5088348e5c52c084501d [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 Tanoused398212021-06-09 17:05:54 -070023#include <registries/privilege_registry.hpp>
Jonathan Doman1e1e5982021-06-11 09:36:17 -070024#include <sdbusplus/asio/property.hpp>
Gunnar Mills02f6ff12020-10-14 15:59:58 -050025#include <utils/collection.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050026
Ed Tanous1abe55e2018-09-05 08:30:59 -070027namespace redfish
28{
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010029
30/**
Gunnar Millsbeeca0a2019-02-14 16:30:45 -060031 * @brief Retrieves chassis state properties over dbus
32 *
33 * @param[in] aResp - Shared pointer for completing asynchronous calls.
34 *
35 * @return None.
36 */
zhanghch058d1b46d2021-04-01 11:18:24 +080037inline void getChassisState(std::shared_ptr<bmcweb::AsyncResp> aResp)
Gunnar Millsbeeca0a2019-02-14 16:30:45 -060038{
Jonathan Doman1e1e5982021-06-11 09:36:17 -070039 // crow::connections::systemBus->async_method_call(
40 sdbusplus::asio::getProperty<std::string>(
41 *crow::connections::systemBus, "xyz.openbmc_project.State.Chassis",
42 "/xyz/openbmc_project/state/chassis0",
43 "xyz.openbmc_project.State.Chassis", "CurrentPowerState",
44 [aResp{std::move(aResp)}](const boost::system::error_code ec,
45 const std::string& chassisState) {
Gunnar Millsbeeca0a2019-02-14 16:30:45 -060046 if (ec)
47 {
Carson Labradoa6e5e0a2022-02-15 00:26:03 +000048 if (ec == boost::system::errc::host_unreachable)
49 {
50 // Service not available, no error, just don't return
51 // chassis state info
52 BMCWEB_LOG_DEBUG << "Service not available " << ec;
53 return;
54 }
Gunnar Millsbeeca0a2019-02-14 16:30:45 -060055 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
56 messages::internalError(aResp->res);
57 return;
58 }
59
Jonathan Doman1e1e5982021-06-11 09:36:17 -070060 BMCWEB_LOG_DEBUG << "Chassis state: " << chassisState;
61 // Verify Chassis State
62 if (chassisState ==
63 "xyz.openbmc_project.State.Chassis.PowerState.On")
Gunnar Millsbeeca0a2019-02-14 16:30:45 -060064 {
Jonathan Doman1e1e5982021-06-11 09:36:17 -070065 aResp->res.jsonValue["PowerState"] = "On";
66 aResp->res.jsonValue["Status"]["State"] = "Enabled";
Gunnar Millsbeeca0a2019-02-14 16:30:45 -060067 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -070068 else if (chassisState ==
69 "xyz.openbmc_project.State.Chassis.PowerState.Off")
70 {
71 aResp->res.jsonValue["PowerState"] = "Off";
72 aResp->res.jsonValue["Status"]["State"] = "StandbyOffline";
73 }
74 });
Gunnar Millsbeeca0a2019-02-14 16:30:45 -060075}
76
zhanghch058d1b46d2021-04-01 11:18:24 +080077inline void getIntrusionByService(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous23a21a12020-07-25 04:45:05 +000078 const std::string& service,
79 const std::string& objPath)
Qiang XUc1819422019-02-27 13:51:32 +080080{
81 BMCWEB_LOG_DEBUG << "Get intrusion status by service \n";
82
Jonathan Doman1e1e5982021-06-11 09:36:17 -070083 sdbusplus::asio::getProperty<std::string>(
84 *crow::connections::systemBus, service, objPath,
85 "xyz.openbmc_project.Chassis.Intrusion", "Status",
Qiang XUc1819422019-02-27 13:51:32 +080086 [aResp{std::move(aResp)}](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -070087 const std::string& value) {
Qiang XUc1819422019-02-27 13:51:32 +080088 if (ec)
89 {
Gunnar Mills4e0453b2020-07-08 14:00:30 -050090 // do not add err msg in redfish response, because this is not
Qiang XUc1819422019-02-27 13:51:32 +080091 // mandatory property
92 BMCWEB_LOG_ERROR << "DBUS response error " << ec << "\n";
93 return;
94 }
95
Qiang XUc1819422019-02-27 13:51:32 +080096 aResp->res.jsonValue["PhysicalSecurity"] = {
Jonathan Doman1e1e5982021-06-11 09:36:17 -070097 {"IntrusionSensorNumber", 1}, {"IntrusionSensor", value}};
98 });
Qiang XUc1819422019-02-27 13:51:32 +080099}
100
101/**
102 * Retrieves physical security properties over dbus
103 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800104inline void getPhysicalSecurityData(std::shared_ptr<bmcweb::AsyncResp> aResp)
Qiang XUc1819422019-02-27 13:51:32 +0800105{
106 crow::connections::systemBus->async_method_call(
107 [aResp{std::move(aResp)}](
108 const boost::system::error_code ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800109 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Qiang XUc1819422019-02-27 13:51:32 +0800110 if (ec)
111 {
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500112 // do not add err msg in redfish response, because this is not
Qiang XUc1819422019-02-27 13:51:32 +0800113 // mandatory property
Andrew Geissler54fbf172021-11-11 15:59:30 -0600114 BMCWEB_LOG_INFO << "DBUS error: no matched iface " << ec
115 << "\n";
Qiang XUc1819422019-02-27 13:51:32 +0800116 return;
117 }
118 // Iterate over all retrieved ObjectPaths.
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500119 for (const auto& object : subtree)
Qiang XUc1819422019-02-27 13:51:32 +0800120 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500121 for (const auto& service : object.second)
Qiang XUc1819422019-02-27 13:51:32 +0800122 {
123 getIntrusionByService(aResp, service.first, object.first);
124 return;
125 }
126 }
127 },
128 "xyz.openbmc_project.ObjectMapper",
129 "/xyz/openbmc_project/object_mapper",
130 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous271584a2019-07-09 16:24:22 -0700131 "/xyz/openbmc_project/Intrusion", 1,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500132 std::array<const char*, 1>{"xyz.openbmc_project.Chassis.Intrusion"});
Qiang XUc1819422019-02-27 13:51:32 +0800133}
134
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100135/**
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100136 * ChassisCollection derived class for delivering Chassis Collection Schema
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700137 * Functions triggers appropriate requests on DBus
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100138 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700139inline void requestRoutesChassisCollection(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700140{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700141 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/")
Ed Tanoused398212021-06-09 17:05:54 -0700142 .privileges(redfish::privileges::getChassisCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700143 .methods(boost::beast::http::verb::get)(
144 [](const crow::Request&,
145 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
146 asyncResp->res.jsonValue["@odata.type"] =
147 "#ChassisCollection.ChassisCollection";
148 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Chassis";
149 asyncResp->res.jsonValue["Name"] = "Chassis Collection";
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100150
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700151 collection_util::getCollectionMembers(
152 asyncResp, "/redfish/v1/Chassis",
153 {"xyz.openbmc_project.Inventory.Item.Board",
154 "xyz.openbmc_project.Inventory.Item.Chassis"});
155 });
156}
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100157
Willy Tu308f70c2021-09-28 20:24:52 -0700158inline void
159 getChassisLocationCode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
160 const std::string& connectionName,
161 const std::string& path)
162{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700163 sdbusplus::asio::getProperty<std::string>(
164 *crow::connections::systemBus, connectionName, path,
165 "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode",
Willy Tu308f70c2021-09-28 20:24:52 -0700166 [asyncResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700167 const std::string& property) {
Willy Tu308f70c2021-09-28 20:24:52 -0700168 if (ec)
169 {
George Liu0fda0f12021-11-16 10:06:17 +0800170 BMCWEB_LOG_DEBUG << "DBUS response error for Location";
Willy Tu308f70c2021-09-28 20:24:52 -0700171 messages::internalError(asyncResp->res);
172 return;
173 }
174
Willy Tu308f70c2021-09-28 20:24:52 -0700175 asyncResp->res
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700176 .jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
177 property;
178 });
Willy Tu308f70c2021-09-28 20:24:52 -0700179}
180
181inline void getChassisUUID(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
182 const std::string& connectionName,
183 const std::string& path)
184{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700185 sdbusplus::asio::getProperty<std::string>(
186 *crow::connections::systemBus, connectionName, path,
187 "xyz.openbmc_project.Common.UUID", "UUID",
Willy Tu308f70c2021-09-28 20:24:52 -0700188 [asyncResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700189 const std::string& chassisUUID) {
Willy Tu308f70c2021-09-28 20:24:52 -0700190 if (ec)
191 {
George Liu0fda0f12021-11-16 10:06:17 +0800192 BMCWEB_LOG_DEBUG << "DBUS response error for UUID";
Willy Tu308f70c2021-09-28 20:24:52 -0700193 messages::internalError(asyncResp->res);
194 return;
195 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700196 asyncResp->res.jsonValue["UUID"] = chassisUUID;
197 });
Willy Tu308f70c2021-09-28 20:24:52 -0700198}
199
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100200/**
201 * Chassis override class for delivering Chassis Schema
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700202 * Functions triggers appropriate requests on DBus
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100203 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700204inline void requestRoutesChassis(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700205{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700206 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700207 .privileges(redfish::privileges::getChassis)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700208 .methods(
209 boost::beast::http::verb::get)([](const crow::Request&,
210 const std::shared_ptr<
211 bmcweb::AsyncResp>& asyncResp,
212 const std::string& chassisId) {
213 const std::array<const char*, 2> interfaces = {
214 "xyz.openbmc_project.Inventory.Item.Board",
215 "xyz.openbmc_project.Inventory.Item.Chassis"};
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100216
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700217 crow::connections::systemBus->async_method_call(
218 [asyncResp, chassisId(std::string(chassisId))](
219 const boost::system::error_code ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800220 const dbus::utility::MapperGetSubTreeResponse& subtree) {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700221 if (ec)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700222 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700223 messages::internalError(asyncResp->res);
224 return;
Ed Tanousdaf36e22018-04-20 16:01:36 -0700225 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700226 // Iterate over all retrieved ObjectPaths.
227 for (const std::pair<
228 std::string,
229 std::vector<std::pair<std::string,
230 std::vector<std::string>>>>&
231 object : subtree)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700232 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700233 const std::string& path = object.first;
234 const std::vector<
235 std::pair<std::string, std::vector<std::string>>>&
236 connectionNames = object.second;
Ed Tanouse0d918b2018-03-27 17:41:04 -0700237
George Liu997093e2021-11-17 17:43:45 +0800238 sdbusplus::message::object_path objPath(path);
239 if (objPath.filename() != chassisId)
James Feist1c8fba92019-12-20 15:12:07 -0800240 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700241 continue;
James Feist1c8fba92019-12-20 15:12:07 -0800242 }
James Feist1c8fba92019-12-20 15:12:07 -0800243
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700244 auto health =
245 std::make_shared<HealthPopulate>(asyncResp);
246
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700247 sdbusplus::asio::getProperty<std::vector<std::string>>(
248 *crow::connections::systemBus,
249 "xyz.openbmc_project.ObjectMapper",
250 path + "/all_sensors",
251 "xyz.openbmc_project.Association", "endpoints",
Ed Tanous168e20c2021-12-13 14:39:53 -0800252 [health](const boost::system::error_code ec2,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700253 const std::vector<std::string>& resp) {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700254 if (ec2)
255 {
256 return; // no sensors = no failures
257 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700258 health->inventory = resp;
259 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700260
261 health->populate();
262
Ed Tanous26f69762022-01-25 09:49:11 -0800263 if (connectionNames.empty())
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700264 {
265 BMCWEB_LOG_ERROR << "Got 0 Connection names";
266 continue;
267 }
268
269 asyncResp->res.jsonValue["@odata.type"] =
Gunnar Mills5ac5a2f2022-01-04 12:26:41 -0600270 "#Chassis.v1_16_0.Chassis";
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700271 asyncResp->res.jsonValue["@odata.id"] =
272 "/redfish/v1/Chassis/" + chassisId;
273 asyncResp->res.jsonValue["Name"] = "Chassis Collection";
274 asyncResp->res.jsonValue["ChassisType"] = "RackMount";
275 asyncResp->res.jsonValue["Actions"]["#Chassis.Reset"] =
276 {{"target", "/redfish/v1/Chassis/" + chassisId +
277 "/Actions/Chassis.Reset"},
278 {"@Redfish.ActionInfo", "/redfish/v1/Chassis/" +
279 chassisId +
280 "/ResetActionInfo"}};
281 asyncResp->res.jsonValue["PCIeDevices"] = {
282 {"@odata.id",
283 "/redfish/v1/Systems/system/PCIeDevices"}};
284
285 const std::string& connectionName =
286 connectionNames[0].first;
287
288 const std::vector<std::string>& interfaces2 =
289 connectionNames[0].second;
290 const std::array<const char*, 2> hasIndicatorLed = {
291 "xyz.openbmc_project.Inventory.Item.Panel",
George Liu0fda0f12021-11-16 10:06:17 +0800292 "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700293
Tejas Patil476b9cc2021-06-04 17:09:14 +0530294 const std::string assetTagInterface =
George Liu0fda0f12021-11-16 10:06:17 +0800295 "xyz.openbmc_project.Inventory.Decorator.AssetTag";
Tejas Patil476b9cc2021-06-04 17:09:14 +0530296 if (std::find(interfaces2.begin(), interfaces2.end(),
297 assetTagInterface) != interfaces2.end())
298 {
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700299 sdbusplus::asio::getProperty<std::string>(
300 *crow::connections::systemBus, connectionName,
301 path, assetTagInterface, "AssetTag",
Tejas Patil476b9cc2021-06-04 17:09:14 +0530302 [asyncResp, chassisId(std::string(chassisId))](
303 const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700304 const std::string& property) {
Tejas Patil476b9cc2021-06-04 17:09:14 +0530305 if (ec)
306 {
307 BMCWEB_LOG_DEBUG
George Liu0fda0f12021-11-16 10:06:17 +0800308 << "DBus response error for AssetTag";
Tejas Patil476b9cc2021-06-04 17:09:14 +0530309 messages::internalError(asyncResp->res);
310 return;
311 }
Tejas Patil476b9cc2021-06-04 17:09:14 +0530312 asyncResp->res.jsonValue["AssetTag"] =
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700313 property;
314 });
Tejas Patil476b9cc2021-06-04 17:09:14 +0530315 }
316
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700317 for (const char* interface : hasIndicatorLed)
318 {
319 if (std::find(interfaces2.begin(),
320 interfaces2.end(),
321 interface) != interfaces2.end())
322 {
323 getIndicatorLedState(asyncResp);
324 getLocationIndicatorActive(asyncResp);
325 break;
326 }
327 }
328
SunnySrivastava198488ad7f02020-12-03 10:27:52 -0600329 crow::connections::systemBus->async_method_call(
330 [asyncResp, chassisId(std::string(chassisId))](
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700331 const boost::system::error_code /*ec2*/,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800332 const dbus::utility::DBusPropertiesMap&
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700333 propertiesList) {
Ed Tanous168e20c2021-12-13 14:39:53 -0800334 for (const std::pair<
335 std::string,
336 dbus::utility::DbusVariantType>&
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700337 property : propertiesList)
SunnySrivastava198488ad7f02020-12-03 10:27:52 -0600338 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700339 // Store DBus properties that are also
340 // Redfish properties with same name and a
341 // string value
342 const std::string& propertyName =
343 property.first;
344 if ((propertyName == "PartNumber") ||
345 (propertyName == "SerialNumber") ||
346 (propertyName == "Manufacturer") ||
Alpana Kumaricaa11f72021-11-09 12:16:18 -0600347 (propertyName == "Model") ||
348 (propertyName == "SparePartNumber"))
Shawn McCarney99cffd72019-03-01 10:46:20 -0600349 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700350 const std::string* value =
351 std::get_if<std::string>(
352 &property.second);
Alpana Kumaricaa11f72021-11-09 12:16:18 -0600353 if (value == nullptr)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700354 {
Alpana Kumaricaa11f72021-11-09 12:16:18 -0600355 BMCWEB_LOG_ERROR
356 << "Null value returned for "
357 << propertyName;
358 messages::internalError(
359 asyncResp->res);
360 return;
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700361 }
Alpana Kumaricaa11f72021-11-09 12:16:18 -0600362 // SparePartNumber is optional on D-Bus
363 // so skip if it is empty
364 if (propertyName == "SparePartNumber")
365 {
Ed Tanous26f69762022-01-25 09:49:11 -0800366 if (value->empty())
Alpana Kumaricaa11f72021-11-09 12:16:18 -0600367 {
368 continue;
369 }
370 }
371 asyncResp->res.jsonValue[propertyName] =
372 *value;
Shawn McCarney99cffd72019-03-01 10:46:20 -0600373 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700374 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700375 asyncResp->res.jsonValue["Name"] = chassisId;
376 asyncResp->res.jsonValue["Id"] = chassisId;
zhanghch050256b692021-06-12 10:26:52 +0800377#ifdef BMCWEB_ALLOW_DEPRECATED_POWER_THERMAL
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700378 asyncResp->res.jsonValue["Thermal"] = {
379 {"@odata.id", "/redfish/v1/Chassis/" +
380 chassisId + "/Thermal"}};
381 // Power object
382 asyncResp->res.jsonValue["Power"] = {
383 {"@odata.id", "/redfish/v1/Chassis/" +
384 chassisId + "/Power"}};
zhanghch050256b692021-06-12 10:26:52 +0800385#endif
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700386 // SensorCollection
387 asyncResp->res.jsonValue["Sensors"] = {
388 {"@odata.id", "/redfish/v1/Chassis/" +
389 chassisId + "/Sensors"}};
390 asyncResp->res.jsonValue["Status"] = {
391 {"State", "Enabled"},
392 };
393
394 asyncResp->res
395 .jsonValue["Links"]["ComputerSystems"] = {
396 {{"@odata.id",
397 "/redfish/v1/Systems/system"}}};
398 asyncResp->res.jsonValue["Links"]["ManagedBy"] =
399 {{{"@odata.id",
400 "/redfish/v1/Managers/bmc"}}};
401 getChassisState(asyncResp);
402 },
403 connectionName, path,
404 "org.freedesktop.DBus.Properties", "GetAll",
405 "xyz.openbmc_project.Inventory.Decorator.Asset");
Sharad Yadav2c37b4b2021-05-10 12:53:38 +0530406
Willy Tu308f70c2021-09-28 20:24:52 -0700407 for (const auto& interface : interfaces2)
Sharad Yadav2c37b4b2021-05-10 12:53:38 +0530408 {
Willy Tu308f70c2021-09-28 20:24:52 -0700409 if (interface == "xyz.openbmc_project.Common.UUID")
410 {
411 getChassisUUID(asyncResp, connectionName, path);
412 }
George Liu0fda0f12021-11-16 10:06:17 +0800413 else if (
414 interface ==
415 "xyz.openbmc_project.Inventory.Decorator.LocationCode")
Willy Tu308f70c2021-09-28 20:24:52 -0700416 {
417 getChassisLocationCode(asyncResp,
418 connectionName, path);
419 }
Sharad Yadav2c37b4b2021-05-10 12:53:38 +0530420 }
421
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700422 return;
423 }
424
425 // Couldn't find an object with that name. return an error
426 messages::resourceNotFound(
Gunnar Mills5ac5a2f2022-01-04 12:26:41 -0600427 asyncResp->res, "#Chassis.v1_16_0.Chassis", chassisId);
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700428 },
429 "xyz.openbmc_project.ObjectMapper",
430 "/xyz/openbmc_project/object_mapper",
431 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
432 "/xyz/openbmc_project/inventory", 0, interfaces);
433
434 getPhysicalSecurityData(asyncResp);
435 });
436
437 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700438 .privileges(redfish::privileges::patchChassis)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700439 .methods(
440 boost::beast::http::verb::
441 patch)([](const crow::Request& req,
442 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
443 const std::string& param) {
444 std::optional<bool> locationIndicatorActive;
445 std::optional<std::string> indicatorLed;
446
447 if (param.empty())
448 {
449 return;
450 }
451
Willy Tu15ed6782021-12-14 11:03:16 -0800452 if (!json_util::readJsonPatch(
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700453 req, asyncResp->res, "LocationIndicatorActive",
454 locationIndicatorActive, "IndicatorLED", indicatorLed))
455 {
456 return;
457 }
458
459 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
460 if (!locationIndicatorActive && !indicatorLed)
461 {
462 return; // delete this when we support more patch properties
463 }
464 if (indicatorLed)
465 {
466 asyncResp->res.addHeader(
467 boost::beast::http::field::warning,
George Liu0fda0f12021-11-16 10:06:17 +0800468 "299 - \"IndicatorLED is deprecated. Use LocationIndicatorActive instead.\"");
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700469 }
470
471 const std::array<const char*, 2> interfaces = {
472 "xyz.openbmc_project.Inventory.Item.Board",
473 "xyz.openbmc_project.Inventory.Item.Chassis"};
474
475 const std::string& chassisId = param;
476
477 crow::connections::systemBus->async_method_call(
478 [asyncResp, chassisId, locationIndicatorActive, indicatorLed](
479 const boost::system::error_code ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800480 const dbus::utility::MapperGetSubTreeResponse& subtree) {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700481 if (ec)
482 {
483 messages::internalError(asyncResp->res);
484 return;
485 }
486
487 // Iterate over all retrieved ObjectPaths.
488 for (const std::pair<
489 std::string,
490 std::vector<std::pair<std::string,
491 std::vector<std::string>>>>&
492 object : subtree)
493 {
494 const std::string& path = object.first;
495 const std::vector<
496 std::pair<std::string, std::vector<std::string>>>&
497 connectionNames = object.second;
498
George Liu997093e2021-11-17 17:43:45 +0800499 sdbusplus::message::object_path objPath(path);
500 if (objPath.filename() != chassisId)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700501 {
502 continue;
503 }
504
Ed Tanous26f69762022-01-25 09:49:11 -0800505 if (connectionNames.empty())
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700506 {
507 BMCWEB_LOG_ERROR << "Got 0 Connection names";
508 continue;
509 }
510
511 const std::vector<std::string>& interfaces3 =
512 connectionNames[0].second;
513
514 const std::array<const char*, 2> hasIndicatorLed = {
515 "xyz.openbmc_project.Inventory.Item.Panel",
George Liu0fda0f12021-11-16 10:06:17 +0800516 "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700517 bool indicatorChassis = false;
518 for (const char* interface : hasIndicatorLed)
519 {
520 if (std::find(interfaces3.begin(),
521 interfaces3.end(),
522 interface) != interfaces3.end())
523 {
524 indicatorChassis = true;
525 break;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700526 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700527 }
528 if (locationIndicatorActive)
529 {
530 if (indicatorChassis)
531 {
532 setLocationIndicatorActive(
533 asyncResp, *locationIndicatorActive);
534 }
535 else
536 {
537 messages::propertyUnknown(
538 asyncResp->res, "LocationIndicatorActive");
539 }
540 }
541 if (indicatorLed)
542 {
543 if (indicatorChassis)
544 {
545 setIndicatorLedState(asyncResp, *indicatorLed);
546 }
547 else
548 {
549 messages::propertyUnknown(asyncResp->res,
550 "IndicatorLED");
551 }
552 }
553 return;
James Feist1c8fba92019-12-20 15:12:07 -0800554 }
555
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700556 messages::resourceNotFound(
557 asyncResp->res, "#Chassis.v1_14_0.Chassis", chassisId);
558 },
559 "xyz.openbmc_project.ObjectMapper",
560 "/xyz/openbmc_project/object_mapper",
561 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
562 "/xyz/openbmc_project/inventory", 0, interfaces);
563 });
564}
P.K. Leedd99e042020-06-17 19:43:16 +0800565
zhanghch058d1b46d2021-04-01 11:18:24 +0800566inline void
567 doChassisPowerCycle(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
P.K. Leedd99e042020-06-17 19:43:16 +0800568{
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700569 const char* busName = "xyz.openbmc_project.ObjectMapper";
570 const char* path = "/xyz/openbmc_project/object_mapper";
571 const char* interface = "xyz.openbmc_project.ObjectMapper";
572 const char* method = "GetSubTreePaths";
P.K. Leedd99e042020-06-17 19:43:16 +0800573
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700574 const std::array<const char*, 1> interfaces = {
575 "xyz.openbmc_project.State.Chassis"};
576
577 // Use mapper to get subtree paths.
P.K. Leedd99e042020-06-17 19:43:16 +0800578 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -0800579 [asyncResp](
580 const boost::system::error_code ec,
581 const dbus::utility::MapperGetSubTreePathsResponse& chassisList) {
P.K. Leedd99e042020-06-17 19:43:16 +0800582 if (ec)
583 {
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700584 BMCWEB_LOG_DEBUG << "[mapper] Bad D-Bus request error: " << ec;
P.K. Leedd99e042020-06-17 19:43:16 +0800585 messages::internalError(asyncResp->res);
586 return;
587 }
588
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700589 const char* processName = "xyz.openbmc_project.State.Chassis";
590 const char* interfaceName = "xyz.openbmc_project.State.Chassis";
591 const char* destProperty = "RequestedPowerTransition";
592 const std::string propertyValue =
593 "xyz.openbmc_project.State.Chassis.Transition.PowerCycle";
594 std::string objectPath =
595 "/xyz/openbmc_project/state/chassis_system0";
596
597 /* Look for system reset chassis path */
598 if ((std::find(chassisList.begin(), chassisList.end(),
599 objectPath)) == chassisList.end())
600 {
601 /* We prefer to reset the full chassis_system, but if it doesn't
602 * exist on some platforms, fall back to a host-only power reset
603 */
604 objectPath = "/xyz/openbmc_project/state/chassis0";
605 }
606
607 crow::connections::systemBus->async_method_call(
608 [asyncResp](const boost::system::error_code ec) {
609 // Use "Set" method to set the property value.
610 if (ec)
611 {
612 BMCWEB_LOG_DEBUG << "[Set] Bad D-Bus request error: "
613 << ec;
614 messages::internalError(asyncResp->res);
615 return;
616 }
617
618 messages::success(asyncResp->res);
619 },
620 processName, objectPath, "org.freedesktop.DBus.Properties",
621 "Set", interfaceName, destProperty,
Ed Tanous168e20c2021-12-13 14:39:53 -0800622 dbus::utility::DbusVariantType{propertyValue});
P.K. Leedd99e042020-06-17 19:43:16 +0800623 },
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700624 busName, path, interface, method, "/", 0, interfaces);
P.K. Leedd99e042020-06-17 19:43:16 +0800625}
626
627/**
628 * ChassisResetAction class supports the POST method for the Reset
629 * action.
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700630 * Function handles POST method request.
631 * Analyzes POST body before sending Reset request data to D-Bus.
P.K. Leedd99e042020-06-17 19:43:16 +0800632 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700633
634inline void requestRoutesChassisResetAction(App& app)
P.K. Leedd99e042020-06-17 19:43:16 +0800635{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700636 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Actions/Chassis.Reset/")
Ed Tanoused398212021-06-09 17:05:54 -0700637 .privileges(redfish::privileges::postChassis)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700638 .methods(boost::beast::http::verb::post)(
639 [](const crow::Request& req,
640 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
641 const std::string&) {
642 BMCWEB_LOG_DEBUG << "Post Chassis Reset.";
P.K. Leedd99e042020-06-17 19:43:16 +0800643
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700644 std::string resetType;
P.K. Leedd99e042020-06-17 19:43:16 +0800645
Willy Tu15ed6782021-12-14 11:03:16 -0800646 if (!json_util::readJsonAction(req, asyncResp->res, "ResetType",
647 resetType))
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700648 {
649 return;
650 }
P.K. Leedd99e042020-06-17 19:43:16 +0800651
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700652 if (resetType != "PowerCycle")
653 {
654 BMCWEB_LOG_DEBUG << "Invalid property value for ResetType: "
655 << resetType;
656 messages::actionParameterNotSupported(
657 asyncResp->res, resetType, "ResetType");
P.K. Leedd99e042020-06-17 19:43:16 +0800658
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700659 return;
660 }
661 doChassisPowerCycle(asyncResp);
662 });
663}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530664
665/**
666 * ChassisResetActionInfo derived class for delivering Chassis
667 * ResetType AllowableValues using ResetInfo schema.
668 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700669inline void requestRoutesChassisResetActionInfo(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530670{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700671 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -0700672 .privileges(redfish::privileges::getActionInfo)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700673 .methods(boost::beast::http::verb::get)(
674 [](const crow::Request&,
675 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
676 const std::string& chassisId)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530677
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700678 {
679 asyncResp->res.jsonValue = {
680 {"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"},
681 {"@odata.id",
682 "/redfish/v1/Chassis/" + chassisId + "/ResetActionInfo"},
683 {"Name", "Reset Action Info"},
684 {"Id", "ResetActionInfo"},
685 {"Parameters",
686 {{{"Name", "ResetType"},
687 {"Required", true},
688 {"DataType", "String"},
689 {"AllowableValues", {"PowerCycle"}}}}}};
690 });
691}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530692
Ed Tanous1abe55e2018-09-05 08:30:59 -0700693} // namespace redfish