blob: 7a7748ac6db20f7ae04e51d0536c57e5447f1101 [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"
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010020#include "node.hpp"
Ed Tanous1abe55e2018-09-05 08:30:59 -070021
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010022#include <boost/container/flat_map.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050023
Ed Tanousabf2add2019-01-22 16:40:12 -080024#include <variant>
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010025
Ed Tanous1abe55e2018-09-05 08:30:59 -070026namespace redfish
27{
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010028
29/**
Gunnar Millsbeeca0a2019-02-14 16:30:45 -060030 * @brief Retrieves chassis state properties over dbus
31 *
32 * @param[in] aResp - Shared pointer for completing asynchronous calls.
33 *
34 * @return None.
35 */
36void getChassisState(std::shared_ptr<AsyncResp> aResp)
37{
38 crow::connections::systemBus->async_method_call(
39 [aResp{std::move(aResp)}](
40 const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -050041 const std::variant<std::string>& chassisState) {
Gunnar Millsbeeca0a2019-02-14 16:30:45 -060042 if (ec)
43 {
44 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
45 messages::internalError(aResp->res);
46 return;
47 }
48
Gunnar Mills1214b7e2020-06-04 10:11:30 -050049 const std::string* s = std::get_if<std::string>(&chassisState);
Gunnar Millsbeeca0a2019-02-14 16:30:45 -060050 BMCWEB_LOG_DEBUG << "Chassis state: " << *s;
51 if (s != nullptr)
52 {
53 // Verify Chassis State
54 if (*s == "xyz.openbmc_project.State.Chassis.PowerState.On")
55 {
56 aResp->res.jsonValue["PowerState"] = "On";
57 aResp->res.jsonValue["Status"]["State"] = "Enabled";
58 }
59 else if (*s ==
60 "xyz.openbmc_project.State.Chassis.PowerState.Off")
61 {
62 aResp->res.jsonValue["PowerState"] = "Off";
63 aResp->res.jsonValue["Status"]["State"] = "StandbyOffline";
64 }
65 }
66 },
67 "xyz.openbmc_project.State.Chassis",
68 "/xyz/openbmc_project/state/chassis0",
69 "org.freedesktop.DBus.Properties", "Get",
70 "xyz.openbmc_project.State.Chassis", "CurrentPowerState");
71}
72
73/**
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010074 * DBus types primitives for several generic DBus interfaces
75 * TODO(Pawel) consider move this to separate file into boost::dbus
76 */
Ed Tanous55c7b7a2018-05-22 15:27:24 -070077// Note, this is not a very useful Variant, but because it isn't used to get
Ed Tanousaa2e59c2018-04-12 12:17:20 -070078// values, it should be as simple as possible
79// TODO(ed) invent a nullvariant type
Cheng C Yang5fd7ba62019-11-28 15:58:08 +080080using VariantType = std::variant<bool, std::string, uint64_t, uint32_t>;
Ed Tanousaa2e59c2018-04-12 12:17:20 -070081using ManagedObjectsType = std::vector<std::pair<
82 sdbusplus::message::object_path,
83 std::vector<std::pair<std::string,
84 std::vector<std::pair<std::string, VariantType>>>>>>;
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010085
Ed Tanousaa2e59c2018-04-12 12:17:20 -070086using PropertiesType = boost::container::flat_map<std::string, VariantType>;
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010087
Qiang XUc1819422019-02-27 13:51:32 +080088void getIntrusionByService(std::shared_ptr<AsyncResp> aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -050089 const std::string& service,
90 const std::string& objPath)
Qiang XUc1819422019-02-27 13:51:32 +080091{
92 BMCWEB_LOG_DEBUG << "Get intrusion status by service \n";
93
94 crow::connections::systemBus->async_method_call(
95 [aResp{std::move(aResp)}](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -050096 const std::variant<std::string>& value) {
Qiang XUc1819422019-02-27 13:51:32 +080097 if (ec)
98 {
Gunnar Mills4e0453b2020-07-08 14:00:30 -050099 // do not add err msg in redfish response, because this is not
Qiang XUc1819422019-02-27 13:51:32 +0800100 // mandatory property
101 BMCWEB_LOG_ERROR << "DBUS response error " << ec << "\n";
102 return;
103 }
104
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500105 const std::string* status = std::get_if<std::string>(&value);
Qiang XUc1819422019-02-27 13:51:32 +0800106
107 if (status == nullptr)
108 {
109 BMCWEB_LOG_ERROR << "intrusion status read error \n";
110 return;
111 }
112
113 aResp->res.jsonValue["PhysicalSecurity"] = {
114 {"IntrusionSensorNumber", 1}, {"IntrusionSensor", *status}};
115 },
116 service, objPath, "org.freedesktop.DBus.Properties", "Get",
117 "xyz.openbmc_project.Chassis.Intrusion", "Status");
118}
119
120/**
121 * Retrieves physical security properties over dbus
122 */
123void getPhysicalSecurityData(std::shared_ptr<AsyncResp> aResp)
124{
125 crow::connections::systemBus->async_method_call(
126 [aResp{std::move(aResp)}](
127 const boost::system::error_code ec,
128 const std::vector<std::pair<
129 std::string,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500130 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
131 subtree) {
Qiang XUc1819422019-02-27 13:51:32 +0800132 if (ec)
133 {
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500134 // do not add err msg in redfish response, because this is not
Qiang XUc1819422019-02-27 13:51:32 +0800135 // mandatory property
136 BMCWEB_LOG_ERROR << "DBUS error: no matched iface " << ec
137 << "\n";
138 return;
139 }
140 // Iterate over all retrieved ObjectPaths.
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500141 for (const auto& object : subtree)
Qiang XUc1819422019-02-27 13:51:32 +0800142 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500143 for (const auto& service : object.second)
Qiang XUc1819422019-02-27 13:51:32 +0800144 {
145 getIntrusionByService(aResp, service.first, object.first);
146 return;
147 }
148 }
149 },
150 "xyz.openbmc_project.ObjectMapper",
151 "/xyz/openbmc_project/object_mapper",
152 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous271584a2019-07-09 16:24:22 -0700153 "/xyz/openbmc_project/Intrusion", 1,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500154 std::array<const char*, 1>{"xyz.openbmc_project.Chassis.Intrusion"});
Qiang XUc1819422019-02-27 13:51:32 +0800155}
156
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100157/**
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100158 * ChassisCollection derived class for delivering Chassis Collection Schema
159 */
Ed Tanous1abe55e2018-09-05 08:30:59 -0700160class ChassisCollection : public Node
161{
162 public:
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500163 ChassisCollection(CrowApp& app) : Node(app, "/redfish/v1/Chassis/")
Ed Tanous1abe55e2018-09-05 08:30:59 -0700164 {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700165 entityPrivileges = {
166 {boost::beast::http::verb::get, {{"Login"}}},
167 {boost::beast::http::verb::head, {{"Login"}}},
168 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
169 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
170 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
171 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
172 }
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100173
Ed Tanous1abe55e2018-09-05 08:30:59 -0700174 private:
175 /**
176 * Functions triggers appropriate requests on DBus
177 */
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500178 void doGet(crow::Response& res, const crow::Request& req,
179 const std::vector<std::string>& params) override
Ed Tanous1abe55e2018-09-05 08:30:59 -0700180 {
Ed Tanous0f74e642018-11-12 15:17:05 -0800181 res.jsonValue["@odata.type"] = "#ChassisCollection.ChassisCollection";
182 res.jsonValue["@odata.id"] = "/redfish/v1/Chassis";
Ed Tanous0f74e642018-11-12 15:17:05 -0800183 res.jsonValue["Name"] = "Chassis Collection";
184
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500185 const std::array<const char*, 2> interfaces = {
Gunnar Mills603a6642019-01-21 17:03:51 -0600186 "xyz.openbmc_project.Inventory.Item.Board",
Shawn McCarneyadc4f0d2019-07-24 09:21:50 -0500187 "xyz.openbmc_project.Inventory.Item.Chassis"};
Gunnar Mills603a6642019-01-21 17:03:51 -0600188
Ed Tanous62d5e2e2018-09-05 16:17:25 -0700189 auto asyncResp = std::make_shared<AsyncResp>(res);
190 crow::connections::systemBus->async_method_call(
191 [asyncResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500192 const std::vector<std::string>& chassisList) {
Ed Tanous62d5e2e2018-09-05 16:17:25 -0700193 if (ec)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700194 {
Jason M. Billsf12894f2018-10-09 12:45:45 -0700195 messages::internalError(asyncResp->res);
Ed Tanous62d5e2e2018-09-05 16:17:25 -0700196 return;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700197 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500198 nlohmann::json& chassisArray =
Ed Tanous62d5e2e2018-09-05 16:17:25 -0700199 asyncResp->res.jsonValue["Members"];
200 chassisArray = nlohmann::json::array();
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500201 for (const std::string& objpath : chassisList)
Ed Tanous62d5e2e2018-09-05 16:17:25 -0700202 {
203 std::size_t lastPos = objpath.rfind("/");
204 if (lastPos == std::string::npos)
205 {
206 BMCWEB_LOG_ERROR << "Failed to find '/' in " << objpath;
207 continue;
208 }
209 chassisArray.push_back(
210 {{"@odata.id", "/redfish/v1/Chassis/" +
211 objpath.substr(lastPos + 1)}});
212 }
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100213
Ed Tanous62d5e2e2018-09-05 16:17:25 -0700214 asyncResp->res.jsonValue["Members@odata.count"] =
215 chassisArray.size();
216 },
217 "xyz.openbmc_project.ObjectMapper",
218 "/xyz/openbmc_project/object_mapper",
219 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
Ed Tanous271584a2019-07-09 16:24:22 -0700220 "/xyz/openbmc_project/inventory", 0, interfaces);
Ed Tanous62d5e2e2018-09-05 16:17:25 -0700221 }
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100222};
223
224/**
225 * Chassis override class for delivering Chassis Schema
226 */
Ed Tanous1abe55e2018-09-05 08:30:59 -0700227class Chassis : public Node
228{
229 public:
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500230 Chassis(CrowApp& app) :
Ed Tanous1abe55e2018-09-05 08:30:59 -0700231 Node(app, "/redfish/v1/Chassis/<str>/", std::string())
232 {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700233 entityPrivileges = {
234 {boost::beast::http::verb::get, {{"Login"}}},
235 {boost::beast::http::verb::head, {{"Login"}}},
236 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
237 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
238 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
239 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100240 }
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100241
Ed Tanous1abe55e2018-09-05 08:30:59 -0700242 private:
243 /**
244 * Functions triggers appropriate requests on DBus
245 */
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500246 void doGet(crow::Response& res, const crow::Request& req,
247 const std::vector<std::string>& params) override
Ed Tanous1abe55e2018-09-05 08:30:59 -0700248 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500249 const std::array<const char*, 2> interfaces = {
Gunnar Mills734bfe92019-01-21 16:33:50 -0600250 "xyz.openbmc_project.Inventory.Item.Board",
Shawn McCarneyadc4f0d2019-07-24 09:21:50 -0500251 "xyz.openbmc_project.Inventory.Item.Chassis"};
Gunnar Mills734bfe92019-01-21 16:33:50 -0600252
Ed Tanous1abe55e2018-09-05 08:30:59 -0700253 // Check if there is required param, truly entering this shall be
254 // impossible.
255 if (params.size() != 1)
256 {
Jason M. Billsf12894f2018-10-09 12:45:45 -0700257 messages::internalError(res);
Ed Tanousdaf36e22018-04-20 16:01:36 -0700258 res.end();
259 return;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700260 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500261 const std::string& chassisId = params[0];
Ed Tanouse0d918b2018-03-27 17:41:04 -0700262
Ed Tanous62d5e2e2018-09-05 16:17:25 -0700263 auto asyncResp = std::make_shared<AsyncResp>(res);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700264 crow::connections::systemBus->async_method_call(
Ed Tanous62d5e2e2018-09-05 16:17:25 -0700265 [asyncResp, chassisId(std::string(chassisId))](
266 const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500267 const crow::openbmc_mapper::GetSubTreeType& subtree) {
Ed Tanous62d5e2e2018-09-05 16:17:25 -0700268 if (ec)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700269 {
Jason M. Billsf12894f2018-10-09 12:45:45 -0700270 messages::internalError(asyncResp->res);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700271 return;
272 }
273 // Iterate over all retrieved ObjectPaths.
274 for (const std::pair<
275 std::string,
276 std::vector<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500277 std::pair<std::string, std::vector<std::string>>>>&
278 object : subtree)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700279 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500280 const std::string& path = object.first;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700281 const std::vector<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500282 std::pair<std::string, std::vector<std::string>>>&
283 connectionNames = object.second;
Ed Tanouse0d918b2018-03-27 17:41:04 -0700284
Ed Tanous1abe55e2018-09-05 08:30:59 -0700285 if (!boost::ends_with(path, chassisId))
286 {
287 continue;
Ed Tanousdaf36e22018-04-20 16:01:36 -0700288 }
Shawn McCarney26f03892019-05-03 13:20:24 -0500289
James Feistb49ac872019-05-21 15:12:01 -0700290 auto health = std::make_shared<HealthPopulate>(asyncResp);
291
292 crow::connections::systemBus->async_method_call(
293 [health](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500294 std::variant<std::vector<std::string>>& resp) {
James Feistb49ac872019-05-21 15:12:01 -0700295 if (ec)
296 {
297 return; // no sensors = no failures
298 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500299 std::vector<std::string>* data =
James Feistb49ac872019-05-21 15:12:01 -0700300 std::get_if<std::vector<std::string>>(&resp);
301 if (data == nullptr)
302 {
303 return;
304 }
305 health->inventory = std::move(*data);
306 },
307 "xyz.openbmc_project.ObjectMapper",
308 path + "/all_sensors",
309 "org.freedesktop.DBus.Properties", "Get",
310 "xyz.openbmc_project.Association", "endpoints");
311
312 health->populate();
313
Ed Tanous1abe55e2018-09-05 08:30:59 -0700314 if (connectionNames.size() < 1)
315 {
James Feist1c8fba92019-12-20 15:12:07 -0800316 BMCWEB_LOG_ERROR << "Got 0 Connection names";
Ed Tanous1abe55e2018-09-05 08:30:59 -0700317 continue;
318 }
Ed Tanouse0d918b2018-03-27 17:41:04 -0700319
Johnathan Mantey49c53ac2019-05-02 09:22:38 -0700320 asyncResp->res.jsonValue["@odata.type"] =
Jason M. Billsadbe1922019-10-14 15:44:35 -0700321 "#Chassis.v1_10_0.Chassis";
Johnathan Mantey49c53ac2019-05-02 09:22:38 -0700322 asyncResp->res.jsonValue["@odata.id"] =
323 "/redfish/v1/Chassis/" + chassisId;
Johnathan Mantey49c53ac2019-05-02 09:22:38 -0700324 asyncResp->res.jsonValue["Name"] = "Chassis Collection";
325 asyncResp->res.jsonValue["ChassisType"] = "RackMount";
P.K. Leedd99e042020-06-17 19:43:16 +0800326 asyncResp->res.jsonValue["Actions"]["#Chassis.Reset"] = {
327 {"target", "/redfish/v1/Chassis/" + chassisId +
328 "/Actions/Chassis.Reset"},
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530329 {"@Redfish.ActionInfo", "/redfish/v1/Chassis/" +
330 chassisId +
331 "/ResetActionInfo"}};
Jason M. Billsadbe1922019-10-14 15:44:35 -0700332 asyncResp->res.jsonValue["PCIeDevices"] = {
333 {"@odata.id",
334 "/redfish/v1/Systems/system/PCIeDevices"}};
Johnathan Mantey49c53ac2019-05-02 09:22:38 -0700335
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500336 const std::string& connectionName =
Johnathan Mantey49c53ac2019-05-02 09:22:38 -0700337 connectionNames[0].first;
James Feist1c8fba92019-12-20 15:12:07 -0800338
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500339 const std::vector<std::string>& interfaces =
James Feist1c8fba92019-12-20 15:12:07 -0800340 connectionNames[0].second;
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500341 const std::array<const char*, 2> hasIndicatorLed = {
James Feist1c8fba92019-12-20 15:12:07 -0800342 "xyz.openbmc_project.Inventory.Item.Panel",
343 "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
344
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500345 for (const char* interface : hasIndicatorLed)
James Feist1c8fba92019-12-20 15:12:07 -0800346 {
347 if (std::find(interfaces.begin(), interfaces.end(),
348 interface) != interfaces.end())
349 {
350 getIndicatorLedState(asyncResp);
351 break;
352 }
353 }
354
Ed Tanous1abe55e2018-09-05 08:30:59 -0700355 crow::connections::systemBus->async_method_call(
Ed Tanous62d5e2e2018-09-05 16:17:25 -0700356 [asyncResp, chassisId(std::string(chassisId))](
357 const boost::system::error_code ec,
Ed Tanous1abe55e2018-09-05 08:30:59 -0700358 const std::vector<std::pair<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500359 std::string, VariantType>>& propertiesList) {
360 for (const std::pair<std::string, VariantType>&
361 property : propertiesList)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700362 {
Shawn McCarney99cffd72019-03-01 10:46:20 -0600363 // Store DBus properties that are also Redfish
364 // properties with same name and a string value
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500365 const std::string& propertyName =
Shawn McCarney99cffd72019-03-01 10:46:20 -0600366 property.first;
367 if ((propertyName == "PartNumber") ||
368 (propertyName == "SerialNumber") ||
369 (propertyName == "Manufacturer") ||
370 (propertyName == "Model"))
Ed Tanous1abe55e2018-09-05 08:30:59 -0700371 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500372 const std::string* value =
Shawn McCarney99cffd72019-03-01 10:46:20 -0600373 std::get_if<std::string>(
374 &property.second);
375 if (value != nullptr)
376 {
377 asyncResp->res.jsonValue[propertyName] =
378 *value;
379 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700380 }
381 }
Ed Tanous62d5e2e2018-09-05 16:17:25 -0700382 asyncResp->res.jsonValue["Name"] = chassisId;
383 asyncResp->res.jsonValue["Id"] = chassisId;
384 asyncResp->res.jsonValue["Thermal"] = {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700385 {"@odata.id", "/redfish/v1/Chassis/" +
386 chassisId + "/Thermal"}};
Ed Tanous2474adf2018-09-05 16:31:16 -0700387 // Power object
388 asyncResp->res.jsonValue["Power"] = {
389 {"@odata.id", "/redfish/v1/Chassis/" +
390 chassisId + "/Power"}};
Anthony Wilson95a3eca2019-06-11 10:44:47 -0500391 // SensorCollection
392 asyncResp->res.jsonValue["Sensors"] = {
393 {"@odata.id", "/redfish/v1/Chassis/" +
394 chassisId + "/Sensors"}};
Ed Tanous029573d2019-02-01 10:57:49 -0800395 asyncResp->res.jsonValue["Status"] = {
Ed Tanous029573d2019-02-01 10:57:49 -0800396 {"State", "Enabled"},
397 };
Ed Tanous2474adf2018-09-05 16:31:16 -0700398
Ed Tanous029573d2019-02-01 10:57:49 -0800399 asyncResp->res
400 .jsonValue["Links"]["ComputerSystems"] = {
401 {{"@odata.id", "/redfish/v1/Systems/system"}}};
402 asyncResp->res.jsonValue["Links"]["ManagedBy"] = {
403 {{"@odata.id", "/redfish/v1/Managers/bmc"}}};
Gunnar Millsbeeca0a2019-02-14 16:30:45 -0600404 getChassisState(asyncResp);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700405 },
406 connectionName, path, "org.freedesktop.DBus.Properties",
407 "GetAll",
408 "xyz.openbmc_project.Inventory.Decorator.Asset");
Ed Tanous1abe55e2018-09-05 08:30:59 -0700409 return;
410 }
Ed Tanouse0d918b2018-03-27 17:41:04 -0700411
Ed Tanous1abe55e2018-09-05 08:30:59 -0700412 // Couldn't find an object with that name. return an error
Jason M. Billsf12894f2018-10-09 12:45:45 -0700413 messages::resourceNotFound(
Jason M. Billsadbe1922019-10-14 15:44:35 -0700414 asyncResp->res, "#Chassis.v1_10_0.Chassis", chassisId);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700415 },
416 "xyz.openbmc_project.ObjectMapper",
417 "/xyz/openbmc_project/object_mapper",
418 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous271584a2019-07-09 16:24:22 -0700419 "/xyz/openbmc_project/inventory", 0, interfaces);
Qiang XUc1819422019-02-27 13:51:32 +0800420
421 getPhysicalSecurityData(asyncResp);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700422 }
James Feist1c8fba92019-12-20 15:12:07 -0800423
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500424 void doPatch(crow::Response& res, const crow::Request& req,
425 const std::vector<std::string>& params) override
James Feist1c8fba92019-12-20 15:12:07 -0800426 {
427 std::optional<std::string> indicatorLed;
428 auto asyncResp = std::make_shared<AsyncResp>(res);
429
430 if (params.size() != 1)
431 {
432 return;
433 }
434
435 if (!json_util::readJson(req, res, "IndicatorLED", indicatorLed))
436 {
437 return;
438 }
439
440 if (!indicatorLed)
441 {
442 return; // delete this when we support more patch properties
443 }
444
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500445 const std::array<const char*, 2> interfaces = {
James Feist1c8fba92019-12-20 15:12:07 -0800446 "xyz.openbmc_project.Inventory.Item.Board",
447 "xyz.openbmc_project.Inventory.Item.Chassis"};
448
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500449 const std::string& chassisId = params[0];
James Feist1c8fba92019-12-20 15:12:07 -0800450
451 crow::connections::systemBus->async_method_call(
452 [asyncResp, chassisId, indicatorLed](
453 const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500454 const crow::openbmc_mapper::GetSubTreeType& subtree) {
James Feist1c8fba92019-12-20 15:12:07 -0800455 if (ec)
456 {
457 messages::internalError(asyncResp->res);
458 return;
459 }
460
461 // Iterate over all retrieved ObjectPaths.
462 for (const std::pair<
463 std::string,
464 std::vector<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500465 std::pair<std::string, std::vector<std::string>>>>&
466 object : subtree)
James Feist1c8fba92019-12-20 15:12:07 -0800467 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500468 const std::string& path = object.first;
James Feist1c8fba92019-12-20 15:12:07 -0800469 const std::vector<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500470 std::pair<std::string, std::vector<std::string>>>&
471 connectionNames = object.second;
James Feist1c8fba92019-12-20 15:12:07 -0800472
473 if (!boost::ends_with(path, chassisId))
474 {
475 continue;
476 }
477
478 if (connectionNames.size() < 1)
479 {
480 BMCWEB_LOG_ERROR << "Got 0 Connection names";
481 continue;
482 }
483
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500484 const std::vector<std::string>& interfaces =
James Feist1c8fba92019-12-20 15:12:07 -0800485 connectionNames[0].second;
486
487 if (indicatorLed)
488 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500489 const std::array<const char*, 2> hasIndicatorLed = {
James Feist1c8fba92019-12-20 15:12:07 -0800490 "xyz.openbmc_project.Inventory.Item.Panel",
491 "xyz.openbmc_project.Inventory.Item.Board."
492 "Motherboard"};
493 bool indicatorChassis = false;
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500494 for (const char* interface : hasIndicatorLed)
James Feist1c8fba92019-12-20 15:12:07 -0800495 {
496 if (std::find(interfaces.begin(), interfaces.end(),
497 interface) != interfaces.end())
498 {
499 indicatorChassis = true;
500 break;
501 }
502 }
503 if (indicatorChassis)
504 {
505 setIndicatorLedState(asyncResp,
506 std::move(*indicatorLed));
507 }
508 else
509 {
510 messages::propertyUnknown(asyncResp->res,
511 "IndicatorLED");
512 }
513 }
514 return;
515 }
516
517 messages::resourceNotFound(
518 asyncResp->res, "#Chassis.v1_10_0.Chassis", chassisId);
519 },
520 "xyz.openbmc_project.ObjectMapper",
521 "/xyz/openbmc_project/object_mapper",
522 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
523 "/xyz/openbmc_project/inventory", 0, interfaces);
524 }
Ed Tanous62d5e2e2018-09-05 16:17:25 -0700525};
P.K. Leedd99e042020-06-17 19:43:16 +0800526
527void doChassisPowerCycle(std::shared_ptr<AsyncResp> asyncResp)
528{
529 const char* processName = "xyz.openbmc_project.State.Chassis";
530 const char* objectPath = "/xyz/openbmc_project/state/chassis0";
531 const char* interfaceName = "xyz.openbmc_project.State.Chassis";
532 const char* destProperty = "RequestedPowerTransition";
533 const std::string propertyValue =
534 "xyz.openbmc_project.State.Chassis.Transition.PowerCycle";
535
536 crow::connections::systemBus->async_method_call(
537 [asyncResp](const boost::system::error_code ec) {
538 // Use "Set" method to set the property value.
539 if (ec)
540 {
541 BMCWEB_LOG_DEBUG << "[Set] Bad D-Bus request error: " << ec;
542 messages::internalError(asyncResp->res);
543 return;
544 }
545
546 messages::success(asyncResp->res);
547 },
548 processName, objectPath, "org.freedesktop.DBus.Properties", "Set",
549 interfaceName, destProperty, std::variant<std::string>{propertyValue});
550}
551
552/**
553 * ChassisResetAction class supports the POST method for the Reset
554 * action.
555 */
556class ChassisResetAction : public Node
557{
558 public:
559 ChassisResetAction(CrowApp& app) :
560 Node(app, "/redfish/v1/Chassis/<str>/Actions/Chassis.Reset/",
561 std::string())
562 {
563 entityPrivileges = {
564 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
565 }
566
567 private:
568 /**
569 * Function handles POST method request.
570 * Analyzes POST body before sending Reset request data to D-Bus.
571 */
572 void doPost(crow::Response& res, const crow::Request& req,
573 const std::vector<std::string>& params) override
574 {
575 BMCWEB_LOG_DEBUG << "Post Chassis Reset.";
576
577 std::string resetType;
578 auto asyncResp = std::make_shared<AsyncResp>(res);
579
580 if (!json_util::readJson(req, asyncResp->res, "ResetType", resetType))
581 {
582 return;
583 }
584
585 if (resetType != "PowerCycle")
586 {
587 BMCWEB_LOG_DEBUG << "Invalid property value for ResetType: "
588 << resetType;
589 messages::actionParameterNotSupported(asyncResp->res, resetType,
590 "ResetType");
591
592 return;
593 }
594 doChassisPowerCycle(asyncResp);
595 }
596};
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530597
598/**
599 * ChassisResetActionInfo derived class for delivering Chassis
600 * ResetType AllowableValues using ResetInfo schema.
601 */
602class ChassisResetActionInfo : public Node
603{
604 public:
605 /*
606 * Default Constructor
607 */
608 ChassisResetActionInfo(CrowApp& app) :
609 Node(app, "/redfish/v1/Chassis/<str>/ResetActionInfo/", std::string())
610 {
611 entityPrivileges = {
612 {boost::beast::http::verb::get, {{"Login"}}},
613 {boost::beast::http::verb::head, {{"Login"}}},
614 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
615 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
616 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
617 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
618 }
619
620 private:
621 /**
622 * Functions triggers appropriate requests on DBus
623 */
624 void doGet(crow::Response& res, const crow::Request& req,
625 const std::vector<std::string>& params) override
626 {
627 if (params.size() != 1)
628 {
629 messages::internalError(res);
630 res.end();
631 return;
632 }
633 const std::string& chassisId = params[0];
634
635 res.jsonValue = {{"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"},
636 {"@odata.id", "/redfish/v1/Chassis/" + chassisId +
637 "/ResetActionInfo"},
638 {"Name", "Reset Action Info"},
639 {"Id", "ResetActionInfo"},
640 {"Parameters",
641 {{{"Name", "ResetType"},
642 {"Required", true},
643 {"DataType", "String"},
644 {"AllowableValues", {"PowerCycle"}}}}}};
645 res.end();
646 }
647};
648
Ed Tanous1abe55e2018-09-05 08:30:59 -0700649} // namespace redfish