blob: 4245595364d04e5e36529110a3bd0faaf749019a [file] [log] [blame]
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001/*
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 <boost/container/flat_map.hpp>
19#include <node.hpp>
20#include <utils/json_utils.hpp>
Ed Tanousabf2add2019-01-22 16:40:12 -080021#include <variant>
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020022
23namespace redfish
24{
25
Ed Tanous029573d2019-02-01 10:57:49 -080026void getResourceList(std::shared_ptr<AsyncResp> aResp,
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020027 const std::string &subclass,
28 const std::string &collectionName)
29{
30 BMCWEB_LOG_DEBUG << "Get available system cpu/mem resources.";
31 crow::connections::systemBus->async_method_call(
Ed Tanous029573d2019-02-01 10:57:49 -080032 [subclass, aResp{std::move(aResp)}](
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020033 const boost::system::error_code ec,
34 const boost::container::flat_map<
35 std::string, boost::container::flat_map<
36 std::string, std::vector<std::string>>>
37 &subtree) {
38 if (ec)
39 {
40 BMCWEB_LOG_DEBUG << "DBUS response error";
41 messages::internalError(aResp->res);
42 return;
43 }
44 nlohmann::json &members = aResp->res.jsonValue["Members"];
45 members = nlohmann::json::array();
46
47 for (const auto &object : subtree)
48 {
49 auto iter = object.first.rfind("/");
50 if ((iter != std::string::npos) && (iter < object.first.size()))
51 {
52 members.push_back(
Ed Tanous029573d2019-02-01 10:57:49 -080053 {{"@odata.id", "/redfish/v1/Systems/system/" +
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020054 subclass + "/" +
55 object.first.substr(iter + 1)}});
56 }
57 }
58 aResp->res.jsonValue["Members@odata.count"] = members.size();
59 },
60 "xyz.openbmc_project.ObjectMapper",
61 "/xyz/openbmc_project/object_mapper",
62 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
63 "/xyz/openbmc_project/inventory", int32_t(0),
64 std::array<const char *, 1>{collectionName.c_str()});
65}
66
67void getCpuDataByService(std::shared_ptr<AsyncResp> aResp,
Ed Tanous029573d2019-02-01 10:57:49 -080068 const std::string &cpuId, const std::string &service,
69 const std::string &objPath)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020070{
71 BMCWEB_LOG_DEBUG << "Get available system cpu resources by service.";
72 crow::connections::systemBus->async_method_call(
Ed Tanous029573d2019-02-01 10:57:49 -080073 [cpuId, aResp{std::move(aResp)}](
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020074 const boost::system::error_code ec,
75 const boost::container::flat_map<
Ed Tanousabf2add2019-01-22 16:40:12 -080076 std::string, std::variant<std::string, uint32_t, uint16_t>>
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020077 &properties) {
78 if (ec)
79 {
80 BMCWEB_LOG_DEBUG << "DBUS response error";
81 messages::internalError(aResp->res);
82
83 return;
84 }
85 aResp->res.jsonValue["Id"] = cpuId;
86 aResp->res.jsonValue["Name"] = "Processor";
87 const auto coresCountProperty =
88 properties.find("ProcessorCoreCount");
Ed Tanous883b3112018-12-06 16:13:35 -080089 if (coresCountProperty != properties.end())
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +020090 {
Ed Tanous883b3112018-12-06 16:13:35 -080091 const uint16_t *coresCount =
Ed Tanousabf2add2019-01-22 16:40:12 -080092 std::get_if<uint16_t>(&coresCountProperty->second);
Ed Tanous883b3112018-12-06 16:13:35 -080093 if (coresCount == nullptr)
94 {
95 // Important property not in desired type
96 messages::internalError(aResp->res);
97 return;
98 }
99 if (*coresCount == 0)
100 {
101 // Slot is not populated, set status end return
102 aResp->res.jsonValue["Status"]["State"] = "Absent";
103 aResp->res.jsonValue["Status"]["Health"] = "OK";
104 // HTTP Code will be set up automatically, just return
105 return;
106 }
107
108 aResp->res.jsonValue["TotalCores"] = *coresCount;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200109 }
110
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200111 aResp->res.jsonValue["Status"]["State"] = "Enabled";
112 aResp->res.jsonValue["Status"]["Health"] = "OK";
113
114 for (const auto &property : properties)
115 {
116 if (property.first == "ProcessorType")
117 {
118 aResp->res.jsonValue["Name"] = property.second;
119 }
120 else if (property.first == "ProcessorManufacturer")
121 {
122 aResp->res.jsonValue["Manufacturer"] = property.second;
123 const std::string *value =
Ed Tanousabf2add2019-01-22 16:40:12 -0800124 std::get_if<std::string>(&property.second);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200125 if (value != nullptr)
126 {
127 // Otherwise would be unexpected.
128 if (value->find("Intel") != std::string::npos)
129 {
130 aResp->res.jsonValue["ProcessorArchitecture"] =
131 "x86";
132 aResp->res.jsonValue["InstructionSet"] = "x86-64";
133 }
Gunnar Millsb957ba52019-01-31 15:58:15 -0600134 else if (value->find("IBM") != std::string::npos)
135 {
136 aResp->res.jsonValue["ProcessorArchitecture"] =
137 "Power";
138 aResp->res.jsonValue["InstructionSet"] = "PowerISA";
139 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200140 }
141 }
142 else if (property.first == "ProcessorMaxSpeed")
143 {
144 aResp->res.jsonValue["MaxSpeedMHz"] = property.second;
145 }
146 else if (property.first == "ProcessorThreadCount")
147 {
148 aResp->res.jsonValue["TotalThreads"] = property.second;
149 }
150 else if (property.first == "ProcessorVersion")
151 {
152 aResp->res.jsonValue["Model"] = property.second;
153 }
154 }
155 },
156 service, objPath, "org.freedesktop.DBus.Properties", "GetAll", "");
157}
158
Ed Tanous029573d2019-02-01 10:57:49 -0800159void getCpuData(std::shared_ptr<AsyncResp> aResp, const std::string &cpuId)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200160{
161 BMCWEB_LOG_DEBUG << "Get available system cpu resources.";
162 crow::connections::systemBus->async_method_call(
Ed Tanous029573d2019-02-01 10:57:49 -0800163 [cpuId, aResp{std::move(aResp)}](
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200164 const boost::system::error_code ec,
165 const boost::container::flat_map<
166 std::string, boost::container::flat_map<
167 std::string, std::vector<std::string>>>
168 &subtree) {
169 if (ec)
170 {
171 BMCWEB_LOG_DEBUG << "DBUS response error";
172 messages::internalError(aResp->res);
173 return;
174 }
175 for (const auto &object : subtree)
176 {
177 if (boost::ends_with(object.first, cpuId))
178 {
179 for (const auto &service : object.second)
180 {
Ed Tanous029573d2019-02-01 10:57:49 -0800181 getCpuDataByService(aResp, cpuId, service.first,
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200182 object.first);
183 return;
184 }
185 }
186 }
187 // Object not found
188 messages::resourceNotFound(aResp->res, "Processor", cpuId);
189 return;
190 },
191 "xyz.openbmc_project.ObjectMapper",
192 "/xyz/openbmc_project/object_mapper",
193 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
194 "/xyz/openbmc_project/inventory", int32_t(0),
195 std::array<const char *, 1>{"xyz.openbmc_project.Inventory.Item.Cpu"});
196};
197
198void getDimmDataByService(std::shared_ptr<AsyncResp> aResp,
Ed Tanous029573d2019-02-01 10:57:49 -0800199 const std::string &dimmId, const std::string &service,
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200200 const std::string &objPath)
201{
202 BMCWEB_LOG_DEBUG << "Get available system components.";
203 crow::connections::systemBus->async_method_call(
Ed Tanous029573d2019-02-01 10:57:49 -0800204 [dimmId, aResp{std::move(aResp)}](
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200205 const boost::system::error_code ec,
206 const boost::container::flat_map<
Ed Tanousabf2add2019-01-22 16:40:12 -0800207 std::string, std::variant<std::string, uint32_t, uint16_t>>
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200208 &properties) {
209 if (ec)
210 {
211 BMCWEB_LOG_DEBUG << "DBUS response error";
212 messages::internalError(aResp->res);
213
214 return;
215 }
216 aResp->res.jsonValue["Id"] = dimmId;
217 aResp->res.jsonValue["Name"] = "DIMM Slot";
218
219 const auto memorySizeProperty = properties.find("MemorySizeInKB");
Gunnar Millsaceb7fc2018-12-10 15:17:20 -0600220 if (memorySizeProperty != properties.end())
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200221 {
Gunnar Millsaceb7fc2018-12-10 15:17:20 -0600222 const uint32_t *memorySize =
Ed Tanousabf2add2019-01-22 16:40:12 -0800223 std::get_if<uint32_t>(&memorySizeProperty->second);
Gunnar Millsaceb7fc2018-12-10 15:17:20 -0600224 if (memorySize == nullptr)
225 {
226 // Important property not in desired type
227 messages::internalError(aResp->res);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200228
Gunnar Millsaceb7fc2018-12-10 15:17:20 -0600229 return;
230 }
231 if (*memorySize == 0)
232 {
233 // Slot is not populated, set status end return
234 aResp->res.jsonValue["Status"]["State"] = "Absent";
235 aResp->res.jsonValue["Status"]["Health"] = "OK";
236 // HTTP Code will be set up automatically, just return
237 return;
238 }
239 aResp->res.jsonValue["CapacityMiB"] = (*memorySize >> 10);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200240 }
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200241 aResp->res.jsonValue["Status"]["State"] = "Enabled";
242 aResp->res.jsonValue["Status"]["Health"] = "OK";
243
244 for (const auto &property : properties)
245 {
246 if (property.first == "MemoryDataWidth")
247 {
248 aResp->res.jsonValue["DataWidthBits"] = property.second;
249 }
250 else if (property.first == "MemoryType")
251 {
252 const auto *value =
Ed Tanousabf2add2019-01-22 16:40:12 -0800253 std::get_if<std::string>(&property.second);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200254 if (value != nullptr)
255 {
256 aResp->res.jsonValue["MemoryDeviceType"] = *value;
257 if (boost::starts_with(*value, "DDR"))
258 {
259 aResp->res.jsonValue["MemoryType"] = "DRAM";
260 }
261 }
262 }
263 }
264 },
265 service, objPath, "org.freedesktop.DBus.Properties", "GetAll", "");
266}
267
Ed Tanous029573d2019-02-01 10:57:49 -0800268void getDimmData(std::shared_ptr<AsyncResp> aResp, const std::string &dimmId)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200269{
270 BMCWEB_LOG_DEBUG << "Get available system dimm resources.";
271 crow::connections::systemBus->async_method_call(
Ed Tanous029573d2019-02-01 10:57:49 -0800272 [dimmId, aResp{std::move(aResp)}](
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200273 const boost::system::error_code ec,
274 const boost::container::flat_map<
275 std::string, boost::container::flat_map<
276 std::string, std::vector<std::string>>>
277 &subtree) {
278 if (ec)
279 {
280 BMCWEB_LOG_DEBUG << "DBUS response error";
281 messages::internalError(aResp->res);
282
283 return;
284 }
285 for (const auto &object : subtree)
286 {
287 if (boost::ends_with(object.first, dimmId))
288 {
289 for (const auto &service : object.second)
290 {
Ed Tanous029573d2019-02-01 10:57:49 -0800291 getDimmDataByService(aResp, dimmId, service.first,
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200292 object.first);
293 return;
294 }
295 }
296 }
297 // Object not found
298 messages::resourceNotFound(aResp->res, "Memory", dimmId);
299 return;
300 },
301 "xyz.openbmc_project.ObjectMapper",
302 "/xyz/openbmc_project/object_mapper",
303 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
304 "/xyz/openbmc_project/inventory", int32_t(0),
305 std::array<const char *, 1>{"xyz.openbmc_project.Inventory.Item.Dimm"});
306};
307
308class ProcessorCollection : public Node
309{
310 public:
311 /*
312 * Default Constructor
313 */
314 ProcessorCollection(CrowApp &app) :
Ed Tanous029573d2019-02-01 10:57:49 -0800315 Node(app, "/redfish/v1/Systems/system/Processors/")
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200316 {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200317 entityPrivileges = {
318 {boost::beast::http::verb::get, {{"Login"}}},
319 {boost::beast::http::verb::head, {{"Login"}}},
320 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
321 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
322 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
323 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
324 }
325
326 private:
327 /**
328 * Functions triggers appropriate requests on DBus
329 */
330 void doGet(crow::Response &res, const crow::Request &req,
331 const std::vector<std::string> &params) override
332 {
Ed Tanous0f74e642018-11-12 15:17:05 -0800333 res.jsonValue["@odata.type"] =
334 "#ProcessorCollection.ProcessorCollection";
335 res.jsonValue["Name"] = "Processor Collection";
336 res.jsonValue["@odata.context"] =
337 "/redfish/v1/$metadata#ProcessorCollection.ProcessorCollection";
338
Ed Tanous029573d2019-02-01 10:57:49 -0800339 res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system/Processors/";
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200340 auto asyncResp = std::make_shared<AsyncResp>(res);
341
Ed Tanous029573d2019-02-01 10:57:49 -0800342 getResourceList(asyncResp, "Processors",
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200343 "xyz.openbmc_project.Inventory.Item.Cpu");
344 }
345};
346
347class Processor : public Node
348{
349 public:
350 /*
351 * Default Constructor
352 */
353 Processor(CrowApp &app) :
Ed Tanous029573d2019-02-01 10:57:49 -0800354 Node(app, "/redfish/v1/Systems/system/Processors/<str>/", std::string())
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200355 {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200356 entityPrivileges = {
357 {boost::beast::http::verb::get, {{"Login"}}},
358 {boost::beast::http::verb::head, {{"Login"}}},
359 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
360 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
361 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
362 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
363 }
364
365 private:
366 /**
367 * Functions triggers appropriate requests on DBus
368 */
369 void doGet(crow::Response &res, const crow::Request &req,
370 const std::vector<std::string> &params) override
371 {
372 // Check if there is required param, truly entering this shall be
373 // impossible
374 if (params.size() != 1)
375 {
376 messages::internalError(res);
377
378 res.end();
379 return;
380 }
Ed Tanous029573d2019-02-01 10:57:49 -0800381 const std::string &cpuId = params[0];
382 res.jsonValue["@odata.type"] = "#Processor.v1_3_1.Processor";
383 res.jsonValue["@odata.context"] =
384 "/redfish/v1/$metadata#Processor.Processor";
385 res.jsonValue["@odata.id"] =
386 "/redfish/v1/Systems/system/Processors/" + cpuId;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200387
Ed Tanous029573d2019-02-01 10:57:49 -0800388 auto asyncResp = std::make_shared<AsyncResp>(res);
389
390 getCpuData(asyncResp, cpuId);
391 }
392};
393
394class MemoryCollection : public Node
395{
396 public:
397 /*
398 * Default Constructor
399 */
400 MemoryCollection(CrowApp &app) :
401 Node(app, "/redfish/v1/Systems/system/Memory/")
402 {
403 entityPrivileges = {
404 {boost::beast::http::verb::get, {{"Login"}}},
405 {boost::beast::http::verb::head, {{"Login"}}},
406 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
407 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
408 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
409 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
410 }
411
412 private:
413 /**
414 * Functions triggers appropriate requests on DBus
415 */
416 void doGet(crow::Response &res, const crow::Request &req,
417 const std::vector<std::string> &params) override
418 {
Ed Tanous0f74e642018-11-12 15:17:05 -0800419 res.jsonValue["@odata.type"] = "#MemoryCollection.MemoryCollection";
420 res.jsonValue["Name"] = "Memory Module Collection";
421 res.jsonValue["@odata.context"] =
422 "/redfish/v1/$metadata#MemoryCollection.MemoryCollection";
Ed Tanous029573d2019-02-01 10:57:49 -0800423 res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system/Memory/";
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200424 auto asyncResp = std::make_shared<AsyncResp>(res);
425
Ed Tanous029573d2019-02-01 10:57:49 -0800426 getResourceList(asyncResp, "Memory",
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200427 "xyz.openbmc_project.Inventory.Item.Dimm");
428 }
429};
430
431class Memory : public Node
432{
433 public:
434 /*
435 * Default Constructor
436 */
437 Memory(CrowApp &app) :
Ed Tanous029573d2019-02-01 10:57:49 -0800438 Node(app, "/redfish/v1/Systems/system/Memory/<str>/", std::string())
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200439 {
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200440 entityPrivileges = {
441 {boost::beast::http::verb::get, {{"Login"}}},
442 {boost::beast::http::verb::head, {{"Login"}}},
443 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
444 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
445 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
446 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
447 }
448
449 private:
450 /**
451 * Functions triggers appropriate requests on DBus
452 */
453 void doGet(crow::Response &res, const crow::Request &req,
454 const std::vector<std::string> &params) override
455 {
456 // Check if there is required param, truly entering this shall be
457 // impossible
Ed Tanous029573d2019-02-01 10:57:49 -0800458 if (params.size() != 1)
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200459 {
460 messages::internalError(res);
461 res.end();
462 return;
463 }
Ed Tanous029573d2019-02-01 10:57:49 -0800464 const std::string &dimmId = params[0];
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200465
Rapkiewicz, Pawelbb3d9942018-11-22 10:59:11 +0100466 res.jsonValue["@odata.type"] = "#Memory.v1_6_0.Memory";
Ed Tanous0f74e642018-11-12 15:17:05 -0800467 res.jsonValue["@odata.context"] = "/redfish/v1/$metadata#Memory.Memory";
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200468 res.jsonValue["@odata.id"] =
Ed Tanous029573d2019-02-01 10:57:49 -0800469 "/redfish/v1/Systems/system/Memory/" + dimmId;
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200470 auto asyncResp = std::make_shared<AsyncResp>(res);
471
Ed Tanous029573d2019-02-01 10:57:49 -0800472 getDimmData(asyncResp, dimmId);
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +0200473 }
474};
475
476} // namespace redfish