blob: c7db3708305fc9862583883b8f07fcccca9c7218 [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 */
Ed Tanous23a21a12020-07-25 04:45:05 +000036inline void getChassisState(std::shared_ptr<AsyncResp> aResp)
Gunnar Millsbeeca0a2019-02-14 16:30:45 -060037{
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
Ed Tanous23a21a12020-07-25 04:45:05 +000088inline void getIntrusionByService(std::shared_ptr<AsyncResp> aResp,
89 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 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000123inline void getPhysicalSecurityData(std::shared_ptr<AsyncResp> aResp)
Qiang XUc1819422019-02-27 13:51:32 +0800124{
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:
Ed Tanous52cc1122020-07-18 13:51:21 -0700163 ChassisCollection(App& 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 */
Ed Tanouscb13a392020-07-25 19:02:03 +0000178 void doGet(crow::Response& res, const crow::Request&,
179 const std::vector<std::string>&) 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:
Ed Tanous52cc1122020-07-18 13:51:21 -0700230 Chassis(App& app) : Node(app, "/redfish/v1/Chassis/<str>/", std::string())
Ed Tanous1abe55e2018-09-05 08:30:59 -0700231 {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700232 entityPrivileges = {
233 {boost::beast::http::verb::get, {{"Login"}}},
234 {boost::beast::http::verb::head, {{"Login"}}},
235 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
236 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
237 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
238 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100239 }
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100240
Ed Tanous1abe55e2018-09-05 08:30:59 -0700241 private:
242 /**
243 * Functions triggers appropriate requests on DBus
244 */
Ed Tanouscb13a392020-07-25 19:02:03 +0000245 void doGet(crow::Response& res, const crow::Request&,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500246 const std::vector<std::string>& params) override
Ed Tanous1abe55e2018-09-05 08:30:59 -0700247 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500248 const std::array<const char*, 2> interfaces = {
Gunnar Mills734bfe92019-01-21 16:33:50 -0600249 "xyz.openbmc_project.Inventory.Item.Board",
Shawn McCarneyadc4f0d2019-07-24 09:21:50 -0500250 "xyz.openbmc_project.Inventory.Item.Chassis"};
Gunnar Mills734bfe92019-01-21 16:33:50 -0600251
Ed Tanous1abe55e2018-09-05 08:30:59 -0700252 // Check if there is required param, truly entering this shall be
253 // impossible.
254 if (params.size() != 1)
255 {
Jason M. Billsf12894f2018-10-09 12:45:45 -0700256 messages::internalError(res);
Ed Tanousdaf36e22018-04-20 16:01:36 -0700257 res.end();
258 return;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700259 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500260 const std::string& chassisId = params[0];
Ed Tanouse0d918b2018-03-27 17:41:04 -0700261
Ed Tanous62d5e2e2018-09-05 16:17:25 -0700262 auto asyncResp = std::make_shared<AsyncResp>(res);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700263 crow::connections::systemBus->async_method_call(
Ed Tanous62d5e2e2018-09-05 16:17:25 -0700264 [asyncResp, chassisId(std::string(chassisId))](
265 const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500266 const crow::openbmc_mapper::GetSubTreeType& subtree) {
Ed Tanous62d5e2e2018-09-05 16:17:25 -0700267 if (ec)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700268 {
Jason M. Billsf12894f2018-10-09 12:45:45 -0700269 messages::internalError(asyncResp->res);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700270 return;
271 }
272 // Iterate over all retrieved ObjectPaths.
273 for (const std::pair<
274 std::string,
275 std::vector<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500276 std::pair<std::string, std::vector<std::string>>>>&
277 object : subtree)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700278 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500279 const std::string& path = object.first;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700280 const std::vector<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500281 std::pair<std::string, std::vector<std::string>>>&
282 connectionNames = object.second;
Ed Tanouse0d918b2018-03-27 17:41:04 -0700283
Ed Tanous1abe55e2018-09-05 08:30:59 -0700284 if (!boost::ends_with(path, chassisId))
285 {
286 continue;
Ed Tanousdaf36e22018-04-20 16:01:36 -0700287 }
Shawn McCarney26f03892019-05-03 13:20:24 -0500288
James Feistb49ac872019-05-21 15:12:01 -0700289 auto health = std::make_shared<HealthPopulate>(asyncResp);
290
291 crow::connections::systemBus->async_method_call(
Ed Tanous23a21a12020-07-25 04:45:05 +0000292 [health](const boost::system::error_code ec2,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500293 std::variant<std::vector<std::string>>& resp) {
Ed Tanous23a21a12020-07-25 04:45:05 +0000294 if (ec2)
James Feistb49ac872019-05-21 15:12:01 -0700295 {
296 return; // no sensors = no failures
297 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500298 std::vector<std::string>* data =
James Feistb49ac872019-05-21 15:12:01 -0700299 std::get_if<std::vector<std::string>>(&resp);
300 if (data == nullptr)
301 {
302 return;
303 }
304 health->inventory = std::move(*data);
305 },
306 "xyz.openbmc_project.ObjectMapper",
307 path + "/all_sensors",
308 "org.freedesktop.DBus.Properties", "Get",
309 "xyz.openbmc_project.Association", "endpoints");
310
311 health->populate();
312
Ed Tanous1abe55e2018-09-05 08:30:59 -0700313 if (connectionNames.size() < 1)
314 {
James Feist1c8fba92019-12-20 15:12:07 -0800315 BMCWEB_LOG_ERROR << "Got 0 Connection names";
Ed Tanous1abe55e2018-09-05 08:30:59 -0700316 continue;
317 }
Ed Tanouse0d918b2018-03-27 17:41:04 -0700318
Johnathan Mantey49c53ac2019-05-02 09:22:38 -0700319 asyncResp->res.jsonValue["@odata.type"] =
Jason M. Billsadbe1922019-10-14 15:44:35 -0700320 "#Chassis.v1_10_0.Chassis";
Johnathan Mantey49c53ac2019-05-02 09:22:38 -0700321 asyncResp->res.jsonValue["@odata.id"] =
322 "/redfish/v1/Chassis/" + chassisId;
Johnathan Mantey49c53ac2019-05-02 09:22:38 -0700323 asyncResp->res.jsonValue["Name"] = "Chassis Collection";
324 asyncResp->res.jsonValue["ChassisType"] = "RackMount";
P.K. Leedd99e042020-06-17 19:43:16 +0800325 asyncResp->res.jsonValue["Actions"]["#Chassis.Reset"] = {
326 {"target", "/redfish/v1/Chassis/" + chassisId +
327 "/Actions/Chassis.Reset"},
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530328 {"@Redfish.ActionInfo", "/redfish/v1/Chassis/" +
329 chassisId +
330 "/ResetActionInfo"}};
Jason M. Billsadbe1922019-10-14 15:44:35 -0700331 asyncResp->res.jsonValue["PCIeDevices"] = {
332 {"@odata.id",
333 "/redfish/v1/Systems/system/PCIeDevices"}};
Johnathan Mantey49c53ac2019-05-02 09:22:38 -0700334
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500335 const std::string& connectionName =
Johnathan Mantey49c53ac2019-05-02 09:22:38 -0700336 connectionNames[0].first;
James Feist1c8fba92019-12-20 15:12:07 -0800337
Ed Tanous23a21a12020-07-25 04:45:05 +0000338 const std::vector<std::string>& interfaces2 =
James Feist1c8fba92019-12-20 15:12:07 -0800339 connectionNames[0].second;
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500340 const std::array<const char*, 2> hasIndicatorLed = {
James Feist1c8fba92019-12-20 15:12:07 -0800341 "xyz.openbmc_project.Inventory.Item.Panel",
342 "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
343
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500344 for (const char* interface : hasIndicatorLed)
James Feist1c8fba92019-12-20 15:12:07 -0800345 {
Ed Tanous23a21a12020-07-25 04:45:05 +0000346 if (std::find(interfaces2.begin(), interfaces2.end(),
347 interface) != interfaces2.end())
James Feist1c8fba92019-12-20 15:12:07 -0800348 {
349 getIndicatorLedState(asyncResp);
350 break;
351 }
352 }
353
Ed Tanous1abe55e2018-09-05 08:30:59 -0700354 crow::connections::systemBus->async_method_call(
Ed Tanous62d5e2e2018-09-05 16:17:25 -0700355 [asyncResp, chassisId(std::string(chassisId))](
Ed Tanous23a21a12020-07-25 04:45:05 +0000356 const boost::system::error_code ec2,
Ed Tanous1abe55e2018-09-05 08:30:59 -0700357 const std::vector<std::pair<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500358 std::string, VariantType>>& propertiesList) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000359 if (ec2)
360 {
361 return;
362 }
363
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500364 for (const std::pair<std::string, VariantType>&
365 property : propertiesList)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700366 {
Shawn McCarney99cffd72019-03-01 10:46:20 -0600367 // Store DBus properties that are also Redfish
368 // properties with same name and a string value
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500369 const std::string& propertyName =
Shawn McCarney99cffd72019-03-01 10:46:20 -0600370 property.first;
371 if ((propertyName == "PartNumber") ||
372 (propertyName == "SerialNumber") ||
373 (propertyName == "Manufacturer") ||
374 (propertyName == "Model"))
Ed Tanous1abe55e2018-09-05 08:30:59 -0700375 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500376 const std::string* value =
Shawn McCarney99cffd72019-03-01 10:46:20 -0600377 std::get_if<std::string>(
378 &property.second);
379 if (value != nullptr)
380 {
381 asyncResp->res.jsonValue[propertyName] =
382 *value;
383 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700384 }
385 }
Ed Tanous62d5e2e2018-09-05 16:17:25 -0700386 asyncResp->res.jsonValue["Name"] = chassisId;
387 asyncResp->res.jsonValue["Id"] = chassisId;
388 asyncResp->res.jsonValue["Thermal"] = {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700389 {"@odata.id", "/redfish/v1/Chassis/" +
390 chassisId + "/Thermal"}};
Ed Tanous2474adf2018-09-05 16:31:16 -0700391 // Power object
392 asyncResp->res.jsonValue["Power"] = {
393 {"@odata.id", "/redfish/v1/Chassis/" +
394 chassisId + "/Power"}};
Anthony Wilson95a3eca2019-06-11 10:44:47 -0500395 // SensorCollection
396 asyncResp->res.jsonValue["Sensors"] = {
397 {"@odata.id", "/redfish/v1/Chassis/" +
398 chassisId + "/Sensors"}};
Ed Tanous029573d2019-02-01 10:57:49 -0800399 asyncResp->res.jsonValue["Status"] = {
Ed Tanous029573d2019-02-01 10:57:49 -0800400 {"State", "Enabled"},
401 };
Ed Tanous2474adf2018-09-05 16:31:16 -0700402
Ed Tanous029573d2019-02-01 10:57:49 -0800403 asyncResp->res
404 .jsonValue["Links"]["ComputerSystems"] = {
405 {{"@odata.id", "/redfish/v1/Systems/system"}}};
406 asyncResp->res.jsonValue["Links"]["ManagedBy"] = {
407 {{"@odata.id", "/redfish/v1/Managers/bmc"}}};
Gunnar Millsbeeca0a2019-02-14 16:30:45 -0600408 getChassisState(asyncResp);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700409 },
410 connectionName, path, "org.freedesktop.DBus.Properties",
411 "GetAll",
412 "xyz.openbmc_project.Inventory.Decorator.Asset");
Ed Tanous1abe55e2018-09-05 08:30:59 -0700413 return;
414 }
Ed Tanouse0d918b2018-03-27 17:41:04 -0700415
Ed Tanous1abe55e2018-09-05 08:30:59 -0700416 // Couldn't find an object with that name. return an error
Jason M. Billsf12894f2018-10-09 12:45:45 -0700417 messages::resourceNotFound(
Jason M. Billsadbe1922019-10-14 15:44:35 -0700418 asyncResp->res, "#Chassis.v1_10_0.Chassis", chassisId);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700419 },
420 "xyz.openbmc_project.ObjectMapper",
421 "/xyz/openbmc_project/object_mapper",
422 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous271584a2019-07-09 16:24:22 -0700423 "/xyz/openbmc_project/inventory", 0, interfaces);
Qiang XUc1819422019-02-27 13:51:32 +0800424
425 getPhysicalSecurityData(asyncResp);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700426 }
James Feist1c8fba92019-12-20 15:12:07 -0800427
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500428 void doPatch(crow::Response& res, const crow::Request& req,
429 const std::vector<std::string>& params) override
James Feist1c8fba92019-12-20 15:12:07 -0800430 {
431 std::optional<std::string> indicatorLed;
432 auto asyncResp = std::make_shared<AsyncResp>(res);
433
434 if (params.size() != 1)
435 {
436 return;
437 }
438
439 if (!json_util::readJson(req, res, "IndicatorLED", indicatorLed))
440 {
441 return;
442 }
443
444 if (!indicatorLed)
445 {
446 return; // delete this when we support more patch properties
447 }
448
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500449 const std::array<const char*, 2> interfaces = {
James Feist1c8fba92019-12-20 15:12:07 -0800450 "xyz.openbmc_project.Inventory.Item.Board",
451 "xyz.openbmc_project.Inventory.Item.Chassis"};
452
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500453 const std::string& chassisId = params[0];
James Feist1c8fba92019-12-20 15:12:07 -0800454
455 crow::connections::systemBus->async_method_call(
456 [asyncResp, chassisId, indicatorLed](
457 const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500458 const crow::openbmc_mapper::GetSubTreeType& subtree) {
James Feist1c8fba92019-12-20 15:12:07 -0800459 if (ec)
460 {
461 messages::internalError(asyncResp->res);
462 return;
463 }
464
465 // Iterate over all retrieved ObjectPaths.
466 for (const std::pair<
467 std::string,
468 std::vector<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500469 std::pair<std::string, std::vector<std::string>>>>&
470 object : subtree)
James Feist1c8fba92019-12-20 15:12:07 -0800471 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500472 const std::string& path = object.first;
James Feist1c8fba92019-12-20 15:12:07 -0800473 const std::vector<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500474 std::pair<std::string, std::vector<std::string>>>&
475 connectionNames = object.second;
James Feist1c8fba92019-12-20 15:12:07 -0800476
477 if (!boost::ends_with(path, chassisId))
478 {
479 continue;
480 }
481
482 if (connectionNames.size() < 1)
483 {
484 BMCWEB_LOG_ERROR << "Got 0 Connection names";
485 continue;
486 }
487
Ed Tanous23a21a12020-07-25 04:45:05 +0000488 const std::vector<std::string>& interfaces3 =
James Feist1c8fba92019-12-20 15:12:07 -0800489 connectionNames[0].second;
490
491 if (indicatorLed)
492 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500493 const std::array<const char*, 2> hasIndicatorLed = {
James Feist1c8fba92019-12-20 15:12:07 -0800494 "xyz.openbmc_project.Inventory.Item.Panel",
495 "xyz.openbmc_project.Inventory.Item.Board."
496 "Motherboard"};
497 bool indicatorChassis = false;
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500498 for (const char* interface : hasIndicatorLed)
James Feist1c8fba92019-12-20 15:12:07 -0800499 {
Ed Tanous23a21a12020-07-25 04:45:05 +0000500 if (std::find(interfaces3.begin(),
501 interfaces3.end(),
502 interface) != interfaces3.end())
James Feist1c8fba92019-12-20 15:12:07 -0800503 {
504 indicatorChassis = true;
505 break;
506 }
507 }
508 if (indicatorChassis)
509 {
510 setIndicatorLedState(asyncResp,
511 std::move(*indicatorLed));
512 }
513 else
514 {
515 messages::propertyUnknown(asyncResp->res,
516 "IndicatorLED");
517 }
518 }
519 return;
520 }
521
522 messages::resourceNotFound(
523 asyncResp->res, "#Chassis.v1_10_0.Chassis", chassisId);
524 },
525 "xyz.openbmc_project.ObjectMapper",
526 "/xyz/openbmc_project/object_mapper",
527 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
528 "/xyz/openbmc_project/inventory", 0, interfaces);
529 }
Ed Tanous62d5e2e2018-09-05 16:17:25 -0700530};
P.K. Leedd99e042020-06-17 19:43:16 +0800531
Ed Tanous23a21a12020-07-25 04:45:05 +0000532inline void doChassisPowerCycle(std::shared_ptr<AsyncResp> asyncResp)
P.K. Leedd99e042020-06-17 19:43:16 +0800533{
534 const char* processName = "xyz.openbmc_project.State.Chassis";
535 const char* objectPath = "/xyz/openbmc_project/state/chassis0";
536 const char* interfaceName = "xyz.openbmc_project.State.Chassis";
537 const char* destProperty = "RequestedPowerTransition";
538 const std::string propertyValue =
539 "xyz.openbmc_project.State.Chassis.Transition.PowerCycle";
540
541 crow::connections::systemBus->async_method_call(
542 [asyncResp](const boost::system::error_code ec) {
543 // Use "Set" method to set the property value.
544 if (ec)
545 {
546 BMCWEB_LOG_DEBUG << "[Set] Bad D-Bus request error: " << ec;
547 messages::internalError(asyncResp->res);
548 return;
549 }
550
551 messages::success(asyncResp->res);
552 },
553 processName, objectPath, "org.freedesktop.DBus.Properties", "Set",
554 interfaceName, destProperty, std::variant<std::string>{propertyValue});
555}
556
557/**
558 * ChassisResetAction class supports the POST method for the Reset
559 * action.
560 */
561class ChassisResetAction : public Node
562{
563 public:
Ed Tanous52cc1122020-07-18 13:51:21 -0700564 ChassisResetAction(App& app) :
P.K. Leedd99e042020-06-17 19:43:16 +0800565 Node(app, "/redfish/v1/Chassis/<str>/Actions/Chassis.Reset/",
566 std::string())
567 {
568 entityPrivileges = {
569 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
570 }
571
572 private:
573 /**
574 * Function handles POST method request.
575 * Analyzes POST body before sending Reset request data to D-Bus.
576 */
577 void doPost(crow::Response& res, const crow::Request& req,
Ed Tanouscb13a392020-07-25 19:02:03 +0000578 const std::vector<std::string>&) override
P.K. Leedd99e042020-06-17 19:43:16 +0800579 {
580 BMCWEB_LOG_DEBUG << "Post Chassis Reset.";
581
582 std::string resetType;
583 auto asyncResp = std::make_shared<AsyncResp>(res);
584
585 if (!json_util::readJson(req, asyncResp->res, "ResetType", resetType))
586 {
587 return;
588 }
589
590 if (resetType != "PowerCycle")
591 {
592 BMCWEB_LOG_DEBUG << "Invalid property value for ResetType: "
593 << resetType;
594 messages::actionParameterNotSupported(asyncResp->res, resetType,
595 "ResetType");
596
597 return;
598 }
599 doChassisPowerCycle(asyncResp);
600 }
601};
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530602
603/**
604 * ChassisResetActionInfo derived class for delivering Chassis
605 * ResetType AllowableValues using ResetInfo schema.
606 */
607class ChassisResetActionInfo : public Node
608{
609 public:
610 /*
611 * Default Constructor
612 */
Ed Tanous52cc1122020-07-18 13:51:21 -0700613 ChassisResetActionInfo(App& app) :
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530614 Node(app, "/redfish/v1/Chassis/<str>/ResetActionInfo/", std::string())
615 {
616 entityPrivileges = {
617 {boost::beast::http::verb::get, {{"Login"}}},
618 {boost::beast::http::verb::head, {{"Login"}}},
619 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
620 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
621 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
622 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
623 }
624
625 private:
626 /**
627 * Functions triggers appropriate requests on DBus
628 */
Ed Tanouscb13a392020-07-25 19:02:03 +0000629 void doGet(crow::Response& res, const crow::Request&,
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530630 const std::vector<std::string>& params) override
631 {
632 if (params.size() != 1)
633 {
634 messages::internalError(res);
635 res.end();
636 return;
637 }
638 const std::string& chassisId = params[0];
639
640 res.jsonValue = {{"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"},
641 {"@odata.id", "/redfish/v1/Chassis/" + chassisId +
642 "/ResetActionInfo"},
643 {"Name", "Reset Action Info"},
644 {"Id", "ResetActionInfo"},
645 {"Parameters",
646 {{{"Name", "ResetType"},
647 {"Required", true},
648 {"DataType", "String"},
649 {"AllowableValues", {"PowerCycle"}}}}}};
650 res.end();
651 }
652};
653
Ed Tanous1abe55e2018-09-05 08:30:59 -0700654} // namespace redfish