blob: be1e947c08d5e611579ddf0f20a311501c54de84 [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;
Wludzik, Jozef48411912020-09-11 14:55:59 +0200207 messages::internalError(asyncResp->res);
208 return;
209 }
210 if ((lastPos + 1) >= objpath.size())
211 {
212 BMCWEB_LOG_ERROR << "Failed to parse path " << objpath;
213 messages::internalError(asyncResp->res);
214 return;
Ed Tanous62d5e2e2018-09-05 16:17:25 -0700215 }
216 chassisArray.push_back(
217 {{"@odata.id", "/redfish/v1/Chassis/" +
218 objpath.substr(lastPos + 1)}});
219 }
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100220
Ed Tanous62d5e2e2018-09-05 16:17:25 -0700221 asyncResp->res.jsonValue["Members@odata.count"] =
222 chassisArray.size();
223 },
224 "xyz.openbmc_project.ObjectMapper",
225 "/xyz/openbmc_project/object_mapper",
226 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
Ed Tanous271584a2019-07-09 16:24:22 -0700227 "/xyz/openbmc_project/inventory", 0, interfaces);
Ed Tanous62d5e2e2018-09-05 16:17:25 -0700228 }
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100229};
230
231/**
232 * Chassis override class for delivering Chassis Schema
233 */
Ed Tanous1abe55e2018-09-05 08:30:59 -0700234class Chassis : public Node
235{
236 public:
Ed Tanous52cc1122020-07-18 13:51:21 -0700237 Chassis(App& app) : Node(app, "/redfish/v1/Chassis/<str>/", std::string())
Ed Tanous1abe55e2018-09-05 08:30:59 -0700238 {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700239 entityPrivileges = {
240 {boost::beast::http::verb::get, {{"Login"}}},
241 {boost::beast::http::verb::head, {{"Login"}}},
242 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
243 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
244 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
245 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100246 }
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100247
Ed Tanous1abe55e2018-09-05 08:30:59 -0700248 private:
249 /**
250 * Functions triggers appropriate requests on DBus
251 */
Ed Tanouscb13a392020-07-25 19:02:03 +0000252 void doGet(crow::Response& res, const crow::Request&,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500253 const std::vector<std::string>& params) override
Ed Tanous1abe55e2018-09-05 08:30:59 -0700254 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500255 const std::array<const char*, 2> interfaces = {
Gunnar Mills734bfe92019-01-21 16:33:50 -0600256 "xyz.openbmc_project.Inventory.Item.Board",
Shawn McCarneyadc4f0d2019-07-24 09:21:50 -0500257 "xyz.openbmc_project.Inventory.Item.Chassis"};
Gunnar Mills734bfe92019-01-21 16:33:50 -0600258
Ed Tanous1abe55e2018-09-05 08:30:59 -0700259 // Check if there is required param, truly entering this shall be
260 // impossible.
261 if (params.size() != 1)
262 {
Jason M. Billsf12894f2018-10-09 12:45:45 -0700263 messages::internalError(res);
Ed Tanousdaf36e22018-04-20 16:01:36 -0700264 res.end();
265 return;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700266 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500267 const std::string& chassisId = params[0];
Ed Tanouse0d918b2018-03-27 17:41:04 -0700268
Ed Tanous62d5e2e2018-09-05 16:17:25 -0700269 auto asyncResp = std::make_shared<AsyncResp>(res);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700270 crow::connections::systemBus->async_method_call(
Ed Tanous62d5e2e2018-09-05 16:17:25 -0700271 [asyncResp, chassisId(std::string(chassisId))](
272 const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500273 const crow::openbmc_mapper::GetSubTreeType& subtree) {
Ed Tanous62d5e2e2018-09-05 16:17:25 -0700274 if (ec)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700275 {
Jason M. Billsf12894f2018-10-09 12:45:45 -0700276 messages::internalError(asyncResp->res);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700277 return;
278 }
279 // Iterate over all retrieved ObjectPaths.
280 for (const std::pair<
281 std::string,
282 std::vector<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500283 std::pair<std::string, std::vector<std::string>>>>&
284 object : subtree)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700285 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500286 const std::string& path = object.first;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700287 const std::vector<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500288 std::pair<std::string, std::vector<std::string>>>&
289 connectionNames = object.second;
Ed Tanouse0d918b2018-03-27 17:41:04 -0700290
Ed Tanous1abe55e2018-09-05 08:30:59 -0700291 if (!boost::ends_with(path, chassisId))
292 {
293 continue;
Ed Tanousdaf36e22018-04-20 16:01:36 -0700294 }
Shawn McCarney26f03892019-05-03 13:20:24 -0500295
James Feistb49ac872019-05-21 15:12:01 -0700296 auto health = std::make_shared<HealthPopulate>(asyncResp);
297
298 crow::connections::systemBus->async_method_call(
Ed Tanous23a21a12020-07-25 04:45:05 +0000299 [health](const boost::system::error_code ec2,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500300 std::variant<std::vector<std::string>>& resp) {
Ed Tanous23a21a12020-07-25 04:45:05 +0000301 if (ec2)
James Feistb49ac872019-05-21 15:12:01 -0700302 {
303 return; // no sensors = no failures
304 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500305 std::vector<std::string>* data =
James Feistb49ac872019-05-21 15:12:01 -0700306 std::get_if<std::vector<std::string>>(&resp);
307 if (data == nullptr)
308 {
309 return;
310 }
311 health->inventory = std::move(*data);
312 },
313 "xyz.openbmc_project.ObjectMapper",
314 path + "/all_sensors",
315 "org.freedesktop.DBus.Properties", "Get",
316 "xyz.openbmc_project.Association", "endpoints");
317
318 health->populate();
319
Ed Tanous1abe55e2018-09-05 08:30:59 -0700320 if (connectionNames.size() < 1)
321 {
James Feist1c8fba92019-12-20 15:12:07 -0800322 BMCWEB_LOG_ERROR << "Got 0 Connection names";
Ed Tanous1abe55e2018-09-05 08:30:59 -0700323 continue;
324 }
Ed Tanouse0d918b2018-03-27 17:41:04 -0700325
Johnathan Mantey49c53ac2019-05-02 09:22:38 -0700326 asyncResp->res.jsonValue["@odata.type"] =
Jason M. Billsadbe1922019-10-14 15:44:35 -0700327 "#Chassis.v1_10_0.Chassis";
Johnathan Mantey49c53ac2019-05-02 09:22:38 -0700328 asyncResp->res.jsonValue["@odata.id"] =
329 "/redfish/v1/Chassis/" + chassisId;
Johnathan Mantey49c53ac2019-05-02 09:22:38 -0700330 asyncResp->res.jsonValue["Name"] = "Chassis Collection";
331 asyncResp->res.jsonValue["ChassisType"] = "RackMount";
P.K. Leedd99e042020-06-17 19:43:16 +0800332 asyncResp->res.jsonValue["Actions"]["#Chassis.Reset"] = {
333 {"target", "/redfish/v1/Chassis/" + chassisId +
334 "/Actions/Chassis.Reset"},
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530335 {"@Redfish.ActionInfo", "/redfish/v1/Chassis/" +
336 chassisId +
337 "/ResetActionInfo"}};
Jason M. Billsadbe1922019-10-14 15:44:35 -0700338 asyncResp->res.jsonValue["PCIeDevices"] = {
339 {"@odata.id",
340 "/redfish/v1/Systems/system/PCIeDevices"}};
Johnathan Mantey49c53ac2019-05-02 09:22:38 -0700341
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500342 const std::string& connectionName =
Johnathan Mantey49c53ac2019-05-02 09:22:38 -0700343 connectionNames[0].first;
James Feist1c8fba92019-12-20 15:12:07 -0800344
Ed Tanous23a21a12020-07-25 04:45:05 +0000345 const std::vector<std::string>& interfaces2 =
James Feist1c8fba92019-12-20 15:12:07 -0800346 connectionNames[0].second;
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500347 const std::array<const char*, 2> hasIndicatorLed = {
James Feist1c8fba92019-12-20 15:12:07 -0800348 "xyz.openbmc_project.Inventory.Item.Panel",
349 "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
350
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500351 for (const char* interface : hasIndicatorLed)
James Feist1c8fba92019-12-20 15:12:07 -0800352 {
Ed Tanous23a21a12020-07-25 04:45:05 +0000353 if (std::find(interfaces2.begin(), interfaces2.end(),
354 interface) != interfaces2.end())
James Feist1c8fba92019-12-20 15:12:07 -0800355 {
356 getIndicatorLedState(asyncResp);
357 break;
358 }
359 }
360
Ed Tanous1abe55e2018-09-05 08:30:59 -0700361 crow::connections::systemBus->async_method_call(
Ed Tanous62d5e2e2018-09-05 16:17:25 -0700362 [asyncResp, chassisId(std::string(chassisId))](
Ed Tanous90728b52020-08-19 09:06:34 -0700363 const boost::system::error_code /*ec2*/,
Ed Tanous1abe55e2018-09-05 08:30:59 -0700364 const std::vector<std::pair<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500365 std::string, VariantType>>& propertiesList) {
366 for (const std::pair<std::string, VariantType>&
367 property : propertiesList)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700368 {
Shawn McCarney99cffd72019-03-01 10:46:20 -0600369 // Store DBus properties that are also Redfish
370 // properties with same name and a string value
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500371 const std::string& propertyName =
Shawn McCarney99cffd72019-03-01 10:46:20 -0600372 property.first;
373 if ((propertyName == "PartNumber") ||
374 (propertyName == "SerialNumber") ||
375 (propertyName == "Manufacturer") ||
376 (propertyName == "Model"))
Ed Tanous1abe55e2018-09-05 08:30:59 -0700377 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500378 const std::string* value =
Shawn McCarney99cffd72019-03-01 10:46:20 -0600379 std::get_if<std::string>(
380 &property.second);
381 if (value != nullptr)
382 {
383 asyncResp->res.jsonValue[propertyName] =
384 *value;
385 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700386 }
387 }
Ed Tanous62d5e2e2018-09-05 16:17:25 -0700388 asyncResp->res.jsonValue["Name"] = chassisId;
389 asyncResp->res.jsonValue["Id"] = chassisId;
390 asyncResp->res.jsonValue["Thermal"] = {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700391 {"@odata.id", "/redfish/v1/Chassis/" +
392 chassisId + "/Thermal"}};
Ed Tanous2474adf2018-09-05 16:31:16 -0700393 // Power object
394 asyncResp->res.jsonValue["Power"] = {
395 {"@odata.id", "/redfish/v1/Chassis/" +
396 chassisId + "/Power"}};
Anthony Wilson95a3eca2019-06-11 10:44:47 -0500397 // SensorCollection
398 asyncResp->res.jsonValue["Sensors"] = {
399 {"@odata.id", "/redfish/v1/Chassis/" +
400 chassisId + "/Sensors"}};
Ed Tanous029573d2019-02-01 10:57:49 -0800401 asyncResp->res.jsonValue["Status"] = {
Ed Tanous029573d2019-02-01 10:57:49 -0800402 {"State", "Enabled"},
403 };
Ed Tanous2474adf2018-09-05 16:31:16 -0700404
Ed Tanous029573d2019-02-01 10:57:49 -0800405 asyncResp->res
406 .jsonValue["Links"]["ComputerSystems"] = {
407 {{"@odata.id", "/redfish/v1/Systems/system"}}};
408 asyncResp->res.jsonValue["Links"]["ManagedBy"] = {
409 {{"@odata.id", "/redfish/v1/Managers/bmc"}}};
Gunnar Millsbeeca0a2019-02-14 16:30:45 -0600410 getChassisState(asyncResp);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700411 },
412 connectionName, path, "org.freedesktop.DBus.Properties",
413 "GetAll",
414 "xyz.openbmc_project.Inventory.Decorator.Asset");
Ed Tanous1abe55e2018-09-05 08:30:59 -0700415 return;
416 }
Ed Tanouse0d918b2018-03-27 17:41:04 -0700417
Ed Tanous1abe55e2018-09-05 08:30:59 -0700418 // Couldn't find an object with that name. return an error
Jason M. Billsf12894f2018-10-09 12:45:45 -0700419 messages::resourceNotFound(
Jason M. Billsadbe1922019-10-14 15:44:35 -0700420 asyncResp->res, "#Chassis.v1_10_0.Chassis", chassisId);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700421 },
422 "xyz.openbmc_project.ObjectMapper",
423 "/xyz/openbmc_project/object_mapper",
424 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous271584a2019-07-09 16:24:22 -0700425 "/xyz/openbmc_project/inventory", 0, interfaces);
Qiang XUc1819422019-02-27 13:51:32 +0800426
427 getPhysicalSecurityData(asyncResp);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700428 }
James Feist1c8fba92019-12-20 15:12:07 -0800429
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500430 void doPatch(crow::Response& res, const crow::Request& req,
431 const std::vector<std::string>& params) override
James Feist1c8fba92019-12-20 15:12:07 -0800432 {
433 std::optional<std::string> indicatorLed;
434 auto asyncResp = std::make_shared<AsyncResp>(res);
435
436 if (params.size() != 1)
437 {
438 return;
439 }
440
441 if (!json_util::readJson(req, res, "IndicatorLED", indicatorLed))
442 {
443 return;
444 }
445
446 if (!indicatorLed)
447 {
448 return; // delete this when we support more patch properties
449 }
450
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500451 const std::array<const char*, 2> interfaces = {
James Feist1c8fba92019-12-20 15:12:07 -0800452 "xyz.openbmc_project.Inventory.Item.Board",
453 "xyz.openbmc_project.Inventory.Item.Chassis"};
454
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500455 const std::string& chassisId = params[0];
James Feist1c8fba92019-12-20 15:12:07 -0800456
457 crow::connections::systemBus->async_method_call(
458 [asyncResp, chassisId, indicatorLed](
459 const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500460 const crow::openbmc_mapper::GetSubTreeType& subtree) {
James Feist1c8fba92019-12-20 15:12:07 -0800461 if (ec)
462 {
463 messages::internalError(asyncResp->res);
464 return;
465 }
466
467 // Iterate over all retrieved ObjectPaths.
468 for (const std::pair<
469 std::string,
470 std::vector<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500471 std::pair<std::string, std::vector<std::string>>>>&
472 object : subtree)
James Feist1c8fba92019-12-20 15:12:07 -0800473 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500474 const std::string& path = object.first;
James Feist1c8fba92019-12-20 15:12:07 -0800475 const std::vector<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500476 std::pair<std::string, std::vector<std::string>>>&
477 connectionNames = object.second;
James Feist1c8fba92019-12-20 15:12:07 -0800478
479 if (!boost::ends_with(path, chassisId))
480 {
481 continue;
482 }
483
484 if (connectionNames.size() < 1)
485 {
486 BMCWEB_LOG_ERROR << "Got 0 Connection names";
487 continue;
488 }
489
Ed Tanous23a21a12020-07-25 04:45:05 +0000490 const std::vector<std::string>& interfaces3 =
James Feist1c8fba92019-12-20 15:12:07 -0800491 connectionNames[0].second;
492
493 if (indicatorLed)
494 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500495 const std::array<const char*, 2> hasIndicatorLed = {
James Feist1c8fba92019-12-20 15:12:07 -0800496 "xyz.openbmc_project.Inventory.Item.Panel",
497 "xyz.openbmc_project.Inventory.Item.Board."
498 "Motherboard"};
499 bool indicatorChassis = false;
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500500 for (const char* interface : hasIndicatorLed)
James Feist1c8fba92019-12-20 15:12:07 -0800501 {
Ed Tanous23a21a12020-07-25 04:45:05 +0000502 if (std::find(interfaces3.begin(),
503 interfaces3.end(),
504 interface) != interfaces3.end())
James Feist1c8fba92019-12-20 15:12:07 -0800505 {
506 indicatorChassis = true;
507 break;
508 }
509 }
510 if (indicatorChassis)
511 {
512 setIndicatorLedState(asyncResp,
513 std::move(*indicatorLed));
514 }
515 else
516 {
517 messages::propertyUnknown(asyncResp->res,
518 "IndicatorLED");
519 }
520 }
521 return;
522 }
523
524 messages::resourceNotFound(
525 asyncResp->res, "#Chassis.v1_10_0.Chassis", chassisId);
526 },
527 "xyz.openbmc_project.ObjectMapper",
528 "/xyz/openbmc_project/object_mapper",
529 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
530 "/xyz/openbmc_project/inventory", 0, interfaces);
531 }
Ed Tanous62d5e2e2018-09-05 16:17:25 -0700532};
P.K. Leedd99e042020-06-17 19:43:16 +0800533
Ed Tanousb5a76932020-09-29 16:16:58 -0700534inline void doChassisPowerCycle(const std::shared_ptr<AsyncResp>& asyncResp)
P.K. Leedd99e042020-06-17 19:43:16 +0800535{
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700536 const char* busName = "xyz.openbmc_project.ObjectMapper";
537 const char* path = "/xyz/openbmc_project/object_mapper";
538 const char* interface = "xyz.openbmc_project.ObjectMapper";
539 const char* method = "GetSubTreePaths";
P.K. Leedd99e042020-06-17 19:43:16 +0800540
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700541 const std::array<const char*, 1> interfaces = {
542 "xyz.openbmc_project.State.Chassis"};
543
544 // Use mapper to get subtree paths.
P.K. Leedd99e042020-06-17 19:43:16 +0800545 crow::connections::systemBus->async_method_call(
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700546 [asyncResp](const boost::system::error_code ec,
547 const std::vector<std::string>& chassisList) {
P.K. Leedd99e042020-06-17 19:43:16 +0800548 if (ec)
549 {
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700550 BMCWEB_LOG_DEBUG << "[mapper] Bad D-Bus request error: " << ec;
P.K. Leedd99e042020-06-17 19:43:16 +0800551 messages::internalError(asyncResp->res);
552 return;
553 }
554
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700555 const char* processName = "xyz.openbmc_project.State.Chassis";
556 const char* interfaceName = "xyz.openbmc_project.State.Chassis";
557 const char* destProperty = "RequestedPowerTransition";
558 const std::string propertyValue =
559 "xyz.openbmc_project.State.Chassis.Transition.PowerCycle";
560 std::string objectPath =
561 "/xyz/openbmc_project/state/chassis_system0";
562
563 /* Look for system reset chassis path */
564 if ((std::find(chassisList.begin(), chassisList.end(),
565 objectPath)) == chassisList.end())
566 {
567 /* We prefer to reset the full chassis_system, but if it doesn't
568 * exist on some platforms, fall back to a host-only power reset
569 */
570 objectPath = "/xyz/openbmc_project/state/chassis0";
571 }
572
573 crow::connections::systemBus->async_method_call(
574 [asyncResp](const boost::system::error_code ec) {
575 // Use "Set" method to set the property value.
576 if (ec)
577 {
578 BMCWEB_LOG_DEBUG << "[Set] Bad D-Bus request error: "
579 << ec;
580 messages::internalError(asyncResp->res);
581 return;
582 }
583
584 messages::success(asyncResp->res);
585 },
586 processName, objectPath, "org.freedesktop.DBus.Properties",
587 "Set", interfaceName, destProperty,
588 std::variant<std::string>{propertyValue});
P.K. Leedd99e042020-06-17 19:43:16 +0800589 },
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700590 busName, path, interface, method, "/", 0, interfaces);
P.K. Leedd99e042020-06-17 19:43:16 +0800591}
592
593/**
594 * ChassisResetAction class supports the POST method for the Reset
595 * action.
596 */
597class ChassisResetAction : public Node
598{
599 public:
Ed Tanous52cc1122020-07-18 13:51:21 -0700600 ChassisResetAction(App& app) :
P.K. Leedd99e042020-06-17 19:43:16 +0800601 Node(app, "/redfish/v1/Chassis/<str>/Actions/Chassis.Reset/",
602 std::string())
603 {
604 entityPrivileges = {
605 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
606 }
607
608 private:
609 /**
610 * Function handles POST method request.
611 * Analyzes POST body before sending Reset request data to D-Bus.
612 */
613 void doPost(crow::Response& res, const crow::Request& req,
Ed Tanouscb13a392020-07-25 19:02:03 +0000614 const std::vector<std::string>&) override
P.K. Leedd99e042020-06-17 19:43:16 +0800615 {
616 BMCWEB_LOG_DEBUG << "Post Chassis Reset.";
617
618 std::string resetType;
619 auto asyncResp = std::make_shared<AsyncResp>(res);
620
621 if (!json_util::readJson(req, asyncResp->res, "ResetType", resetType))
622 {
623 return;
624 }
625
626 if (resetType != "PowerCycle")
627 {
628 BMCWEB_LOG_DEBUG << "Invalid property value for ResetType: "
629 << resetType;
630 messages::actionParameterNotSupported(asyncResp->res, resetType,
631 "ResetType");
632
633 return;
634 }
635 doChassisPowerCycle(asyncResp);
636 }
637};
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530638
639/**
640 * ChassisResetActionInfo derived class for delivering Chassis
641 * ResetType AllowableValues using ResetInfo schema.
642 */
643class ChassisResetActionInfo : public Node
644{
645 public:
646 /*
647 * Default Constructor
648 */
Ed Tanous52cc1122020-07-18 13:51:21 -0700649 ChassisResetActionInfo(App& app) :
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530650 Node(app, "/redfish/v1/Chassis/<str>/ResetActionInfo/", std::string())
651 {
652 entityPrivileges = {
653 {boost::beast::http::verb::get, {{"Login"}}},
654 {boost::beast::http::verb::head, {{"Login"}}},
655 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
656 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
657 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
658 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
659 }
660
661 private:
662 /**
663 * Functions triggers appropriate requests on DBus
664 */
Ed Tanouscb13a392020-07-25 19:02:03 +0000665 void doGet(crow::Response& res, const crow::Request&,
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530666 const std::vector<std::string>& params) override
667 {
668 if (params.size() != 1)
669 {
670 messages::internalError(res);
671 res.end();
672 return;
673 }
674 const std::string& chassisId = params[0];
675
676 res.jsonValue = {{"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"},
677 {"@odata.id", "/redfish/v1/Chassis/" + chassisId +
678 "/ResetActionInfo"},
679 {"Name", "Reset Action Info"},
680 {"Id", "ResetActionInfo"},
681 {"Parameters",
682 {{{"Name", "ResetType"},
683 {"Required", true},
684 {"DataType", "String"},
685 {"AllowableValues", {"PowerCycle"}}}}}};
686 res.end();
687 }
688};
689
Ed Tanous1abe55e2018-09-05 08:30:59 -0700690} // namespace redfish