blob: 8fa25f0b59ed179fc278e8e32a6ae2ea4630de36 [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>
Gunnar Mills02f6ff12020-10-14 15:59:58 -050023#include <utils/collection.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050024
Ed Tanousabf2add2019-01-22 16:40:12 -080025#include <variant>
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010026
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,
Gunnar Mills1214b7e2020-06-04 10:11:30 -050042 const std::variant<std::string>& 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 Tanous55c7b7a2018-05-22 15:27:24 -070078// Note, this is not a very useful Variant, but because it isn't used to get
Ed Tanousaa2e59c2018-04-12 12:17:20 -070079// values, it should be as simple as possible
80// TODO(ed) invent a nullvariant type
Cheng C Yang5fd7ba62019-11-28 15:58:08 +080081using VariantType = std::variant<bool, std::string, uint64_t, uint32_t>;
Ed Tanousaa2e59c2018-04-12 12:17:20 -070082using ManagedObjectsType = std::vector<std::pair<
83 sdbusplus::message::object_path,
84 std::vector<std::pair<std::string,
85 std::vector<std::pair<std::string, VariantType>>>>>>;
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010086
Ed Tanousaa2e59c2018-04-12 12:17:20 -070087using PropertiesType = boost::container::flat_map<std::string, VariantType>;
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010088
zhanghch058d1b46d2021-04-01 11:18:24 +080089inline void getIntrusionByService(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous23a21a12020-07-25 04:45:05 +000090 const std::string& service,
91 const std::string& objPath)
Qiang XUc1819422019-02-27 13:51:32 +080092{
93 BMCWEB_LOG_DEBUG << "Get intrusion status by service \n";
94
95 crow::connections::systemBus->async_method_call(
96 [aResp{std::move(aResp)}](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -050097 const std::variant<std::string>& value) {
Qiang XUc1819422019-02-27 13:51:32 +080098 if (ec)
99 {
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500100 // do not add err msg in redfish response, because this is not
Qiang XUc1819422019-02-27 13:51:32 +0800101 // mandatory property
102 BMCWEB_LOG_ERROR << "DBUS response error " << ec << "\n";
103 return;
104 }
105
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500106 const std::string* status = std::get_if<std::string>(&value);
Qiang XUc1819422019-02-27 13:51:32 +0800107
108 if (status == nullptr)
109 {
110 BMCWEB_LOG_ERROR << "intrusion status read error \n";
111 return;
112 }
113
114 aResp->res.jsonValue["PhysicalSecurity"] = {
115 {"IntrusionSensorNumber", 1}, {"IntrusionSensor", *status}};
116 },
117 service, objPath, "org.freedesktop.DBus.Properties", "Get",
118 "xyz.openbmc_project.Chassis.Intrusion", "Status");
119}
120
121/**
122 * Retrieves physical security properties over dbus
123 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800124inline void getPhysicalSecurityData(std::shared_ptr<bmcweb::AsyncResp> aResp)
Qiang XUc1819422019-02-27 13:51:32 +0800125{
126 crow::connections::systemBus->async_method_call(
127 [aResp{std::move(aResp)}](
128 const boost::system::error_code ec,
129 const std::vector<std::pair<
130 std::string,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500131 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
132 subtree) {
Qiang XUc1819422019-02-27 13:51:32 +0800133 if (ec)
134 {
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500135 // do not add err msg in redfish response, because this is not
Qiang XUc1819422019-02-27 13:51:32 +0800136 // mandatory property
137 BMCWEB_LOG_ERROR << "DBUS error: no matched iface " << ec
138 << "\n";
139 return;
140 }
141 // Iterate over all retrieved ObjectPaths.
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500142 for (const auto& object : subtree)
Qiang XUc1819422019-02-27 13:51:32 +0800143 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500144 for (const auto& service : object.second)
Qiang XUc1819422019-02-27 13:51:32 +0800145 {
146 getIntrusionByService(aResp, service.first, object.first);
147 return;
148 }
149 }
150 },
151 "xyz.openbmc_project.ObjectMapper",
152 "/xyz/openbmc_project/object_mapper",
153 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous271584a2019-07-09 16:24:22 -0700154 "/xyz/openbmc_project/Intrusion", 1,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500155 std::array<const char*, 1>{"xyz.openbmc_project.Chassis.Intrusion"});
Qiang XUc1819422019-02-27 13:51:32 +0800156}
157
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100158/**
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100159 * ChassisCollection derived class for delivering Chassis Collection Schema
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700160 * Functions triggers appropriate requests on DBus
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100161 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700162inline void requestRoutesChassisCollection(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700163{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700164 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/")
Ed Tanous432a8902021-06-14 15:28:56 -0700165 .privileges({{"Login"}})
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700166 .methods(boost::beast::http::verb::get)(
167 [](const crow::Request&,
168 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
169 asyncResp->res.jsonValue["@odata.type"] =
170 "#ChassisCollection.ChassisCollection";
171 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Chassis";
172 asyncResp->res.jsonValue["Name"] = "Chassis Collection";
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100173
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700174 collection_util::getCollectionMembers(
175 asyncResp, "/redfish/v1/Chassis",
176 {"xyz.openbmc_project.Inventory.Item.Board",
177 "xyz.openbmc_project.Inventory.Item.Chassis"});
178 });
179}
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100180
181/**
182 * Chassis override class for delivering Chassis Schema
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700183 * Functions triggers appropriate requests on DBus
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100184 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700185inline void requestRoutesChassis(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700186{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700187 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/")
Ed Tanous432a8902021-06-14 15:28:56 -0700188 .privileges({{"Login"}})
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700189 .methods(
190 boost::beast::http::verb::get)([](const crow::Request&,
191 const std::shared_ptr<
192 bmcweb::AsyncResp>& asyncResp,
193 const std::string& chassisId) {
194 const std::array<const char*, 2> interfaces = {
195 "xyz.openbmc_project.Inventory.Item.Board",
196 "xyz.openbmc_project.Inventory.Item.Chassis"};
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100197
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700198 crow::connections::systemBus->async_method_call(
199 [asyncResp, chassisId(std::string(chassisId))](
200 const boost::system::error_code ec,
201 const crow::openbmc_mapper::GetSubTreeType& subtree) {
202 if (ec)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700203 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700204 messages::internalError(asyncResp->res);
205 return;
Ed Tanousdaf36e22018-04-20 16:01:36 -0700206 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700207 // Iterate over all retrieved ObjectPaths.
208 for (const std::pair<
209 std::string,
210 std::vector<std::pair<std::string,
211 std::vector<std::string>>>>&
212 object : subtree)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700213 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700214 const std::string& path = object.first;
215 const std::vector<
216 std::pair<std::string, std::vector<std::string>>>&
217 connectionNames = object.second;
Ed Tanouse0d918b2018-03-27 17:41:04 -0700218
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700219 if (!boost::ends_with(path, chassisId))
James Feist1c8fba92019-12-20 15:12:07 -0800220 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700221 continue;
James Feist1c8fba92019-12-20 15:12:07 -0800222 }
James Feist1c8fba92019-12-20 15:12:07 -0800223
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700224 auto health =
225 std::make_shared<HealthPopulate>(asyncResp);
226
227 crow::connections::systemBus->async_method_call(
228 [health](
229 const boost::system::error_code ec2,
230 std::variant<std::vector<std::string>>& resp) {
231 if (ec2)
232 {
233 return; // no sensors = no failures
234 }
235 std::vector<std::string>* data =
236 std::get_if<std::vector<std::string>>(
237 &resp);
238 if (data == nullptr)
239 {
240 return;
241 }
242 health->inventory = std::move(*data);
243 },
244 "xyz.openbmc_project.ObjectMapper",
245 path + "/all_sensors",
246 "org.freedesktop.DBus.Properties", "Get",
247 "xyz.openbmc_project.Association", "endpoints");
248
249 health->populate();
250
251 if (connectionNames.size() < 1)
252 {
253 BMCWEB_LOG_ERROR << "Got 0 Connection names";
254 continue;
255 }
256
257 asyncResp->res.jsonValue["@odata.type"] =
258 "#Chassis.v1_14_0.Chassis";
259 asyncResp->res.jsonValue["@odata.id"] =
260 "/redfish/v1/Chassis/" + chassisId;
261 asyncResp->res.jsonValue["Name"] = "Chassis Collection";
262 asyncResp->res.jsonValue["ChassisType"] = "RackMount";
263 asyncResp->res.jsonValue["Actions"]["#Chassis.Reset"] =
264 {{"target", "/redfish/v1/Chassis/" + chassisId +
265 "/Actions/Chassis.Reset"},
266 {"@Redfish.ActionInfo", "/redfish/v1/Chassis/" +
267 chassisId +
268 "/ResetActionInfo"}};
269 asyncResp->res.jsonValue["PCIeDevices"] = {
270 {"@odata.id",
271 "/redfish/v1/Systems/system/PCIeDevices"}};
272
273 const std::string& connectionName =
274 connectionNames[0].first;
275
276 const std::vector<std::string>& interfaces2 =
277 connectionNames[0].second;
278 const std::array<const char*, 2> hasIndicatorLed = {
279 "xyz.openbmc_project.Inventory.Item.Panel",
280 "xyz.openbmc_project.Inventory.Item.Board."
281 "Motherboard"};
282
283 for (const char* interface : hasIndicatorLed)
284 {
285 if (std::find(interfaces2.begin(),
286 interfaces2.end(),
287 interface) != interfaces2.end())
288 {
289 getIndicatorLedState(asyncResp);
290 getLocationIndicatorActive(asyncResp);
291 break;
292 }
293 }
294
295 const std::string locationInterface =
296 "xyz.openbmc_project.Inventory.Decorator."
297 "LocationCode";
298 if (std::find(interfaces2.begin(), interfaces2.end(),
299 locationInterface) != interfaces2.end())
300 {
301 crow::connections::systemBus->async_method_call(
302 [asyncResp, chassisId(std::string(chassisId))](
303 const boost::system::error_code ec,
304 const std::variant<std::string>& property) {
305 if (ec)
306 {
307 BMCWEB_LOG_DEBUG
308 << "DBUS response error for "
309 "Location";
310 messages::internalError(asyncResp->res);
311 return;
312 }
313
314 const std::string* value =
315 std::get_if<std::string>(&property);
316 if (value == nullptr)
317 {
318 BMCWEB_LOG_DEBUG
319 << "Null value returned "
320 "for locaton code";
321 messages::internalError(asyncResp->res);
322 return;
323 }
324 asyncResp->res
325 .jsonValue["Location"]["PartLocation"]
326 ["ServiceLabel"] = *value;
327 },
328 connectionName, path,
329 "org.freedesktop.DBus.Properties", "Get",
330 locationInterface, "LocationCode");
331 }
332
SunnySrivastava198488ad7f02020-12-03 10:27:52 -0600333 crow::connections::systemBus->async_method_call(
334 [asyncResp, chassisId(std::string(chassisId))](
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700335 const boost::system::error_code /*ec2*/,
336 const std::vector<
337 std::pair<std::string, VariantType>>&
338 propertiesList) {
339 for (const std::pair<std::string, VariantType>&
340 property : propertiesList)
SunnySrivastava198488ad7f02020-12-03 10:27:52 -0600341 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700342 // Store DBus properties that are also
343 // Redfish properties with same name and a
344 // string value
345 const std::string& propertyName =
346 property.first;
347 if ((propertyName == "PartNumber") ||
348 (propertyName == "SerialNumber") ||
349 (propertyName == "Manufacturer") ||
350 (propertyName == "Model"))
Shawn McCarney99cffd72019-03-01 10:46:20 -0600351 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700352 const std::string* value =
353 std::get_if<std::string>(
354 &property.second);
355 if (value != nullptr)
356 {
357 asyncResp->res
358 .jsonValue[propertyName] =
359 *value;
360 }
Shawn McCarney99cffd72019-03-01 10:46:20 -0600361 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700362 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700363 asyncResp->res.jsonValue["Name"] = chassisId;
364 asyncResp->res.jsonValue["Id"] = chassisId;
zhanghch050256b692021-06-12 10:26:52 +0800365#ifdef BMCWEB_ALLOW_DEPRECATED_POWER_THERMAL
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700366 asyncResp->res.jsonValue["Thermal"] = {
367 {"@odata.id", "/redfish/v1/Chassis/" +
368 chassisId + "/Thermal"}};
369 // Power object
370 asyncResp->res.jsonValue["Power"] = {
371 {"@odata.id", "/redfish/v1/Chassis/" +
372 chassisId + "/Power"}};
zhanghch050256b692021-06-12 10:26:52 +0800373#endif
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700374 // SensorCollection
375 asyncResp->res.jsonValue["Sensors"] = {
376 {"@odata.id", "/redfish/v1/Chassis/" +
377 chassisId + "/Sensors"}};
378 asyncResp->res.jsonValue["Status"] = {
379 {"State", "Enabled"},
380 };
381
382 asyncResp->res
383 .jsonValue["Links"]["ComputerSystems"] = {
384 {{"@odata.id",
385 "/redfish/v1/Systems/system"}}};
386 asyncResp->res.jsonValue["Links"]["ManagedBy"] =
387 {{{"@odata.id",
388 "/redfish/v1/Managers/bmc"}}};
389 getChassisState(asyncResp);
390 },
391 connectionName, path,
392 "org.freedesktop.DBus.Properties", "GetAll",
393 "xyz.openbmc_project.Inventory.Decorator.Asset");
Sharad Yadav2c37b4b2021-05-10 12:53:38 +0530394
395 // Chassis UUID
396 const std::string uuidInterface =
397 "xyz.openbmc_project.Common.UUID";
398 if (std::find(interfaces2.begin(), interfaces2.end(),
399 uuidInterface) != interfaces2.end())
400 {
401 crow::connections::systemBus->async_method_call(
402 [asyncResp](const boost::system::error_code ec,
403 const std::variant<std::string>&
404 chassisUUID) {
405 if (ec)
406 {
407 BMCWEB_LOG_DEBUG
408 << "DBUS response error for "
409 "UUID";
410 messages::internalError(asyncResp->res);
411 return;
412 }
413 const std::string* value =
414 std::get_if<std::string>(&chassisUUID);
415 if (value == nullptr)
416 {
417 BMCWEB_LOG_DEBUG
418 << "Null value returned "
419 "for UUID";
420 messages::internalError(asyncResp->res);
421 return;
422 }
423 asyncResp->res.jsonValue["UUID"] = *value;
424 },
425 connectionName, path,
426 "org.freedesktop.DBus.Properties", "Get",
427 uuidInterface, "UUID");
428 }
429
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700430 return;
431 }
432
433 // Couldn't find an object with that name. return an error
434 messages::resourceNotFound(
435 asyncResp->res, "#Chassis.v1_14_0.Chassis", chassisId);
436 },
437 "xyz.openbmc_project.ObjectMapper",
438 "/xyz/openbmc_project/object_mapper",
439 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
440 "/xyz/openbmc_project/inventory", 0, interfaces);
441
442 getPhysicalSecurityData(asyncResp);
443 });
444
445 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/")
Ed Tanous432a8902021-06-14 15:28:56 -0700446 .privileges({{"ConfigureComponents"}})
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700447 .methods(
448 boost::beast::http::verb::
449 patch)([](const crow::Request& req,
450 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
451 const std::string& param) {
452 std::optional<bool> locationIndicatorActive;
453 std::optional<std::string> indicatorLed;
454
455 if (param.empty())
456 {
457 return;
458 }
459
460 if (!json_util::readJson(
461 req, asyncResp->res, "LocationIndicatorActive",
462 locationIndicatorActive, "IndicatorLED", indicatorLed))
463 {
464 return;
465 }
466
467 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
468 if (!locationIndicatorActive && !indicatorLed)
469 {
470 return; // delete this when we support more patch properties
471 }
472 if (indicatorLed)
473 {
474 asyncResp->res.addHeader(
475 boost::beast::http::field::warning,
476 "299 - \"IndicatorLED is deprecated. Use "
477 "LocationIndicatorActive instead.\"");
478 }
479
480 const std::array<const char*, 2> interfaces = {
481 "xyz.openbmc_project.Inventory.Item.Board",
482 "xyz.openbmc_project.Inventory.Item.Chassis"};
483
484 const std::string& chassisId = param;
485
486 crow::connections::systemBus->async_method_call(
487 [asyncResp, chassisId, locationIndicatorActive, indicatorLed](
488 const boost::system::error_code ec,
489 const crow::openbmc_mapper::GetSubTreeType& subtree) {
490 if (ec)
491 {
492 messages::internalError(asyncResp->res);
493 return;
494 }
495
496 // Iterate over all retrieved ObjectPaths.
497 for (const std::pair<
498 std::string,
499 std::vector<std::pair<std::string,
500 std::vector<std::string>>>>&
501 object : subtree)
502 {
503 const std::string& path = object.first;
504 const std::vector<
505 std::pair<std::string, std::vector<std::string>>>&
506 connectionNames = object.second;
507
508 if (!boost::ends_with(path, chassisId))
509 {
510 continue;
511 }
512
513 if (connectionNames.size() < 1)
514 {
515 BMCWEB_LOG_ERROR << "Got 0 Connection names";
516 continue;
517 }
518
519 const std::vector<std::string>& interfaces3 =
520 connectionNames[0].second;
521
522 const std::array<const char*, 2> hasIndicatorLed = {
523 "xyz.openbmc_project.Inventory.Item.Panel",
524 "xyz.openbmc_project.Inventory.Item.Board."
525 "Motherboard"};
526 bool indicatorChassis = false;
527 for (const char* interface : hasIndicatorLed)
528 {
529 if (std::find(interfaces3.begin(),
530 interfaces3.end(),
531 interface) != interfaces3.end())
532 {
533 indicatorChassis = true;
534 break;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700535 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700536 }
537 if (locationIndicatorActive)
538 {
539 if (indicatorChassis)
540 {
541 setLocationIndicatorActive(
542 asyncResp, *locationIndicatorActive);
543 }
544 else
545 {
546 messages::propertyUnknown(
547 asyncResp->res, "LocationIndicatorActive");
548 }
549 }
550 if (indicatorLed)
551 {
552 if (indicatorChassis)
553 {
554 setIndicatorLedState(asyncResp, *indicatorLed);
555 }
556 else
557 {
558 messages::propertyUnknown(asyncResp->res,
559 "IndicatorLED");
560 }
561 }
562 return;
James Feist1c8fba92019-12-20 15:12:07 -0800563 }
564
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700565 messages::resourceNotFound(
566 asyncResp->res, "#Chassis.v1_14_0.Chassis", chassisId);
567 },
568 "xyz.openbmc_project.ObjectMapper",
569 "/xyz/openbmc_project/object_mapper",
570 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
571 "/xyz/openbmc_project/inventory", 0, interfaces);
572 });
573}
P.K. Leedd99e042020-06-17 19:43:16 +0800574
zhanghch058d1b46d2021-04-01 11:18:24 +0800575inline void
576 doChassisPowerCycle(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
P.K. Leedd99e042020-06-17 19:43:16 +0800577{
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700578 const char* busName = "xyz.openbmc_project.ObjectMapper";
579 const char* path = "/xyz/openbmc_project/object_mapper";
580 const char* interface = "xyz.openbmc_project.ObjectMapper";
581 const char* method = "GetSubTreePaths";
P.K. Leedd99e042020-06-17 19:43:16 +0800582
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700583 const std::array<const char*, 1> interfaces = {
584 "xyz.openbmc_project.State.Chassis"};
585
586 // Use mapper to get subtree paths.
P.K. Leedd99e042020-06-17 19:43:16 +0800587 crow::connections::systemBus->async_method_call(
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700588 [asyncResp](const boost::system::error_code ec,
589 const std::vector<std::string>& chassisList) {
P.K. Leedd99e042020-06-17 19:43:16 +0800590 if (ec)
591 {
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700592 BMCWEB_LOG_DEBUG << "[mapper] Bad D-Bus request error: " << ec;
P.K. Leedd99e042020-06-17 19:43:16 +0800593 messages::internalError(asyncResp->res);
594 return;
595 }
596
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700597 const char* processName = "xyz.openbmc_project.State.Chassis";
598 const char* interfaceName = "xyz.openbmc_project.State.Chassis";
599 const char* destProperty = "RequestedPowerTransition";
600 const std::string propertyValue =
601 "xyz.openbmc_project.State.Chassis.Transition.PowerCycle";
602 std::string objectPath =
603 "/xyz/openbmc_project/state/chassis_system0";
604
605 /* Look for system reset chassis path */
606 if ((std::find(chassisList.begin(), chassisList.end(),
607 objectPath)) == chassisList.end())
608 {
609 /* We prefer to reset the full chassis_system, but if it doesn't
610 * exist on some platforms, fall back to a host-only power reset
611 */
612 objectPath = "/xyz/openbmc_project/state/chassis0";
613 }
614
615 crow::connections::systemBus->async_method_call(
616 [asyncResp](const boost::system::error_code ec) {
617 // Use "Set" method to set the property value.
618 if (ec)
619 {
620 BMCWEB_LOG_DEBUG << "[Set] Bad D-Bus request error: "
621 << ec;
622 messages::internalError(asyncResp->res);
623 return;
624 }
625
626 messages::success(asyncResp->res);
627 },
628 processName, objectPath, "org.freedesktop.DBus.Properties",
629 "Set", interfaceName, destProperty,
630 std::variant<std::string>{propertyValue});
P.K. Leedd99e042020-06-17 19:43:16 +0800631 },
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700632 busName, path, interface, method, "/", 0, interfaces);
P.K. Leedd99e042020-06-17 19:43:16 +0800633}
634
635/**
636 * ChassisResetAction class supports the POST method for the Reset
637 * action.
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700638 * Function handles POST method request.
639 * Analyzes POST body before sending Reset request data to D-Bus.
P.K. Leedd99e042020-06-17 19:43:16 +0800640 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700641
642inline void requestRoutesChassisResetAction(App& app)
P.K. Leedd99e042020-06-17 19:43:16 +0800643{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700644 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Actions/Chassis.Reset/")
Ed Tanous432a8902021-06-14 15:28:56 -0700645 .privileges({{"ConfigureComponents"}})
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700646 .methods(boost::beast::http::verb::post)(
647 [](const crow::Request& req,
648 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
649 const std::string&) {
650 BMCWEB_LOG_DEBUG << "Post Chassis Reset.";
P.K. Leedd99e042020-06-17 19:43:16 +0800651
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700652 std::string resetType;
P.K. Leedd99e042020-06-17 19:43:16 +0800653
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700654 if (!json_util::readJson(req, asyncResp->res, "ResetType",
655 resetType))
656 {
657 return;
658 }
P.K. Leedd99e042020-06-17 19:43:16 +0800659
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700660 if (resetType != "PowerCycle")
661 {
662 BMCWEB_LOG_DEBUG << "Invalid property value for ResetType: "
663 << resetType;
664 messages::actionParameterNotSupported(
665 asyncResp->res, resetType, "ResetType");
P.K. Leedd99e042020-06-17 19:43:16 +0800666
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700667 return;
668 }
669 doChassisPowerCycle(asyncResp);
670 });
671}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530672
673/**
674 * ChassisResetActionInfo derived class for delivering Chassis
675 * ResetType AllowableValues using ResetInfo schema.
676 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700677inline void requestRoutesChassisResetActionInfo(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530678{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700679 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ResetActionInfo/")
Ed Tanous432a8902021-06-14 15:28:56 -0700680 .privileges({{"Login"}})
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700681 .methods(boost::beast::http::verb::get)(
682 [](const crow::Request&,
683 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
684 const std::string& chassisId)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530685
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700686 {
687 asyncResp->res.jsonValue = {
688 {"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"},
689 {"@odata.id",
690 "/redfish/v1/Chassis/" + chassisId + "/ResetActionInfo"},
691 {"Name", "Reset Action Info"},
692 {"Id", "ResetActionInfo"},
693 {"Parameters",
694 {{{"Name", "ResetType"},
695 {"Required", true},
696 {"DataType", "String"},
697 {"AllowableValues", {"PowerCycle"}}}}}};
698 });
699}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530700
Ed Tanous1abe55e2018-09-05 08:30:59 -0700701} // namespace redfish