blob: 8fc9129c206bb0396dddb03a31eba45d7a4ae54b [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 Tanoused398212021-06-09 17:05:54 -070023#include <registries/privilege_registry.hpp>
Gunnar Mills02f6ff12020-10-14 15:59:58 -050024#include <utils/collection.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050025
Ed Tanousabf2add2019-01-22 16:40:12 -080026#include <variant>
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010027
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{
40 crow::connections::systemBus->async_method_call(
41 [aResp{std::move(aResp)}](
42 const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -050043 const std::variant<std::string>& chassisState) {
Gunnar Millsbeeca0a2019-02-14 16:30:45 -060044 if (ec)
45 {
46 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
47 messages::internalError(aResp->res);
48 return;
49 }
50
Gunnar Mills1214b7e2020-06-04 10:11:30 -050051 const std::string* s = std::get_if<std::string>(&chassisState);
Gunnar Millsbeeca0a2019-02-14 16:30:45 -060052 BMCWEB_LOG_DEBUG << "Chassis state: " << *s;
53 if (s != nullptr)
54 {
55 // Verify Chassis State
56 if (*s == "xyz.openbmc_project.State.Chassis.PowerState.On")
57 {
58 aResp->res.jsonValue["PowerState"] = "On";
59 aResp->res.jsonValue["Status"]["State"] = "Enabled";
60 }
61 else if (*s ==
62 "xyz.openbmc_project.State.Chassis.PowerState.Off")
63 {
64 aResp->res.jsonValue["PowerState"] = "Off";
65 aResp->res.jsonValue["Status"]["State"] = "StandbyOffline";
66 }
67 }
68 },
69 "xyz.openbmc_project.State.Chassis",
70 "/xyz/openbmc_project/state/chassis0",
71 "org.freedesktop.DBus.Properties", "Get",
72 "xyz.openbmc_project.State.Chassis", "CurrentPowerState");
73}
74
75/**
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010076 * DBus types primitives for several generic DBus interfaces
77 * TODO(Pawel) consider move this to separate file into boost::dbus
78 */
Ed Tanous55c7b7a2018-05-22 15:27:24 -070079// Note, this is not a very useful Variant, but because it isn't used to get
Ed Tanousaa2e59c2018-04-12 12:17:20 -070080// values, it should be as simple as possible
81// TODO(ed) invent a nullvariant type
Cheng C Yang5fd7ba62019-11-28 15:58:08 +080082using VariantType = std::variant<bool, std::string, uint64_t, uint32_t>;
Ed Tanousaa2e59c2018-04-12 12:17:20 -070083using ManagedObjectsType = std::vector<std::pair<
84 sdbusplus::message::object_path,
85 std::vector<std::pair<std::string,
86 std::vector<std::pair<std::string, VariantType>>>>>>;
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010087
Ed Tanousaa2e59c2018-04-12 12:17:20 -070088using PropertiesType = boost::container::flat_map<std::string, VariantType>;
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010089
zhanghch058d1b46d2021-04-01 11:18:24 +080090inline void getIntrusionByService(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous23a21a12020-07-25 04:45:05 +000091 const std::string& service,
92 const std::string& objPath)
Qiang XUc1819422019-02-27 13:51:32 +080093{
94 BMCWEB_LOG_DEBUG << "Get intrusion status by service \n";
95
96 crow::connections::systemBus->async_method_call(
97 [aResp{std::move(aResp)}](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -050098 const std::variant<std::string>& value) {
Qiang XUc1819422019-02-27 13:51:32 +080099 if (ec)
100 {
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500101 // do not add err msg in redfish response, because this is not
Qiang XUc1819422019-02-27 13:51:32 +0800102 // mandatory property
103 BMCWEB_LOG_ERROR << "DBUS response error " << ec << "\n";
104 return;
105 }
106
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500107 const std::string* status = std::get_if<std::string>(&value);
Qiang XUc1819422019-02-27 13:51:32 +0800108
109 if (status == nullptr)
110 {
111 BMCWEB_LOG_ERROR << "intrusion status read error \n";
112 return;
113 }
114
115 aResp->res.jsonValue["PhysicalSecurity"] = {
116 {"IntrusionSensorNumber", 1}, {"IntrusionSensor", *status}};
117 },
118 service, objPath, "org.freedesktop.DBus.Properties", "Get",
119 "xyz.openbmc_project.Chassis.Intrusion", "Status");
120}
121
122/**
123 * Retrieves physical security properties over dbus
124 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800125inline void getPhysicalSecurityData(std::shared_ptr<bmcweb::AsyncResp> aResp)
Qiang XUc1819422019-02-27 13:51:32 +0800126{
127 crow::connections::systemBus->async_method_call(
128 [aResp{std::move(aResp)}](
129 const boost::system::error_code ec,
130 const std::vector<std::pair<
131 std::string,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500132 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
133 subtree) {
Qiang XUc1819422019-02-27 13:51:32 +0800134 if (ec)
135 {
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500136 // do not add err msg in redfish response, because this is not
Qiang XUc1819422019-02-27 13:51:32 +0800137 // mandatory property
Andrew Geissler54fbf172021-11-11 15:59:30 -0600138 BMCWEB_LOG_INFO << "DBUS error: no matched iface " << ec
139 << "\n";
Qiang XUc1819422019-02-27 13:51:32 +0800140 return;
141 }
142 // Iterate over all retrieved ObjectPaths.
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500143 for (const auto& object : subtree)
Qiang XUc1819422019-02-27 13:51:32 +0800144 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500145 for (const auto& service : object.second)
Qiang XUc1819422019-02-27 13:51:32 +0800146 {
147 getIntrusionByService(aResp, service.first, object.first);
148 return;
149 }
150 }
151 },
152 "xyz.openbmc_project.ObjectMapper",
153 "/xyz/openbmc_project/object_mapper",
154 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous271584a2019-07-09 16:24:22 -0700155 "/xyz/openbmc_project/Intrusion", 1,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500156 std::array<const char*, 1>{"xyz.openbmc_project.Chassis.Intrusion"});
Qiang XUc1819422019-02-27 13:51:32 +0800157}
158
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100159/**
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100160 * ChassisCollection derived class for delivering Chassis Collection Schema
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700161 * Functions triggers appropriate requests on DBus
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100162 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700163inline void requestRoutesChassisCollection(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700164{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700165 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/")
Ed Tanoused398212021-06-09 17:05:54 -0700166 .privileges(redfish::privileges::getChassisCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700167 .methods(boost::beast::http::verb::get)(
168 [](const crow::Request&,
169 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
170 asyncResp->res.jsonValue["@odata.type"] =
171 "#ChassisCollection.ChassisCollection";
172 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Chassis";
173 asyncResp->res.jsonValue["Name"] = "Chassis Collection";
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100174
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700175 collection_util::getCollectionMembers(
176 asyncResp, "/redfish/v1/Chassis",
177 {"xyz.openbmc_project.Inventory.Item.Board",
178 "xyz.openbmc_project.Inventory.Item.Chassis"});
179 });
180}
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100181
Willy Tu308f70c2021-09-28 20:24:52 -0700182inline void
183 getChassisLocationCode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
184 const std::string& connectionName,
185 const std::string& path)
186{
187 crow::connections::systemBus->async_method_call(
188 [asyncResp](const boost::system::error_code ec,
189 const std::variant<std::string>& property) {
190 if (ec)
191 {
George Liu0fda0f12021-11-16 10:06:17 +0800192 BMCWEB_LOG_DEBUG << "DBUS response error for Location";
Willy Tu308f70c2021-09-28 20:24:52 -0700193 messages::internalError(asyncResp->res);
194 return;
195 }
196
197 const std::string* value = std::get_if<std::string>(&property);
198 if (value == nullptr)
199 {
George Liu0fda0f12021-11-16 10:06:17 +0800200 BMCWEB_LOG_DEBUG << "Null value returned for locaton code";
Willy Tu308f70c2021-09-28 20:24:52 -0700201 messages::internalError(asyncResp->res);
202 return;
203 }
204 asyncResp->res
205 .jsonValue["Location"]["PartLocation"]["ServiceLabel"] = *value;
206 },
207 connectionName, path, "org.freedesktop.DBus.Properties", "Get",
208 "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode");
209}
210
211inline void getChassisUUID(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
212 const std::string& connectionName,
213 const std::string& path)
214{
215 crow::connections::systemBus->async_method_call(
216 [asyncResp](const boost::system::error_code ec,
217 const std::variant<std::string>& chassisUUID) {
218 if (ec)
219 {
George Liu0fda0f12021-11-16 10:06:17 +0800220 BMCWEB_LOG_DEBUG << "DBUS response error for UUID";
Willy Tu308f70c2021-09-28 20:24:52 -0700221 messages::internalError(asyncResp->res);
222 return;
223 }
224 const std::string* value = std::get_if<std::string>(&chassisUUID);
225 if (value == nullptr)
226 {
George Liu0fda0f12021-11-16 10:06:17 +0800227 BMCWEB_LOG_DEBUG << "Null value returned for UUID";
Willy Tu308f70c2021-09-28 20:24:52 -0700228 messages::internalError(asyncResp->res);
229 return;
230 }
231 asyncResp->res.jsonValue["UUID"] = *value;
232 },
233 connectionName, path, "org.freedesktop.DBus.Properties", "Get",
234 "xyz.openbmc_project.Common.UUID", "UUID");
235}
236
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100237/**
238 * Chassis override class for delivering Chassis Schema
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700239 * Functions triggers appropriate requests on DBus
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100240 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700241inline void requestRoutesChassis(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700242{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700243 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700244 .privileges(redfish::privileges::getChassis)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700245 .methods(
246 boost::beast::http::verb::get)([](const crow::Request&,
247 const std::shared_ptr<
248 bmcweb::AsyncResp>& asyncResp,
249 const std::string& chassisId) {
250 const std::array<const char*, 2> interfaces = {
251 "xyz.openbmc_project.Inventory.Item.Board",
252 "xyz.openbmc_project.Inventory.Item.Chassis"};
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100253
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700254 crow::connections::systemBus->async_method_call(
255 [asyncResp, chassisId(std::string(chassisId))](
256 const boost::system::error_code ec,
257 const crow::openbmc_mapper::GetSubTreeType& subtree) {
258 if (ec)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700259 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700260 messages::internalError(asyncResp->res);
261 return;
Ed Tanousdaf36e22018-04-20 16:01:36 -0700262 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700263 // Iterate over all retrieved ObjectPaths.
264 for (const std::pair<
265 std::string,
266 std::vector<std::pair<std::string,
267 std::vector<std::string>>>>&
268 object : subtree)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700269 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700270 const std::string& path = object.first;
271 const std::vector<
272 std::pair<std::string, std::vector<std::string>>>&
273 connectionNames = object.second;
Ed Tanouse0d918b2018-03-27 17:41:04 -0700274
George Liu997093e2021-11-17 17:43:45 +0800275 sdbusplus::message::object_path objPath(path);
276 if (objPath.filename() != chassisId)
James Feist1c8fba92019-12-20 15:12:07 -0800277 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700278 continue;
James Feist1c8fba92019-12-20 15:12:07 -0800279 }
James Feist1c8fba92019-12-20 15:12:07 -0800280
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700281 auto health =
282 std::make_shared<HealthPopulate>(asyncResp);
283
284 crow::connections::systemBus->async_method_call(
285 [health](
286 const boost::system::error_code ec2,
287 std::variant<std::vector<std::string>>& resp) {
288 if (ec2)
289 {
290 return; // no sensors = no failures
291 }
292 std::vector<std::string>* data =
293 std::get_if<std::vector<std::string>>(
294 &resp);
295 if (data == nullptr)
296 {
297 return;
298 }
299 health->inventory = std::move(*data);
300 },
301 "xyz.openbmc_project.ObjectMapper",
302 path + "/all_sensors",
303 "org.freedesktop.DBus.Properties", "Get",
304 "xyz.openbmc_project.Association", "endpoints");
305
306 health->populate();
307
308 if (connectionNames.size() < 1)
309 {
310 BMCWEB_LOG_ERROR << "Got 0 Connection names";
311 continue;
312 }
313
314 asyncResp->res.jsonValue["@odata.type"] =
315 "#Chassis.v1_14_0.Chassis";
316 asyncResp->res.jsonValue["@odata.id"] =
317 "/redfish/v1/Chassis/" + chassisId;
318 asyncResp->res.jsonValue["Name"] = "Chassis Collection";
319 asyncResp->res.jsonValue["ChassisType"] = "RackMount";
320 asyncResp->res.jsonValue["Actions"]["#Chassis.Reset"] =
321 {{"target", "/redfish/v1/Chassis/" + chassisId +
322 "/Actions/Chassis.Reset"},
323 {"@Redfish.ActionInfo", "/redfish/v1/Chassis/" +
324 chassisId +
325 "/ResetActionInfo"}};
326 asyncResp->res.jsonValue["PCIeDevices"] = {
327 {"@odata.id",
328 "/redfish/v1/Systems/system/PCIeDevices"}};
329
330 const std::string& connectionName =
331 connectionNames[0].first;
332
333 const std::vector<std::string>& interfaces2 =
334 connectionNames[0].second;
335 const std::array<const char*, 2> hasIndicatorLed = {
336 "xyz.openbmc_project.Inventory.Item.Panel",
George Liu0fda0f12021-11-16 10:06:17 +0800337 "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700338
Tejas Patil476b9cc2021-06-04 17:09:14 +0530339 const std::string assetTagInterface =
George Liu0fda0f12021-11-16 10:06:17 +0800340 "xyz.openbmc_project.Inventory.Decorator.AssetTag";
Tejas Patil476b9cc2021-06-04 17:09:14 +0530341 if (std::find(interfaces2.begin(), interfaces2.end(),
342 assetTagInterface) != interfaces2.end())
343 {
344 crow::connections::systemBus->async_method_call(
345 [asyncResp, chassisId(std::string(chassisId))](
346 const boost::system::error_code ec,
347 const std::variant<std::string>& property) {
348 if (ec)
349 {
350 BMCWEB_LOG_DEBUG
George Liu0fda0f12021-11-16 10:06:17 +0800351 << "DBus response error for AssetTag";
Tejas Patil476b9cc2021-06-04 17:09:14 +0530352 messages::internalError(asyncResp->res);
353 return;
354 }
355
356 const std::string* assetTag =
357 std::get_if<std::string>(&property);
358 if (assetTag == nullptr)
359 {
360 BMCWEB_LOG_DEBUG
George Liu0fda0f12021-11-16 10:06:17 +0800361 << "Null value returned for Chassis AssetTag";
Tejas Patil476b9cc2021-06-04 17:09:14 +0530362 messages::internalError(asyncResp->res);
363 return;
364 }
365 asyncResp->res.jsonValue["AssetTag"] =
366 *assetTag;
367 },
368 connectionName, path,
369 "org.freedesktop.DBus.Properties", "Get",
370 assetTagInterface, "AssetTag");
371 }
372
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700373 for (const char* interface : hasIndicatorLed)
374 {
375 if (std::find(interfaces2.begin(),
376 interfaces2.end(),
377 interface) != interfaces2.end())
378 {
379 getIndicatorLedState(asyncResp);
380 getLocationIndicatorActive(asyncResp);
381 break;
382 }
383 }
384
SunnySrivastava198488ad7f02020-12-03 10:27:52 -0600385 crow::connections::systemBus->async_method_call(
386 [asyncResp, chassisId(std::string(chassisId))](
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700387 const boost::system::error_code /*ec2*/,
388 const std::vector<
389 std::pair<std::string, VariantType>>&
390 propertiesList) {
391 for (const std::pair<std::string, VariantType>&
392 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") ||
402 (propertyName == "Model"))
Shawn McCarney99cffd72019-03-01 10:46:20 -0600403 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700404 const std::string* value =
405 std::get_if<std::string>(
406 &property.second);
407 if (value != nullptr)
408 {
409 asyncResp->res
410 .jsonValue[propertyName] =
411 *value;
412 }
Shawn McCarney99cffd72019-03-01 10:46:20 -0600413 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700414 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700415 asyncResp->res.jsonValue["Name"] = chassisId;
416 asyncResp->res.jsonValue["Id"] = chassisId;
zhanghch050256b692021-06-12 10:26:52 +0800417#ifdef BMCWEB_ALLOW_DEPRECATED_POWER_THERMAL
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700418 asyncResp->res.jsonValue["Thermal"] = {
419 {"@odata.id", "/redfish/v1/Chassis/" +
420 chassisId + "/Thermal"}};
421 // Power object
422 asyncResp->res.jsonValue["Power"] = {
423 {"@odata.id", "/redfish/v1/Chassis/" +
424 chassisId + "/Power"}};
zhanghch050256b692021-06-12 10:26:52 +0800425#endif
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700426 // SensorCollection
427 asyncResp->res.jsonValue["Sensors"] = {
428 {"@odata.id", "/redfish/v1/Chassis/" +
429 chassisId + "/Sensors"}};
430 asyncResp->res.jsonValue["Status"] = {
431 {"State", "Enabled"},
432 };
433
434 asyncResp->res
435 .jsonValue["Links"]["ComputerSystems"] = {
436 {{"@odata.id",
437 "/redfish/v1/Systems/system"}}};
438 asyncResp->res.jsonValue["Links"]["ManagedBy"] =
439 {{{"@odata.id",
440 "/redfish/v1/Managers/bmc"}}};
441 getChassisState(asyncResp);
442 },
443 connectionName, path,
444 "org.freedesktop.DBus.Properties", "GetAll",
445 "xyz.openbmc_project.Inventory.Decorator.Asset");
Sharad Yadav2c37b4b2021-05-10 12:53:38 +0530446
Willy Tu308f70c2021-09-28 20:24:52 -0700447 for (const auto& interface : interfaces2)
Sharad Yadav2c37b4b2021-05-10 12:53:38 +0530448 {
Willy Tu308f70c2021-09-28 20:24:52 -0700449 if (interface == "xyz.openbmc_project.Common.UUID")
450 {
451 getChassisUUID(asyncResp, connectionName, path);
452 }
George Liu0fda0f12021-11-16 10:06:17 +0800453 else if (
454 interface ==
455 "xyz.openbmc_project.Inventory.Decorator.LocationCode")
Willy Tu308f70c2021-09-28 20:24:52 -0700456 {
457 getChassisLocationCode(asyncResp,
458 connectionName, path);
459 }
Sharad Yadav2c37b4b2021-05-10 12:53:38 +0530460 }
461
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700462 return;
463 }
464
465 // Couldn't find an object with that name. return an error
466 messages::resourceNotFound(
467 asyncResp->res, "#Chassis.v1_14_0.Chassis", chassisId);
468 },
469 "xyz.openbmc_project.ObjectMapper",
470 "/xyz/openbmc_project/object_mapper",
471 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
472 "/xyz/openbmc_project/inventory", 0, interfaces);
473
474 getPhysicalSecurityData(asyncResp);
475 });
476
477 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700478 .privileges(redfish::privileges::patchChassis)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700479 .methods(
480 boost::beast::http::verb::
481 patch)([](const crow::Request& req,
482 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
483 const std::string& param) {
484 std::optional<bool> locationIndicatorActive;
485 std::optional<std::string> indicatorLed;
486
487 if (param.empty())
488 {
489 return;
490 }
491
492 if (!json_util::readJson(
493 req, asyncResp->res, "LocationIndicatorActive",
494 locationIndicatorActive, "IndicatorLED", indicatorLed))
495 {
496 return;
497 }
498
499 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
500 if (!locationIndicatorActive && !indicatorLed)
501 {
502 return; // delete this when we support more patch properties
503 }
504 if (indicatorLed)
505 {
506 asyncResp->res.addHeader(
507 boost::beast::http::field::warning,
George Liu0fda0f12021-11-16 10:06:17 +0800508 "299 - \"IndicatorLED is deprecated. Use LocationIndicatorActive instead.\"");
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700509 }
510
511 const std::array<const char*, 2> interfaces = {
512 "xyz.openbmc_project.Inventory.Item.Board",
513 "xyz.openbmc_project.Inventory.Item.Chassis"};
514
515 const std::string& chassisId = param;
516
517 crow::connections::systemBus->async_method_call(
518 [asyncResp, chassisId, locationIndicatorActive, indicatorLed](
519 const boost::system::error_code ec,
520 const crow::openbmc_mapper::GetSubTreeType& subtree) {
521 if (ec)
522 {
523 messages::internalError(asyncResp->res);
524 return;
525 }
526
527 // Iterate over all retrieved ObjectPaths.
528 for (const std::pair<
529 std::string,
530 std::vector<std::pair<std::string,
531 std::vector<std::string>>>>&
532 object : subtree)
533 {
534 const std::string& path = object.first;
535 const std::vector<
536 std::pair<std::string, std::vector<std::string>>>&
537 connectionNames = object.second;
538
George Liu997093e2021-11-17 17:43:45 +0800539 sdbusplus::message::object_path objPath(path);
540 if (objPath.filename() != chassisId)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700541 {
542 continue;
543 }
544
545 if (connectionNames.size() < 1)
546 {
547 BMCWEB_LOG_ERROR << "Got 0 Connection names";
548 continue;
549 }
550
551 const std::vector<std::string>& interfaces3 =
552 connectionNames[0].second;
553
554 const std::array<const char*, 2> hasIndicatorLed = {
555 "xyz.openbmc_project.Inventory.Item.Panel",
George Liu0fda0f12021-11-16 10:06:17 +0800556 "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700557 bool indicatorChassis = false;
558 for (const char* interface : hasIndicatorLed)
559 {
560 if (std::find(interfaces3.begin(),
561 interfaces3.end(),
562 interface) != interfaces3.end())
563 {
564 indicatorChassis = true;
565 break;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700566 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700567 }
568 if (locationIndicatorActive)
569 {
570 if (indicatorChassis)
571 {
572 setLocationIndicatorActive(
573 asyncResp, *locationIndicatorActive);
574 }
575 else
576 {
577 messages::propertyUnknown(
578 asyncResp->res, "LocationIndicatorActive");
579 }
580 }
581 if (indicatorLed)
582 {
583 if (indicatorChassis)
584 {
585 setIndicatorLedState(asyncResp, *indicatorLed);
586 }
587 else
588 {
589 messages::propertyUnknown(asyncResp->res,
590 "IndicatorLED");
591 }
592 }
593 return;
James Feist1c8fba92019-12-20 15:12:07 -0800594 }
595
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700596 messages::resourceNotFound(
597 asyncResp->res, "#Chassis.v1_14_0.Chassis", chassisId);
598 },
599 "xyz.openbmc_project.ObjectMapper",
600 "/xyz/openbmc_project/object_mapper",
601 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
602 "/xyz/openbmc_project/inventory", 0, interfaces);
603 });
604}
P.K. Leedd99e042020-06-17 19:43:16 +0800605
zhanghch058d1b46d2021-04-01 11:18:24 +0800606inline void
607 doChassisPowerCycle(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
P.K. Leedd99e042020-06-17 19:43:16 +0800608{
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700609 const char* busName = "xyz.openbmc_project.ObjectMapper";
610 const char* path = "/xyz/openbmc_project/object_mapper";
611 const char* interface = "xyz.openbmc_project.ObjectMapper";
612 const char* method = "GetSubTreePaths";
P.K. Leedd99e042020-06-17 19:43:16 +0800613
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700614 const std::array<const char*, 1> interfaces = {
615 "xyz.openbmc_project.State.Chassis"};
616
617 // Use mapper to get subtree paths.
P.K. Leedd99e042020-06-17 19:43:16 +0800618 crow::connections::systemBus->async_method_call(
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700619 [asyncResp](const boost::system::error_code ec,
620 const std::vector<std::string>& chassisList) {
P.K. Leedd99e042020-06-17 19:43:16 +0800621 if (ec)
622 {
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700623 BMCWEB_LOG_DEBUG << "[mapper] Bad D-Bus request error: " << ec;
P.K. Leedd99e042020-06-17 19:43:16 +0800624 messages::internalError(asyncResp->res);
625 return;
626 }
627
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700628 const char* processName = "xyz.openbmc_project.State.Chassis";
629 const char* interfaceName = "xyz.openbmc_project.State.Chassis";
630 const char* destProperty = "RequestedPowerTransition";
631 const std::string propertyValue =
632 "xyz.openbmc_project.State.Chassis.Transition.PowerCycle";
633 std::string objectPath =
634 "/xyz/openbmc_project/state/chassis_system0";
635
636 /* Look for system reset chassis path */
637 if ((std::find(chassisList.begin(), chassisList.end(),
638 objectPath)) == chassisList.end())
639 {
640 /* We prefer to reset the full chassis_system, but if it doesn't
641 * exist on some platforms, fall back to a host-only power reset
642 */
643 objectPath = "/xyz/openbmc_project/state/chassis0";
644 }
645
646 crow::connections::systemBus->async_method_call(
647 [asyncResp](const boost::system::error_code ec) {
648 // Use "Set" method to set the property value.
649 if (ec)
650 {
651 BMCWEB_LOG_DEBUG << "[Set] Bad D-Bus request error: "
652 << ec;
653 messages::internalError(asyncResp->res);
654 return;
655 }
656
657 messages::success(asyncResp->res);
658 },
659 processName, objectPath, "org.freedesktop.DBus.Properties",
660 "Set", interfaceName, destProperty,
661 std::variant<std::string>{propertyValue});
P.K. Leedd99e042020-06-17 19:43:16 +0800662 },
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700663 busName, path, interface, method, "/", 0, interfaces);
P.K. Leedd99e042020-06-17 19:43:16 +0800664}
665
666/**
667 * ChassisResetAction class supports the POST method for the Reset
668 * action.
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700669 * Function handles POST method request.
670 * Analyzes POST body before sending Reset request data to D-Bus.
P.K. Leedd99e042020-06-17 19:43:16 +0800671 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700672
673inline void requestRoutesChassisResetAction(App& app)
P.K. Leedd99e042020-06-17 19:43:16 +0800674{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700675 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Actions/Chassis.Reset/")
Ed Tanoused398212021-06-09 17:05:54 -0700676 .privileges(redfish::privileges::postChassis)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700677 .methods(boost::beast::http::verb::post)(
678 [](const crow::Request& req,
679 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
680 const std::string&) {
681 BMCWEB_LOG_DEBUG << "Post Chassis Reset.";
P.K. Leedd99e042020-06-17 19:43:16 +0800682
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700683 std::string resetType;
P.K. Leedd99e042020-06-17 19:43:16 +0800684
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700685 if (!json_util::readJson(req, asyncResp->res, "ResetType",
686 resetType))
687 {
688 return;
689 }
P.K. Leedd99e042020-06-17 19:43:16 +0800690
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700691 if (resetType != "PowerCycle")
692 {
693 BMCWEB_LOG_DEBUG << "Invalid property value for ResetType: "
694 << resetType;
695 messages::actionParameterNotSupported(
696 asyncResp->res, resetType, "ResetType");
P.K. Leedd99e042020-06-17 19:43:16 +0800697
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700698 return;
699 }
700 doChassisPowerCycle(asyncResp);
701 });
702}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530703
704/**
705 * ChassisResetActionInfo derived class for delivering Chassis
706 * ResetType AllowableValues using ResetInfo schema.
707 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700708inline void requestRoutesChassisResetActionInfo(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530709{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700710 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -0700711 .privileges(redfish::privileges::getActionInfo)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700712 .methods(boost::beast::http::verb::get)(
713 [](const crow::Request&,
714 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
715 const std::string& chassisId)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530716
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700717 {
718 asyncResp->res.jsonValue = {
719 {"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"},
720 {"@odata.id",
721 "/redfish/v1/Chassis/" + chassisId + "/ResetActionInfo"},
722 {"Name", "Reset Action Info"},
723 {"Id", "ResetActionInfo"},
724 {"Parameters",
725 {{{"Name", "ResetType"},
726 {"Required", true},
727 {"DataType", "String"},
728 {"AllowableValues", {"PowerCycle"}}}}}};
729 });
730}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530731
Ed Tanous1abe55e2018-09-05 08:30:59 -0700732} // namespace redfish