blob: 43bef62795fbf62330eb154d0bf71fe763c4b38a [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
18#include "node.hpp"
Ed Tanous1abe55e2018-09-05 08:30:59 -070019
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010020#include <boost/container/flat_map.hpp>
Ed Tanousabf2add2019-01-22 16:40:12 -080021#include <variant>
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010022
Ed Tanous1abe55e2018-09-05 08:30:59 -070023namespace redfish
24{
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010025
26/**
27 * DBus types primitives for several generic DBus interfaces
28 * TODO(Pawel) consider move this to separate file into boost::dbus
29 */
Ed Tanous55c7b7a2018-05-22 15:27:24 -070030// Note, this is not a very useful Variant, but because it isn't used to get
Ed Tanousaa2e59c2018-04-12 12:17:20 -070031// values, it should be as simple as possible
32// TODO(ed) invent a nullvariant type
Ed Tanousabf2add2019-01-22 16:40:12 -080033using VariantType = std::variant<bool, std::string, uint64_t>;
Ed Tanousaa2e59c2018-04-12 12:17:20 -070034using ManagedObjectsType = std::vector<std::pair<
35 sdbusplus::message::object_path,
36 std::vector<std::pair<std::string,
37 std::vector<std::pair<std::string, VariantType>>>>>>;
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010038
Ed Tanousaa2e59c2018-04-12 12:17:20 -070039using PropertiesType = boost::container::flat_map<std::string, VariantType>;
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010040
41/**
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010042 * ChassisCollection derived class for delivering Chassis Collection Schema
43 */
Ed Tanous1abe55e2018-09-05 08:30:59 -070044class ChassisCollection : public Node
45{
46 public:
47 ChassisCollection(CrowApp &app) : Node(app, "/redfish/v1/Chassis/")
48 {
Ed Tanous1abe55e2018-09-05 08:30:59 -070049 entityPrivileges = {
50 {boost::beast::http::verb::get, {{"Login"}}},
51 {boost::beast::http::verb::head, {{"Login"}}},
52 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
53 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
54 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
55 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
56 }
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010057
Ed Tanous1abe55e2018-09-05 08:30:59 -070058 private:
59 /**
60 * Functions triggers appropriate requests on DBus
61 */
62 void doGet(crow::Response &res, const crow::Request &req,
63 const std::vector<std::string> &params) override
64 {
Gunnar Mills8f1ac8e2018-12-06 15:52:46 -060065 const std::array<const char *, 3> interfaces = {
Ed Tanous62d5e2e2018-09-05 16:17:25 -070066 "xyz.openbmc_project.Inventory.Item.Board",
67 "xyz.openbmc_project.Inventory.Item.Chassis",
Gunnar Mills8f1ac8e2018-12-06 15:52:46 -060068 "xyz.openbmc_project.Inventory.Item.PowerSupply"};
Ed Tanous0f74e642018-11-12 15:17:05 -080069 res.jsonValue["@odata.type"] = "#ChassisCollection.ChassisCollection";
70 res.jsonValue["@odata.id"] = "/redfish/v1/Chassis";
71 res.jsonValue["@odata.context"] =
72 "/redfish/v1/$metadata#ChassisCollection.ChassisCollection";
73 res.jsonValue["Name"] = "Chassis Collection";
74
Ed Tanous62d5e2e2018-09-05 16:17:25 -070075 auto asyncResp = std::make_shared<AsyncResp>(res);
76 crow::connections::systemBus->async_method_call(
77 [asyncResp](const boost::system::error_code ec,
78 const std::vector<std::string> &chassisList) {
79 if (ec)
Ed Tanous1abe55e2018-09-05 08:30:59 -070080 {
Jason M. Billsf12894f2018-10-09 12:45:45 -070081 messages::internalError(asyncResp->res);
Ed Tanous62d5e2e2018-09-05 16:17:25 -070082 return;
Ed Tanous1abe55e2018-09-05 08:30:59 -070083 }
Ed Tanous62d5e2e2018-09-05 16:17:25 -070084 nlohmann::json &chassisArray =
85 asyncResp->res.jsonValue["Members"];
86 chassisArray = nlohmann::json::array();
87 for (const std::string &objpath : chassisList)
88 {
89 std::size_t lastPos = objpath.rfind("/");
90 if (lastPos == std::string::npos)
91 {
92 BMCWEB_LOG_ERROR << "Failed to find '/' in " << objpath;
93 continue;
94 }
95 chassisArray.push_back(
96 {{"@odata.id", "/redfish/v1/Chassis/" +
97 objpath.substr(lastPos + 1)}});
98 }
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +010099
Ed Tanous62d5e2e2018-09-05 16:17:25 -0700100 asyncResp->res.jsonValue["Members@odata.count"] =
101 chassisArray.size();
102 },
103 "xyz.openbmc_project.ObjectMapper",
104 "/xyz/openbmc_project/object_mapper",
105 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
Gunnar Mills734bfe92019-01-21 16:33:50 -0600106 "/xyz/openbmc_project/inventory", int32_t(0), interfaces);
Ed Tanous62d5e2e2018-09-05 16:17:25 -0700107 }
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100108};
109
110/**
111 * Chassis override class for delivering Chassis Schema
112 */
Ed Tanous1abe55e2018-09-05 08:30:59 -0700113class Chassis : public Node
114{
115 public:
116 Chassis(CrowApp &app) :
117 Node(app, "/redfish/v1/Chassis/<str>/", std::string())
118 {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700119 entityPrivileges = {
120 {boost::beast::http::verb::get, {{"Login"}}},
121 {boost::beast::http::verb::head, {{"Login"}}},
122 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
123 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
124 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
125 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100126 }
Rapkiewicz, Pawele37f8452018-03-09 13:49:50 +0100127
Ed Tanous1abe55e2018-09-05 08:30:59 -0700128 private:
129 /**
130 * Functions triggers appropriate requests on DBus
131 */
132 void doGet(crow::Response &res, const crow::Request &req,
133 const std::vector<std::string> &params) override
134 {
Gunnar Mills734bfe92019-01-21 16:33:50 -0600135 const std::array<const char *, 3> interfaces = {
136 "xyz.openbmc_project.Inventory.Item.Board",
137 "xyz.openbmc_project.Inventory.Item.Chassis",
138 "xyz.openbmc_project.Inventory.Item.PowerSupply"};
139
Ed Tanous1abe55e2018-09-05 08:30:59 -0700140 // Check if there is required param, truly entering this shall be
141 // impossible.
142 if (params.size() != 1)
143 {
Jason M. Billsf12894f2018-10-09 12:45:45 -0700144 messages::internalError(res);
Ed Tanousdaf36e22018-04-20 16:01:36 -0700145 res.end();
146 return;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700147 }
Shawn McCarney99cffd72019-03-01 10:46:20 -0600148 const std::string &chassisId = params[0];
Ed Tanouse0d918b2018-03-27 17:41:04 -0700149
Ed Tanous0f74e642018-11-12 15:17:05 -0800150 res.jsonValue["@odata.type"] = "#Chassis.v1_4_0.Chassis";
Shawn McCarney99cffd72019-03-01 10:46:20 -0600151 res.jsonValue["@odata.id"] = "/redfish/v1/Chassis/" + chassisId;
Ed Tanous0f74e642018-11-12 15:17:05 -0800152 res.jsonValue["@odata.context"] =
153 "/redfish/v1/$metadata#Chassis.Chassis";
154 res.jsonValue["Name"] = "Chassis Collection";
155 res.jsonValue["ChassisType"] = "RackMount";
156 res.jsonValue["PowerState"] = "On";
157
Ed Tanous62d5e2e2018-09-05 16:17:25 -0700158 auto asyncResp = std::make_shared<AsyncResp>(res);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700159 crow::connections::systemBus->async_method_call(
Ed Tanous62d5e2e2018-09-05 16:17:25 -0700160 [asyncResp, chassisId(std::string(chassisId))](
161 const boost::system::error_code ec,
Ed Tanous1abe55e2018-09-05 08:30:59 -0700162 const std::vector<std::pair<
163 std::string, std::vector<std::pair<
164 std::string, std::vector<std::string>>>>>
165 &subtree) {
Ed Tanous62d5e2e2018-09-05 16:17:25 -0700166 if (ec)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700167 {
Jason M. Billsf12894f2018-10-09 12:45:45 -0700168 messages::internalError(asyncResp->res);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700169 return;
170 }
171 // Iterate over all retrieved ObjectPaths.
172 for (const std::pair<
173 std::string,
174 std::vector<
175 std::pair<std::string, std::vector<std::string>>>>
176 &object : subtree)
177 {
178 const std::string &path = object.first;
179 const std::vector<
180 std::pair<std::string, std::vector<std::string>>>
181 &connectionNames = object.second;
Ed Tanouse0d918b2018-03-27 17:41:04 -0700182
Ed Tanous1abe55e2018-09-05 08:30:59 -0700183 if (!boost::ends_with(path, chassisId))
184 {
185 continue;
Ed Tanousdaf36e22018-04-20 16:01:36 -0700186 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700187 if (connectionNames.size() < 1)
188 {
189 BMCWEB_LOG_ERROR << "Only got "
190 << connectionNames.size()
191 << " Connection names";
192 continue;
193 }
Ed Tanouse0d918b2018-03-27 17:41:04 -0700194
Ed Tanous1abe55e2018-09-05 08:30:59 -0700195 const std::string connectionName = connectionNames[0].first;
196 crow::connections::systemBus->async_method_call(
Ed Tanous62d5e2e2018-09-05 16:17:25 -0700197 [asyncResp, chassisId(std::string(chassisId))](
198 const boost::system::error_code ec,
Ed Tanous1abe55e2018-09-05 08:30:59 -0700199 const std::vector<std::pair<
200 std::string, VariantType>> &propertiesList) {
201 for (const std::pair<std::string, VariantType>
202 &property : propertiesList)
203 {
Shawn McCarney99cffd72019-03-01 10:46:20 -0600204 // Store DBus properties that are also Redfish
205 // properties with same name and a string value
206 const std::string &propertyName =
207 property.first;
208 if ((propertyName == "PartNumber") ||
209 (propertyName == "SerialNumber") ||
210 (propertyName == "Manufacturer") ||
211 (propertyName == "Model"))
Ed Tanous1abe55e2018-09-05 08:30:59 -0700212 {
Shawn McCarney99cffd72019-03-01 10:46:20 -0600213 const std::string *value =
214 std::get_if<std::string>(
215 &property.second);
216 if (value != nullptr)
217 {
218 asyncResp->res.jsonValue[propertyName] =
219 *value;
220 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700221 }
222 }
Ed Tanous62d5e2e2018-09-05 16:17:25 -0700223 asyncResp->res.jsonValue["Name"] = chassisId;
224 asyncResp->res.jsonValue["Id"] = chassisId;
225 asyncResp->res.jsonValue["Thermal"] = {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700226 {"@odata.id", "/redfish/v1/Chassis/" +
227 chassisId + "/Thermal"}};
Ed Tanous2474adf2018-09-05 16:31:16 -0700228 // Power object
229 asyncResp->res.jsonValue["Power"] = {
230 {"@odata.id", "/redfish/v1/Chassis/" +
231 chassisId + "/Power"}};
Ed Tanous029573d2019-02-01 10:57:49 -0800232 asyncResp->res.jsonValue["Status"] = {
233 {"Health", "OK"},
234 {"State", "Enabled"},
235 };
Ed Tanous2474adf2018-09-05 16:31:16 -0700236
Ed Tanous029573d2019-02-01 10:57:49 -0800237 asyncResp->res
238 .jsonValue["Links"]["ComputerSystems"] = {
239 {{"@odata.id", "/redfish/v1/Systems/system"}}};
240 asyncResp->res.jsonValue["Links"]["ManagedBy"] = {
241 {{"@odata.id", "/redfish/v1/Managers/bmc"}}};
Ed Tanous1abe55e2018-09-05 08:30:59 -0700242 },
243 connectionName, path, "org.freedesktop.DBus.Properties",
244 "GetAll",
245 "xyz.openbmc_project.Inventory.Decorator.Asset");
Ed Tanous1abe55e2018-09-05 08:30:59 -0700246 return;
247 }
Ed Tanouse0d918b2018-03-27 17:41:04 -0700248
Ed Tanous1abe55e2018-09-05 08:30:59 -0700249 // Couldn't find an object with that name. return an error
Jason M. Billsf12894f2018-10-09 12:45:45 -0700250 messages::resourceNotFound(
251 asyncResp->res, "#Chassis.v1_4_0.Chassis", chassisId);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700252 },
253 "xyz.openbmc_project.ObjectMapper",
254 "/xyz/openbmc_project/object_mapper",
255 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Gunnar Mills734bfe92019-01-21 16:33:50 -0600256 "/xyz/openbmc_project/inventory", int32_t(0), interfaces);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700257 }
Ed Tanous62d5e2e2018-09-05 16:17:25 -0700258};
Ed Tanous1abe55e2018-09-05 08:30:59 -0700259} // namespace redfish