blob: df7e205686d288f4228ba8199b2d050858a8f865 [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>
Gunnar Mills02f6ff12020-10-14 15:59:58 -050025#include <utils/collection.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050026
Ed Tanous1abe55e2018-09-05 08:30:59 -070027namespace redfish
28{
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010029
30/**
Gunnar Millsbeeca0a2019-02-14 16:30:45 -060031 * @brief Retrieves chassis state properties over dbus
32 *
33 * @param[in] aResp - Shared pointer for completing asynchronous calls.
34 *
35 * @return None.
36 */
zhanghch058d1b46d2021-04-01 11:18:24 +080037inline void getChassisState(std::shared_ptr<bmcweb::AsyncResp> aResp)
Gunnar Millsbeeca0a2019-02-14 16:30:45 -060038{
39 crow::connections::systemBus->async_method_call(
40 [aResp{std::move(aResp)}](
41 const boost::system::error_code ec,
Ed Tanous168e20c2021-12-13 14:39:53 -080042 const dbus::utility::DbusVariantType& chassisState) {
Gunnar Millsbeeca0a2019-02-14 16:30:45 -060043 if (ec)
44 {
45 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
46 messages::internalError(aResp->res);
47 return;
48 }
49
Gunnar Mills1214b7e2020-06-04 10:11:30 -050050 const std::string* s = std::get_if<std::string>(&chassisState);
Gunnar Millsbeeca0a2019-02-14 16:30:45 -060051 BMCWEB_LOG_DEBUG << "Chassis state: " << *s;
52 if (s != nullptr)
53 {
54 // Verify Chassis State
55 if (*s == "xyz.openbmc_project.State.Chassis.PowerState.On")
56 {
57 aResp->res.jsonValue["PowerState"] = "On";
58 aResp->res.jsonValue["Status"]["State"] = "Enabled";
59 }
60 else if (*s ==
61 "xyz.openbmc_project.State.Chassis.PowerState.Off")
62 {
63 aResp->res.jsonValue["PowerState"] = "Off";
64 aResp->res.jsonValue["Status"]["State"] = "StandbyOffline";
65 }
66 }
67 },
68 "xyz.openbmc_project.State.Chassis",
69 "/xyz/openbmc_project/state/chassis0",
70 "org.freedesktop.DBus.Properties", "Get",
71 "xyz.openbmc_project.State.Chassis", "CurrentPowerState");
72}
73
74/**
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010075 * DBus types primitives for several generic DBus interfaces
76 * TODO(Pawel) consider move this to separate file into boost::dbus
77 */
Ed Tanousaa2e59c2018-04-12 12:17:20 -070078using ManagedObjectsType = std::vector<std::pair<
79 sdbusplus::message::object_path,
Ed Tanous168e20c2021-12-13 14:39:53 -080080 std::vector<std::pair<
81 std::string,
82 std::vector<std::pair<std::string, dbus::utility::DbusVariantType>>>>>>;
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010083
Ed Tanous168e20c2021-12-13 14:39:53 -080084using PropertiesType =
85 boost::container::flat_map<std::string, dbus::utility::DbusVariantType>;
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010086
zhanghch058d1b46d2021-04-01 11:18:24 +080087inline void getIntrusionByService(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous23a21a12020-07-25 04:45:05 +000088 const std::string& service,
89 const std::string& objPath)
Qiang XUc1819422019-02-27 13:51:32 +080090{
91 BMCWEB_LOG_DEBUG << "Get intrusion status by service \n";
92
93 crow::connections::systemBus->async_method_call(
94 [aResp{std::move(aResp)}](const boost::system::error_code ec,
Ed Tanous168e20c2021-12-13 14:39:53 -080095 const dbus::utility::DbusVariantType& value) {
Qiang XUc1819422019-02-27 13:51:32 +080096 if (ec)
97 {
Gunnar Mills4e0453b2020-07-08 14:00:30 -050098 // do not add err msg in redfish response, because this is not
Qiang XUc1819422019-02-27 13:51:32 +080099 // mandatory property
100 BMCWEB_LOG_ERROR << "DBUS response error " << ec << "\n";
101 return;
102 }
103
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500104 const std::string* status = std::get_if<std::string>(&value);
Qiang XUc1819422019-02-27 13:51:32 +0800105
106 if (status == nullptr)
107 {
108 BMCWEB_LOG_ERROR << "intrusion status read error \n";
109 return;
110 }
111
112 aResp->res.jsonValue["PhysicalSecurity"] = {
113 {"IntrusionSensorNumber", 1}, {"IntrusionSensor", *status}};
114 },
115 service, objPath, "org.freedesktop.DBus.Properties", "Get",
116 "xyz.openbmc_project.Chassis.Intrusion", "Status");
117}
118
119/**
120 * Retrieves physical security properties over dbus
121 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800122inline void getPhysicalSecurityData(std::shared_ptr<bmcweb::AsyncResp> aResp)
Qiang XUc1819422019-02-27 13:51:32 +0800123{
124 crow::connections::systemBus->async_method_call(
125 [aResp{std::move(aResp)}](
126 const boost::system::error_code ec,
127 const std::vector<std::pair<
128 std::string,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500129 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
130 subtree) {
Qiang XUc1819422019-02-27 13:51:32 +0800131 if (ec)
132 {
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500133 // do not add err msg in redfish response, because this is not
Qiang XUc1819422019-02-27 13:51:32 +0800134 // mandatory property
Andrew Geissler54fbf172021-11-11 15:59:30 -0600135 BMCWEB_LOG_INFO << "DBUS error: no matched iface " << ec
136 << "\n";
Qiang XUc1819422019-02-27 13:51:32 +0800137 return;
138 }
139 // Iterate over all retrieved ObjectPaths.
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500140 for (const auto& object : subtree)
Qiang XUc1819422019-02-27 13:51:32 +0800141 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500142 for (const auto& service : object.second)
Qiang XUc1819422019-02-27 13:51:32 +0800143 {
144 getIntrusionByService(aResp, service.first, object.first);
145 return;
146 }
147 }
148 },
149 "xyz.openbmc_project.ObjectMapper",
150 "/xyz/openbmc_project/object_mapper",
151 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous271584a2019-07-09 16:24:22 -0700152 "/xyz/openbmc_project/Intrusion", 1,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500153 std::array<const char*, 1>{"xyz.openbmc_project.Chassis.Intrusion"});
Qiang XUc1819422019-02-27 13:51:32 +0800154}
155
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100156/**
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100157 * ChassisCollection derived class for delivering Chassis Collection Schema
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700158 * Functions triggers appropriate requests on DBus
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100159 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700160inline void requestRoutesChassisCollection(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700161{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700162 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/")
Ed Tanoused398212021-06-09 17:05:54 -0700163 .privileges(redfish::privileges::getChassisCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700164 .methods(boost::beast::http::verb::get)(
165 [](const crow::Request&,
166 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
167 asyncResp->res.jsonValue["@odata.type"] =
168 "#ChassisCollection.ChassisCollection";
169 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Chassis";
170 asyncResp->res.jsonValue["Name"] = "Chassis Collection";
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100171
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700172 collection_util::getCollectionMembers(
173 asyncResp, "/redfish/v1/Chassis",
174 {"xyz.openbmc_project.Inventory.Item.Board",
175 "xyz.openbmc_project.Inventory.Item.Chassis"});
176 });
177}
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100178
Willy Tu308f70c2021-09-28 20:24:52 -0700179inline void
180 getChassisLocationCode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
181 const std::string& connectionName,
182 const std::string& path)
183{
184 crow::connections::systemBus->async_method_call(
185 [asyncResp](const boost::system::error_code ec,
Ed Tanous168e20c2021-12-13 14:39:53 -0800186 const dbus::utility::DbusVariantType& property) {
Willy Tu308f70c2021-09-28 20:24:52 -0700187 if (ec)
188 {
George Liu0fda0f12021-11-16 10:06:17 +0800189 BMCWEB_LOG_DEBUG << "DBUS response error for Location";
Willy Tu308f70c2021-09-28 20:24:52 -0700190 messages::internalError(asyncResp->res);
191 return;
192 }
193
194 const std::string* value = std::get_if<std::string>(&property);
195 if (value == nullptr)
196 {
George Liu0fda0f12021-11-16 10:06:17 +0800197 BMCWEB_LOG_DEBUG << "Null value returned for locaton code";
Willy Tu308f70c2021-09-28 20:24:52 -0700198 messages::internalError(asyncResp->res);
199 return;
200 }
201 asyncResp->res
202 .jsonValue["Location"]["PartLocation"]["ServiceLabel"] = *value;
203 },
204 connectionName, path, "org.freedesktop.DBus.Properties", "Get",
205 "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode");
206}
207
208inline void getChassisUUID(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
209 const std::string& connectionName,
210 const std::string& path)
211{
212 crow::connections::systemBus->async_method_call(
213 [asyncResp](const boost::system::error_code ec,
Ed Tanous168e20c2021-12-13 14:39:53 -0800214 const dbus::utility::DbusVariantType& chassisUUID) {
Willy Tu308f70c2021-09-28 20:24:52 -0700215 if (ec)
216 {
George Liu0fda0f12021-11-16 10:06:17 +0800217 BMCWEB_LOG_DEBUG << "DBUS response error for UUID";
Willy Tu308f70c2021-09-28 20:24:52 -0700218 messages::internalError(asyncResp->res);
219 return;
220 }
221 const std::string* value = std::get_if<std::string>(&chassisUUID);
222 if (value == nullptr)
223 {
George Liu0fda0f12021-11-16 10:06:17 +0800224 BMCWEB_LOG_DEBUG << "Null value returned for UUID";
Willy Tu308f70c2021-09-28 20:24:52 -0700225 messages::internalError(asyncResp->res);
226 return;
227 }
228 asyncResp->res.jsonValue["UUID"] = *value;
229 },
230 connectionName, path, "org.freedesktop.DBus.Properties", "Get",
231 "xyz.openbmc_project.Common.UUID", "UUID");
232}
233
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100234/**
235 * Chassis override class for delivering Chassis Schema
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700236 * Functions triggers appropriate requests on DBus
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100237 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700238inline void requestRoutesChassis(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700239{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700240 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700241 .privileges(redfish::privileges::getChassis)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700242 .methods(
243 boost::beast::http::verb::get)([](const crow::Request&,
244 const std::shared_ptr<
245 bmcweb::AsyncResp>& asyncResp,
246 const std::string& chassisId) {
247 const std::array<const char*, 2> interfaces = {
248 "xyz.openbmc_project.Inventory.Item.Board",
249 "xyz.openbmc_project.Inventory.Item.Chassis"};
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100250
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700251 crow::connections::systemBus->async_method_call(
252 [asyncResp, chassisId(std::string(chassisId))](
253 const boost::system::error_code ec,
254 const crow::openbmc_mapper::GetSubTreeType& subtree) {
255 if (ec)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700256 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700257 messages::internalError(asyncResp->res);
258 return;
Ed Tanousdaf36e22018-04-20 16:01:36 -0700259 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700260 // Iterate over all retrieved ObjectPaths.
261 for (const std::pair<
262 std::string,
263 std::vector<std::pair<std::string,
264 std::vector<std::string>>>>&
265 object : subtree)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700266 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700267 const std::string& path = object.first;
268 const std::vector<
269 std::pair<std::string, std::vector<std::string>>>&
270 connectionNames = object.second;
Ed Tanouse0d918b2018-03-27 17:41:04 -0700271
George Liu997093e2021-11-17 17:43:45 +0800272 sdbusplus::message::object_path objPath(path);
273 if (objPath.filename() != chassisId)
James Feist1c8fba92019-12-20 15:12:07 -0800274 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700275 continue;
James Feist1c8fba92019-12-20 15:12:07 -0800276 }
James Feist1c8fba92019-12-20 15:12:07 -0800277
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700278 auto health =
279 std::make_shared<HealthPopulate>(asyncResp);
280
281 crow::connections::systemBus->async_method_call(
Ed Tanous168e20c2021-12-13 14:39:53 -0800282 [health](const boost::system::error_code ec2,
283 dbus::utility::DbusVariantType& resp) {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700284 if (ec2)
285 {
286 return; // no sensors = no failures
287 }
288 std::vector<std::string>* data =
289 std::get_if<std::vector<std::string>>(
290 &resp);
291 if (data == nullptr)
292 {
293 return;
294 }
295 health->inventory = std::move(*data);
296 },
297 "xyz.openbmc_project.ObjectMapper",
298 path + "/all_sensors",
299 "org.freedesktop.DBus.Properties", "Get",
300 "xyz.openbmc_project.Association", "endpoints");
301
302 health->populate();
303
304 if (connectionNames.size() < 1)
305 {
306 BMCWEB_LOG_ERROR << "Got 0 Connection names";
307 continue;
308 }
309
310 asyncResp->res.jsonValue["@odata.type"] =
311 "#Chassis.v1_14_0.Chassis";
312 asyncResp->res.jsonValue["@odata.id"] =
313 "/redfish/v1/Chassis/" + chassisId;
314 asyncResp->res.jsonValue["Name"] = "Chassis Collection";
315 asyncResp->res.jsonValue["ChassisType"] = "RackMount";
316 asyncResp->res.jsonValue["Actions"]["#Chassis.Reset"] =
317 {{"target", "/redfish/v1/Chassis/" + chassisId +
318 "/Actions/Chassis.Reset"},
319 {"@Redfish.ActionInfo", "/redfish/v1/Chassis/" +
320 chassisId +
321 "/ResetActionInfo"}};
322 asyncResp->res.jsonValue["PCIeDevices"] = {
323 {"@odata.id",
324 "/redfish/v1/Systems/system/PCIeDevices"}};
325
326 const std::string& connectionName =
327 connectionNames[0].first;
328
329 const std::vector<std::string>& interfaces2 =
330 connectionNames[0].second;
331 const std::array<const char*, 2> hasIndicatorLed = {
332 "xyz.openbmc_project.Inventory.Item.Panel",
George Liu0fda0f12021-11-16 10:06:17 +0800333 "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700334
Tejas Patil476b9cc2021-06-04 17:09:14 +0530335 const std::string assetTagInterface =
George Liu0fda0f12021-11-16 10:06:17 +0800336 "xyz.openbmc_project.Inventory.Decorator.AssetTag";
Tejas Patil476b9cc2021-06-04 17:09:14 +0530337 if (std::find(interfaces2.begin(), interfaces2.end(),
338 assetTagInterface) != interfaces2.end())
339 {
340 crow::connections::systemBus->async_method_call(
341 [asyncResp, chassisId(std::string(chassisId))](
342 const boost::system::error_code ec,
Ed Tanous168e20c2021-12-13 14:39:53 -0800343 const dbus::utility::DbusVariantType&
344 property) {
Tejas Patil476b9cc2021-06-04 17:09:14 +0530345 if (ec)
346 {
347 BMCWEB_LOG_DEBUG
George Liu0fda0f12021-11-16 10:06:17 +0800348 << "DBus response error for AssetTag";
Tejas Patil476b9cc2021-06-04 17:09:14 +0530349 messages::internalError(asyncResp->res);
350 return;
351 }
352
353 const std::string* assetTag =
354 std::get_if<std::string>(&property);
355 if (assetTag == nullptr)
356 {
357 BMCWEB_LOG_DEBUG
George Liu0fda0f12021-11-16 10:06:17 +0800358 << "Null value returned for Chassis AssetTag";
Tejas Patil476b9cc2021-06-04 17:09:14 +0530359 messages::internalError(asyncResp->res);
360 return;
361 }
362 asyncResp->res.jsonValue["AssetTag"] =
363 *assetTag;
364 },
365 connectionName, path,
366 "org.freedesktop.DBus.Properties", "Get",
367 assetTagInterface, "AssetTag");
368 }
369
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700370 for (const char* interface : hasIndicatorLed)
371 {
372 if (std::find(interfaces2.begin(),
373 interfaces2.end(),
374 interface) != interfaces2.end())
375 {
376 getIndicatorLedState(asyncResp);
377 getLocationIndicatorActive(asyncResp);
378 break;
379 }
380 }
381
SunnySrivastava198488ad7f02020-12-03 10:27:52 -0600382 crow::connections::systemBus->async_method_call(
383 [asyncResp, chassisId(std::string(chassisId))](
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700384 const boost::system::error_code /*ec2*/,
385 const std::vector<
Ed Tanous168e20c2021-12-13 14:39:53 -0800386 std::pair<std::string,
387 dbus::utility::DbusVariantType>>&
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700388 propertiesList) {
Ed Tanous168e20c2021-12-13 14:39:53 -0800389 for (const std::pair<
390 std::string,
391 dbus::utility::DbusVariantType>&
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700392 property : propertiesList)
SunnySrivastava198488ad7f02020-12-03 10:27:52 -0600393 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700394 // Store DBus properties that are also
395 // Redfish properties with same name and a
396 // string value
397 const std::string& propertyName =
398 property.first;
399 if ((propertyName == "PartNumber") ||
400 (propertyName == "SerialNumber") ||
401 (propertyName == "Manufacturer") ||
Alpana Kumaricaa11f72021-11-09 12:16:18 -0600402 (propertyName == "Model") ||
403 (propertyName == "SparePartNumber"))
Shawn McCarney99cffd72019-03-01 10:46:20 -0600404 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700405 const std::string* value =
406 std::get_if<std::string>(
407 &property.second);
Alpana Kumaricaa11f72021-11-09 12:16:18 -0600408 if (value == nullptr)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700409 {
Alpana Kumaricaa11f72021-11-09 12:16:18 -0600410 BMCWEB_LOG_ERROR
411 << "Null value returned for "
412 << propertyName;
413 messages::internalError(
414 asyncResp->res);
415 return;
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700416 }
Alpana Kumaricaa11f72021-11-09 12:16:18 -0600417 // SparePartNumber is optional on D-Bus
418 // so skip if it is empty
419 if (propertyName == "SparePartNumber")
420 {
421 if (*value == "")
422 {
423 continue;
424 }
425 }
426 asyncResp->res.jsonValue[propertyName] =
427 *value;
Shawn McCarney99cffd72019-03-01 10:46:20 -0600428 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700429 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700430 asyncResp->res.jsonValue["Name"] = chassisId;
431 asyncResp->res.jsonValue["Id"] = chassisId;
zhanghch050256b692021-06-12 10:26:52 +0800432#ifdef BMCWEB_ALLOW_DEPRECATED_POWER_THERMAL
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700433 asyncResp->res.jsonValue["Thermal"] = {
434 {"@odata.id", "/redfish/v1/Chassis/" +
435 chassisId + "/Thermal"}};
436 // Power object
437 asyncResp->res.jsonValue["Power"] = {
438 {"@odata.id", "/redfish/v1/Chassis/" +
439 chassisId + "/Power"}};
zhanghch050256b692021-06-12 10:26:52 +0800440#endif
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700441 // SensorCollection
442 asyncResp->res.jsonValue["Sensors"] = {
443 {"@odata.id", "/redfish/v1/Chassis/" +
444 chassisId + "/Sensors"}};
445 asyncResp->res.jsonValue["Status"] = {
446 {"State", "Enabled"},
447 };
448
449 asyncResp->res
450 .jsonValue["Links"]["ComputerSystems"] = {
451 {{"@odata.id",
452 "/redfish/v1/Systems/system"}}};
453 asyncResp->res.jsonValue["Links"]["ManagedBy"] =
454 {{{"@odata.id",
455 "/redfish/v1/Managers/bmc"}}};
456 getChassisState(asyncResp);
457 },
458 connectionName, path,
459 "org.freedesktop.DBus.Properties", "GetAll",
460 "xyz.openbmc_project.Inventory.Decorator.Asset");
Sharad Yadav2c37b4b2021-05-10 12:53:38 +0530461
Willy Tu308f70c2021-09-28 20:24:52 -0700462 for (const auto& interface : interfaces2)
Sharad Yadav2c37b4b2021-05-10 12:53:38 +0530463 {
Willy Tu308f70c2021-09-28 20:24:52 -0700464 if (interface == "xyz.openbmc_project.Common.UUID")
465 {
466 getChassisUUID(asyncResp, connectionName, path);
467 }
George Liu0fda0f12021-11-16 10:06:17 +0800468 else if (
469 interface ==
470 "xyz.openbmc_project.Inventory.Decorator.LocationCode")
Willy Tu308f70c2021-09-28 20:24:52 -0700471 {
472 getChassisLocationCode(asyncResp,
473 connectionName, path);
474 }
Sharad Yadav2c37b4b2021-05-10 12:53:38 +0530475 }
476
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700477 return;
478 }
479
480 // Couldn't find an object with that name. return an error
481 messages::resourceNotFound(
482 asyncResp->res, "#Chassis.v1_14_0.Chassis", chassisId);
483 },
484 "xyz.openbmc_project.ObjectMapper",
485 "/xyz/openbmc_project/object_mapper",
486 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
487 "/xyz/openbmc_project/inventory", 0, interfaces);
488
489 getPhysicalSecurityData(asyncResp);
490 });
491
492 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700493 .privileges(redfish::privileges::patchChassis)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700494 .methods(
495 boost::beast::http::verb::
496 patch)([](const crow::Request& req,
497 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
498 const std::string& param) {
499 std::optional<bool> locationIndicatorActive;
500 std::optional<std::string> indicatorLed;
501
502 if (param.empty())
503 {
504 return;
505 }
506
507 if (!json_util::readJson(
508 req, asyncResp->res, "LocationIndicatorActive",
509 locationIndicatorActive, "IndicatorLED", indicatorLed))
510 {
511 return;
512 }
513
514 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
515 if (!locationIndicatorActive && !indicatorLed)
516 {
517 return; // delete this when we support more patch properties
518 }
519 if (indicatorLed)
520 {
521 asyncResp->res.addHeader(
522 boost::beast::http::field::warning,
George Liu0fda0f12021-11-16 10:06:17 +0800523 "299 - \"IndicatorLED is deprecated. Use LocationIndicatorActive instead.\"");
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700524 }
525
526 const std::array<const char*, 2> interfaces = {
527 "xyz.openbmc_project.Inventory.Item.Board",
528 "xyz.openbmc_project.Inventory.Item.Chassis"};
529
530 const std::string& chassisId = param;
531
532 crow::connections::systemBus->async_method_call(
533 [asyncResp, chassisId, locationIndicatorActive, indicatorLed](
534 const boost::system::error_code ec,
535 const crow::openbmc_mapper::GetSubTreeType& subtree) {
536 if (ec)
537 {
538 messages::internalError(asyncResp->res);
539 return;
540 }
541
542 // Iterate over all retrieved ObjectPaths.
543 for (const std::pair<
544 std::string,
545 std::vector<std::pair<std::string,
546 std::vector<std::string>>>>&
547 object : subtree)
548 {
549 const std::string& path = object.first;
550 const std::vector<
551 std::pair<std::string, std::vector<std::string>>>&
552 connectionNames = object.second;
553
George Liu997093e2021-11-17 17:43:45 +0800554 sdbusplus::message::object_path objPath(path);
555 if (objPath.filename() != chassisId)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700556 {
557 continue;
558 }
559
560 if (connectionNames.size() < 1)
561 {
562 BMCWEB_LOG_ERROR << "Got 0 Connection names";
563 continue;
564 }
565
566 const std::vector<std::string>& interfaces3 =
567 connectionNames[0].second;
568
569 const std::array<const char*, 2> hasIndicatorLed = {
570 "xyz.openbmc_project.Inventory.Item.Panel",
George Liu0fda0f12021-11-16 10:06:17 +0800571 "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700572 bool indicatorChassis = false;
573 for (const char* interface : hasIndicatorLed)
574 {
575 if (std::find(interfaces3.begin(),
576 interfaces3.end(),
577 interface) != interfaces3.end())
578 {
579 indicatorChassis = true;
580 break;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700581 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700582 }
583 if (locationIndicatorActive)
584 {
585 if (indicatorChassis)
586 {
587 setLocationIndicatorActive(
588 asyncResp, *locationIndicatorActive);
589 }
590 else
591 {
592 messages::propertyUnknown(
593 asyncResp->res, "LocationIndicatorActive");
594 }
595 }
596 if (indicatorLed)
597 {
598 if (indicatorChassis)
599 {
600 setIndicatorLedState(asyncResp, *indicatorLed);
601 }
602 else
603 {
604 messages::propertyUnknown(asyncResp->res,
605 "IndicatorLED");
606 }
607 }
608 return;
James Feist1c8fba92019-12-20 15:12:07 -0800609 }
610
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700611 messages::resourceNotFound(
612 asyncResp->res, "#Chassis.v1_14_0.Chassis", chassisId);
613 },
614 "xyz.openbmc_project.ObjectMapper",
615 "/xyz/openbmc_project/object_mapper",
616 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
617 "/xyz/openbmc_project/inventory", 0, interfaces);
618 });
619}
P.K. Leedd99e042020-06-17 19:43:16 +0800620
zhanghch058d1b46d2021-04-01 11:18:24 +0800621inline void
622 doChassisPowerCycle(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
P.K. Leedd99e042020-06-17 19:43:16 +0800623{
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700624 const char* busName = "xyz.openbmc_project.ObjectMapper";
625 const char* path = "/xyz/openbmc_project/object_mapper";
626 const char* interface = "xyz.openbmc_project.ObjectMapper";
627 const char* method = "GetSubTreePaths";
P.K. Leedd99e042020-06-17 19:43:16 +0800628
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700629 const std::array<const char*, 1> interfaces = {
630 "xyz.openbmc_project.State.Chassis"};
631
632 // Use mapper to get subtree paths.
P.K. Leedd99e042020-06-17 19:43:16 +0800633 crow::connections::systemBus->async_method_call(
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700634 [asyncResp](const boost::system::error_code ec,
635 const std::vector<std::string>& chassisList) {
P.K. Leedd99e042020-06-17 19:43:16 +0800636 if (ec)
637 {
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700638 BMCWEB_LOG_DEBUG << "[mapper] Bad D-Bus request error: " << ec;
P.K. Leedd99e042020-06-17 19:43:16 +0800639 messages::internalError(asyncResp->res);
640 return;
641 }
642
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700643 const char* processName = "xyz.openbmc_project.State.Chassis";
644 const char* interfaceName = "xyz.openbmc_project.State.Chassis";
645 const char* destProperty = "RequestedPowerTransition";
646 const std::string propertyValue =
647 "xyz.openbmc_project.State.Chassis.Transition.PowerCycle";
648 std::string objectPath =
649 "/xyz/openbmc_project/state/chassis_system0";
650
651 /* Look for system reset chassis path */
652 if ((std::find(chassisList.begin(), chassisList.end(),
653 objectPath)) == chassisList.end())
654 {
655 /* We prefer to reset the full chassis_system, but if it doesn't
656 * exist on some platforms, fall back to a host-only power reset
657 */
658 objectPath = "/xyz/openbmc_project/state/chassis0";
659 }
660
661 crow::connections::systemBus->async_method_call(
662 [asyncResp](const boost::system::error_code ec) {
663 // Use "Set" method to set the property value.
664 if (ec)
665 {
666 BMCWEB_LOG_DEBUG << "[Set] Bad D-Bus request error: "
667 << ec;
668 messages::internalError(asyncResp->res);
669 return;
670 }
671
672 messages::success(asyncResp->res);
673 },
674 processName, objectPath, "org.freedesktop.DBus.Properties",
675 "Set", interfaceName, destProperty,
Ed Tanous168e20c2021-12-13 14:39:53 -0800676 dbus::utility::DbusVariantType{propertyValue});
P.K. Leedd99e042020-06-17 19:43:16 +0800677 },
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700678 busName, path, interface, method, "/", 0, interfaces);
P.K. Leedd99e042020-06-17 19:43:16 +0800679}
680
681/**
682 * ChassisResetAction class supports the POST method for the Reset
683 * action.
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700684 * Function handles POST method request.
685 * Analyzes POST body before sending Reset request data to D-Bus.
P.K. Leedd99e042020-06-17 19:43:16 +0800686 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700687
688inline void requestRoutesChassisResetAction(App& app)
P.K. Leedd99e042020-06-17 19:43:16 +0800689{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700690 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Actions/Chassis.Reset/")
Ed Tanoused398212021-06-09 17:05:54 -0700691 .privileges(redfish::privileges::postChassis)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700692 .methods(boost::beast::http::verb::post)(
693 [](const crow::Request& req,
694 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
695 const std::string&) {
696 BMCWEB_LOG_DEBUG << "Post Chassis Reset.";
P.K. Leedd99e042020-06-17 19:43:16 +0800697
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700698 std::string resetType;
P.K. Leedd99e042020-06-17 19:43:16 +0800699
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700700 if (!json_util::readJson(req, asyncResp->res, "ResetType",
701 resetType))
702 {
703 return;
704 }
P.K. Leedd99e042020-06-17 19:43:16 +0800705
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700706 if (resetType != "PowerCycle")
707 {
708 BMCWEB_LOG_DEBUG << "Invalid property value for ResetType: "
709 << resetType;
710 messages::actionParameterNotSupported(
711 asyncResp->res, resetType, "ResetType");
P.K. Leedd99e042020-06-17 19:43:16 +0800712
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700713 return;
714 }
715 doChassisPowerCycle(asyncResp);
716 });
717}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530718
719/**
720 * ChassisResetActionInfo derived class for delivering Chassis
721 * ResetType AllowableValues using ResetInfo schema.
722 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700723inline void requestRoutesChassisResetActionInfo(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530724{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700725 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -0700726 .privileges(redfish::privileges::getActionInfo)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700727 .methods(boost::beast::http::verb::get)(
728 [](const crow::Request&,
729 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
730 const std::string& chassisId)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530731
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700732 {
733 asyncResp->res.jsonValue = {
734 {"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"},
735 {"@odata.id",
736 "/redfish/v1/Chassis/" + chassisId + "/ResetActionInfo"},
737 {"Name", "Reset Action Info"},
738 {"Id", "ResetActionInfo"},
739 {"Parameters",
740 {{{"Name", "ResetType"},
741 {"Required", true},
742 {"DataType", "String"},
743 {"AllowableValues", {"PowerCycle"}}}}}};
744 });
745}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530746
Ed Tanous1abe55e2018-09-05 08:30:59 -0700747} // namespace redfish