blob: 8eb982198a9297238f9d4d2d987249845f996c15 [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>
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010022#include <boost/container/flat_map.hpp>
Ed Tanous168e20c2021-12-13 14:39:53 -080023#include <dbus_utility.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 {
49 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
50 messages::internalError(aResp->res);
51 return;
52 }
53
Jonathan Doman1e1e5982021-06-11 09:36:17 -070054 BMCWEB_LOG_DEBUG << "Chassis state: " << chassisState;
55 // Verify Chassis State
56 if (chassisState ==
57 "xyz.openbmc_project.State.Chassis.PowerState.On")
Gunnar Millsbeeca0a2019-02-14 16:30:45 -060058 {
Jonathan Doman1e1e5982021-06-11 09:36:17 -070059 aResp->res.jsonValue["PowerState"] = "On";
60 aResp->res.jsonValue["Status"]["State"] = "Enabled";
Gunnar Millsbeeca0a2019-02-14 16:30:45 -060061 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -070062 else if (chassisState ==
63 "xyz.openbmc_project.State.Chassis.PowerState.Off")
64 {
65 aResp->res.jsonValue["PowerState"] = "Off";
66 aResp->res.jsonValue["Status"]["State"] = "StandbyOffline";
67 }
68 });
Gunnar Millsbeeca0a2019-02-14 16:30:45 -060069}
70
71/**
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010072 * DBus types primitives for several generic DBus interfaces
73 * TODO(Pawel) consider move this to separate file into boost::dbus
74 */
Ed Tanousaa2e59c2018-04-12 12:17:20 -070075using ManagedObjectsType = std::vector<std::pair<
76 sdbusplus::message::object_path,
Ed Tanous168e20c2021-12-13 14:39:53 -080077 std::vector<std::pair<
78 std::string,
79 std::vector<std::pair<std::string, dbus::utility::DbusVariantType>>>>>>;
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010080
Ed Tanous168e20c2021-12-13 14:39:53 -080081using PropertiesType =
82 boost::container::flat_map<std::string, dbus::utility::DbusVariantType>;
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010083
zhanghch058d1b46d2021-04-01 11:18:24 +080084inline void getIntrusionByService(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous23a21a12020-07-25 04:45:05 +000085 const std::string& service,
86 const std::string& objPath)
Qiang XUc1819422019-02-27 13:51:32 +080087{
88 BMCWEB_LOG_DEBUG << "Get intrusion status by service \n";
89
Jonathan Doman1e1e5982021-06-11 09:36:17 -070090 sdbusplus::asio::getProperty<std::string>(
91 *crow::connections::systemBus, service, objPath,
92 "xyz.openbmc_project.Chassis.Intrusion", "Status",
Qiang XUc1819422019-02-27 13:51:32 +080093 [aResp{std::move(aResp)}](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -070094 const std::string& value) {
Qiang XUc1819422019-02-27 13:51:32 +080095 if (ec)
96 {
Gunnar Mills4e0453b2020-07-08 14:00:30 -050097 // do not add err msg in redfish response, because this is not
Qiang XUc1819422019-02-27 13:51:32 +080098 // mandatory property
99 BMCWEB_LOG_ERROR << "DBUS response error " << ec << "\n";
100 return;
101 }
102
Qiang XUc1819422019-02-27 13:51:32 +0800103 aResp->res.jsonValue["PhysicalSecurity"] = {
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700104 {"IntrusionSensorNumber", 1}, {"IntrusionSensor", value}};
105 });
Qiang XUc1819422019-02-27 13:51:32 +0800106}
107
108/**
109 * Retrieves physical security properties over dbus
110 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800111inline void getPhysicalSecurityData(std::shared_ptr<bmcweb::AsyncResp> aResp)
Qiang XUc1819422019-02-27 13:51:32 +0800112{
113 crow::connections::systemBus->async_method_call(
114 [aResp{std::move(aResp)}](
115 const boost::system::error_code ec,
116 const std::vector<std::pair<
117 std::string,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500118 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
119 subtree) {
Qiang XUc1819422019-02-27 13:51:32 +0800120 if (ec)
121 {
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500122 // do not add err msg in redfish response, because this is not
Qiang XUc1819422019-02-27 13:51:32 +0800123 // mandatory property
Andrew Geissler54fbf172021-11-11 15:59:30 -0600124 BMCWEB_LOG_INFO << "DBUS error: no matched iface " << ec
125 << "\n";
Qiang XUc1819422019-02-27 13:51:32 +0800126 return;
127 }
128 // Iterate over all retrieved ObjectPaths.
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500129 for (const auto& object : subtree)
Qiang XUc1819422019-02-27 13:51:32 +0800130 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500131 for (const auto& service : object.second)
Qiang XUc1819422019-02-27 13:51:32 +0800132 {
133 getIntrusionByService(aResp, service.first, object.first);
134 return;
135 }
136 }
137 },
138 "xyz.openbmc_project.ObjectMapper",
139 "/xyz/openbmc_project/object_mapper",
140 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous271584a2019-07-09 16:24:22 -0700141 "/xyz/openbmc_project/Intrusion", 1,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500142 std::array<const char*, 1>{"xyz.openbmc_project.Chassis.Intrusion"});
Qiang XUc1819422019-02-27 13:51:32 +0800143}
144
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100145/**
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100146 * ChassisCollection derived class for delivering Chassis Collection Schema
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700147 * Functions triggers appropriate requests on DBus
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100148 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700149inline void requestRoutesChassisCollection(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700150{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700151 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/")
Ed Tanoused398212021-06-09 17:05:54 -0700152 .privileges(redfish::privileges::getChassisCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700153 .methods(boost::beast::http::verb::get)(
154 [](const crow::Request&,
155 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
156 asyncResp->res.jsonValue["@odata.type"] =
157 "#ChassisCollection.ChassisCollection";
158 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Chassis";
159 asyncResp->res.jsonValue["Name"] = "Chassis Collection";
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100160
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700161 collection_util::getCollectionMembers(
162 asyncResp, "/redfish/v1/Chassis",
163 {"xyz.openbmc_project.Inventory.Item.Board",
164 "xyz.openbmc_project.Inventory.Item.Chassis"});
165 });
166}
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100167
Willy Tu308f70c2021-09-28 20:24:52 -0700168inline void
169 getChassisLocationCode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
170 const std::string& connectionName,
171 const std::string& path)
172{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700173 sdbusplus::asio::getProperty<std::string>(
174 *crow::connections::systemBus, connectionName, path,
175 "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode",
Willy Tu308f70c2021-09-28 20:24:52 -0700176 [asyncResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700177 const std::string& property) {
Willy Tu308f70c2021-09-28 20:24:52 -0700178 if (ec)
179 {
George Liu0fda0f12021-11-16 10:06:17 +0800180 BMCWEB_LOG_DEBUG << "DBUS response error for Location";
Willy Tu308f70c2021-09-28 20:24:52 -0700181 messages::internalError(asyncResp->res);
182 return;
183 }
184
Willy Tu308f70c2021-09-28 20:24:52 -0700185 asyncResp->res
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700186 .jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
187 property;
188 });
Willy Tu308f70c2021-09-28 20:24:52 -0700189}
190
191inline void getChassisUUID(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
192 const std::string& connectionName,
193 const std::string& path)
194{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700195 sdbusplus::asio::getProperty<std::string>(
196 *crow::connections::systemBus, connectionName, path,
197 "xyz.openbmc_project.Common.UUID", "UUID",
Willy Tu308f70c2021-09-28 20:24:52 -0700198 [asyncResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700199 const std::string& chassisUUID) {
Willy Tu308f70c2021-09-28 20:24:52 -0700200 if (ec)
201 {
George Liu0fda0f12021-11-16 10:06:17 +0800202 BMCWEB_LOG_DEBUG << "DBUS response error for UUID";
Willy Tu308f70c2021-09-28 20:24:52 -0700203 messages::internalError(asyncResp->res);
204 return;
205 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700206 asyncResp->res.jsonValue["UUID"] = chassisUUID;
207 });
Willy Tu308f70c2021-09-28 20:24:52 -0700208}
209
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100210/**
211 * Chassis override class for delivering Chassis Schema
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700212 * Functions triggers appropriate requests on DBus
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100213 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700214inline void requestRoutesChassis(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700215{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700216 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700217 .privileges(redfish::privileges::getChassis)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700218 .methods(
219 boost::beast::http::verb::get)([](const crow::Request&,
220 const std::shared_ptr<
221 bmcweb::AsyncResp>& asyncResp,
222 const std::string& chassisId) {
223 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,
230 const crow::openbmc_mapper::GetSubTreeType& subtree) {
231 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
273 if (connectionNames.size() < 1)
274 {
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";
285 asyncResp->res.jsonValue["Actions"]["#Chassis.Reset"] =
286 {{"target", "/redfish/v1/Chassis/" + chassisId +
287 "/Actions/Chassis.Reset"},
288 {"@Redfish.ActionInfo", "/redfish/v1/Chassis/" +
289 chassisId +
290 "/ResetActionInfo"}};
291 asyncResp->res.jsonValue["PCIeDevices"] = {
292 {"@odata.id",
293 "/redfish/v1/Systems/system/PCIeDevices"}};
294
295 const std::string& connectionName =
296 connectionNames[0].first;
297
298 const std::vector<std::string>& interfaces2 =
299 connectionNames[0].second;
300 const std::array<const char*, 2> hasIndicatorLed = {
301 "xyz.openbmc_project.Inventory.Item.Panel",
George Liu0fda0f12021-11-16 10:06:17 +0800302 "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700303
Tejas Patil476b9cc2021-06-04 17:09:14 +0530304 const std::string assetTagInterface =
George Liu0fda0f12021-11-16 10:06:17 +0800305 "xyz.openbmc_project.Inventory.Decorator.AssetTag";
Tejas Patil476b9cc2021-06-04 17:09:14 +0530306 if (std::find(interfaces2.begin(), interfaces2.end(),
307 assetTagInterface) != interfaces2.end())
308 {
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700309 sdbusplus::asio::getProperty<std::string>(
310 *crow::connections::systemBus, connectionName,
311 path, assetTagInterface, "AssetTag",
Tejas Patil476b9cc2021-06-04 17:09:14 +0530312 [asyncResp, chassisId(std::string(chassisId))](
313 const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700314 const std::string& property) {
Tejas Patil476b9cc2021-06-04 17:09:14 +0530315 if (ec)
316 {
317 BMCWEB_LOG_DEBUG
George Liu0fda0f12021-11-16 10:06:17 +0800318 << "DBus response error for AssetTag";
Tejas Patil476b9cc2021-06-04 17:09:14 +0530319 messages::internalError(asyncResp->res);
320 return;
321 }
Tejas Patil476b9cc2021-06-04 17:09:14 +0530322 asyncResp->res.jsonValue["AssetTag"] =
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700323 property;
324 });
Tejas Patil476b9cc2021-06-04 17:09:14 +0530325 }
326
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700327 for (const char* interface : hasIndicatorLed)
328 {
329 if (std::find(interfaces2.begin(),
330 interfaces2.end(),
331 interface) != interfaces2.end())
332 {
333 getIndicatorLedState(asyncResp);
334 getLocationIndicatorActive(asyncResp);
335 break;
336 }
337 }
338
SunnySrivastava198488ad7f02020-12-03 10:27:52 -0600339 crow::connections::systemBus->async_method_call(
340 [asyncResp, chassisId(std::string(chassisId))](
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700341 const boost::system::error_code /*ec2*/,
342 const std::vector<
Ed Tanous168e20c2021-12-13 14:39:53 -0800343 std::pair<std::string,
344 dbus::utility::DbusVariantType>>&
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700345 propertiesList) {
Ed Tanous168e20c2021-12-13 14:39:53 -0800346 for (const std::pair<
347 std::string,
348 dbus::utility::DbusVariantType>&
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700349 property : propertiesList)
SunnySrivastava198488ad7f02020-12-03 10:27:52 -0600350 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700351 // Store DBus properties that are also
352 // Redfish properties with same name and a
353 // string value
354 const std::string& propertyName =
355 property.first;
356 if ((propertyName == "PartNumber") ||
357 (propertyName == "SerialNumber") ||
358 (propertyName == "Manufacturer") ||
Alpana Kumaricaa11f72021-11-09 12:16:18 -0600359 (propertyName == "Model") ||
360 (propertyName == "SparePartNumber"))
Shawn McCarney99cffd72019-03-01 10:46:20 -0600361 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700362 const std::string* value =
363 std::get_if<std::string>(
364 &property.second);
Alpana Kumaricaa11f72021-11-09 12:16:18 -0600365 if (value == nullptr)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700366 {
Alpana Kumaricaa11f72021-11-09 12:16:18 -0600367 BMCWEB_LOG_ERROR
368 << "Null value returned for "
369 << propertyName;
370 messages::internalError(
371 asyncResp->res);
372 return;
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700373 }
Alpana Kumaricaa11f72021-11-09 12:16:18 -0600374 // SparePartNumber is optional on D-Bus
375 // so skip if it is empty
376 if (propertyName == "SparePartNumber")
377 {
378 if (*value == "")
379 {
380 continue;
381 }
382 }
383 asyncResp->res.jsonValue[propertyName] =
384 *value;
Shawn McCarney99cffd72019-03-01 10:46:20 -0600385 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700386 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700387 asyncResp->res.jsonValue["Name"] = chassisId;
388 asyncResp->res.jsonValue["Id"] = chassisId;
zhanghch050256b692021-06-12 10:26:52 +0800389#ifdef BMCWEB_ALLOW_DEPRECATED_POWER_THERMAL
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700390 asyncResp->res.jsonValue["Thermal"] = {
391 {"@odata.id", "/redfish/v1/Chassis/" +
392 chassisId + "/Thermal"}};
393 // Power object
394 asyncResp->res.jsonValue["Power"] = {
395 {"@odata.id", "/redfish/v1/Chassis/" +
396 chassisId + "/Power"}};
zhanghch050256b692021-06-12 10:26:52 +0800397#endif
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700398 // SensorCollection
399 asyncResp->res.jsonValue["Sensors"] = {
400 {"@odata.id", "/redfish/v1/Chassis/" +
401 chassisId + "/Sensors"}};
402 asyncResp->res.jsonValue["Status"] = {
403 {"State", "Enabled"},
404 };
405
406 asyncResp->res
407 .jsonValue["Links"]["ComputerSystems"] = {
408 {{"@odata.id",
409 "/redfish/v1/Systems/system"}}};
410 asyncResp->res.jsonValue["Links"]["ManagedBy"] =
411 {{{"@odata.id",
412 "/redfish/v1/Managers/bmc"}}};
413 getChassisState(asyncResp);
414 },
415 connectionName, path,
416 "org.freedesktop.DBus.Properties", "GetAll",
417 "xyz.openbmc_project.Inventory.Decorator.Asset");
Sharad Yadav2c37b4b2021-05-10 12:53:38 +0530418
Willy Tu308f70c2021-09-28 20:24:52 -0700419 for (const auto& interface : interfaces2)
Sharad Yadav2c37b4b2021-05-10 12:53:38 +0530420 {
Willy Tu308f70c2021-09-28 20:24:52 -0700421 if (interface == "xyz.openbmc_project.Common.UUID")
422 {
423 getChassisUUID(asyncResp, connectionName, path);
424 }
George Liu0fda0f12021-11-16 10:06:17 +0800425 else if (
426 interface ==
427 "xyz.openbmc_project.Inventory.Decorator.LocationCode")
Willy Tu308f70c2021-09-28 20:24:52 -0700428 {
429 getChassisLocationCode(asyncResp,
430 connectionName, path);
431 }
Sharad Yadav2c37b4b2021-05-10 12:53:38 +0530432 }
433
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700434 return;
435 }
436
437 // Couldn't find an object with that name. return an error
438 messages::resourceNotFound(
Gunnar Mills5ac5a2f2022-01-04 12:26:41 -0600439 asyncResp->res, "#Chassis.v1_16_0.Chassis", chassisId);
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700440 },
441 "xyz.openbmc_project.ObjectMapper",
442 "/xyz/openbmc_project/object_mapper",
443 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
444 "/xyz/openbmc_project/inventory", 0, interfaces);
445
446 getPhysicalSecurityData(asyncResp);
447 });
448
449 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700450 .privileges(redfish::privileges::patchChassis)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700451 .methods(
452 boost::beast::http::verb::
453 patch)([](const crow::Request& req,
454 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
455 const std::string& param) {
456 std::optional<bool> locationIndicatorActive;
457 std::optional<std::string> indicatorLed;
458
459 if (param.empty())
460 {
461 return;
462 }
463
464 if (!json_util::readJson(
465 req, asyncResp->res, "LocationIndicatorActive",
466 locationIndicatorActive, "IndicatorLED", indicatorLed))
467 {
468 return;
469 }
470
471 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
472 if (!locationIndicatorActive && !indicatorLed)
473 {
474 return; // delete this when we support more patch properties
475 }
476 if (indicatorLed)
477 {
478 asyncResp->res.addHeader(
479 boost::beast::http::field::warning,
George Liu0fda0f12021-11-16 10:06:17 +0800480 "299 - \"IndicatorLED is deprecated. Use LocationIndicatorActive instead.\"");
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700481 }
482
483 const std::array<const char*, 2> interfaces = {
484 "xyz.openbmc_project.Inventory.Item.Board",
485 "xyz.openbmc_project.Inventory.Item.Chassis"};
486
487 const std::string& chassisId = param;
488
489 crow::connections::systemBus->async_method_call(
490 [asyncResp, chassisId, locationIndicatorActive, indicatorLed](
491 const boost::system::error_code ec,
492 const crow::openbmc_mapper::GetSubTreeType& subtree) {
493 if (ec)
494 {
495 messages::internalError(asyncResp->res);
496 return;
497 }
498
499 // Iterate over all retrieved ObjectPaths.
500 for (const std::pair<
501 std::string,
502 std::vector<std::pair<std::string,
503 std::vector<std::string>>>>&
504 object : subtree)
505 {
506 const std::string& path = object.first;
507 const std::vector<
508 std::pair<std::string, std::vector<std::string>>>&
509 connectionNames = object.second;
510
George Liu997093e2021-11-17 17:43:45 +0800511 sdbusplus::message::object_path objPath(path);
512 if (objPath.filename() != chassisId)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700513 {
514 continue;
515 }
516
517 if (connectionNames.size() < 1)
518 {
519 BMCWEB_LOG_ERROR << "Got 0 Connection names";
520 continue;
521 }
522
523 const std::vector<std::string>& interfaces3 =
524 connectionNames[0].second;
525
526 const std::array<const char*, 2> hasIndicatorLed = {
527 "xyz.openbmc_project.Inventory.Item.Panel",
George Liu0fda0f12021-11-16 10:06:17 +0800528 "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700529 bool indicatorChassis = false;
530 for (const char* interface : hasIndicatorLed)
531 {
532 if (std::find(interfaces3.begin(),
533 interfaces3.end(),
534 interface) != interfaces3.end())
535 {
536 indicatorChassis = true;
537 break;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700538 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700539 }
540 if (locationIndicatorActive)
541 {
542 if (indicatorChassis)
543 {
544 setLocationIndicatorActive(
545 asyncResp, *locationIndicatorActive);
546 }
547 else
548 {
549 messages::propertyUnknown(
550 asyncResp->res, "LocationIndicatorActive");
551 }
552 }
553 if (indicatorLed)
554 {
555 if (indicatorChassis)
556 {
557 setIndicatorLedState(asyncResp, *indicatorLed);
558 }
559 else
560 {
561 messages::propertyUnknown(asyncResp->res,
562 "IndicatorLED");
563 }
564 }
565 return;
James Feist1c8fba92019-12-20 15:12:07 -0800566 }
567
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700568 messages::resourceNotFound(
569 asyncResp->res, "#Chassis.v1_14_0.Chassis", chassisId);
570 },
571 "xyz.openbmc_project.ObjectMapper",
572 "/xyz/openbmc_project/object_mapper",
573 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
574 "/xyz/openbmc_project/inventory", 0, interfaces);
575 });
576}
P.K. Leedd99e042020-06-17 19:43:16 +0800577
zhanghch058d1b46d2021-04-01 11:18:24 +0800578inline void
579 doChassisPowerCycle(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
P.K. Leedd99e042020-06-17 19:43:16 +0800580{
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700581 const char* busName = "xyz.openbmc_project.ObjectMapper";
582 const char* path = "/xyz/openbmc_project/object_mapper";
583 const char* interface = "xyz.openbmc_project.ObjectMapper";
584 const char* method = "GetSubTreePaths";
P.K. Leedd99e042020-06-17 19:43:16 +0800585
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700586 const std::array<const char*, 1> interfaces = {
587 "xyz.openbmc_project.State.Chassis"};
588
589 // Use mapper to get subtree paths.
P.K. Leedd99e042020-06-17 19:43:16 +0800590 crow::connections::systemBus->async_method_call(
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700591 [asyncResp](const boost::system::error_code ec,
592 const std::vector<std::string>& chassisList) {
P.K. Leedd99e042020-06-17 19:43:16 +0800593 if (ec)
594 {
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700595 BMCWEB_LOG_DEBUG << "[mapper] Bad D-Bus request error: " << ec;
P.K. Leedd99e042020-06-17 19:43:16 +0800596 messages::internalError(asyncResp->res);
597 return;
598 }
599
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700600 const char* processName = "xyz.openbmc_project.State.Chassis";
601 const char* interfaceName = "xyz.openbmc_project.State.Chassis";
602 const char* destProperty = "RequestedPowerTransition";
603 const std::string propertyValue =
604 "xyz.openbmc_project.State.Chassis.Transition.PowerCycle";
605 std::string objectPath =
606 "/xyz/openbmc_project/state/chassis_system0";
607
608 /* Look for system reset chassis path */
609 if ((std::find(chassisList.begin(), chassisList.end(),
610 objectPath)) == chassisList.end())
611 {
612 /* We prefer to reset the full chassis_system, but if it doesn't
613 * exist on some platforms, fall back to a host-only power reset
614 */
615 objectPath = "/xyz/openbmc_project/state/chassis0";
616 }
617
618 crow::connections::systemBus->async_method_call(
619 [asyncResp](const boost::system::error_code ec) {
620 // Use "Set" method to set the property value.
621 if (ec)
622 {
623 BMCWEB_LOG_DEBUG << "[Set] Bad D-Bus request error: "
624 << ec;
625 messages::internalError(asyncResp->res);
626 return;
627 }
628
629 messages::success(asyncResp->res);
630 },
631 processName, objectPath, "org.freedesktop.DBus.Properties",
632 "Set", interfaceName, destProperty,
Ed Tanous168e20c2021-12-13 14:39:53 -0800633 dbus::utility::DbusVariantType{propertyValue});
P.K. Leedd99e042020-06-17 19:43:16 +0800634 },
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700635 busName, path, interface, method, "/", 0, interfaces);
P.K. Leedd99e042020-06-17 19:43:16 +0800636}
637
638/**
639 * ChassisResetAction class supports the POST method for the Reset
640 * action.
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700641 * Function handles POST method request.
642 * Analyzes POST body before sending Reset request data to D-Bus.
P.K. Leedd99e042020-06-17 19:43:16 +0800643 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700644
645inline void requestRoutesChassisResetAction(App& app)
P.K. Leedd99e042020-06-17 19:43:16 +0800646{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700647 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Actions/Chassis.Reset/")
Ed Tanoused398212021-06-09 17:05:54 -0700648 .privileges(redfish::privileges::postChassis)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700649 .methods(boost::beast::http::verb::post)(
650 [](const crow::Request& req,
651 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
652 const std::string&) {
653 BMCWEB_LOG_DEBUG << "Post Chassis Reset.";
P.K. Leedd99e042020-06-17 19:43:16 +0800654
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700655 std::string resetType;
P.K. Leedd99e042020-06-17 19:43:16 +0800656
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700657 if (!json_util::readJson(req, asyncResp->res, "ResetType",
658 resetType))
659 {
660 return;
661 }
P.K. Leedd99e042020-06-17 19:43:16 +0800662
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700663 if (resetType != "PowerCycle")
664 {
665 BMCWEB_LOG_DEBUG << "Invalid property value for ResetType: "
666 << resetType;
667 messages::actionParameterNotSupported(
668 asyncResp->res, resetType, "ResetType");
P.K. Leedd99e042020-06-17 19:43:16 +0800669
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700670 return;
671 }
672 doChassisPowerCycle(asyncResp);
673 });
674}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530675
676/**
677 * ChassisResetActionInfo derived class for delivering Chassis
678 * ResetType AllowableValues using ResetInfo schema.
679 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700680inline void requestRoutesChassisResetActionInfo(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530681{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700682 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -0700683 .privileges(redfish::privileges::getActionInfo)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700684 .methods(boost::beast::http::verb::get)(
685 [](const crow::Request&,
686 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
687 const std::string& chassisId)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530688
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700689 {
690 asyncResp->res.jsonValue = {
691 {"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"},
692 {"@odata.id",
693 "/redfish/v1/Chassis/" + chassisId + "/ResetActionInfo"},
694 {"Name", "Reset Action Info"},
695 {"Id", "ResetActionInfo"},
696 {"Parameters",
697 {{{"Name", "ResetType"},
698 {"Required", true},
699 {"DataType", "String"},
700 {"AllowableValues", {"PowerCycle"}}}}}};
701 });
702}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530703
Ed Tanous1abe55e2018-09-05 08:30:59 -0700704} // namespace redfish