blob: 597e5d0261caf7fc8c20153f9787a571580e650f [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 {
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
78/**
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010079 * DBus types primitives for several generic DBus interfaces
80 * TODO(Pawel) consider move this to separate file into boost::dbus
81 */
Ed Tanousaa2e59c2018-04-12 12:17:20 -070082using ManagedObjectsType = std::vector<std::pair<
83 sdbusplus::message::object_path,
Ed Tanous168e20c2021-12-13 14:39:53 -080084 std::vector<std::pair<
85 std::string,
86 std::vector<std::pair<std::string, dbus::utility::DbusVariantType>>>>>>;
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010087
Ed Tanous168e20c2021-12-13 14:39:53 -080088using PropertiesType =
89 boost::container::flat_map<std::string, dbus::utility::DbusVariantType>;
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010090
zhanghch058d1b46d2021-04-01 11:18:24 +080091inline void getIntrusionByService(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous23a21a12020-07-25 04:45:05 +000092 const std::string& service,
93 const std::string& objPath)
Qiang XUc1819422019-02-27 13:51:32 +080094{
95 BMCWEB_LOG_DEBUG << "Get intrusion status by service \n";
96
Jonathan Doman1e1e5982021-06-11 09:36:17 -070097 sdbusplus::asio::getProperty<std::string>(
98 *crow::connections::systemBus, service, objPath,
99 "xyz.openbmc_project.Chassis.Intrusion", "Status",
Qiang XUc1819422019-02-27 13:51:32 +0800100 [aResp{std::move(aResp)}](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700101 const std::string& value) {
Qiang XUc1819422019-02-27 13:51:32 +0800102 if (ec)
103 {
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500104 // do not add err msg in redfish response, because this is not
Qiang XUc1819422019-02-27 13:51:32 +0800105 // mandatory property
106 BMCWEB_LOG_ERROR << "DBUS response error " << ec << "\n";
107 return;
108 }
109
Qiang XUc1819422019-02-27 13:51:32 +0800110 aResp->res.jsonValue["PhysicalSecurity"] = {
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700111 {"IntrusionSensorNumber", 1}, {"IntrusionSensor", value}};
112 });
Qiang XUc1819422019-02-27 13:51:32 +0800113}
114
115/**
116 * Retrieves physical security properties over dbus
117 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800118inline void getPhysicalSecurityData(std::shared_ptr<bmcweb::AsyncResp> aResp)
Qiang XUc1819422019-02-27 13:51:32 +0800119{
120 crow::connections::systemBus->async_method_call(
121 [aResp{std::move(aResp)}](
122 const boost::system::error_code ec,
123 const std::vector<std::pair<
124 std::string,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500125 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
126 subtree) {
Qiang XUc1819422019-02-27 13:51:32 +0800127 if (ec)
128 {
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500129 // do not add err msg in redfish response, because this is not
Qiang XUc1819422019-02-27 13:51:32 +0800130 // mandatory property
Andrew Geissler54fbf172021-11-11 15:59:30 -0600131 BMCWEB_LOG_INFO << "DBUS error: no matched iface " << ec
132 << "\n";
Qiang XUc1819422019-02-27 13:51:32 +0800133 return;
134 }
135 // Iterate over all retrieved ObjectPaths.
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500136 for (const auto& object : subtree)
Qiang XUc1819422019-02-27 13:51:32 +0800137 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500138 for (const auto& service : object.second)
Qiang XUc1819422019-02-27 13:51:32 +0800139 {
140 getIntrusionByService(aResp, service.first, object.first);
141 return;
142 }
143 }
144 },
145 "xyz.openbmc_project.ObjectMapper",
146 "/xyz/openbmc_project/object_mapper",
147 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous271584a2019-07-09 16:24:22 -0700148 "/xyz/openbmc_project/Intrusion", 1,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500149 std::array<const char*, 1>{"xyz.openbmc_project.Chassis.Intrusion"});
Qiang XUc1819422019-02-27 13:51:32 +0800150}
151
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100152/**
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100153 * ChassisCollection derived class for delivering Chassis Collection Schema
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700154 * Functions triggers appropriate requests on DBus
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100155 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700156inline void requestRoutesChassisCollection(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700157{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700158 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/")
Ed Tanoused398212021-06-09 17:05:54 -0700159 .privileges(redfish::privileges::getChassisCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700160 .methods(boost::beast::http::verb::get)(
161 [](const crow::Request&,
162 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
163 asyncResp->res.jsonValue["@odata.type"] =
164 "#ChassisCollection.ChassisCollection";
165 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Chassis";
166 asyncResp->res.jsonValue["Name"] = "Chassis Collection";
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100167
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700168 collection_util::getCollectionMembers(
169 asyncResp, "/redfish/v1/Chassis",
170 {"xyz.openbmc_project.Inventory.Item.Board",
171 "xyz.openbmc_project.Inventory.Item.Chassis"});
172 });
173}
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100174
Willy Tu308f70c2021-09-28 20:24:52 -0700175inline void
176 getChassisLocationCode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
177 const std::string& connectionName,
178 const std::string& path)
179{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700180 sdbusplus::asio::getProperty<std::string>(
181 *crow::connections::systemBus, connectionName, path,
182 "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode",
Willy Tu308f70c2021-09-28 20:24:52 -0700183 [asyncResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700184 const std::string& property) {
Willy Tu308f70c2021-09-28 20:24:52 -0700185 if (ec)
186 {
George Liu0fda0f12021-11-16 10:06:17 +0800187 BMCWEB_LOG_DEBUG << "DBUS response error for Location";
Willy Tu308f70c2021-09-28 20:24:52 -0700188 messages::internalError(asyncResp->res);
189 return;
190 }
191
Willy Tu308f70c2021-09-28 20:24:52 -0700192 asyncResp->res
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700193 .jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
194 property;
195 });
Willy Tu308f70c2021-09-28 20:24:52 -0700196}
197
198inline void getChassisUUID(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
199 const std::string& connectionName,
200 const std::string& path)
201{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700202 sdbusplus::asio::getProperty<std::string>(
203 *crow::connections::systemBus, connectionName, path,
204 "xyz.openbmc_project.Common.UUID", "UUID",
Willy Tu308f70c2021-09-28 20:24:52 -0700205 [asyncResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700206 const std::string& chassisUUID) {
Willy Tu308f70c2021-09-28 20:24:52 -0700207 if (ec)
208 {
George Liu0fda0f12021-11-16 10:06:17 +0800209 BMCWEB_LOG_DEBUG << "DBUS response error for UUID";
Willy Tu308f70c2021-09-28 20:24:52 -0700210 messages::internalError(asyncResp->res);
211 return;
212 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700213 asyncResp->res.jsonValue["UUID"] = chassisUUID;
214 });
Willy Tu308f70c2021-09-28 20:24:52 -0700215}
216
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100217/**
218 * Chassis override class for delivering Chassis Schema
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700219 * Functions triggers appropriate requests on DBus
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100220 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700221inline void requestRoutesChassis(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700222{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700223 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700224 .privileges(redfish::privileges::getChassis)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700225 .methods(
226 boost::beast::http::verb::get)([](const crow::Request&,
227 const std::shared_ptr<
228 bmcweb::AsyncResp>& asyncResp,
229 const std::string& chassisId) {
230 const std::array<const char*, 2> interfaces = {
231 "xyz.openbmc_project.Inventory.Item.Board",
232 "xyz.openbmc_project.Inventory.Item.Chassis"};
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100233
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700234 crow::connections::systemBus->async_method_call(
235 [asyncResp, chassisId(std::string(chassisId))](
236 const boost::system::error_code ec,
237 const crow::openbmc_mapper::GetSubTreeType& subtree) {
238 if (ec)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700239 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700240 messages::internalError(asyncResp->res);
241 return;
Ed Tanousdaf36e22018-04-20 16:01:36 -0700242 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700243 // Iterate over all retrieved ObjectPaths.
244 for (const std::pair<
245 std::string,
246 std::vector<std::pair<std::string,
247 std::vector<std::string>>>>&
248 object : subtree)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700249 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700250 const std::string& path = object.first;
251 const std::vector<
252 std::pair<std::string, std::vector<std::string>>>&
253 connectionNames = object.second;
Ed Tanouse0d918b2018-03-27 17:41:04 -0700254
George Liu997093e2021-11-17 17:43:45 +0800255 sdbusplus::message::object_path objPath(path);
256 if (objPath.filename() != chassisId)
James Feist1c8fba92019-12-20 15:12:07 -0800257 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700258 continue;
James Feist1c8fba92019-12-20 15:12:07 -0800259 }
James Feist1c8fba92019-12-20 15:12:07 -0800260
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700261 auto health =
262 std::make_shared<HealthPopulate>(asyncResp);
263
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700264 sdbusplus::asio::getProperty<std::vector<std::string>>(
265 *crow::connections::systemBus,
266 "xyz.openbmc_project.ObjectMapper",
267 path + "/all_sensors",
268 "xyz.openbmc_project.Association", "endpoints",
Ed Tanous168e20c2021-12-13 14:39:53 -0800269 [health](const boost::system::error_code ec2,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700270 const std::vector<std::string>& resp) {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700271 if (ec2)
272 {
273 return; // no sensors = no failures
274 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700275 health->inventory = resp;
276 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700277
278 health->populate();
279
Ed Tanous26f69762022-01-25 09:49:11 -0800280 if (connectionNames.empty())
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700281 {
282 BMCWEB_LOG_ERROR << "Got 0 Connection names";
283 continue;
284 }
285
286 asyncResp->res.jsonValue["@odata.type"] =
Gunnar Mills5ac5a2f2022-01-04 12:26:41 -0600287 "#Chassis.v1_16_0.Chassis";
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700288 asyncResp->res.jsonValue["@odata.id"] =
289 "/redfish/v1/Chassis/" + chassisId;
290 asyncResp->res.jsonValue["Name"] = "Chassis Collection";
291 asyncResp->res.jsonValue["ChassisType"] = "RackMount";
292 asyncResp->res.jsonValue["Actions"]["#Chassis.Reset"] =
293 {{"target", "/redfish/v1/Chassis/" + chassisId +
294 "/Actions/Chassis.Reset"},
295 {"@Redfish.ActionInfo", "/redfish/v1/Chassis/" +
296 chassisId +
297 "/ResetActionInfo"}};
298 asyncResp->res.jsonValue["PCIeDevices"] = {
299 {"@odata.id",
300 "/redfish/v1/Systems/system/PCIeDevices"}};
301
302 const std::string& connectionName =
303 connectionNames[0].first;
304
305 const std::vector<std::string>& interfaces2 =
306 connectionNames[0].second;
307 const std::array<const char*, 2> hasIndicatorLed = {
308 "xyz.openbmc_project.Inventory.Item.Panel",
George Liu0fda0f12021-11-16 10:06:17 +0800309 "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700310
Tejas Patil476b9cc2021-06-04 17:09:14 +0530311 const std::string assetTagInterface =
George Liu0fda0f12021-11-16 10:06:17 +0800312 "xyz.openbmc_project.Inventory.Decorator.AssetTag";
Tejas Patil476b9cc2021-06-04 17:09:14 +0530313 if (std::find(interfaces2.begin(), interfaces2.end(),
314 assetTagInterface) != interfaces2.end())
315 {
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700316 sdbusplus::asio::getProperty<std::string>(
317 *crow::connections::systemBus, connectionName,
318 path, assetTagInterface, "AssetTag",
Tejas Patil476b9cc2021-06-04 17:09:14 +0530319 [asyncResp, chassisId(std::string(chassisId))](
320 const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700321 const std::string& property) {
Tejas Patil476b9cc2021-06-04 17:09:14 +0530322 if (ec)
323 {
324 BMCWEB_LOG_DEBUG
George Liu0fda0f12021-11-16 10:06:17 +0800325 << "DBus response error for AssetTag";
Tejas Patil476b9cc2021-06-04 17:09:14 +0530326 messages::internalError(asyncResp->res);
327 return;
328 }
Tejas Patil476b9cc2021-06-04 17:09:14 +0530329 asyncResp->res.jsonValue["AssetTag"] =
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700330 property;
331 });
Tejas Patil476b9cc2021-06-04 17:09:14 +0530332 }
333
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700334 for (const char* interface : hasIndicatorLed)
335 {
336 if (std::find(interfaces2.begin(),
337 interfaces2.end(),
338 interface) != interfaces2.end())
339 {
340 getIndicatorLedState(asyncResp);
341 getLocationIndicatorActive(asyncResp);
342 break;
343 }
344 }
345
SunnySrivastava198488ad7f02020-12-03 10:27:52 -0600346 crow::connections::systemBus->async_method_call(
347 [asyncResp, chassisId(std::string(chassisId))](
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700348 const boost::system::error_code /*ec2*/,
349 const std::vector<
Ed Tanous168e20c2021-12-13 14:39:53 -0800350 std::pair<std::string,
351 dbus::utility::DbusVariantType>>&
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700352 propertiesList) {
Ed Tanous168e20c2021-12-13 14:39:53 -0800353 for (const std::pair<
354 std::string,
355 dbus::utility::DbusVariantType>&
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700356 property : propertiesList)
SunnySrivastava198488ad7f02020-12-03 10:27:52 -0600357 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700358 // Store DBus properties that are also
359 // Redfish properties with same name and a
360 // string value
361 const std::string& propertyName =
362 property.first;
363 if ((propertyName == "PartNumber") ||
364 (propertyName == "SerialNumber") ||
365 (propertyName == "Manufacturer") ||
Alpana Kumaricaa11f72021-11-09 12:16:18 -0600366 (propertyName == "Model") ||
367 (propertyName == "SparePartNumber"))
Shawn McCarney99cffd72019-03-01 10:46:20 -0600368 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700369 const std::string* value =
370 std::get_if<std::string>(
371 &property.second);
Alpana Kumaricaa11f72021-11-09 12:16:18 -0600372 if (value == nullptr)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700373 {
Alpana Kumaricaa11f72021-11-09 12:16:18 -0600374 BMCWEB_LOG_ERROR
375 << "Null value returned for "
376 << propertyName;
377 messages::internalError(
378 asyncResp->res);
379 return;
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700380 }
Alpana Kumaricaa11f72021-11-09 12:16:18 -0600381 // SparePartNumber is optional on D-Bus
382 // so skip if it is empty
383 if (propertyName == "SparePartNumber")
384 {
Ed Tanous26f69762022-01-25 09:49:11 -0800385 if (value->empty())
Alpana Kumaricaa11f72021-11-09 12:16:18 -0600386 {
387 continue;
388 }
389 }
390 asyncResp->res.jsonValue[propertyName] =
391 *value;
Shawn McCarney99cffd72019-03-01 10:46:20 -0600392 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700393 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700394 asyncResp->res.jsonValue["Name"] = chassisId;
395 asyncResp->res.jsonValue["Id"] = chassisId;
zhanghch050256b692021-06-12 10:26:52 +0800396#ifdef BMCWEB_ALLOW_DEPRECATED_POWER_THERMAL
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700397 asyncResp->res.jsonValue["Thermal"] = {
398 {"@odata.id", "/redfish/v1/Chassis/" +
399 chassisId + "/Thermal"}};
400 // Power object
401 asyncResp->res.jsonValue["Power"] = {
402 {"@odata.id", "/redfish/v1/Chassis/" +
403 chassisId + "/Power"}};
zhanghch050256b692021-06-12 10:26:52 +0800404#endif
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700405 // SensorCollection
406 asyncResp->res.jsonValue["Sensors"] = {
407 {"@odata.id", "/redfish/v1/Chassis/" +
408 chassisId + "/Sensors"}};
409 asyncResp->res.jsonValue["Status"] = {
410 {"State", "Enabled"},
411 };
412
413 asyncResp->res
414 .jsonValue["Links"]["ComputerSystems"] = {
415 {{"@odata.id",
416 "/redfish/v1/Systems/system"}}};
417 asyncResp->res.jsonValue["Links"]["ManagedBy"] =
418 {{{"@odata.id",
419 "/redfish/v1/Managers/bmc"}}};
420 getChassisState(asyncResp);
421 },
422 connectionName, path,
423 "org.freedesktop.DBus.Properties", "GetAll",
424 "xyz.openbmc_project.Inventory.Decorator.Asset");
Sharad Yadav2c37b4b2021-05-10 12:53:38 +0530425
Willy Tu308f70c2021-09-28 20:24:52 -0700426 for (const auto& interface : interfaces2)
Sharad Yadav2c37b4b2021-05-10 12:53:38 +0530427 {
Willy Tu308f70c2021-09-28 20:24:52 -0700428 if (interface == "xyz.openbmc_project.Common.UUID")
429 {
430 getChassisUUID(asyncResp, connectionName, path);
431 }
George Liu0fda0f12021-11-16 10:06:17 +0800432 else if (
433 interface ==
434 "xyz.openbmc_project.Inventory.Decorator.LocationCode")
Willy Tu308f70c2021-09-28 20:24:52 -0700435 {
436 getChassisLocationCode(asyncResp,
437 connectionName, path);
438 }
Sharad Yadav2c37b4b2021-05-10 12:53:38 +0530439 }
440
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700441 return;
442 }
443
444 // Couldn't find an object with that name. return an error
445 messages::resourceNotFound(
Gunnar Mills5ac5a2f2022-01-04 12:26:41 -0600446 asyncResp->res, "#Chassis.v1_16_0.Chassis", chassisId);
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700447 },
448 "xyz.openbmc_project.ObjectMapper",
449 "/xyz/openbmc_project/object_mapper",
450 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
451 "/xyz/openbmc_project/inventory", 0, interfaces);
452
453 getPhysicalSecurityData(asyncResp);
454 });
455
456 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700457 .privileges(redfish::privileges::patchChassis)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700458 .methods(
459 boost::beast::http::verb::
460 patch)([](const crow::Request& req,
461 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
462 const std::string& param) {
463 std::optional<bool> locationIndicatorActive;
464 std::optional<std::string> indicatorLed;
465
466 if (param.empty())
467 {
468 return;
469 }
470
Willy Tu15ed6782021-12-14 11:03:16 -0800471 if (!json_util::readJsonPatch(
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700472 req, asyncResp->res, "LocationIndicatorActive",
473 locationIndicatorActive, "IndicatorLED", indicatorLed))
474 {
475 return;
476 }
477
478 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
479 if (!locationIndicatorActive && !indicatorLed)
480 {
481 return; // delete this when we support more patch properties
482 }
483 if (indicatorLed)
484 {
485 asyncResp->res.addHeader(
486 boost::beast::http::field::warning,
George Liu0fda0f12021-11-16 10:06:17 +0800487 "299 - \"IndicatorLED is deprecated. Use LocationIndicatorActive instead.\"");
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700488 }
489
490 const std::array<const char*, 2> interfaces = {
491 "xyz.openbmc_project.Inventory.Item.Board",
492 "xyz.openbmc_project.Inventory.Item.Chassis"};
493
494 const std::string& chassisId = param;
495
496 crow::connections::systemBus->async_method_call(
497 [asyncResp, chassisId, locationIndicatorActive, indicatorLed](
498 const boost::system::error_code ec,
499 const crow::openbmc_mapper::GetSubTreeType& subtree) {
500 if (ec)
501 {
502 messages::internalError(asyncResp->res);
503 return;
504 }
505
506 // Iterate over all retrieved ObjectPaths.
507 for (const std::pair<
508 std::string,
509 std::vector<std::pair<std::string,
510 std::vector<std::string>>>>&
511 object : subtree)
512 {
513 const std::string& path = object.first;
514 const std::vector<
515 std::pair<std::string, std::vector<std::string>>>&
516 connectionNames = object.second;
517
George Liu997093e2021-11-17 17:43:45 +0800518 sdbusplus::message::object_path objPath(path);
519 if (objPath.filename() != chassisId)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700520 {
521 continue;
522 }
523
Ed Tanous26f69762022-01-25 09:49:11 -0800524 if (connectionNames.empty())
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700525 {
526 BMCWEB_LOG_ERROR << "Got 0 Connection names";
527 continue;
528 }
529
530 const std::vector<std::string>& interfaces3 =
531 connectionNames[0].second;
532
533 const std::array<const char*, 2> hasIndicatorLed = {
534 "xyz.openbmc_project.Inventory.Item.Panel",
George Liu0fda0f12021-11-16 10:06:17 +0800535 "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700536 bool indicatorChassis = false;
537 for (const char* interface : hasIndicatorLed)
538 {
539 if (std::find(interfaces3.begin(),
540 interfaces3.end(),
541 interface) != interfaces3.end())
542 {
543 indicatorChassis = true;
544 break;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700545 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700546 }
547 if (locationIndicatorActive)
548 {
549 if (indicatorChassis)
550 {
551 setLocationIndicatorActive(
552 asyncResp, *locationIndicatorActive);
553 }
554 else
555 {
556 messages::propertyUnknown(
557 asyncResp->res, "LocationIndicatorActive");
558 }
559 }
560 if (indicatorLed)
561 {
562 if (indicatorChassis)
563 {
564 setIndicatorLedState(asyncResp, *indicatorLed);
565 }
566 else
567 {
568 messages::propertyUnknown(asyncResp->res,
569 "IndicatorLED");
570 }
571 }
572 return;
James Feist1c8fba92019-12-20 15:12:07 -0800573 }
574
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700575 messages::resourceNotFound(
576 asyncResp->res, "#Chassis.v1_14_0.Chassis", chassisId);
577 },
578 "xyz.openbmc_project.ObjectMapper",
579 "/xyz/openbmc_project/object_mapper",
580 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
581 "/xyz/openbmc_project/inventory", 0, interfaces);
582 });
583}
P.K. Leedd99e042020-06-17 19:43:16 +0800584
zhanghch058d1b46d2021-04-01 11:18:24 +0800585inline void
586 doChassisPowerCycle(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
P.K. Leedd99e042020-06-17 19:43:16 +0800587{
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700588 const char* busName = "xyz.openbmc_project.ObjectMapper";
589 const char* path = "/xyz/openbmc_project/object_mapper";
590 const char* interface = "xyz.openbmc_project.ObjectMapper";
591 const char* method = "GetSubTreePaths";
P.K. Leedd99e042020-06-17 19:43:16 +0800592
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700593 const std::array<const char*, 1> interfaces = {
594 "xyz.openbmc_project.State.Chassis"};
595
596 // Use mapper to get subtree paths.
P.K. Leedd99e042020-06-17 19:43:16 +0800597 crow::connections::systemBus->async_method_call(
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700598 [asyncResp](const boost::system::error_code ec,
599 const std::vector<std::string>& chassisList) {
P.K. Leedd99e042020-06-17 19:43:16 +0800600 if (ec)
601 {
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700602 BMCWEB_LOG_DEBUG << "[mapper] Bad D-Bus request error: " << ec;
P.K. Leedd99e042020-06-17 19:43:16 +0800603 messages::internalError(asyncResp->res);
604 return;
605 }
606
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700607 const char* processName = "xyz.openbmc_project.State.Chassis";
608 const char* interfaceName = "xyz.openbmc_project.State.Chassis";
609 const char* destProperty = "RequestedPowerTransition";
610 const std::string propertyValue =
611 "xyz.openbmc_project.State.Chassis.Transition.PowerCycle";
612 std::string objectPath =
613 "/xyz/openbmc_project/state/chassis_system0";
614
615 /* Look for system reset chassis path */
616 if ((std::find(chassisList.begin(), chassisList.end(),
617 objectPath)) == chassisList.end())
618 {
619 /* We prefer to reset the full chassis_system, but if it doesn't
620 * exist on some platforms, fall back to a host-only power reset
621 */
622 objectPath = "/xyz/openbmc_project/state/chassis0";
623 }
624
625 crow::connections::systemBus->async_method_call(
626 [asyncResp](const boost::system::error_code ec) {
627 // Use "Set" method to set the property value.
628 if (ec)
629 {
630 BMCWEB_LOG_DEBUG << "[Set] Bad D-Bus request error: "
631 << ec;
632 messages::internalError(asyncResp->res);
633 return;
634 }
635
636 messages::success(asyncResp->res);
637 },
638 processName, objectPath, "org.freedesktop.DBus.Properties",
639 "Set", interfaceName, destProperty,
Ed Tanous168e20c2021-12-13 14:39:53 -0800640 dbus::utility::DbusVariantType{propertyValue});
P.K. Leedd99e042020-06-17 19:43:16 +0800641 },
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700642 busName, path, interface, method, "/", 0, interfaces);
P.K. Leedd99e042020-06-17 19:43:16 +0800643}
644
645/**
646 * ChassisResetAction class supports the POST method for the Reset
647 * action.
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700648 * Function handles POST method request.
649 * Analyzes POST body before sending Reset request data to D-Bus.
P.K. Leedd99e042020-06-17 19:43:16 +0800650 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700651
652inline void requestRoutesChassisResetAction(App& app)
P.K. Leedd99e042020-06-17 19:43:16 +0800653{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700654 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Actions/Chassis.Reset/")
Ed Tanoused398212021-06-09 17:05:54 -0700655 .privileges(redfish::privileges::postChassis)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700656 .methods(boost::beast::http::verb::post)(
657 [](const crow::Request& req,
658 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
659 const std::string&) {
660 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)(
692 [](const crow::Request&,
693 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
694 const std::string& chassisId)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530695
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700696 {
697 asyncResp->res.jsonValue = {
698 {"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"},
699 {"@odata.id",
700 "/redfish/v1/Chassis/" + chassisId + "/ResetActionInfo"},
701 {"Name", "Reset Action Info"},
702 {"Id", "ResetActionInfo"},
703 {"Parameters",
704 {{{"Name", "ResetType"},
705 {"Required", true},
706 {"DataType", "String"},
707 {"AllowableValues", {"PowerCycle"}}}}}};
708 });
709}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530710
Ed Tanous1abe55e2018-09-05 08:30:59 -0700711} // namespace redfish