blob: c41b7e1497925938b6f3040015fc885a2a3c451d [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
138 BMCWEB_LOG_ERROR << "DBUS error: no matched iface " << ec
139 << "\n";
140 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
182/**
183 * Chassis override class for delivering Chassis Schema
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700184 * Functions triggers appropriate requests on DBus
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100185 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700186inline void requestRoutesChassis(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700187{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700188 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700189 .privileges(redfish::privileges::getChassis)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700190 .methods(
191 boost::beast::http::verb::get)([](const crow::Request&,
192 const std::shared_ptr<
193 bmcweb::AsyncResp>& asyncResp,
194 const std::string& chassisId) {
195 const std::array<const char*, 2> interfaces = {
196 "xyz.openbmc_project.Inventory.Item.Board",
197 "xyz.openbmc_project.Inventory.Item.Chassis"};
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100198
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700199 crow::connections::systemBus->async_method_call(
200 [asyncResp, chassisId(std::string(chassisId))](
201 const boost::system::error_code ec,
202 const crow::openbmc_mapper::GetSubTreeType& subtree) {
203 if (ec)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700204 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700205 messages::internalError(asyncResp->res);
206 return;
Ed Tanousdaf36e22018-04-20 16:01:36 -0700207 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700208 // Iterate over all retrieved ObjectPaths.
209 for (const std::pair<
210 std::string,
211 std::vector<std::pair<std::string,
212 std::vector<std::string>>>>&
213 object : subtree)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700214 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700215 const std::string& path = object.first;
216 const std::vector<
217 std::pair<std::string, std::vector<std::string>>>&
218 connectionNames = object.second;
Ed Tanouse0d918b2018-03-27 17:41:04 -0700219
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700220 if (!boost::ends_with(path, chassisId))
James Feist1c8fba92019-12-20 15:12:07 -0800221 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700222 continue;
James Feist1c8fba92019-12-20 15:12:07 -0800223 }
James Feist1c8fba92019-12-20 15:12:07 -0800224
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700225 auto health =
226 std::make_shared<HealthPopulate>(asyncResp);
227
228 crow::connections::systemBus->async_method_call(
229 [health](
230 const boost::system::error_code ec2,
231 std::variant<std::vector<std::string>>& resp) {
232 if (ec2)
233 {
234 return; // no sensors = no failures
235 }
236 std::vector<std::string>* data =
237 std::get_if<std::vector<std::string>>(
238 &resp);
239 if (data == nullptr)
240 {
241 return;
242 }
243 health->inventory = std::move(*data);
244 },
245 "xyz.openbmc_project.ObjectMapper",
246 path + "/all_sensors",
247 "org.freedesktop.DBus.Properties", "Get",
248 "xyz.openbmc_project.Association", "endpoints");
249
250 health->populate();
251
252 if (connectionNames.size() < 1)
253 {
254 BMCWEB_LOG_ERROR << "Got 0 Connection names";
255 continue;
256 }
257
258 asyncResp->res.jsonValue["@odata.type"] =
259 "#Chassis.v1_14_0.Chassis";
260 asyncResp->res.jsonValue["@odata.id"] =
261 "/redfish/v1/Chassis/" + chassisId;
262 asyncResp->res.jsonValue["Name"] = "Chassis Collection";
263 asyncResp->res.jsonValue["ChassisType"] = "RackMount";
264 asyncResp->res.jsonValue["Actions"]["#Chassis.Reset"] =
265 {{"target", "/redfish/v1/Chassis/" + chassisId +
266 "/Actions/Chassis.Reset"},
267 {"@Redfish.ActionInfo", "/redfish/v1/Chassis/" +
268 chassisId +
269 "/ResetActionInfo"}};
270 asyncResp->res.jsonValue["PCIeDevices"] = {
271 {"@odata.id",
272 "/redfish/v1/Systems/system/PCIeDevices"}};
273
274 const std::string& connectionName =
275 connectionNames[0].first;
276
277 const std::vector<std::string>& interfaces2 =
278 connectionNames[0].second;
279 const std::array<const char*, 2> hasIndicatorLed = {
280 "xyz.openbmc_project.Inventory.Item.Panel",
281 "xyz.openbmc_project.Inventory.Item.Board."
282 "Motherboard"};
283
284 for (const char* interface : hasIndicatorLed)
285 {
286 if (std::find(interfaces2.begin(),
287 interfaces2.end(),
288 interface) != interfaces2.end())
289 {
290 getIndicatorLedState(asyncResp);
291 getLocationIndicatorActive(asyncResp);
292 break;
293 }
294 }
295
296 const std::string locationInterface =
297 "xyz.openbmc_project.Inventory.Decorator."
298 "LocationCode";
299 if (std::find(interfaces2.begin(), interfaces2.end(),
300 locationInterface) != interfaces2.end())
301 {
302 crow::connections::systemBus->async_method_call(
303 [asyncResp, chassisId(std::string(chassisId))](
304 const boost::system::error_code ec,
305 const std::variant<std::string>& property) {
306 if (ec)
307 {
308 BMCWEB_LOG_DEBUG
309 << "DBUS response error for "
310 "Location";
311 messages::internalError(asyncResp->res);
312 return;
313 }
314
315 const std::string* value =
316 std::get_if<std::string>(&property);
317 if (value == nullptr)
318 {
319 BMCWEB_LOG_DEBUG
320 << "Null value returned "
321 "for locaton code";
322 messages::internalError(asyncResp->res);
323 return;
324 }
325 asyncResp->res
326 .jsonValue["Location"]["PartLocation"]
327 ["ServiceLabel"] = *value;
328 },
329 connectionName, path,
330 "org.freedesktop.DBus.Properties", "Get",
331 locationInterface, "LocationCode");
332 }
333
SunnySrivastava198488ad7f02020-12-03 10:27:52 -0600334 crow::connections::systemBus->async_method_call(
335 [asyncResp, chassisId(std::string(chassisId))](
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700336 const boost::system::error_code /*ec2*/,
337 const std::vector<
338 std::pair<std::string, VariantType>>&
339 propertiesList) {
340 for (const std::pair<std::string, VariantType>&
341 property : propertiesList)
SunnySrivastava198488ad7f02020-12-03 10:27:52 -0600342 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700343 // Store DBus properties that are also
344 // Redfish properties with same name and a
345 // string value
346 const std::string& propertyName =
347 property.first;
348 if ((propertyName == "PartNumber") ||
349 (propertyName == "SerialNumber") ||
350 (propertyName == "Manufacturer") ||
351 (propertyName == "Model"))
Shawn McCarney99cffd72019-03-01 10:46:20 -0600352 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700353 const std::string* value =
354 std::get_if<std::string>(
355 &property.second);
356 if (value != nullptr)
357 {
358 asyncResp->res
359 .jsonValue[propertyName] =
360 *value;
361 }
Shawn McCarney99cffd72019-03-01 10:46:20 -0600362 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700363 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700364 asyncResp->res.jsonValue["Name"] = chassisId;
365 asyncResp->res.jsonValue["Id"] = chassisId;
zhanghch050256b692021-06-12 10:26:52 +0800366#ifdef BMCWEB_ALLOW_DEPRECATED_POWER_THERMAL
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700367 asyncResp->res.jsonValue["Thermal"] = {
368 {"@odata.id", "/redfish/v1/Chassis/" +
369 chassisId + "/Thermal"}};
370 // Power object
371 asyncResp->res.jsonValue["Power"] = {
372 {"@odata.id", "/redfish/v1/Chassis/" +
373 chassisId + "/Power"}};
zhanghch050256b692021-06-12 10:26:52 +0800374#endif
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700375 // SensorCollection
376 asyncResp->res.jsonValue["Sensors"] = {
377 {"@odata.id", "/redfish/v1/Chassis/" +
378 chassisId + "/Sensors"}};
379 asyncResp->res.jsonValue["Status"] = {
380 {"State", "Enabled"},
381 };
382
383 asyncResp->res
384 .jsonValue["Links"]["ComputerSystems"] = {
385 {{"@odata.id",
386 "/redfish/v1/Systems/system"}}};
387 asyncResp->res.jsonValue["Links"]["ManagedBy"] =
388 {{{"@odata.id",
389 "/redfish/v1/Managers/bmc"}}};
390 getChassisState(asyncResp);
391 },
392 connectionName, path,
393 "org.freedesktop.DBus.Properties", "GetAll",
394 "xyz.openbmc_project.Inventory.Decorator.Asset");
Sharad Yadav2c37b4b2021-05-10 12:53:38 +0530395
396 // Chassis UUID
397 const std::string uuidInterface =
398 "xyz.openbmc_project.Common.UUID";
399 if (std::find(interfaces2.begin(), interfaces2.end(),
400 uuidInterface) != interfaces2.end())
401 {
402 crow::connections::systemBus->async_method_call(
403 [asyncResp](const boost::system::error_code ec,
404 const std::variant<std::string>&
405 chassisUUID) {
406 if (ec)
407 {
408 BMCWEB_LOG_DEBUG
409 << "DBUS response error for "
410 "UUID";
411 messages::internalError(asyncResp->res);
412 return;
413 }
414 const std::string* value =
415 std::get_if<std::string>(&chassisUUID);
416 if (value == nullptr)
417 {
418 BMCWEB_LOG_DEBUG
419 << "Null value returned "
420 "for UUID";
421 messages::internalError(asyncResp->res);
422 return;
423 }
424 asyncResp->res.jsonValue["UUID"] = *value;
425 },
426 connectionName, path,
427 "org.freedesktop.DBus.Properties", "Get",
428 uuidInterface, "UUID");
429 }
430
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700431 return;
432 }
433
434 // Couldn't find an object with that name. return an error
435 messages::resourceNotFound(
436 asyncResp->res, "#Chassis.v1_14_0.Chassis", chassisId);
437 },
438 "xyz.openbmc_project.ObjectMapper",
439 "/xyz/openbmc_project/object_mapper",
440 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
441 "/xyz/openbmc_project/inventory", 0, interfaces);
442
443 getPhysicalSecurityData(asyncResp);
444 });
445
446 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700447 .privileges(redfish::privileges::patchChassis)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700448 .methods(
449 boost::beast::http::verb::
450 patch)([](const crow::Request& req,
451 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
452 const std::string& param) {
453 std::optional<bool> locationIndicatorActive;
454 std::optional<std::string> indicatorLed;
455
456 if (param.empty())
457 {
458 return;
459 }
460
461 if (!json_util::readJson(
462 req, asyncResp->res, "LocationIndicatorActive",
463 locationIndicatorActive, "IndicatorLED", indicatorLed))
464 {
465 return;
466 }
467
468 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
469 if (!locationIndicatorActive && !indicatorLed)
470 {
471 return; // delete this when we support more patch properties
472 }
473 if (indicatorLed)
474 {
475 asyncResp->res.addHeader(
476 boost::beast::http::field::warning,
477 "299 - \"IndicatorLED is deprecated. Use "
478 "LocationIndicatorActive instead.\"");
479 }
480
481 const std::array<const char*, 2> interfaces = {
482 "xyz.openbmc_project.Inventory.Item.Board",
483 "xyz.openbmc_project.Inventory.Item.Chassis"};
484
485 const std::string& chassisId = param;
486
487 crow::connections::systemBus->async_method_call(
488 [asyncResp, chassisId, locationIndicatorActive, indicatorLed](
489 const boost::system::error_code ec,
490 const crow::openbmc_mapper::GetSubTreeType& subtree) {
491 if (ec)
492 {
493 messages::internalError(asyncResp->res);
494 return;
495 }
496
497 // Iterate over all retrieved ObjectPaths.
498 for (const std::pair<
499 std::string,
500 std::vector<std::pair<std::string,
501 std::vector<std::string>>>>&
502 object : subtree)
503 {
504 const std::string& path = object.first;
505 const std::vector<
506 std::pair<std::string, std::vector<std::string>>>&
507 connectionNames = object.second;
508
509 if (!boost::ends_with(path, chassisId))
510 {
511 continue;
512 }
513
514 if (connectionNames.size() < 1)
515 {
516 BMCWEB_LOG_ERROR << "Got 0 Connection names";
517 continue;
518 }
519
520 const std::vector<std::string>& interfaces3 =
521 connectionNames[0].second;
522
523 const std::array<const char*, 2> hasIndicatorLed = {
524 "xyz.openbmc_project.Inventory.Item.Panel",
525 "xyz.openbmc_project.Inventory.Item.Board."
526 "Motherboard"};
527 bool indicatorChassis = false;
528 for (const char* interface : hasIndicatorLed)
529 {
530 if (std::find(interfaces3.begin(),
531 interfaces3.end(),
532 interface) != interfaces3.end())
533 {
534 indicatorChassis = true;
535 break;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700536 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700537 }
538 if (locationIndicatorActive)
539 {
540 if (indicatorChassis)
541 {
542 setLocationIndicatorActive(
543 asyncResp, *locationIndicatorActive);
544 }
545 else
546 {
547 messages::propertyUnknown(
548 asyncResp->res, "LocationIndicatorActive");
549 }
550 }
551 if (indicatorLed)
552 {
553 if (indicatorChassis)
554 {
555 setIndicatorLedState(asyncResp, *indicatorLed);
556 }
557 else
558 {
559 messages::propertyUnknown(asyncResp->res,
560 "IndicatorLED");
561 }
562 }
563 return;
James Feist1c8fba92019-12-20 15:12:07 -0800564 }
565
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700566 messages::resourceNotFound(
567 asyncResp->res, "#Chassis.v1_14_0.Chassis", chassisId);
568 },
569 "xyz.openbmc_project.ObjectMapper",
570 "/xyz/openbmc_project/object_mapper",
571 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
572 "/xyz/openbmc_project/inventory", 0, interfaces);
573 });
574}
P.K. Leedd99e042020-06-17 19:43:16 +0800575
zhanghch058d1b46d2021-04-01 11:18:24 +0800576inline void
577 doChassisPowerCycle(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
P.K. Leedd99e042020-06-17 19:43:16 +0800578{
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700579 const char* busName = "xyz.openbmc_project.ObjectMapper";
580 const char* path = "/xyz/openbmc_project/object_mapper";
581 const char* interface = "xyz.openbmc_project.ObjectMapper";
582 const char* method = "GetSubTreePaths";
P.K. Leedd99e042020-06-17 19:43:16 +0800583
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700584 const std::array<const char*, 1> interfaces = {
585 "xyz.openbmc_project.State.Chassis"};
586
587 // Use mapper to get subtree paths.
P.K. Leedd99e042020-06-17 19:43:16 +0800588 crow::connections::systemBus->async_method_call(
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700589 [asyncResp](const boost::system::error_code ec,
590 const std::vector<std::string>& chassisList) {
P.K. Leedd99e042020-06-17 19:43:16 +0800591 if (ec)
592 {
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700593 BMCWEB_LOG_DEBUG << "[mapper] Bad D-Bus request error: " << ec;
P.K. Leedd99e042020-06-17 19:43:16 +0800594 messages::internalError(asyncResp->res);
595 return;
596 }
597
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700598 const char* processName = "xyz.openbmc_project.State.Chassis";
599 const char* interfaceName = "xyz.openbmc_project.State.Chassis";
600 const char* destProperty = "RequestedPowerTransition";
601 const std::string propertyValue =
602 "xyz.openbmc_project.State.Chassis.Transition.PowerCycle";
603 std::string objectPath =
604 "/xyz/openbmc_project/state/chassis_system0";
605
606 /* Look for system reset chassis path */
607 if ((std::find(chassisList.begin(), chassisList.end(),
608 objectPath)) == chassisList.end())
609 {
610 /* We prefer to reset the full chassis_system, but if it doesn't
611 * exist on some platforms, fall back to a host-only power reset
612 */
613 objectPath = "/xyz/openbmc_project/state/chassis0";
614 }
615
616 crow::connections::systemBus->async_method_call(
617 [asyncResp](const boost::system::error_code ec) {
618 // Use "Set" method to set the property value.
619 if (ec)
620 {
621 BMCWEB_LOG_DEBUG << "[Set] Bad D-Bus request error: "
622 << ec;
623 messages::internalError(asyncResp->res);
624 return;
625 }
626
627 messages::success(asyncResp->res);
628 },
629 processName, objectPath, "org.freedesktop.DBus.Properties",
630 "Set", interfaceName, destProperty,
631 std::variant<std::string>{propertyValue});
P.K. Leedd99e042020-06-17 19:43:16 +0800632 },
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700633 busName, path, interface, method, "/", 0, interfaces);
P.K. Leedd99e042020-06-17 19:43:16 +0800634}
635
636/**
637 * ChassisResetAction class supports the POST method for the Reset
638 * action.
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700639 * Function handles POST method request.
640 * Analyzes POST body before sending Reset request data to D-Bus.
P.K. Leedd99e042020-06-17 19:43:16 +0800641 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700642
643inline void requestRoutesChassisResetAction(App& app)
P.K. Leedd99e042020-06-17 19:43:16 +0800644{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700645 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Actions/Chassis.Reset/")
Ed Tanoused398212021-06-09 17:05:54 -0700646 .privileges(redfish::privileges::postChassis)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700647 .methods(boost::beast::http::verb::post)(
648 [](const crow::Request& req,
649 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
650 const std::string&) {
651 BMCWEB_LOG_DEBUG << "Post Chassis Reset.";
P.K. Leedd99e042020-06-17 19:43:16 +0800652
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700653 std::string resetType;
P.K. Leedd99e042020-06-17 19:43:16 +0800654
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700655 if (!json_util::readJson(req, asyncResp->res, "ResetType",
656 resetType))
657 {
658 return;
659 }
P.K. Leedd99e042020-06-17 19:43:16 +0800660
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700661 if (resetType != "PowerCycle")
662 {
663 BMCWEB_LOG_DEBUG << "Invalid property value for ResetType: "
664 << resetType;
665 messages::actionParameterNotSupported(
666 asyncResp->res, resetType, "ResetType");
P.K. Leedd99e042020-06-17 19:43:16 +0800667
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700668 return;
669 }
670 doChassisPowerCycle(asyncResp);
671 });
672}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530673
674/**
675 * ChassisResetActionInfo derived class for delivering Chassis
676 * ResetType AllowableValues using ResetInfo schema.
677 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700678inline void requestRoutesChassisResetActionInfo(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530679{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700680 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -0700681 .privileges(redfish::privileges::getActionInfo)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700682 .methods(boost::beast::http::verb::get)(
683 [](const crow::Request&,
684 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
685 const std::string& chassisId)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530686
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700687 {
688 asyncResp->res.jsonValue = {
689 {"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"},
690 {"@odata.id",
691 "/redfish/v1/Chassis/" + chassisId + "/ResetActionInfo"},
692 {"Name", "Reset Action Info"},
693 {"Id", "ResetActionInfo"},
694 {"Parameters",
695 {{{"Name", "ResetType"},
696 {"Required", true},
697 {"DataType", "String"},
698 {"AllowableValues", {"PowerCycle"}}}}}};
699 });
700}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530701
Ed Tanous1abe55e2018-09-05 08:30:59 -0700702} // namespace redfish