blob: e96a678f9ba4aa427322aca35da543e46c97c824 [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 Mills02f6ff12020-10-14 15:59:58 -050023#include <utils/collection.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050024
Ed Tanousabf2add2019-01-22 16:40:12 -080025#include <variant>
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010026
Ed Tanous1abe55e2018-09-05 08:30:59 -070027namespace redfish
28{
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010029
30/**
Gunnar Millsbeeca0a2019-02-14 16:30:45 -060031 * @brief Retrieves chassis state properties over dbus
32 *
33 * @param[in] aResp - Shared pointer for completing asynchronous calls.
34 *
35 * @return None.
36 */
zhanghch058d1b46d2021-04-01 11:18:24 +080037inline void getChassisState(std::shared_ptr<bmcweb::AsyncResp> aResp)
Gunnar Millsbeeca0a2019-02-14 16:30:45 -060038{
39 crow::connections::systemBus->async_method_call(
40 [aResp{std::move(aResp)}](
41 const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -050042 const std::variant<std::string>& chassisState) {
Gunnar Millsbeeca0a2019-02-14 16:30:45 -060043 if (ec)
44 {
45 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
46 messages::internalError(aResp->res);
47 return;
48 }
49
Gunnar Mills1214b7e2020-06-04 10:11:30 -050050 const std::string* s = std::get_if<std::string>(&chassisState);
Gunnar Millsbeeca0a2019-02-14 16:30:45 -060051 BMCWEB_LOG_DEBUG << "Chassis state: " << *s;
52 if (s != nullptr)
53 {
54 // Verify Chassis State
55 if (*s == "xyz.openbmc_project.State.Chassis.PowerState.On")
56 {
57 aResp->res.jsonValue["PowerState"] = "On";
58 aResp->res.jsonValue["Status"]["State"] = "Enabled";
59 }
60 else if (*s ==
61 "xyz.openbmc_project.State.Chassis.PowerState.Off")
62 {
63 aResp->res.jsonValue["PowerState"] = "Off";
64 aResp->res.jsonValue["Status"]["State"] = "StandbyOffline";
65 }
66 }
67 },
68 "xyz.openbmc_project.State.Chassis",
69 "/xyz/openbmc_project/state/chassis0",
70 "org.freedesktop.DBus.Properties", "Get",
71 "xyz.openbmc_project.State.Chassis", "CurrentPowerState");
72}
73
74/**
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010075 * DBus types primitives for several generic DBus interfaces
76 * TODO(Pawel) consider move this to separate file into boost::dbus
77 */
Ed Tanous55c7b7a2018-05-22 15:27:24 -070078// Note, this is not a very useful Variant, but because it isn't used to get
Ed Tanousaa2e59c2018-04-12 12:17:20 -070079// values, it should be as simple as possible
80// TODO(ed) invent a nullvariant type
Cheng C Yang5fd7ba62019-11-28 15:58:08 +080081using VariantType = std::variant<bool, std::string, uint64_t, uint32_t>;
Ed Tanousaa2e59c2018-04-12 12:17:20 -070082using ManagedObjectsType = std::vector<std::pair<
83 sdbusplus::message::object_path,
84 std::vector<std::pair<std::string,
85 std::vector<std::pair<std::string, VariantType>>>>>>;
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010086
Ed Tanousaa2e59c2018-04-12 12:17:20 -070087using PropertiesType = boost::container::flat_map<std::string, VariantType>;
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010088
zhanghch058d1b46d2021-04-01 11:18:24 +080089inline void getIntrusionByService(std::shared_ptr<bmcweb::AsyncResp> aResp,
Ed Tanous23a21a12020-07-25 04:45:05 +000090 const std::string& service,
91 const std::string& objPath)
Qiang XUc1819422019-02-27 13:51:32 +080092{
93 BMCWEB_LOG_DEBUG << "Get intrusion status by service \n";
94
95 crow::connections::systemBus->async_method_call(
96 [aResp{std::move(aResp)}](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -050097 const std::variant<std::string>& value) {
Qiang XUc1819422019-02-27 13:51:32 +080098 if (ec)
99 {
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500100 // do not add err msg in redfish response, because this is not
Qiang XUc1819422019-02-27 13:51:32 +0800101 // mandatory property
102 BMCWEB_LOG_ERROR << "DBUS response error " << ec << "\n";
103 return;
104 }
105
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500106 const std::string* status = std::get_if<std::string>(&value);
Qiang XUc1819422019-02-27 13:51:32 +0800107
108 if (status == nullptr)
109 {
110 BMCWEB_LOG_ERROR << "intrusion status read error \n";
111 return;
112 }
113
114 aResp->res.jsonValue["PhysicalSecurity"] = {
115 {"IntrusionSensorNumber", 1}, {"IntrusionSensor", *status}};
116 },
117 service, objPath, "org.freedesktop.DBus.Properties", "Get",
118 "xyz.openbmc_project.Chassis.Intrusion", "Status");
119}
120
121/**
122 * Retrieves physical security properties over dbus
123 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800124inline void getPhysicalSecurityData(std::shared_ptr<bmcweb::AsyncResp> aResp)
Qiang XUc1819422019-02-27 13:51:32 +0800125{
126 crow::connections::systemBus->async_method_call(
127 [aResp{std::move(aResp)}](
128 const boost::system::error_code ec,
129 const std::vector<std::pair<
130 std::string,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500131 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
132 subtree) {
Qiang XUc1819422019-02-27 13:51:32 +0800133 if (ec)
134 {
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500135 // do not add err msg in redfish response, because this is not
Qiang XUc1819422019-02-27 13:51:32 +0800136 // mandatory property
137 BMCWEB_LOG_ERROR << "DBUS error: no matched iface " << ec
138 << "\n";
139 return;
140 }
141 // Iterate over all retrieved ObjectPaths.
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500142 for (const auto& object : subtree)
Qiang XUc1819422019-02-27 13:51:32 +0800143 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500144 for (const auto& service : object.second)
Qiang XUc1819422019-02-27 13:51:32 +0800145 {
146 getIntrusionByService(aResp, service.first, object.first);
147 return;
148 }
149 }
150 },
151 "xyz.openbmc_project.ObjectMapper",
152 "/xyz/openbmc_project/object_mapper",
153 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous271584a2019-07-09 16:24:22 -0700154 "/xyz/openbmc_project/Intrusion", 1,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500155 std::array<const char*, 1>{"xyz.openbmc_project.Chassis.Intrusion"});
Qiang XUc1819422019-02-27 13:51:32 +0800156}
157
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100158/**
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100159 * ChassisCollection derived class for delivering Chassis Collection Schema
160 */
Ed Tanous1abe55e2018-09-05 08:30:59 -0700161class ChassisCollection : public Node
162{
163 public:
Ed Tanous52cc1122020-07-18 13:51:21 -0700164 ChassisCollection(App& app) : Node(app, "/redfish/v1/Chassis/")
Ed Tanous1abe55e2018-09-05 08:30:59 -0700165 {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700166 entityPrivileges = {
167 {boost::beast::http::verb::get, {{"Login"}}},
168 {boost::beast::http::verb::head, {{"Login"}}},
169 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
170 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
171 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
172 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
173 }
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100174
Ed Tanous1abe55e2018-09-05 08:30:59 -0700175 private:
176 /**
177 * Functions triggers appropriate requests on DBus
178 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800179 void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
180 const crow::Request&, const std::vector<std::string>&) override
Ed Tanous1abe55e2018-09-05 08:30:59 -0700181 {
zhanghch058d1b46d2021-04-01 11:18:24 +0800182 asyncResp->res.jsonValue["@odata.type"] =
183 "#ChassisCollection.ChassisCollection";
184 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Chassis";
185 asyncResp->res.jsonValue["Name"] = "Chassis Collection";
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100186
Gunnar Mills02f6ff12020-10-14 15:59:58 -0500187 collection_util::getCollectionMembers(
188 asyncResp, "/redfish/v1/Chassis",
189 {"xyz.openbmc_project.Inventory.Item.Board",
190 "xyz.openbmc_project.Inventory.Item.Chassis"});
Ed Tanous62d5e2e2018-09-05 16:17:25 -0700191 }
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100192};
193
194/**
195 * Chassis override class for delivering Chassis Schema
196 */
Ed Tanous1abe55e2018-09-05 08:30:59 -0700197class Chassis : public Node
198{
199 public:
Ed Tanous52cc1122020-07-18 13:51:21 -0700200 Chassis(App& app) : Node(app, "/redfish/v1/Chassis/<str>/", std::string())
Ed Tanous1abe55e2018-09-05 08:30:59 -0700201 {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700202 entityPrivileges = {
203 {boost::beast::http::verb::get, {{"Login"}}},
204 {boost::beast::http::verb::head, {{"Login"}}},
205 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
206 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
207 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
208 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100209 }
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100210
Ed Tanous1abe55e2018-09-05 08:30:59 -0700211 private:
212 /**
213 * Functions triggers appropriate requests on DBus
214 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800215 void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
216 const crow::Request&,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500217 const std::vector<std::string>& params) override
Ed Tanous1abe55e2018-09-05 08:30:59 -0700218 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500219 const std::array<const char*, 2> interfaces = {
Gunnar Mills734bfe92019-01-21 16:33:50 -0600220 "xyz.openbmc_project.Inventory.Item.Board",
Shawn McCarneyadc4f0d2019-07-24 09:21:50 -0500221 "xyz.openbmc_project.Inventory.Item.Chassis"};
Gunnar Mills734bfe92019-01-21 16:33:50 -0600222
Ed Tanous1abe55e2018-09-05 08:30:59 -0700223 // Check if there is required param, truly entering this shall be
224 // impossible.
225 if (params.size() != 1)
226 {
zhanghch058d1b46d2021-04-01 11:18:24 +0800227 messages::internalError(asyncResp->res);
Ed Tanousdaf36e22018-04-20 16:01:36 -0700228 return;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700229 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500230 const std::string& chassisId = params[0];
Ed Tanouse0d918b2018-03-27 17:41:04 -0700231
Ed Tanous1abe55e2018-09-05 08:30:59 -0700232 crow::connections::systemBus->async_method_call(
Ed Tanous62d5e2e2018-09-05 16:17:25 -0700233 [asyncResp, chassisId(std::string(chassisId))](
234 const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500235 const crow::openbmc_mapper::GetSubTreeType& subtree) {
Ed Tanous62d5e2e2018-09-05 16:17:25 -0700236 if (ec)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700237 {
Jason M. Billsf12894f2018-10-09 12:45:45 -0700238 messages::internalError(asyncResp->res);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700239 return;
240 }
241 // Iterate over all retrieved ObjectPaths.
242 for (const std::pair<
243 std::string,
244 std::vector<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500245 std::pair<std::string, std::vector<std::string>>>>&
246 object : subtree)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700247 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500248 const std::string& path = object.first;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700249 const std::vector<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500250 std::pair<std::string, std::vector<std::string>>>&
251 connectionNames = object.second;
Ed Tanousffed87b2021-04-26 08:11:18 -0700252 sdbusplus::message::object_path objPath(path);
253 if (objPath.filename() != chassisId)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700254 {
255 continue;
Ed Tanousdaf36e22018-04-20 16:01:36 -0700256 }
Shawn McCarney26f03892019-05-03 13:20:24 -0500257
James Feistb49ac872019-05-21 15:12:01 -0700258 auto health = std::make_shared<HealthPopulate>(asyncResp);
259
260 crow::connections::systemBus->async_method_call(
Ed Tanous23a21a12020-07-25 04:45:05 +0000261 [health](const boost::system::error_code ec2,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500262 std::variant<std::vector<std::string>>& resp) {
Ed Tanous23a21a12020-07-25 04:45:05 +0000263 if (ec2)
James Feistb49ac872019-05-21 15:12:01 -0700264 {
265 return; // no sensors = no failures
266 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500267 std::vector<std::string>* data =
James Feistb49ac872019-05-21 15:12:01 -0700268 std::get_if<std::vector<std::string>>(&resp);
269 if (data == nullptr)
270 {
271 return;
272 }
273 health->inventory = std::move(*data);
274 },
275 "xyz.openbmc_project.ObjectMapper",
276 path + "/all_sensors",
277 "org.freedesktop.DBus.Properties", "Get",
278 "xyz.openbmc_project.Association", "endpoints");
279
280 health->populate();
281
Ed Tanous1abe55e2018-09-05 08:30:59 -0700282 if (connectionNames.size() < 1)
283 {
James Feist1c8fba92019-12-20 15:12:07 -0800284 BMCWEB_LOG_ERROR << "Got 0 Connection names";
Ed Tanous1abe55e2018-09-05 08:30:59 -0700285 continue;
286 }
Ed Tanouse0d918b2018-03-27 17:41:04 -0700287
Johnathan Mantey49c53ac2019-05-02 09:22:38 -0700288 asyncResp->res.jsonValue["@odata.type"] =
Gunnar Mills9f8bfa72020-09-28 13:45:19 -0500289 "#Chassis.v1_14_0.Chassis";
Johnathan Mantey49c53ac2019-05-02 09:22:38 -0700290 asyncResp->res.jsonValue["@odata.id"] =
291 "/redfish/v1/Chassis/" + chassisId;
Johnathan Mantey49c53ac2019-05-02 09:22:38 -0700292 asyncResp->res.jsonValue["Name"] = "Chassis Collection";
293 asyncResp->res.jsonValue["ChassisType"] = "RackMount";
P.K. Leedd99e042020-06-17 19:43:16 +0800294 asyncResp->res.jsonValue["Actions"]["#Chassis.Reset"] = {
295 {"target", "/redfish/v1/Chassis/" + chassisId +
296 "/Actions/Chassis.Reset"},
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530297 {"@Redfish.ActionInfo", "/redfish/v1/Chassis/" +
298 chassisId +
299 "/ResetActionInfo"}};
Jason M. Billsadbe1922019-10-14 15:44:35 -0700300 asyncResp->res.jsonValue["PCIeDevices"] = {
301 {"@odata.id",
302 "/redfish/v1/Systems/system/PCIeDevices"}};
Johnathan Mantey49c53ac2019-05-02 09:22:38 -0700303
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500304 const std::string& connectionName =
Johnathan Mantey49c53ac2019-05-02 09:22:38 -0700305 connectionNames[0].first;
James Feist1c8fba92019-12-20 15:12:07 -0800306
Ed Tanous23a21a12020-07-25 04:45:05 +0000307 const std::vector<std::string>& interfaces2 =
James Feist1c8fba92019-12-20 15:12:07 -0800308 connectionNames[0].second;
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500309 const std::array<const char*, 2> hasIndicatorLed = {
James Feist1c8fba92019-12-20 15:12:07 -0800310 "xyz.openbmc_project.Inventory.Item.Panel",
311 "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
312
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500313 for (const char* interface : hasIndicatorLed)
James Feist1c8fba92019-12-20 15:12:07 -0800314 {
Ed Tanous23a21a12020-07-25 04:45:05 +0000315 if (std::find(interfaces2.begin(), interfaces2.end(),
316 interface) != interfaces2.end())
James Feist1c8fba92019-12-20 15:12:07 -0800317 {
318 getIndicatorLedState(asyncResp);
Gunnar Mills9f8bfa72020-09-28 13:45:19 -0500319 getLocationIndicatorActive(asyncResp);
James Feist1c8fba92019-12-20 15:12:07 -0800320 break;
321 }
322 }
323
SunnySrivastava198488ad7f02020-12-03 10:27:52 -0600324 const std::string locationInterface =
325 "xyz.openbmc_project.Inventory.Decorator.LocationCode";
326 if (std::find(interfaces2.begin(), interfaces2.end(),
327 locationInterface) != interfaces2.end())
328 {
329 crow::connections::systemBus->async_method_call(
330 [asyncResp, chassisId(std::string(chassisId))](
331 const boost::system::error_code ec,
332 const std::variant<std::string>& property) {
333 if (ec)
334 {
335 BMCWEB_LOG_DEBUG
336 << "DBUS response error for Location";
337 messages::internalError(asyncResp->res);
338 return;
339 }
340
341 const std::string* value =
342 std::get_if<std::string>(&property);
343 if (value == nullptr)
344 {
345 BMCWEB_LOG_DEBUG << "Null value returned "
346 "for locaton code";
347 messages::internalError(asyncResp->res);
348 return;
349 }
350 asyncResp->res
351 .jsonValue["Location"]["PartLocation"]
352 ["ServiceLabel"] = *value;
353 },
354 connectionName, path,
355 "org.freedesktop.DBus.Properties", "Get",
356 locationInterface, "LocationCode");
357 }
358
Ed Tanous1abe55e2018-09-05 08:30:59 -0700359 crow::connections::systemBus->async_method_call(
Ed Tanous62d5e2e2018-09-05 16:17:25 -0700360 [asyncResp, chassisId(std::string(chassisId))](
Ed Tanous90728b52020-08-19 09:06:34 -0700361 const boost::system::error_code /*ec2*/,
Ed Tanous1abe55e2018-09-05 08:30:59 -0700362 const std::vector<std::pair<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500363 std::string, VariantType>>& propertiesList) {
364 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(
Gunnar Mills9f8bfa72020-09-28 13:45:19 -0500418 asyncResp->res, "#Chassis.v1_14_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
zhanghch058d1b46d2021-04-01 11:18:24 +0800428 void doPatch(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
429 const crow::Request& req,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500430 const std::vector<std::string>& params) override
James Feist1c8fba92019-12-20 15:12:07 -0800431 {
Gunnar Mills9f8bfa72020-09-28 13:45:19 -0500432 std::optional<bool> locationIndicatorActive;
James Feist1c8fba92019-12-20 15:12:07 -0800433 std::optional<std::string> indicatorLed;
James Feist1c8fba92019-12-20 15:12:07 -0800434
435 if (params.size() != 1)
436 {
437 return;
438 }
439
zhanghch058d1b46d2021-04-01 11:18:24 +0800440 if (!json_util::readJson(req, asyncResp->res, "LocationIndicatorActive",
Gunnar Mills9f8bfa72020-09-28 13:45:19 -0500441 locationIndicatorActive, "IndicatorLED",
442 indicatorLed))
James Feist1c8fba92019-12-20 15:12:07 -0800443 {
444 return;
445 }
446
Gunnar Mills9f8bfa72020-09-28 13:45:19 -0500447 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
448 if (!locationIndicatorActive && !indicatorLed)
James Feist1c8fba92019-12-20 15:12:07 -0800449 {
450 return; // delete this when we support more patch properties
451 }
Gunnar Millsd6aa0092020-11-25 14:17:37 -0600452 if (indicatorLed)
453 {
zhanghch058d1b46d2021-04-01 11:18:24 +0800454 asyncResp->res.addHeader(boost::beast::http::field::warning,
455 "299 - \"IndicatorLED is deprecated. Use "
456 "LocationIndicatorActive instead.\"");
Gunnar Millsd6aa0092020-11-25 14:17:37 -0600457 }
James Feist1c8fba92019-12-20 15:12:07 -0800458
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500459 const std::array<const char*, 2> interfaces = {
James Feist1c8fba92019-12-20 15:12:07 -0800460 "xyz.openbmc_project.Inventory.Item.Board",
461 "xyz.openbmc_project.Inventory.Item.Chassis"};
462
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500463 const std::string& chassisId = params[0];
James Feist1c8fba92019-12-20 15:12:07 -0800464
465 crow::connections::systemBus->async_method_call(
Gunnar Mills9f8bfa72020-09-28 13:45:19 -0500466 [asyncResp, chassisId, locationIndicatorActive, indicatorLed](
James Feist1c8fba92019-12-20 15:12:07 -0800467 const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500468 const crow::openbmc_mapper::GetSubTreeType& subtree) {
James Feist1c8fba92019-12-20 15:12:07 -0800469 if (ec)
470 {
471 messages::internalError(asyncResp->res);
472 return;
473 }
474
475 // Iterate over all retrieved ObjectPaths.
476 for (const std::pair<
477 std::string,
478 std::vector<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500479 std::pair<std::string, std::vector<std::string>>>>&
480 object : subtree)
James Feist1c8fba92019-12-20 15:12:07 -0800481 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500482 const std::string& path = object.first;
James Feist1c8fba92019-12-20 15:12:07 -0800483 const std::vector<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500484 std::pair<std::string, std::vector<std::string>>>&
485 connectionNames = object.second;
James Feist1c8fba92019-12-20 15:12:07 -0800486
487 if (!boost::ends_with(path, chassisId))
488 {
489 continue;
490 }
491
492 if (connectionNames.size() < 1)
493 {
494 BMCWEB_LOG_ERROR << "Got 0 Connection names";
495 continue;
496 }
497
Ed Tanous23a21a12020-07-25 04:45:05 +0000498 const std::vector<std::string>& interfaces3 =
James Feist1c8fba92019-12-20 15:12:07 -0800499 connectionNames[0].second;
500
Gunnar Mills9f8bfa72020-09-28 13:45:19 -0500501 const std::array<const char*, 2> hasIndicatorLed = {
502 "xyz.openbmc_project.Inventory.Item.Panel",
503 "xyz.openbmc_project.Inventory.Item.Board."
504 "Motherboard"};
505 bool indicatorChassis = false;
506 for (const char* interface : hasIndicatorLed)
507 {
508 if (std::find(interfaces3.begin(), interfaces3.end(),
509 interface) != interfaces3.end())
510 {
511 indicatorChassis = true;
512 break;
513 }
514 }
515 if (locationIndicatorActive)
516 {
517 if (indicatorChassis)
518 {
519 setLocationIndicatorActive(
520 asyncResp, *locationIndicatorActive);
521 }
522 else
523 {
524 messages::propertyUnknown(
525 asyncResp->res, "LocationIndicatorActive");
526 }
527 }
James Feist1c8fba92019-12-20 15:12:07 -0800528 if (indicatorLed)
529 {
James Feist1c8fba92019-12-20 15:12:07 -0800530 if (indicatorChassis)
531 {
Ed Tanousf23b7292020-10-15 09:41:17 -0700532 setIndicatorLedState(asyncResp, *indicatorLed);
James Feist1c8fba92019-12-20 15:12:07 -0800533 }
534 else
535 {
536 messages::propertyUnknown(asyncResp->res,
537 "IndicatorLED");
538 }
539 }
540 return;
541 }
542
543 messages::resourceNotFound(
Gunnar Mills9f8bfa72020-09-28 13:45:19 -0500544 asyncResp->res, "#Chassis.v1_14_0.Chassis", chassisId);
James Feist1c8fba92019-12-20 15:12:07 -0800545 },
546 "xyz.openbmc_project.ObjectMapper",
547 "/xyz/openbmc_project/object_mapper",
548 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
549 "/xyz/openbmc_project/inventory", 0, interfaces);
550 }
Ed Tanous62d5e2e2018-09-05 16:17:25 -0700551};
P.K. Leedd99e042020-06-17 19:43:16 +0800552
zhanghch058d1b46d2021-04-01 11:18:24 +0800553inline void
554 doChassisPowerCycle(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
P.K. Leedd99e042020-06-17 19:43:16 +0800555{
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700556 const char* busName = "xyz.openbmc_project.ObjectMapper";
557 const char* path = "/xyz/openbmc_project/object_mapper";
558 const char* interface = "xyz.openbmc_project.ObjectMapper";
559 const char* method = "GetSubTreePaths";
P.K. Leedd99e042020-06-17 19:43:16 +0800560
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700561 const std::array<const char*, 1> interfaces = {
562 "xyz.openbmc_project.State.Chassis"};
563
564 // Use mapper to get subtree paths.
P.K. Leedd99e042020-06-17 19:43:16 +0800565 crow::connections::systemBus->async_method_call(
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700566 [asyncResp](const boost::system::error_code ec,
567 const std::vector<std::string>& chassisList) {
P.K. Leedd99e042020-06-17 19:43:16 +0800568 if (ec)
569 {
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700570 BMCWEB_LOG_DEBUG << "[mapper] Bad D-Bus request error: " << ec;
P.K. Leedd99e042020-06-17 19:43:16 +0800571 messages::internalError(asyncResp->res);
572 return;
573 }
574
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700575 const char* processName = "xyz.openbmc_project.State.Chassis";
576 const char* interfaceName = "xyz.openbmc_project.State.Chassis";
577 const char* destProperty = "RequestedPowerTransition";
578 const std::string propertyValue =
579 "xyz.openbmc_project.State.Chassis.Transition.PowerCycle";
580 std::string objectPath =
581 "/xyz/openbmc_project/state/chassis_system0";
582
583 /* Look for system reset chassis path */
584 if ((std::find(chassisList.begin(), chassisList.end(),
585 objectPath)) == chassisList.end())
586 {
587 /* We prefer to reset the full chassis_system, but if it doesn't
588 * exist on some platforms, fall back to a host-only power reset
589 */
590 objectPath = "/xyz/openbmc_project/state/chassis0";
591 }
592
593 crow::connections::systemBus->async_method_call(
594 [asyncResp](const boost::system::error_code ec) {
595 // Use "Set" method to set the property value.
596 if (ec)
597 {
598 BMCWEB_LOG_DEBUG << "[Set] Bad D-Bus request error: "
599 << ec;
600 messages::internalError(asyncResp->res);
601 return;
602 }
603
604 messages::success(asyncResp->res);
605 },
606 processName, objectPath, "org.freedesktop.DBus.Properties",
607 "Set", interfaceName, destProperty,
608 std::variant<std::string>{propertyValue});
P.K. Leedd99e042020-06-17 19:43:16 +0800609 },
Vijay Khemkac3b3c922020-09-22 23:00:12 -0700610 busName, path, interface, method, "/", 0, interfaces);
P.K. Leedd99e042020-06-17 19:43:16 +0800611}
612
613/**
614 * ChassisResetAction class supports the POST method for the Reset
615 * action.
616 */
617class ChassisResetAction : public Node
618{
619 public:
Ed Tanous52cc1122020-07-18 13:51:21 -0700620 ChassisResetAction(App& app) :
P.K. Leedd99e042020-06-17 19:43:16 +0800621 Node(app, "/redfish/v1/Chassis/<str>/Actions/Chassis.Reset/",
622 std::string())
623 {
624 entityPrivileges = {
625 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
626 }
627
628 private:
629 /**
630 * Function handles POST method request.
631 * Analyzes POST body before sending Reset request data to D-Bus.
632 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800633 void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
634 const crow::Request& req,
Ed Tanouscb13a392020-07-25 19:02:03 +0000635 const std::vector<std::string>&) override
P.K. Leedd99e042020-06-17 19:43:16 +0800636 {
637 BMCWEB_LOG_DEBUG << "Post Chassis Reset.";
638
639 std::string resetType;
P.K. Leedd99e042020-06-17 19:43:16 +0800640
641 if (!json_util::readJson(req, asyncResp->res, "ResetType", resetType))
642 {
643 return;
644 }
645
646 if (resetType != "PowerCycle")
647 {
648 BMCWEB_LOG_DEBUG << "Invalid property value for ResetType: "
649 << resetType;
650 messages::actionParameterNotSupported(asyncResp->res, resetType,
651 "ResetType");
652
653 return;
654 }
655 doChassisPowerCycle(asyncResp);
656 }
657};
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530658
659/**
660 * ChassisResetActionInfo derived class for delivering Chassis
661 * ResetType AllowableValues using ResetInfo schema.
662 */
663class ChassisResetActionInfo : public Node
664{
665 public:
666 /*
667 * Default Constructor
668 */
Ed Tanous52cc1122020-07-18 13:51:21 -0700669 ChassisResetActionInfo(App& app) :
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530670 Node(app, "/redfish/v1/Chassis/<str>/ResetActionInfo/", std::string())
671 {
672 entityPrivileges = {
673 {boost::beast::http::verb::get, {{"Login"}}},
674 {boost::beast::http::verb::head, {{"Login"}}},
675 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
676 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
677 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
678 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
679 }
680
681 private:
682 /**
683 * Functions triggers appropriate requests on DBus
684 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800685 void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
686 const crow::Request&,
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530687 const std::vector<std::string>& params) override
688 {
689 if (params.size() != 1)
690 {
zhanghch058d1b46d2021-04-01 11:18:24 +0800691 messages::internalError(asyncResp->res);
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530692 return;
693 }
694 const std::string& chassisId = params[0];
695
zhanghch058d1b46d2021-04-01 11:18:24 +0800696 asyncResp->res.jsonValue = {
697 {"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"},
698 {"@odata.id",
699 "/redfish/v1/Chassis/" + chassisId + "/ResetActionInfo"},
700 {"Name", "Reset Action Info"},
701 {"Id", "ResetActionInfo"},
702 {"Parameters",
703 {{{"Name", "ResetType"},
704 {"Required", true},
705 {"DataType", "String"},
706 {"AllowableValues", {"PowerCycle"}}}}}};
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +0530707 }
708};
709
Ed Tanous1abe55e2018-09-05 08:30:59 -0700710} // namespace redfish