blob: 11c04b4cd72ca94e4eca9fa26bd5bf307db8757b [file] [log] [blame]
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +01001/*
2// Copyright (c) 2018 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16#pragma once
17
James Feistb49ac872019-05-21 15:12:01 -070018#include "health.hpp"
James Feist1c8fba92019-12-20 15:12:07 -080019#include "led.hpp"
Ed Tanous1abe55e2018-09-05 08:30:59 -070020
John Edward Broadbent7e860f12021-04-08 15:57:16 -070021#include <app.hpp>
Ed Tanous168e20c2021-12-13 14:39:53 -080022#include <dbus_utility.hpp>
Ed Tanous45ca1b82022-03-25 13:07:27 -070023#include <query.hpp>
Ed Tanoused398212021-06-09 17:05:54 -070024#include <registries/privilege_registry.hpp>
Jonathan Doman1e1e5982021-06-11 09:36:17 -070025#include <sdbusplus/asio/property.hpp>
Gunnar Mills02f6ff12020-10-14 15:59:58 -050026#include <utils/collection.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050027
Ed Tanous1abe55e2018-09-05 08:30:59 -070028namespace redfish
29{
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010030
31/**
Gunnar Millsbeeca0a2019-02-14 16:30:45 -060032 * @brief Retrieves chassis state properties over dbus
33 *
34 * @param[in] aResp - Shared pointer for completing asynchronous calls.
35 *
36 * @return None.
37 */
zhanghch058d1b46d2021-04-01 11:18:24 +080038inline void getChassisState(std::shared_ptr<bmcweb::AsyncResp> aResp)
Gunnar Millsbeeca0a2019-02-14 16:30:45 -060039{
Jonathan Doman1e1e5982021-06-11 09:36:17 -070040 // crow::connections::systemBus->async_method_call(
41 sdbusplus::asio::getProperty<std::string>(
42 *crow::connections::systemBus, "xyz.openbmc_project.State.Chassis",
43 "/xyz/openbmc_project/state/chassis0",
44 "xyz.openbmc_project.State.Chassis", "CurrentPowerState",
45 [aResp{std::move(aResp)}](const boost::system::error_code ec,
46 const std::string& chassisState) {
Ed Tanous002d39b2022-05-31 08:59:27 -070047 if (ec)
48 {
49 if (ec == boost::system::errc::host_unreachable)
Gunnar Millsbeeca0a2019-02-14 16:30:45 -060050 {
Ed Tanous002d39b2022-05-31 08:59:27 -070051 // Service not available, no error, just don't return
52 // chassis state info
53 BMCWEB_LOG_DEBUG << "Service not available " << ec;
Gunnar Millsbeeca0a2019-02-14 16:30:45 -060054 return;
55 }
Ed Tanous002d39b2022-05-31 08:59:27 -070056 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
57 messages::internalError(aResp->res);
58 return;
59 }
Gunnar Millsbeeca0a2019-02-14 16:30:45 -060060
Ed Tanous002d39b2022-05-31 08:59:27 -070061 BMCWEB_LOG_DEBUG << "Chassis state: " << chassisState;
62 // Verify Chassis State
63 if (chassisState == "xyz.openbmc_project.State.Chassis.PowerState.On")
64 {
65 aResp->res.jsonValue["PowerState"] = "On";
66 aResp->res.jsonValue["Status"]["State"] = "Enabled";
67 }
68 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 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -070074 });
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) {
Ed Tanous002d39b2022-05-31 08:59:27 -070088 if (ec)
89 {
90 // do not add err msg in redfish response, because this is not
91 // mandatory property
92 BMCWEB_LOG_ERROR << "DBUS response error " << ec << "\n";
93 return;
94 }
Qiang XUc1819422019-02-27 13:51:32 +080095
Ed Tanous002d39b2022-05-31 08:59:27 -070096 aResp->res.jsonValue["PhysicalSecurity"]["IntrusionSensorNumber"] = 1;
97 aResp->res.jsonValue["PhysicalSecurity"]["IntrusionSensor"] = value;
Jonathan Doman1e1e5982021-06-11 09:36:17 -070098 });
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) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700110 if (ec)
111 {
112 // do not add err msg in redfish response, because this is not
113 // mandatory property
114 BMCWEB_LOG_INFO << "DBUS error: no matched iface " << ec << "\n";
115 return;
116 }
117 // Iterate over all retrieved ObjectPaths.
118 for (const auto& object : subtree)
119 {
120 for (const auto& service : object.second)
Qiang XUc1819422019-02-27 13:51:32 +0800121 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700122 getIntrusionByService(aResp, service.first, object.first);
Qiang XUc1819422019-02-27 13:51:32 +0800123 return;
124 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700125 }
Qiang XUc1819422019-02-27 13:51:32 +0800126 },
127 "xyz.openbmc_project.ObjectMapper",
128 "/xyz/openbmc_project/object_mapper",
129 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous271584a2019-07-09 16:24:22 -0700130 "/xyz/openbmc_project/Intrusion", 1,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500131 std::array<const char*, 1>{"xyz.openbmc_project.Chassis.Intrusion"});
Qiang XUc1819422019-02-27 13:51:32 +0800132}
133
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100134/**
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100135 * ChassisCollection derived class for delivering Chassis Collection Schema
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700136 * Functions triggers appropriate requests on DBus
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100137 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700138inline void requestRoutesChassisCollection(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700139{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700140 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/")
Ed Tanoused398212021-06-09 17:05:54 -0700141 .privileges(redfish::privileges::getChassisCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700142 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700143 [&app](const crow::Request& req,
144 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +0000145 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -0700146 {
147 return;
148 }
149 asyncResp->res.jsonValue["@odata.type"] =
150 "#ChassisCollection.ChassisCollection";
151 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Chassis";
152 asyncResp->res.jsonValue["Name"] = "Chassis Collection";
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100153
Ed Tanous002d39b2022-05-31 08:59:27 -0700154 collection_util::getCollectionMembers(
155 asyncResp, "/redfish/v1/Chassis",
156 {"xyz.openbmc_project.Inventory.Item.Board",
157 "xyz.openbmc_project.Inventory.Item.Chassis"});
158 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700159}
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100160
Willy Tu308f70c2021-09-28 20:24:52 -0700161inline void
162 getChassisLocationCode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
163 const std::string& connectionName,
164 const std::string& path)
165{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700166 sdbusplus::asio::getProperty<std::string>(
167 *crow::connections::systemBus, connectionName, path,
168 "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode",
Willy Tu308f70c2021-09-28 20:24:52 -0700169 [asyncResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700170 const std::string& property) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700171 if (ec)
172 {
173 BMCWEB_LOG_DEBUG << "DBUS response error for Location";
174 messages::internalError(asyncResp->res);
175 return;
176 }
Willy Tu308f70c2021-09-28 20:24:52 -0700177
Ed Tanous002d39b2022-05-31 08:59:27 -0700178 asyncResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
179 property;
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700180 });
Willy Tu308f70c2021-09-28 20:24:52 -0700181}
182
183inline void getChassisUUID(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
184 const std::string& connectionName,
185 const std::string& path)
186{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700187 sdbusplus::asio::getProperty<std::string>(
188 *crow::connections::systemBus, connectionName, path,
189 "xyz.openbmc_project.Common.UUID", "UUID",
Willy Tu308f70c2021-09-28 20:24:52 -0700190 [asyncResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700191 const std::string& chassisUUID) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700192 if (ec)
193 {
194 BMCWEB_LOG_DEBUG << "DBUS response error for UUID";
195 messages::internalError(asyncResp->res);
196 return;
197 }
198 asyncResp->res.jsonValue["UUID"] = chassisUUID;
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700199 });
Willy Tu308f70c2021-09-28 20:24:52 -0700200}
201
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100202/**
203 * Chassis override class for delivering Chassis Schema
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700204 * Functions triggers appropriate requests on DBus
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100205 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700206inline void requestRoutesChassis(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700207{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700208 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700209 .privileges(redfish::privileges::getChassis)
Ed Tanous002d39b2022-05-31 08:59:27 -0700210 .methods(boost::beast::http::verb::get)(
211 [&app](const crow::Request& req,
212 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
213 const std::string& chassisId) {
Carson Labrado3ba00072022-06-06 19:40:56 +0000214 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -0700215 {
216 return;
217 }
218 const std::array<const char*, 2> interfaces = {
219 "xyz.openbmc_project.Inventory.Item.Board",
220 "xyz.openbmc_project.Inventory.Item.Chassis"};
221
222 crow::connections::systemBus->async_method_call(
223 [asyncResp, chassisId(std::string(chassisId))](
224 const boost::system::error_code ec,
225 const dbus::utility::MapperGetSubTreeResponse& subtree) {
226 if (ec)
Ed Tanous45ca1b82022-03-25 13:07:27 -0700227 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700228 messages::internalError(asyncResp->res);
Ed Tanous45ca1b82022-03-25 13:07:27 -0700229 return;
230 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700231 // Iterate over all retrieved ObjectPaths.
232 for (const std::pair<std::string,
233 std::vector<std::pair<
234 std::string, std::vector<std::string>>>>&
235 object : subtree)
236 {
237 const std::string& path = object.first;
238 const std::vector<
239 std::pair<std::string, std::vector<std::string>>>&
240 connectionNames = object.second;
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100241
Ed Tanous002d39b2022-05-31 08:59:27 -0700242 sdbusplus::message::object_path objPath(path);
243 if (objPath.filename() != chassisId)
244 {
245 continue;
246 }
247
248 auto health = std::make_shared<HealthPopulate>(asyncResp);
249
250 sdbusplus::asio::getProperty<std::vector<std::string>>(
251 *crow::connections::systemBus,
252 "xyz.openbmc_project.ObjectMapper", path + "/all_sensors",
253 "xyz.openbmc_project.Association", "endpoints",
254 [health](const boost::system::error_code ec2,
255 const std::vector<std::string>& resp) {
256 if (ec2)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700257 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700258 return; // no sensors = no failures
Ed Tanousdaf36e22018-04-20 16:01:36 -0700259 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700260 health->inventory = resp;
261 });
262
263 health->populate();
264
265 if (connectionNames.empty())
266 {
267 BMCWEB_LOG_ERROR << "Got 0 Connection names";
268 continue;
269 }
270
271 asyncResp->res.jsonValue["@odata.type"] =
272 "#Chassis.v1_16_0.Chassis";
273 asyncResp->res.jsonValue["@odata.id"] =
274 "/redfish/v1/Chassis/" + chassisId;
275 asyncResp->res.jsonValue["Name"] = "Chassis Collection";
276 asyncResp->res.jsonValue["ChassisType"] = "RackMount";
277 asyncResp->res
278 .jsonValue["Actions"]["#Chassis.Reset"]["target"] =
279 "/redfish/v1/Chassis/" + chassisId +
280 "/Actions/Chassis.Reset";
281 asyncResp->res.jsonValue["Actions"]["#Chassis.Reset"]
282 ["@Redfish.ActionInfo"] =
283 "/redfish/v1/Chassis/" + chassisId + "/ResetActionInfo";
284 asyncResp->res.jsonValue["PCIeDevices"]["@odata.id"] =
285 "/redfish/v1/Systems/system/PCIeDevices";
286
John Edward Broadbent92903bd2022-04-26 13:40:59 -0700287 sdbusplus::asio::getProperty<std::vector<std::string>>(
288 *crow::connections::systemBus,
289 "xyz.openbmc_project.ObjectMapper", path + "/drive",
290 "xyz.openbmc_project.Association", "endpoints",
291 [asyncResp,
292 chassisId](const boost::system::error_code ec3,
293 const std::vector<std::string>& resp) {
294 if (ec3 || resp.empty())
295 {
296 return; // no drives = no failures
297 }
298
299 nlohmann::json reference;
300 reference["odata.id"] = crow::utility::urlFromPieces(
301 "redfish", "v1", "Chassis", chassisId, "Drives");
302 asyncResp->res.jsonValue["Drives"] = std::move(reference);
303 });
304
Ed Tanous002d39b2022-05-31 08:59:27 -0700305 const std::string& connectionName = connectionNames[0].first;
306
307 const std::vector<std::string>& interfaces2 =
308 connectionNames[0].second;
309 const std::array<const char*, 2> hasIndicatorLed = {
310 "xyz.openbmc_project.Inventory.Item.Panel",
311 "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
312
313 const std::string assetTagInterface =
314 "xyz.openbmc_project.Inventory.Decorator.AssetTag";
315 if (std::find(interfaces2.begin(), interfaces2.end(),
316 assetTagInterface) != interfaces2.end())
317 {
318 sdbusplus::asio::getProperty<std::string>(
319 *crow::connections::systemBus, connectionName, path,
320 assetTagInterface, "AssetTag",
321 [asyncResp, chassisId(std::string(chassisId))](
322 const boost::system::error_code ec,
323 const std::string& property) {
324 if (ec)
325 {
326 BMCWEB_LOG_DEBUG
327 << "DBus response error for AssetTag";
328 messages::internalError(asyncResp->res);
329 return;
330 }
331 asyncResp->res.jsonValue["AssetTag"] = property;
332 });
333 }
334
335 for (const char* interface : hasIndicatorLed)
336 {
337 if (std::find(interfaces2.begin(), interfaces2.end(),
338 interface) != interfaces2.end())
Ed Tanous1abe55e2018-09-05 08:30:59 -0700339 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700340 getIndicatorLedState(asyncResp);
341 getLocationIndicatorActive(asyncResp);
342 break;
343 }
344 }
Ed Tanouse0d918b2018-03-27 17:41:04 -0700345
Ed Tanous002d39b2022-05-31 08:59:27 -0700346 crow::connections::systemBus->async_method_call(
347 [asyncResp, chassisId(std::string(chassisId))](
348 const boost::system::error_code /*ec2*/,
349 const dbus::utility::DBusPropertiesMap&
350 propertiesList) {
351 for (const std::pair<std::string,
Ed Tanous168e20c2021-12-13 14:39:53 -0800352 dbus::utility::DbusVariantType>&
Ed Tanous002d39b2022-05-31 08:59:27 -0700353 property : propertiesList)
354 {
355 // Store DBus properties that are also
356 // Redfish properties with same name and a
357 // string value
358 const std::string& propertyName = property.first;
359 if ((propertyName == "PartNumber") ||
360 (propertyName == "SerialNumber") ||
361 (propertyName == "Manufacturer") ||
362 (propertyName == "Model") ||
363 (propertyName == "SparePartNumber"))
Sharad Yadav2c37b4b2021-05-10 12:53:38 +0530364 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700365 const std::string* value =
366 std::get_if<std::string>(&property.second);
367 if (value == nullptr)
Willy Tu308f70c2021-09-28 20:24:52 -0700368 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700369 BMCWEB_LOG_ERROR << "Null value returned for "
370 << propertyName;
371 messages::internalError(asyncResp->res);
372 return;
Willy Tu308f70c2021-09-28 20:24:52 -0700373 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700374 // SparePartNumber is optional on D-Bus
375 // so skip if it is empty
376 if (propertyName == "SparePartNumber")
Willy Tu308f70c2021-09-28 20:24:52 -0700377 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700378 if (value->empty())
379 {
380 continue;
381 }
Willy Tu308f70c2021-09-28 20:24:52 -0700382 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700383 asyncResp->res.jsonValue[propertyName] = *value;
Sharad Yadav2c37b4b2021-05-10 12:53:38 +0530384 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700385 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700386 asyncResp->res.jsonValue["Name"] = chassisId;
387 asyncResp->res.jsonValue["Id"] = chassisId;
388#ifdef BMCWEB_ALLOW_DEPRECATED_POWER_THERMAL
389 asyncResp->res.jsonValue["Thermal"]["@odata.id"] =
390 "/redfish/v1/Chassis/" + chassisId + "/Thermal";
391 // Power object
392 asyncResp->res.jsonValue["Power"]["@odata.id"] =
393 "/redfish/v1/Chassis/" + chassisId + "/Power";
394#endif
395 // SensorCollection
396 asyncResp->res.jsonValue["Sensors"]["@odata.id"] =
397 "/redfish/v1/Chassis/" + chassisId + "/Sensors";
398 asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700399
Chicago Duan7691cc22021-01-25 19:52:35 +0800400 asyncResp->res.jsonValue["PCIeSlots"]["@odata.id"] =
401 crow::utility::urlFromPieces("redfish", "v1", "Chassis",
402 chassisId, "PCIeSlots");
403
Ed Tanous002d39b2022-05-31 08:59:27 -0700404 nlohmann::json::array_t computerSystems;
405 nlohmann::json::object_t system;
406 system["@odata.id"] = "/redfish/v1/Systems/system";
407 computerSystems.push_back(std::move(system));
408 asyncResp->res.jsonValue["Links"]["ComputerSystems"] =
409 std::move(computerSystems);
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700410
Ed Tanous002d39b2022-05-31 08:59:27 -0700411 nlohmann::json::array_t managedBy;
412 nlohmann::json::object_t manager;
413 manager["@odata.id"] = "/redfish/v1/Managers/bmc";
414 managedBy.push_back(std::move(manager));
415 asyncResp->res.jsonValue["Links"]["ManagedBy"] =
416 std::move(managedBy);
417 getChassisState(asyncResp);
418 },
419 connectionName, path, "org.freedesktop.DBus.Properties",
420 "GetAll", "xyz.openbmc_project.Inventory.Decorator.Asset");
421
422 for (const auto& interface : interfaces2)
423 {
424 if (interface == "xyz.openbmc_project.Common.UUID")
425 {
426 getChassisUUID(asyncResp, connectionName, path);
427 }
428 else if (
429 interface ==
430 "xyz.openbmc_project.Inventory.Decorator.LocationCode")
431 {
432 getChassisLocationCode(asyncResp, connectionName, path);
433 }
434 }
435
436 return;
437 }
438
439 // Couldn't find an object with that name. return an error
440 messages::resourceNotFound(asyncResp->res,
441 "#Chassis.v1_16_0.Chassis", chassisId);
442 },
443 "xyz.openbmc_project.ObjectMapper",
444 "/xyz/openbmc_project/object_mapper",
445 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
446 "/xyz/openbmc_project/inventory", 0, interfaces);
447
448 getPhysicalSecurityData(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700449 });
450
451 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700452 .privileges(redfish::privileges::patchChassis)
Ed Tanous002d39b2022-05-31 08:59:27 -0700453 .methods(boost::beast::http::verb::patch)(
454 [&app](const crow::Request& req,
455 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
456 const std::string& param) {
Carson Labrado3ba00072022-06-06 19:40:56 +0000457 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -0700458 {
459 return;
460 }
461 std::optional<bool> locationIndicatorActive;
462 std::optional<std::string> indicatorLed;
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700463
Ed Tanous002d39b2022-05-31 08:59:27 -0700464 if (param.empty())
465 {
466 return;
467 }
468
469 if (!json_util::readJsonPatch(
470 req, asyncResp->res, "LocationIndicatorActive",
471 locationIndicatorActive, "IndicatorLED", indicatorLed))
472 {
473 return;
474 }
475
476 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
477 if (!locationIndicatorActive && !indicatorLed)
478 {
479 return; // delete this when we support more patch properties
480 }
481 if (indicatorLed)
482 {
483 asyncResp->res.addHeader(
484 boost::beast::http::field::warning,
485 "299 - \"IndicatorLED is deprecated. Use LocationIndicatorActive instead.\"");
486 }
487
488 const std::array<const char*, 2> interfaces = {
489 "xyz.openbmc_project.Inventory.Item.Board",
490 "xyz.openbmc_project.Inventory.Item.Chassis"};
491
492 const std::string& chassisId = param;
493
494 crow::connections::systemBus->async_method_call(
495 [asyncResp, chassisId, locationIndicatorActive, indicatorLed](
496 const boost::system::error_code ec,
497 const dbus::utility::MapperGetSubTreeResponse& subtree) {
498 if (ec)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700499 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700500 messages::internalError(asyncResp->res);
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700501 return;
502 }
503
Ed Tanous002d39b2022-05-31 08:59:27 -0700504 // Iterate over all retrieved ObjectPaths.
505 for (const std::pair<std::string,
506 std::vector<std::pair<
507 std::string, std::vector<std::string>>>>&
508 object : subtree)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700509 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700510 const std::string& path = object.first;
511 const std::vector<
512 std::pair<std::string, std::vector<std::string>>>&
513 connectionNames = object.second;
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700514
Ed Tanous002d39b2022-05-31 08:59:27 -0700515 sdbusplus::message::object_path objPath(path);
516 if (objPath.filename() != chassisId)
517 {
518 continue;
519 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700520
Ed Tanous002d39b2022-05-31 08:59:27 -0700521 if (connectionNames.empty())
522 {
523 BMCWEB_LOG_ERROR << "Got 0 Connection names";
524 continue;
525 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700526
Ed Tanous002d39b2022-05-31 08:59:27 -0700527 const std::vector<std::string>& interfaces3 =
528 connectionNames[0].second;
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700529
Ed Tanous002d39b2022-05-31 08:59:27 -0700530 const std::array<const char*, 2> hasIndicatorLed = {
531 "xyz.openbmc_project.Inventory.Item.Panel",
532 "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
533 bool indicatorChassis = false;
534 for (const char* interface : hasIndicatorLed)
535 {
536 if (std::find(interfaces3.begin(), interfaces3.end(),
537 interface) != interfaces3.end())
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700538 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700539 indicatorChassis = true;
540 break;
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700541 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700542 }
543 if (locationIndicatorActive)
544 {
545 if (indicatorChassis)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700546 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700547 setLocationIndicatorActive(asyncResp,
548 *locationIndicatorActive);
James Feist1c8fba92019-12-20 15:12:07 -0800549 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700550 else
551 {
552 messages::propertyUnknown(asyncResp->res,
553 "LocationIndicatorActive");
554 }
555 }
556 if (indicatorLed)
557 {
558 if (indicatorChassis)
559 {
560 setIndicatorLedState(asyncResp, *indicatorLed);
561 }
562 else
563 {
564 messages::propertyUnknown(asyncResp->res,
565 "IndicatorLED");
566 }
567 }
568 return;
569 }
James Feist1c8fba92019-12-20 15:12:07 -0800570
Ed Tanous002d39b2022-05-31 08:59:27 -0700571 messages::resourceNotFound(asyncResp->res,
572 "#Chassis.v1_14_0.Chassis", chassisId);
573 },
574 "xyz.openbmc_project.ObjectMapper",
575 "/xyz/openbmc_project/object_mapper",
576 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
577 "/xyz/openbmc_project/inventory", 0, interfaces);
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700578 });
579}
P.K. Leedd99e042020-06-17 19:43:16 +0800580
zhanghch058d1b46d2021-04-01 11:18:24 +0800581inline void
582 doChassisPowerCycle(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
P.K. Leedd99e042020-06-17 19:43:16 +0800583{
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700584 const char* busName = "xyz.openbmc_project.ObjectMapper";
585 const char* path = "/xyz/openbmc_project/object_mapper";
586 const char* interface = "xyz.openbmc_project.ObjectMapper";
587 const char* method = "GetSubTreePaths";
P.K. Leedd99e042020-06-17 19:43:16 +0800588
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700589 const std::array<const char*, 1> interfaces = {
590 "xyz.openbmc_project.State.Chassis"};
591
592 // Use mapper to get subtree paths.
P.K. Leedd99e042020-06-17 19:43:16 +0800593 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -0800594 [asyncResp](
595 const boost::system::error_code ec,
596 const dbus::utility::MapperGetSubTreePathsResponse& chassisList) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700597 if (ec)
598 {
599 BMCWEB_LOG_DEBUG << "[mapper] Bad D-Bus request error: " << ec;
600 messages::internalError(asyncResp->res);
601 return;
602 }
603
604 const char* processName = "xyz.openbmc_project.State.Chassis";
605 const char* interfaceName = "xyz.openbmc_project.State.Chassis";
606 const char* destProperty = "RequestedPowerTransition";
607 const std::string propertyValue =
608 "xyz.openbmc_project.State.Chassis.Transition.PowerCycle";
609 std::string objectPath = "/xyz/openbmc_project/state/chassis_system0";
610
611 /* Look for system reset chassis path */
612 if ((std::find(chassisList.begin(), chassisList.end(), objectPath)) ==
613 chassisList.end())
614 {
615 /* We prefer to reset the full chassis_system, but if it doesn't
616 * exist on some platforms, fall back to a host-only power reset
617 */
618 objectPath = "/xyz/openbmc_project/state/chassis0";
619 }
620
621 crow::connections::systemBus->async_method_call(
622 [asyncResp](const boost::system::error_code ec) {
623 // Use "Set" method to set the property value.
P.K. Leedd99e042020-06-17 19:43:16 +0800624 if (ec)
625 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700626 BMCWEB_LOG_DEBUG << "[Set] Bad D-Bus request error: " << ec;
P.K. Leedd99e042020-06-17 19:43:16 +0800627 messages::internalError(asyncResp->res);
628 return;
629 }
630
Ed Tanous002d39b2022-05-31 08:59:27 -0700631 messages::success(asyncResp->res);
632 },
633 processName, objectPath, "org.freedesktop.DBus.Properties", "Set",
634 interfaceName, destProperty,
635 dbus::utility::DbusVariantType{propertyValue});
P.K. Leedd99e042020-06-17 19:43:16 +0800636 },
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700637 busName, path, interface, method, "/", 0, interfaces);
P.K. Leedd99e042020-06-17 19:43:16 +0800638}
639
640/**
641 * ChassisResetAction class supports the POST method for the Reset
642 * action.
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700643 * Function handles POST method request.
644 * Analyzes POST body before sending Reset request data to D-Bus.
P.K. Leedd99e042020-06-17 19:43:16 +0800645 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700646
647inline void requestRoutesChassisResetAction(App& app)
P.K. Leedd99e042020-06-17 19:43:16 +0800648{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700649 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Actions/Chassis.Reset/")
Ed Tanoused398212021-06-09 17:05:54 -0700650 .privileges(redfish::privileges::postChassis)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700651 .methods(boost::beast::http::verb::post)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700652 [&app](const crow::Request& req,
653 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
654 const std::string&) {
Carson Labrado3ba00072022-06-06 19:40:56 +0000655 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -0700656 {
657 return;
658 }
659 BMCWEB_LOG_DEBUG << "Post Chassis Reset.";
P.K. Leedd99e042020-06-17 19:43:16 +0800660
Ed Tanous002d39b2022-05-31 08:59:27 -0700661 std::string resetType;
P.K. Leedd99e042020-06-17 19:43:16 +0800662
Ed Tanous002d39b2022-05-31 08:59:27 -0700663 if (!json_util::readJsonAction(req, asyncResp->res, "ResetType",
664 resetType))
665 {
666 return;
667 }
P.K. Leedd99e042020-06-17 19:43:16 +0800668
Ed Tanous002d39b2022-05-31 08:59:27 -0700669 if (resetType != "PowerCycle")
670 {
671 BMCWEB_LOG_DEBUG << "Invalid property value for ResetType: "
672 << resetType;
673 messages::actionParameterNotSupported(asyncResp->res, resetType,
674 "ResetType");
P.K. Leedd99e042020-06-17 19:43:16 +0800675
Ed Tanous002d39b2022-05-31 08:59:27 -0700676 return;
677 }
678 doChassisPowerCycle(asyncResp);
679 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700680}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530681
682/**
683 * ChassisResetActionInfo derived class for delivering Chassis
684 * ResetType AllowableValues using ResetInfo schema.
685 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700686inline void requestRoutesChassisResetActionInfo(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530687{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700688 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -0700689 .privileges(redfish::privileges::getActionInfo)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700690 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700691 [&app](const crow::Request& req,
692 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
693 const std::string& chassisId) {
Carson Labrado3ba00072022-06-06 19:40:56 +0000694 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -0700695 {
696 return;
697 }
698 asyncResp->res.jsonValue["@odata.type"] =
699 "#ActionInfo.v1_1_2.ActionInfo";
700 asyncResp->res.jsonValue["@odata.id"] =
701 "/redfish/v1/Chassis/" + chassisId + "/ResetActionInfo";
702 asyncResp->res.jsonValue["Name"] = "Reset Action Info";
Ed Tanous14766872022-03-15 10:44:42 -0700703
Ed Tanous002d39b2022-05-31 08:59:27 -0700704 asyncResp->res.jsonValue["Id"] = "ResetActionInfo";
Nan Zhou5b9e95a2022-06-01 17:12:23 +0000705 nlohmann::json::array_t parameters;
706 nlohmann::json::object_t parameter;
707 parameter["Name"] = "ResetType";
708 parameter["Required"] = true;
709 parameter["DataType"] = "String";
Ed Tanous002d39b2022-05-31 08:59:27 -0700710 nlohmann::json::array_t allowed;
711 allowed.push_back("PowerCycle");
Nan Zhou5b9e95a2022-06-01 17:12:23 +0000712 parameter["AllowableValues"] = std::move(allowed);
713 parameters.push_back(std::move(parameter));
714
Ed Tanous002d39b2022-05-31 08:59:27 -0700715 asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
716 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700717}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530718
Ed Tanous1abe55e2018-09-05 08:30:59 -0700719} // namespace redfish