blob: 22688973209a750b3a431eb463ef3f1f62f3965b [file] [log] [blame]
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +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
Ed Tanous1abe55e2018-09-05 08:30:59 -070018#include "boost/container/flat_map.hpp"
19#include "node.hpp"
20
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020021#include <utils/json_utils.hpp>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020022
Ed Tanous1abe55e2018-09-05 08:30:59 -070023namespace redfish
24{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020025
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020026/**
Ed Tanous6c34de42018-08-29 13:37:36 -070027 * @brief Retrieves computer system properties over dbus
28 *
29 * @param[in] aResp Shared pointer for completing asynchronous calls
30 * @param[in] name Computer system name from request
31 *
32 * @return None.
33 */
34void getComputerSystem(std::shared_ptr<AsyncResp> aResp,
35 const std::string &name)
36{
Ed Tanous6c34de42018-08-29 13:37:36 -070037 BMCWEB_LOG_DEBUG << "Get available system components.";
38 crow::connections::systemBus->async_method_call(
39 [name, aResp{std::move(aResp)}](
40 const boost::system::error_code ec,
41 const std::vector<std::pair<
42 std::string,
43 std::vector<std::pair<std::string, std::vector<std::string>>>>>
44 &subtree) {
45 if (ec)
46 {
47 BMCWEB_LOG_DEBUG << "DBUS response error";
48 aResp->res.result(
49 boost::beast::http::status::internal_server_error);
50 return;
51 }
52 bool foundName = false;
53 // Iterate over all retrieved ObjectPaths.
54 for (const std::pair<std::string,
55 std::vector<std::pair<
56 std::string, std::vector<std::string>>>>
57 &object : subtree)
58 {
59 const std::string &path = object.first;
60 BMCWEB_LOG_DEBUG << "Got path: " << path;
61 const std::vector<
62 std::pair<std::string, std::vector<std::string>>>
63 &connectionNames = object.second;
64 if (connectionNames.size() < 1)
65 {
66 continue;
67 }
68 // Check if computer system exist
69 if (boost::ends_with(path, name))
70 {
71 foundName = true;
72 BMCWEB_LOG_DEBUG << "Found name: " << name;
73 const std::string connectionName = connectionNames[0].first;
74 crow::connections::systemBus->async_method_call(
75 [aResp, name(std::string(name))](
76 const boost::system::error_code ec,
77 const std::vector<std::pair<
78 std::string, VariantType>> &propertiesList) {
79 if (ec)
80 {
81 BMCWEB_LOG_ERROR << "DBUS response error: "
82 << ec;
83 aResp->res.result(boost::beast::http::status::
84 internal_server_error);
85 return;
86 }
87 BMCWEB_LOG_DEBUG << "Got " << propertiesList.size()
88 << "properties for system";
89 for (const std::pair<std::string, VariantType>
90 &property : propertiesList)
91 {
92 const std::string *value =
93 mapbox::getPtr<const std::string>(
94 property.second);
95 if (value != nullptr)
96 {
97 aResp->res.jsonValue[property.first] =
98 *value;
99 }
100 }
101 aResp->res.jsonValue["Name"] = name;
102 aResp->res.jsonValue["Id"] =
103 aResp->res.jsonValue["SerialNumber"];
104 },
105 connectionName, path, "org.freedesktop.DBus.Properties",
106 "GetAll",
107 "xyz.openbmc_project.Inventory.Decorator.Asset");
108 }
109 else
110 {
111 // This is not system, so check if it's cpu, dimm, UUID or
112 // BiosVer
Ed Tanous04a258f2018-10-15 08:00:41 -0700113 for (const auto &connection : connectionNames)
Ed Tanous6c34de42018-08-29 13:37:36 -0700114 {
Ed Tanous04a258f2018-10-15 08:00:41 -0700115 for (const auto &interfaceName : connection.second)
Ed Tanous6c34de42018-08-29 13:37:36 -0700116 {
Ed Tanous04a258f2018-10-15 08:00:41 -0700117 if (interfaceName ==
118 "xyz.openbmc_project.Inventory.Item.Dimm")
Ed Tanous6c34de42018-08-29 13:37:36 -0700119 {
120 BMCWEB_LOG_DEBUG
Ed Tanous04a258f2018-10-15 08:00:41 -0700121 << "Found Dimm, now get its properties.";
Ed Tanous6c34de42018-08-29 13:37:36 -0700122 crow::connections::systemBus->async_method_call(
Ed Tanous66173382018-08-15 18:20:59 -0700123 [aResp](
Ed Tanous6c34de42018-08-29 13:37:36 -0700124 const boost::system::error_code ec,
125 const std::vector<
126 std::pair<std::string, VariantType>>
127 &properties) {
128 if (ec)
129 {
130 BMCWEB_LOG_ERROR
131 << "DBUS response error " << ec;
132 aResp->res.result(
133 boost::beast::http::status::
134 internal_server_error);
135 return;
136 }
137 BMCWEB_LOG_DEBUG << "Got "
138 << properties.size()
139 << "Dimm properties.";
Ed Tanous04a258f2018-10-15 08:00:41 -0700140 for (const std::pair<std::string,
141 VariantType>
142 &property : properties)
Ed Tanous6c34de42018-08-29 13:37:36 -0700143 {
Ed Tanous04a258f2018-10-15 08:00:41 -0700144 if (property.first ==
145 "MemorySizeInKb")
Ed Tanous6c34de42018-08-29 13:37:36 -0700146 {
Ed Tanous04a258f2018-10-15 08:00:41 -0700147 const uint64_t *value =
Ed Tanous6c34de42018-08-29 13:37:36 -0700148 mapbox::getPtr<
Ed Tanous04a258f2018-10-15 08:00:41 -0700149 const uint64_t>(
150 property.second);
151 if (value != nullptr)
Ed Tanous6c34de42018-08-29 13:37:36 -0700152 {
Ed Tanous6c34de42018-08-29 13:37:36 -0700153 aResp->res.jsonValue
154 ["TotalSystemMemoryGi"
155 "B"] +=
Ed Tanous04a258f2018-10-15 08:00:41 -0700156 *value / (1024 * 1024);
Ed Tanous6c34de42018-08-29 13:37:36 -0700157 aResp->res.jsonValue
158 ["MemorySummary"]
159 ["Status"]["State"] =
160 "Enabled";
161 }
162 }
163 }
164 },
Ed Tanous04a258f2018-10-15 08:00:41 -0700165 connection.first, path,
Ed Tanous6c34de42018-08-29 13:37:36 -0700166 "org.freedesktop.DBus.Properties", "GetAll",
167 "xyz.openbmc_project.Inventory.Item.Dimm");
168 }
Ed Tanous04a258f2018-10-15 08:00:41 -0700169 else if (interfaceName ==
170 "xyz.openbmc_project.Inventory.Item.Cpu")
Ed Tanous6c34de42018-08-29 13:37:36 -0700171 {
172 BMCWEB_LOG_DEBUG
Ed Tanous04a258f2018-10-15 08:00:41 -0700173 << "Found Cpu, now get its properties.";
Ed Tanous6c34de42018-08-29 13:37:36 -0700174 crow::connections::systemBus->async_method_call(
Ed Tanous66173382018-08-15 18:20:59 -0700175 [aResp](
Ed Tanous6c34de42018-08-29 13:37:36 -0700176 const boost::system::error_code ec,
177 const std::vector<
178 std::pair<std::string, VariantType>>
179 &properties) {
180 if (ec)
181 {
182 BMCWEB_LOG_ERROR
183 << "DBUS response error " << ec;
184 aResp->res.result(
185 boost::beast::http::status::
186 internal_server_error);
187 return;
188 }
189 BMCWEB_LOG_DEBUG << "Got "
190 << properties.size()
191 << "Cpu properties.";
Ed Tanous04a258f2018-10-15 08:00:41 -0700192 for (const auto &property : properties)
Ed Tanous6c34de42018-08-29 13:37:36 -0700193 {
Ed Tanous04a258f2018-10-15 08:00:41 -0700194 if (property.first ==
195 "ProcessorFamily")
Ed Tanous6c34de42018-08-29 13:37:36 -0700196 {
197 const std::string *value =
198 mapbox::getPtr<
199 const std::string>(
Ed Tanous04a258f2018-10-15 08:00:41 -0700200 property.second);
Ed Tanous6c34de42018-08-29 13:37:36 -0700201 if (value != nullptr)
202 {
Ed Tanous04a258f2018-10-15 08:00:41 -0700203 nlohmann::json
204 &procSummary =
205 aResp->res.jsonValue
Ed Tanous6c34de42018-08-29 13:37:36 -0700206 ["ProcessorSumm"
Ed Tanous04a258f2018-10-15 08:00:41 -0700207 "ary"];
208 nlohmann::json &procCount =
209 procSummary["Count"];
210
211 procCount =
212 procCount.get<int>() +
Ed Tanous6c34de42018-08-29 13:37:36 -0700213 1;
Ed Tanous04a258f2018-10-15 08:00:41 -0700214 procSummary["Status"]
215 ["State"] =
216 "Enabled";
217 procSummary["Model"] =
218 *value;
Ed Tanous6c34de42018-08-29 13:37:36 -0700219 }
220 }
221 }
222 },
Ed Tanous04a258f2018-10-15 08:00:41 -0700223 connection.first, path,
Ed Tanous6c34de42018-08-29 13:37:36 -0700224 "org.freedesktop.DBus.Properties", "GetAll",
225 "xyz.openbmc_project.Inventory.Item.Cpu");
226 }
Ed Tanous04a258f2018-10-15 08:00:41 -0700227 else if (interfaceName ==
228 "xyz.openbmc_project.Common.UUID")
Ed Tanous6c34de42018-08-29 13:37:36 -0700229 {
230 BMCWEB_LOG_DEBUG
Ed Tanous04a258f2018-10-15 08:00:41 -0700231 << "Found UUID, now get its properties.";
Ed Tanous6c34de42018-08-29 13:37:36 -0700232 crow::connections::systemBus->async_method_call(
233 [aResp](
234 const boost::system::error_code ec,
235 const std::vector<
236 std::pair<std::string, VariantType>>
237 &properties) {
238 if (ec)
239 {
240 BMCWEB_LOG_DEBUG
241 << "DBUS response error " << ec;
242 aResp->res.result(
243 boost::beast::http::status::
244 internal_server_error);
245 return;
246 }
247 BMCWEB_LOG_DEBUG << "Got "
248 << properties.size()
249 << "UUID properties.";
250 for (const std::pair<std::string,
Ed Tanous04a258f2018-10-15 08:00:41 -0700251 VariantType>
252 &property : properties)
Ed Tanous6c34de42018-08-29 13:37:36 -0700253 {
Ed Tanous04a258f2018-10-15 08:00:41 -0700254 if (property.first == "BIOSVer")
Ed Tanous6c34de42018-08-29 13:37:36 -0700255 {
256 const std::string *value =
257 mapbox::getPtr<
258 const std::string>(
Ed Tanous04a258f2018-10-15 08:00:41 -0700259 property.second);
Ed Tanous6c34de42018-08-29 13:37:36 -0700260 if (value != nullptr)
261 {
262 aResp->res.jsonValue
263 ["BiosVersion"] =
264 *value;
265 }
266 }
Ed Tanous04a258f2018-10-15 08:00:41 -0700267 if (property.first == "UUID")
Ed Tanous6c34de42018-08-29 13:37:36 -0700268 {
269 const std::string *value =
270 mapbox::getPtr<
271 const std::string>(
Ed Tanous04a258f2018-10-15 08:00:41 -0700272 property.second);
273
Ed Tanous6c34de42018-08-29 13:37:36 -0700274 if (value != nullptr)
275 {
Ed Tanous04a258f2018-10-15 08:00:41 -0700276 std::string valueStr =
277 *value;
278 if (valueStr.size() == 32)
Ed Tanous6c34de42018-08-29 13:37:36 -0700279 {
Ed Tanous04a258f2018-10-15 08:00:41 -0700280 valueStr.insert(8, 1,
281 '-');
282 valueStr.insert(13, 1,
283 '-');
284 valueStr.insert(18, 1,
285 '-');
286 valueStr.insert(23, 1,
287 '-');
Ed Tanous6c34de42018-08-29 13:37:36 -0700288 }
Ed Tanous04a258f2018-10-15 08:00:41 -0700289 BMCWEB_LOG_DEBUG
290 << "UUID = "
291 << valueStr;
292 aResp->res
293 .jsonValue["UUID"] =
294 valueStr;
Ed Tanous6c34de42018-08-29 13:37:36 -0700295 }
296 }
297 }
298 },
Ed Tanous04a258f2018-10-15 08:00:41 -0700299 connection.first, path,
Ed Tanous6c34de42018-08-29 13:37:36 -0700300 "org.freedesktop.DBus.Properties", "GetAll",
301 "xyz.openbmc_project.Common.UUID");
302 }
303 }
304 }
305 }
306 }
307 if (foundName == false)
308 {
309 aResp->res.result(
310 boost::beast::http::status::internal_server_error);
311 }
312 },
313 "xyz.openbmc_project.ObjectMapper",
314 "/xyz/openbmc_project/object_mapper",
315 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous66173382018-08-15 18:20:59 -0700316 "/xyz/openbmc_project/inventory", int32_t(0),
317 std::array<const char *, 5>{
318 "xyz.openbmc_project.Inventory.Decorator.Asset",
319 "xyz.openbmc_project.Inventory.Item.Cpu",
320 "xyz.openbmc_project.Inventory.Item.Dimm",
321 "xyz.openbmc_project.Inventory.Item.System",
322 "xyz.openbmc_project.Common.UUID",
323 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700324}
325
326/**
327 * @brief Retrieves identify led group properties over dbus
328 *
329 * @param[in] aResp Shared pointer for completing asynchronous calls.
330 * @param[in] callback Callback for process retrieved data.
331 *
332 * @return None.
333 */
334template <typename CallbackFunc>
335void getLedGroupIdentify(std::shared_ptr<AsyncResp> aResp,
336 CallbackFunc &&callback)
337{
338 BMCWEB_LOG_DEBUG << "Get led groups";
339 crow::connections::systemBus->async_method_call(
340 [aResp{std::move(aResp)},
Ed Tanous66173382018-08-15 18:20:59 -0700341 callback{std::move(callback)}](const boost::system::error_code &ec,
342 const ManagedObjectsType &resp) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700343 if (ec)
344 {
345 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
346 aResp->res.result(
347 boost::beast::http::status::internal_server_error);
348 return;
349 }
350 BMCWEB_LOG_DEBUG << "Got " << resp.size() << "led group objects.";
351 for (const auto &objPath : resp)
352 {
353 const std::string &path = objPath.first;
354 if (path.rfind("enclosure_identify") != std::string::npos)
355 {
356 for (const auto &interface : objPath.second)
357 {
358 if (interface.first == "xyz.openbmc_project.Led.Group")
359 {
360 for (const auto &property : interface.second)
361 {
362 if (property.first == "Asserted")
363 {
364 const bool *asserted =
365 mapbox::getPtr<const bool>(
366 property.second);
367 if (nullptr != asserted)
368 {
369 callback(*asserted, aResp);
370 }
371 else
372 {
373 callback(false, aResp);
374 }
375 }
376 }
377 }
378 }
379 }
380 }
381 },
382 "xyz.openbmc_project.LED.GroupManager",
383 "/xyz/openbmc_project/led/groups", "org.freedesktop.DBus.ObjectManager",
384 "GetManagedObjects");
385}
386
387template <typename CallbackFunc>
388void getLedIdentify(std::shared_ptr<AsyncResp> aResp, CallbackFunc &&callback)
389{
390 BMCWEB_LOG_DEBUG << "Get identify led properties";
391 crow::connections::systemBus->async_method_call(
Ed Tanous66173382018-08-15 18:20:59 -0700392 [aResp,
393 callback{std::move(callback)}](const boost::system::error_code ec,
394 const PropertiesType &properties) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700395 if (ec)
396 {
397 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
398 aResp->res.result(
399 boost::beast::http::status::internal_server_error);
400 return;
401 }
402 BMCWEB_LOG_DEBUG << "Got " << properties.size()
403 << "led properties.";
404 std::string output;
405 for (const auto &property : properties)
406 {
407 if (property.first == "State")
408 {
409 const std::string *s =
410 mapbox::getPtr<std::string>(property.second);
411 if (nullptr != s)
412 {
413 BMCWEB_LOG_DEBUG << "Identify Led State: " << *s;
414 const auto pos = s->rfind('.');
415 if (pos != std::string::npos)
416 {
417 auto led = s->substr(pos + 1);
418 for (const std::pair<const char *, const char *>
419 &p :
420 std::array<
421 std::pair<const char *, const char *>, 3>{
422 {{"On", "Lit"},
423 {"Blink", "Blinking"},
424 {"Off", "Off"}}})
425 {
426 if (led == p.first)
427 {
428 output = p.second;
429 }
430 }
431 }
432 }
433 }
434 }
435 callback(output, aResp);
436 },
437 "xyz.openbmc_project.LED.Controller.identify",
438 "/xyz/openbmc_project/led/physical/identify",
439 "org.freedesktop.DBus.Properties", "GetAll",
440 "xyz.openbmc_project.Led.Physical");
441}
442
443/**
444 * @brief Retrieves host state properties over dbus
445 *
446 * @param[in] aResp Shared pointer for completing asynchronous calls.
447 *
448 * @return None.
449 */
450void getHostState(std::shared_ptr<AsyncResp> aResp)
451{
452 BMCWEB_LOG_DEBUG << "Get host information.";
453 crow::connections::systemBus->async_method_call(
Ed Tanous66173382018-08-15 18:20:59 -0700454 [aResp{std::move(aResp)}](
455 const boost::system::error_code ec,
456 const sdbusplus::message::variant<std::string> &hostState) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700457 if (ec)
458 {
459 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
460 aResp->res.result(
461 boost::beast::http::status::internal_server_error);
462 return;
463 }
Ed Tanous66173382018-08-15 18:20:59 -0700464
465 const std::string *s = mapbox::getPtr<const std::string>(hostState);
466 BMCWEB_LOG_DEBUG << "Host state: " << *s;
467 if (s != nullptr)
Ed Tanous6c34de42018-08-29 13:37:36 -0700468 {
Ed Tanous66173382018-08-15 18:20:59 -0700469 // Verify Host State
470 if (*s == "xyz.openbmc_project.State.Host.Running")
Ed Tanous6c34de42018-08-29 13:37:36 -0700471 {
Ed Tanous66173382018-08-15 18:20:59 -0700472 aResp->res.jsonValue["PowerState"] = "On";
473 aResp->res.jsonValue["Status"]["State"] = "Enabled";
474 }
475 else
476 {
477 aResp->res.jsonValue["PowerState"] = "Off";
478 aResp->res.jsonValue["Status"]["State"] = "Disabled";
Ed Tanous6c34de42018-08-29 13:37:36 -0700479 }
480 }
481 },
482 "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
Ed Tanous66173382018-08-15 18:20:59 -0700483 "org.freedesktop.DBus.Properties", "Get",
484 "xyz.openbmc_project.State.Host", "CurrentHostState");
Ed Tanous6c34de42018-08-29 13:37:36 -0700485}
486
487/**
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200488 * SystemsCollection derived class for delivering ComputerSystems Collection
489 * Schema
490 */
Ed Tanous1abe55e2018-09-05 08:30:59 -0700491class SystemsCollection : public Node
492{
493 public:
494 SystemsCollection(CrowApp &app) : Node(app, "/redfish/v1/Systems/")
495 {
496 Node::json["@odata.type"] =
497 "#ComputerSystemCollection.ComputerSystemCollection";
498 Node::json["@odata.id"] = "/redfish/v1/Systems";
499 Node::json["@odata.context"] =
500 "/redfish/v1/"
501 "$metadata#ComputerSystemCollection.ComputerSystemCollection";
502 Node::json["Name"] = "Computer System Collection";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200503
Ed Tanous1abe55e2018-09-05 08:30:59 -0700504 entityPrivileges = {
505 {boost::beast::http::verb::get, {{"Login"}}},
506 {boost::beast::http::verb::head, {{"Login"}}},
507 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
508 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
509 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
510 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
511 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200512
Ed Tanous1abe55e2018-09-05 08:30:59 -0700513 private:
Ed Tanous1abe55e2018-09-05 08:30:59 -0700514 void doGet(crow::Response &res, const crow::Request &req,
515 const std::vector<std::string> &params) override
516 {
Ed Tanous66173382018-08-15 18:20:59 -0700517 BMCWEB_LOG_DEBUG << "Get list of available boards.";
518 std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
519 res.jsonValue = Node::json;
520 crow::connections::systemBus->async_method_call(
521 [asyncResp](const boost::system::error_code ec,
522 const std::vector<std::string> &resp) {
523 if (ec)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700524 {
Ed Tanous66173382018-08-15 18:20:59 -0700525 asyncResp->res.result(
526 boost::beast::http::status::internal_server_error);
527 return;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700528 }
Ed Tanous66173382018-08-15 18:20:59 -0700529 BMCWEB_LOG_DEBUG << "Got " << resp.size() << " boards.";
530
531 // ... prepare json array with appropriate @odata.id links
532 nlohmann::json &boardArray =
533 asyncResp->res.jsonValue["Members"];
534 boardArray = nlohmann::json::array();
535
536 // Iterate over all retrieved ObjectPaths.
537 for (const std::string &objpath : resp)
538 {
539 std::size_t lastPos = objpath.rfind("/");
540 if (lastPos != std::string::npos)
541 {
542 boardArray.push_back(
543 {{"@odata.id", "/redfish/v1/Systems/" +
544 objpath.substr(lastPos + 1)}});
545 }
546 }
547
548 asyncResp->res.jsonValue["Members@odata.count"] =
549 boardArray.size();
550 },
551 "xyz.openbmc_project.ObjectMapper",
552 "/xyz/openbmc_project/object_mapper",
553 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
554 "/xyz/openbmc_project/inventory", int32_t(0),
555 std::array<const char *, 1>{
556 "xyz.openbmc_project.Inventory.Item.Board"});
Ed Tanous1abe55e2018-09-05 08:30:59 -0700557 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200558};
559
560/**
Ed Tanouscc340dd2018-08-29 13:43:38 -0700561 * SystemActionsReset class supports handle POST method for Reset action.
562 * The class retrieves and sends data directly to D-Bus.
563 */
564class SystemActionsReset : public Node
565{
566 public:
567 SystemActionsReset(CrowApp &app) :
568 Node(app, "/redfish/v1/Systems/<str>/Actions/ComputerSystem.Reset/",
569 std::string())
570 {
571 entityPrivileges = {
572 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
573 }
574
575 private:
576 /**
577 * Function handles POST method request.
578 * Analyzes POST body message before sends Reset request data to D-Bus.
579 */
580 void doPost(crow::Response &res, const crow::Request &req,
581 const std::vector<std::string> &params) override
582 {
583 // Parse JSON request body.
584 nlohmann::json post;
585 if (!json_util::processJsonFromRequest(res, req, post))
586 {
587 return;
588 }
589
590 auto asyncResp = std::make_shared<AsyncResp>(res);
591
592 for (const auto &item : post.items())
593 {
594 if (item.key() == "ResetType")
595 {
596 const std::string *reqResetType =
597 item.value().get_ptr<const std::string *>();
598 if (reqResetType == nullptr)
599 {
600 res.result(boost::beast::http::status::bad_request);
601 messages::addMessageToErrorJson(
602 asyncResp->res.jsonValue,
603 messages::actionParameterValueFormatError(
604 item.value().dump(), "ResetType",
605 "ComputerSystem.Reset"));
606 res.end();
607 return;
608 }
609
610 if (*reqResetType == "ForceOff")
611 {
612 // Force off acts on the chassis
613 crow::connections::systemBus->async_method_call(
614 [asyncResp](const boost::system::error_code ec) {
615 if (ec)
616 {
617 BMCWEB_LOG_ERROR << "D-Bus responses error: "
618 << ec;
619 asyncResp->res.result(
620 boost::beast::http::status::
621 internal_server_error);
622 return;
623 }
624 // TODO Consider support polling mechanism to verify
625 // status of host and chassis after execute the
626 // requested action.
627 BMCWEB_LOG_DEBUG << "Response with no content";
628 asyncResp->res.result(
629 boost::beast::http::status::no_content);
630 },
631 "xyz.openbmc_project.State.Chassis",
632 "/xyz/openbmc_project/state/chassis0",
633 "org.freedesktop.DBus.Properties", "Set",
634 "RequestedPowerTransition",
635 "xyz.openbmc_project.State.Chassis",
636 sdbusplus::message::variant<std::string>{
637 "xyz.openbmc_project.State.Chassis.Transition."
638 "Off"});
639 return;
640 }
641 // all other actions operate on the host
642 std::string command;
643 // Execute Reset Action regarding to each reset type.
644 if (*reqResetType == "On")
645 {
646 command = "xyz.openbmc_project.State.Host.Transition.On";
647 }
648 else if (*reqResetType == "GracefulShutdown")
649 {
650 command = "xyz.openbmc_project.State.Host.Transition.Off";
651 }
652 else if (*reqResetType == "GracefulRestart")
653 {
654 command =
655 "xyz.openbmc_project.State.Host.Transition.Reboot";
656 }
657 else
658 {
659 res.result(boost::beast::http::status::bad_request);
660 messages::addMessageToErrorJson(
661 asyncResp->res.jsonValue,
662 messages::actionParameterUnknown("Reset",
663 *reqResetType));
664 res.end();
665 return;
666 }
667
668 crow::connections::systemBus->async_method_call(
669 [asyncResp](const boost::system::error_code ec) {
670 if (ec)
671 {
672 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
673 asyncResp->res.result(boost::beast::http::status::
674 internal_server_error);
675 return;
676 }
677 // TODO Consider support polling mechanism to verify
678 // status of host and chassis after execute the
679 // requested action.
680 BMCWEB_LOG_DEBUG << "Response with no content";
681 asyncResp->res.result(
682 boost::beast::http::status::no_content);
683 },
684 "xyz.openbmc_project.State.Host",
685 "/xyz/openbmc_project/state/host0",
686 "org.freedesktop.DBus.Properties", "Set",
687 "RequestedHostTransition", "xyz.openbmc_project.State.Host",
688 sdbusplus::message::variant<std::string>{command});
689 }
690 else
691 {
692 messages::addMessageToErrorJson(
693 asyncResp->res.jsonValue,
694 messages::actionParameterUnknown("ComputerSystem.Reset",
695 item.key()));
696 }
697 }
698 }
699};
700
701/**
Ed Tanous66173382018-08-15 18:20:59 -0700702 * Systems derived class for delivering Computer Systems Schema.
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200703 */
Ed Tanous1abe55e2018-09-05 08:30:59 -0700704class Systems : public Node
705{
706 public:
707 /*
708 * Default Constructor
709 */
710 Systems(CrowApp &app) :
711 Node(app, "/redfish/v1/Systems/<str>/", std::string())
712 {
713 Node::json["@odata.type"] = "#ComputerSystem.v1_3_0.ComputerSystem";
714 Node::json["@odata.context"] =
715 "/redfish/v1/$metadata#ComputerSystem.ComputerSystem";
716 Node::json["SystemType"] = "Physical";
717 Node::json["Description"] = "Computer System";
718 Node::json["Boot"]["BootSourceOverrideEnabled"] =
719 "Disabled"; // TODO(Dawid), get real boot data
720 Node::json["Boot"]["BootSourceOverrideTarget"] =
721 "None"; // TODO(Dawid), get real boot data
722 Node::json["Boot"]["BootSourceOverrideMode"] =
723 "Legacy"; // TODO(Dawid), get real boot data
724 Node::json["Boot"]["BootSourceOverrideTarget@Redfish.AllowableValues"] =
725 {"None", "Pxe", "Hdd", "Cd",
726 "BiosSetup", "UefiShell", "Usb"}; // TODO(Dawid), get real boot
727 // data
Ed Tanous04a258f2018-10-15 08:00:41 -0700728 Node::json["ProcessorSummary"]["Count"] = 0;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700729 Node::json["ProcessorSummary"]["Status"]["State"] = "Disabled";
730 Node::json["MemorySummary"]["TotalSystemMemoryGiB"] = int(0);
731 Node::json["MemorySummary"]["Status"]["State"] = "Disabled";
Ed Tanous1abe55e2018-09-05 08:30:59 -0700732 entityPrivileges = {
733 {boost::beast::http::verb::get, {{"Login"}}},
734 {boost::beast::http::verb::head, {{"Login"}}},
735 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
736 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
737 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
738 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200739 }
740
Ed Tanous1abe55e2018-09-05 08:30:59 -0700741 private:
Ed Tanous1abe55e2018-09-05 08:30:59 -0700742 /**
743 * Functions triggers appropriate requests on DBus
744 */
745 void doGet(crow::Response &res, const crow::Request &req,
746 const std::vector<std::string> &params) override
747 {
748 // Check if there is required param, truly entering this shall be
749 // impossible
750 if (params.size() != 1)
751 {
752 res.result(boost::beast::http::status::internal_server_error);
753 res.end();
754 return;
755 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200756
Ed Tanous1abe55e2018-09-05 08:30:59 -0700757 const std::string &name = params[0];
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200758
Ed Tanous04a258f2018-10-15 08:00:41 -0700759 res.jsonValue = Node::json;
760 res.jsonValue["@odata.id"] = "/redfish/v1/Systems/" + name;
761
Ed Tanouscc340dd2018-08-29 13:43:38 -0700762 // TODO Need to support ForceRestart.
763 res.jsonValue["Actions"]["#ComputerSystem.Reset"] = {
764 {"target",
765 "/redfish/v1/Systems/" + name + "/Actions/ComputerSystem.Reset"},
766 {"ResetType@Redfish.AllowableValues",
767 {"On", "ForceOff", "GracefulRestart", "GracefulShutdown"}}};
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200768
Ed Tanousa0803ef2018-08-29 13:29:23 -0700769 auto asyncResp = std::make_shared<AsyncResp>(res);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700770
Ed Tanous6c34de42018-08-29 13:37:36 -0700771 getLedGroupIdentify(
Ed Tanousa0803ef2018-08-29 13:29:23 -0700772 asyncResp,
773 [&](const bool &asserted, const std::shared_ptr<AsyncResp> &aResp) {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700774 if (asserted)
775 {
776 // If led group is asserted, then another call is needed to
777 // get led status
Ed Tanous6c34de42018-08-29 13:37:36 -0700778 getLedIdentify(
Ed Tanousa0803ef2018-08-29 13:29:23 -0700779 aResp, [](const std::string &ledStatus,
780 const std::shared_ptr<AsyncResp> &aResp) {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700781 if (!ledStatus.empty())
782 {
783 aResp->res.jsonValue["IndicatorLED"] =
784 ledStatus;
785 }
786 });
787 }
788 else
789 {
790 aResp->res.jsonValue["IndicatorLED"] = "Off";
791 }
792 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700793 getComputerSystem(asyncResp, name);
794 getHostState(asyncResp);
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200795 }
796
Ed Tanous1abe55e2018-09-05 08:30:59 -0700797 void doPatch(crow::Response &res, const crow::Request &req,
798 const std::vector<std::string> &params) override
799 {
800 // Check if there is required param, truly entering this shall be
801 // impossible
Ed Tanous66173382018-08-15 18:20:59 -0700802 auto asyncResp = std::make_shared<AsyncResp>(res);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700803 if (params.size() != 1)
804 {
805 res.result(boost::beast::http::status::internal_server_error);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700806 return;
807 }
808 // Parse JSON request body
809 nlohmann::json patch;
810 if (!json_util::processJsonFromRequest(res, req, patch))
811 {
812 return;
813 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700814
Ed Tanous66173382018-08-15 18:20:59 -0700815 const std::string &name = params[0];
816
Ed Tanous1abe55e2018-09-05 08:30:59 -0700817 res.jsonValue = Node::json;
818 res.jsonValue["@odata.id"] = "/redfish/v1/Systems/" + name;
819
Ed Tanous66173382018-08-15 18:20:59 -0700820 for (const auto &item : patch.items())
821 {
822 if (item.key() == "IndicatorLed")
823 {
824 const std::string *reqLedState =
825 item.value().get_ptr<const std::string *>();
826 if (reqLedState == nullptr)
827 {
828 messages::addMessageToErrorJson(
829 asyncResp->res.jsonValue,
830 messages::propertyValueFormatError(item.value().dump(),
831 item.key()));
832 return;
833 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700834
Ed Tanous66173382018-08-15 18:20:59 -0700835 // Verify key value
836 std::string dbusLedState;
837 if (*reqLedState == "On")
838 {
839 dbusLedState =
840 "xyz.openbmc_project.Led.Physical.Action.Lit";
841 }
842 else if (*reqLedState == "Blink")
843 {
844 dbusLedState =
845 "xyz.openbmc_project.Led.Physical.Action.Blinking";
846 }
847 else if (*reqLedState == "Off")
848 {
849 dbusLedState =
850 "xyz.openbmc_project.Led.Physical.Action.Off";
851 }
852 else
853 {
854 messages::addMessageToJsonRoot(
855 res.jsonValue, messages::propertyValueNotInList(
856 *reqLedState, "IndicatorLED"));
857 return;
858 }
859
860 getHostState(asyncResp);
861 getComputerSystem(asyncResp, name);
862
863 // Update led group
864 BMCWEB_LOG_DEBUG << "Update led group.";
865 crow::connections::systemBus->async_method_call(
866 [asyncResp{std::move(asyncResp)}](
867 const boost::system::error_code ec) {
868 if (ec)
869 {
870 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
871 asyncResp->res.result(boost::beast::http::status::
872 internal_server_error);
873 return;
874 }
875 BMCWEB_LOG_DEBUG << "Led group update done.";
876 },
877 "xyz.openbmc_project.LED.GroupManager",
878 "/xyz/openbmc_project/led/groups/enclosure_identify",
879 "org.freedesktop.DBus.Properties", "Set",
880 "xyz.openbmc_project.Led.Group", "Asserted",
881 sdbusplus::message::variant<bool>(
882 (dbusLedState ==
883 "xyz.openbmc_project.Led.Physical.Action.Off"
884 ? false
885 : true)));
886 // Update identify led status
887 BMCWEB_LOG_DEBUG << "Update led SoftwareInventoryCollection.";
888 crow::connections::systemBus->async_method_call(
889 [asyncResp{std::move(asyncResp)},
890 reqLedState{std::move(*reqLedState)}](
891 const boost::system::error_code ec) {
892 if (ec)
893 {
894 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
895 asyncResp->res.result(boost::beast::http::status::
896 internal_server_error);
897 return;
898 }
899 BMCWEB_LOG_DEBUG << "Led state update done.";
900 asyncResp->res.jsonValue["IndicatorLED"] =
901 std::move(reqLedState);
902 },
903 "xyz.openbmc_project.LED.Controller.identify",
904 "/xyz/openbmc_project/led/physical/identify",
905 "org.freedesktop.DBus.Properties", "Set",
906 "xyz.openbmc_project.Led.Physical", "State",
907 sdbusplus::message::variant<std::string>(dbusLedState));
908 }
909 else
910 {
911 messages::addMessageToErrorJson(
912 asyncResp->res.jsonValue,
913 messages::propertyNotWritable(item.key()));
914 return;
915 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700916 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200917 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200918};
Ed Tanous1abe55e2018-09-05 08:30:59 -0700919} // namespace redfish