blob: 4e221cd768a9c535064def2aee84f79b898a833c [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 Tanous90728b52020-08-19 09:06:34 -0700356 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) {
359 for (const std::pair<std::string, VariantType>&
360 property : propertiesList)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700361 {
Shawn McCarney99cffd72019-03-01 10:46:20 -0600362 // Store DBus properties that are also Redfish
363 // properties with same name and a string value
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500364 const std::string& propertyName =
Shawn McCarney99cffd72019-03-01 10:46:20 -0600365 property.first;
366 if ((propertyName == "PartNumber") ||
367 (propertyName == "SerialNumber") ||
368 (propertyName == "Manufacturer") ||
369 (propertyName == "Model"))
Ed Tanous1abe55e2018-09-05 08:30:59 -0700370 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500371 const std::string* value =
Shawn McCarney99cffd72019-03-01 10:46:20 -0600372 std::get_if<std::string>(
373 &property.second);
374 if (value != nullptr)
375 {
376 asyncResp->res.jsonValue[propertyName] =
377 *value;
378 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700379 }
380 }
Ed Tanous62d5e2e2018-09-05 16:17:25 -0700381 asyncResp->res.jsonValue["Name"] = chassisId;
382 asyncResp->res.jsonValue["Id"] = chassisId;
383 asyncResp->res.jsonValue["Thermal"] = {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700384 {"@odata.id", "/redfish/v1/Chassis/" +
385 chassisId + "/Thermal"}};
Ed Tanous2474adf2018-09-05 16:31:16 -0700386 // Power object
387 asyncResp->res.jsonValue["Power"] = {
388 {"@odata.id", "/redfish/v1/Chassis/" +
389 chassisId + "/Power"}};
Anthony Wilson95a3eca2019-06-11 10:44:47 -0500390 // SensorCollection
391 asyncResp->res.jsonValue["Sensors"] = {
392 {"@odata.id", "/redfish/v1/Chassis/" +
393 chassisId + "/Sensors"}};
Ed Tanous029573d2019-02-01 10:57:49 -0800394 asyncResp->res.jsonValue["Status"] = {
Ed Tanous029573d2019-02-01 10:57:49 -0800395 {"State", "Enabled"},
396 };
Ed Tanous2474adf2018-09-05 16:31:16 -0700397
Ed Tanous029573d2019-02-01 10:57:49 -0800398 asyncResp->res
399 .jsonValue["Links"]["ComputerSystems"] = {
400 {{"@odata.id", "/redfish/v1/Systems/system"}}};
401 asyncResp->res.jsonValue["Links"]["ManagedBy"] = {
402 {{"@odata.id", "/redfish/v1/Managers/bmc"}}};
Gunnar Millsbeeca0a2019-02-14 16:30:45 -0600403 getChassisState(asyncResp);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700404 },
405 connectionName, path, "org.freedesktop.DBus.Properties",
406 "GetAll",
407 "xyz.openbmc_project.Inventory.Decorator.Asset");
Ed Tanous1abe55e2018-09-05 08:30:59 -0700408 return;
409 }
Ed Tanouse0d918b2018-03-27 17:41:04 -0700410
Ed Tanous1abe55e2018-09-05 08:30:59 -0700411 // Couldn't find an object with that name. return an error
Jason M. Billsf12894f2018-10-09 12:45:45 -0700412 messages::resourceNotFound(
Jason M. Billsadbe1922019-10-14 15:44:35 -0700413 asyncResp->res, "#Chassis.v1_10_0.Chassis", chassisId);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700414 },
415 "xyz.openbmc_project.ObjectMapper",
416 "/xyz/openbmc_project/object_mapper",
417 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous271584a2019-07-09 16:24:22 -0700418 "/xyz/openbmc_project/inventory", 0, interfaces);
Qiang XUc1819422019-02-27 13:51:32 +0800419
420 getPhysicalSecurityData(asyncResp);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700421 }
James Feist1c8fba92019-12-20 15:12:07 -0800422
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500423 void doPatch(crow::Response& res, const crow::Request& req,
424 const std::vector<std::string>& params) override
James Feist1c8fba92019-12-20 15:12:07 -0800425 {
426 std::optional<std::string> indicatorLed;
427 auto asyncResp = std::make_shared<AsyncResp>(res);
428
429 if (params.size() != 1)
430 {
431 return;
432 }
433
434 if (!json_util::readJson(req, res, "IndicatorLED", indicatorLed))
435 {
436 return;
437 }
438
439 if (!indicatorLed)
440 {
441 return; // delete this when we support more patch properties
442 }
443
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500444 const std::array<const char*, 2> interfaces = {
James Feist1c8fba92019-12-20 15:12:07 -0800445 "xyz.openbmc_project.Inventory.Item.Board",
446 "xyz.openbmc_project.Inventory.Item.Chassis"};
447
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500448 const std::string& chassisId = params[0];
James Feist1c8fba92019-12-20 15:12:07 -0800449
450 crow::connections::systemBus->async_method_call(
451 [asyncResp, chassisId, indicatorLed](
452 const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500453 const crow::openbmc_mapper::GetSubTreeType& subtree) {
James Feist1c8fba92019-12-20 15:12:07 -0800454 if (ec)
455 {
456 messages::internalError(asyncResp->res);
457 return;
458 }
459
460 // Iterate over all retrieved ObjectPaths.
461 for (const std::pair<
462 std::string,
463 std::vector<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500464 std::pair<std::string, std::vector<std::string>>>>&
465 object : subtree)
James Feist1c8fba92019-12-20 15:12:07 -0800466 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500467 const std::string& path = object.first;
James Feist1c8fba92019-12-20 15:12:07 -0800468 const std::vector<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500469 std::pair<std::string, std::vector<std::string>>>&
470 connectionNames = object.second;
James Feist1c8fba92019-12-20 15:12:07 -0800471
472 if (!boost::ends_with(path, chassisId))
473 {
474 continue;
475 }
476
477 if (connectionNames.size() < 1)
478 {
479 BMCWEB_LOG_ERROR << "Got 0 Connection names";
480 continue;
481 }
482
Ed Tanous23a21a12020-07-25 04:45:05 +0000483 const std::vector<std::string>& interfaces3 =
James Feist1c8fba92019-12-20 15:12:07 -0800484 connectionNames[0].second;
485
486 if (indicatorLed)
487 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500488 const std::array<const char*, 2> hasIndicatorLed = {
James Feist1c8fba92019-12-20 15:12:07 -0800489 "xyz.openbmc_project.Inventory.Item.Panel",
490 "xyz.openbmc_project.Inventory.Item.Board."
491 "Motherboard"};
492 bool indicatorChassis = false;
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500493 for (const char* interface : hasIndicatorLed)
James Feist1c8fba92019-12-20 15:12:07 -0800494 {
Ed Tanous23a21a12020-07-25 04:45:05 +0000495 if (std::find(interfaces3.begin(),
496 interfaces3.end(),
497 interface) != interfaces3.end())
James Feist1c8fba92019-12-20 15:12:07 -0800498 {
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
Ed Tanous23a21a12020-07-25 04:45:05 +0000527inline void doChassisPowerCycle(std::shared_ptr<AsyncResp> asyncResp)
P.K. Leedd99e042020-06-17 19:43:16 +0800528{
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:
Ed Tanous52cc1122020-07-18 13:51:21 -0700559 ChassisResetAction(App& app) :
P.K. Leedd99e042020-06-17 19:43:16 +0800560 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,
Ed Tanouscb13a392020-07-25 19:02:03 +0000573 const std::vector<std::string>&) override
P.K. Leedd99e042020-06-17 19:43:16 +0800574 {
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 */
Ed Tanous52cc1122020-07-18 13:51:21 -0700608 ChassisResetActionInfo(App& app) :
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530609 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 */
Ed Tanouscb13a392020-07-25 19:02:03 +0000624 void doGet(crow::Response& res, const crow::Request&,
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530625 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