blob: 13ca90589902394b767ccc036346c07a39250aff [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
113 for (auto const &s : connectionNames)
114 {
115 for (auto const &i : s.second)
116 {
117 if (boost::ends_with(i, "Dimm"))
118 {
119 BMCWEB_LOG_DEBUG
120 << "Found Dimm, now get it properties.";
121 crow::connections::systemBus->async_method_call(
Ed Tanous66173382018-08-15 18:20:59 -0700122 [aResp](
Ed Tanous6c34de42018-08-29 13:37:36 -0700123 const boost::system::error_code ec,
124 const std::vector<
125 std::pair<std::string, VariantType>>
126 &properties) {
127 if (ec)
128 {
129 BMCWEB_LOG_ERROR
130 << "DBUS response error " << ec;
131 aResp->res.result(
132 boost::beast::http::status::
133 internal_server_error);
134 return;
135 }
136 BMCWEB_LOG_DEBUG << "Got "
137 << properties.size()
138 << "Dimm properties.";
139 for (const auto &p : properties)
140 {
141 if (p.first == "MemorySize")
142 {
143 const std::string *value =
144 mapbox::getPtr<
145 const std::string>(
146 p.second);
147 if ((value != nullptr) &&
148 (*value != "NULL"))
149 {
150 // Remove units char
151 int32_t unitCoeff;
152 if (boost::ends_with(*value,
153 "MB"))
154 {
155 unitCoeff = 1000;
156 }
157 else if (boost::ends_with(
158 *value, "KB"))
159 {
160 unitCoeff = 1000000;
161 }
162 else
163 {
164 BMCWEB_LOG_ERROR
165 << "Unsupported "
166 "memory units";
167 aResp->res.result(
168 boost::beast::http::
169 status::
170 internal_server_error);
171 return;
172 }
173
174 auto memSize =
175 boost::lexical_cast<
176 int>(value->substr(
177 0, value->length() -
178 2));
179 aResp->res.jsonValue
180 ["TotalSystemMemoryGi"
181 "B"] +=
182 memSize * unitCoeff;
183 aResp->res.jsonValue
184 ["MemorySummary"]
185 ["Status"]["State"] =
186 "Enabled";
187 }
188 }
189 }
190 },
191 s.first, path,
192 "org.freedesktop.DBus.Properties", "GetAll",
193 "xyz.openbmc_project.Inventory.Item.Dimm");
194 }
195 else if (boost::ends_with(i, "Cpu"))
196 {
197 BMCWEB_LOG_DEBUG
198 << "Found Cpu, now get it properties.";
199 crow::connections::systemBus->async_method_call(
Ed Tanous66173382018-08-15 18:20:59 -0700200 [aResp](
Ed Tanous6c34de42018-08-29 13:37:36 -0700201 const boost::system::error_code ec,
202 const std::vector<
203 std::pair<std::string, VariantType>>
204 &properties) {
205 if (ec)
206 {
207 BMCWEB_LOG_ERROR
208 << "DBUS response error " << ec;
209 aResp->res.result(
210 boost::beast::http::status::
211 internal_server_error);
212 return;
213 }
214 BMCWEB_LOG_DEBUG << "Got "
215 << properties.size()
216 << "Cpu properties.";
217 for (const auto &p : properties)
218 {
219 if (p.first == "ProcessorFamily")
220 {
221 const std::string *value =
222 mapbox::getPtr<
223 const std::string>(
224 p.second);
225 if (value != nullptr)
226 {
227 aResp->res.jsonValue
228 ["ProcessorSummary"]
229 ["Count"] =
230 aResp->res
231 .jsonValue
232 ["ProcessorSumm"
233 "ary"]["Count"]
234 .get<int>() +
235 1;
236 aResp->res.jsonValue
237 ["ProcessorSummary"]
238 ["Status"]["State"] =
239 "Enabled";
240 aResp->res.jsonValue
241 ["ProcessorSummary"]
242 ["Model"] = *value;
243 }
244 }
245 }
246 },
247 s.first, path,
248 "org.freedesktop.DBus.Properties", "GetAll",
249 "xyz.openbmc_project.Inventory.Item.Cpu");
250 }
251 else if (boost::ends_with(i, "UUID"))
252 {
253 BMCWEB_LOG_DEBUG
254 << "Found UUID, now get it properties.";
255 crow::connections::systemBus->async_method_call(
256 [aResp](
257 const boost::system::error_code ec,
258 const std::vector<
259 std::pair<std::string, VariantType>>
260 &properties) {
261 if (ec)
262 {
263 BMCWEB_LOG_DEBUG
264 << "DBUS response error " << ec;
265 aResp->res.result(
266 boost::beast::http::status::
267 internal_server_error);
268 return;
269 }
270 BMCWEB_LOG_DEBUG << "Got "
271 << properties.size()
272 << "UUID properties.";
273 for (const std::pair<std::string,
274 VariantType> &p :
275 properties)
276 {
277 if (p.first == "BIOSVer")
278 {
279 const std::string *value =
280 mapbox::getPtr<
281 const std::string>(
282 p.second);
283 if (value != nullptr)
284 {
285 aResp->res.jsonValue
286 ["BiosVersion"] =
287 *value;
288 }
289 }
290 if (p.first == "UUID")
291 {
292 const std::string *value =
293 mapbox::getPtr<
294 const std::string>(
295 p.second);
296 BMCWEB_LOG_DEBUG
297 << "UUID = " << *value
298 << " length "
299 << value->length();
300 if (value != nullptr)
301 {
302 // Workaround for to short
303 // return str in smbios demo
304 // app, 32 bytes are
305 // described by spec
306 if (value->length() > 0 &&
307 value->length() < 32)
308 {
309 std::string
310 correctedValue =
311 *value;
312 correctedValue.append(
313 32 -
314 value->length(),
315 '0');
316 value = &correctedValue;
317 }
318 else if (value->length() ==
319 32)
320 {
321 aResp->res
322 .jsonValue["UUID"] =
323 value->substr(0,
324 8) +
325 "-" +
326 value->substr(8,
327 4) +
328 "-" +
329 value->substr(12,
330 4) +
331 "-" +
332 value->substr(16,
333 4) +
334 "-" +
335 value->substr(20,
336 12);
337 }
338 }
339 }
340 }
341 },
342 s.first, path,
343 "org.freedesktop.DBus.Properties", "GetAll",
344 "xyz.openbmc_project.Common.UUID");
345 }
346 }
347 }
348 }
349 }
350 if (foundName == false)
351 {
352 aResp->res.result(
353 boost::beast::http::status::internal_server_error);
354 }
355 },
356 "xyz.openbmc_project.ObjectMapper",
357 "/xyz/openbmc_project/object_mapper",
358 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous66173382018-08-15 18:20:59 -0700359 "/xyz/openbmc_project/inventory", int32_t(0),
360 std::array<const char *, 5>{
361 "xyz.openbmc_project.Inventory.Decorator.Asset",
362 "xyz.openbmc_project.Inventory.Item.Cpu",
363 "xyz.openbmc_project.Inventory.Item.Dimm",
364 "xyz.openbmc_project.Inventory.Item.System",
365 "xyz.openbmc_project.Common.UUID",
366 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700367}
368
369/**
370 * @brief Retrieves identify led group properties over dbus
371 *
372 * @param[in] aResp Shared pointer for completing asynchronous calls.
373 * @param[in] callback Callback for process retrieved data.
374 *
375 * @return None.
376 */
377template <typename CallbackFunc>
378void getLedGroupIdentify(std::shared_ptr<AsyncResp> aResp,
379 CallbackFunc &&callback)
380{
381 BMCWEB_LOG_DEBUG << "Get led groups";
382 crow::connections::systemBus->async_method_call(
383 [aResp{std::move(aResp)},
Ed Tanous66173382018-08-15 18:20:59 -0700384 callback{std::move(callback)}](const boost::system::error_code &ec,
385 const ManagedObjectsType &resp) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700386 if (ec)
387 {
388 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
389 aResp->res.result(
390 boost::beast::http::status::internal_server_error);
391 return;
392 }
393 BMCWEB_LOG_DEBUG << "Got " << resp.size() << "led group objects.";
394 for (const auto &objPath : resp)
395 {
396 const std::string &path = objPath.first;
397 if (path.rfind("enclosure_identify") != std::string::npos)
398 {
399 for (const auto &interface : objPath.second)
400 {
401 if (interface.first == "xyz.openbmc_project.Led.Group")
402 {
403 for (const auto &property : interface.second)
404 {
405 if (property.first == "Asserted")
406 {
407 const bool *asserted =
408 mapbox::getPtr<const bool>(
409 property.second);
410 if (nullptr != asserted)
411 {
412 callback(*asserted, aResp);
413 }
414 else
415 {
416 callback(false, aResp);
417 }
418 }
419 }
420 }
421 }
422 }
423 }
424 },
425 "xyz.openbmc_project.LED.GroupManager",
426 "/xyz/openbmc_project/led/groups", "org.freedesktop.DBus.ObjectManager",
427 "GetManagedObjects");
428}
429
430template <typename CallbackFunc>
431void getLedIdentify(std::shared_ptr<AsyncResp> aResp, CallbackFunc &&callback)
432{
433 BMCWEB_LOG_DEBUG << "Get identify led properties";
434 crow::connections::systemBus->async_method_call(
Ed Tanous66173382018-08-15 18:20:59 -0700435 [aResp,
436 callback{std::move(callback)}](const boost::system::error_code ec,
437 const PropertiesType &properties) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700438 if (ec)
439 {
440 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
441 aResp->res.result(
442 boost::beast::http::status::internal_server_error);
443 return;
444 }
445 BMCWEB_LOG_DEBUG << "Got " << properties.size()
446 << "led properties.";
447 std::string output;
448 for (const auto &property : properties)
449 {
450 if (property.first == "State")
451 {
452 const std::string *s =
453 mapbox::getPtr<std::string>(property.second);
454 if (nullptr != s)
455 {
456 BMCWEB_LOG_DEBUG << "Identify Led State: " << *s;
457 const auto pos = s->rfind('.');
458 if (pos != std::string::npos)
459 {
460 auto led = s->substr(pos + 1);
461 for (const std::pair<const char *, const char *>
462 &p :
463 std::array<
464 std::pair<const char *, const char *>, 3>{
465 {{"On", "Lit"},
466 {"Blink", "Blinking"},
467 {"Off", "Off"}}})
468 {
469 if (led == p.first)
470 {
471 output = p.second;
472 }
473 }
474 }
475 }
476 }
477 }
478 callback(output, aResp);
479 },
480 "xyz.openbmc_project.LED.Controller.identify",
481 "/xyz/openbmc_project/led/physical/identify",
482 "org.freedesktop.DBus.Properties", "GetAll",
483 "xyz.openbmc_project.Led.Physical");
484}
485
486/**
487 * @brief Retrieves host state properties over dbus
488 *
489 * @param[in] aResp Shared pointer for completing asynchronous calls.
490 *
491 * @return None.
492 */
493void getHostState(std::shared_ptr<AsyncResp> aResp)
494{
495 BMCWEB_LOG_DEBUG << "Get host information.";
496 crow::connections::systemBus->async_method_call(
Ed Tanous66173382018-08-15 18:20:59 -0700497 [aResp{std::move(aResp)}](
498 const boost::system::error_code ec,
499 const sdbusplus::message::variant<std::string> &hostState) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700500 if (ec)
501 {
502 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
503 aResp->res.result(
504 boost::beast::http::status::internal_server_error);
505 return;
506 }
Ed Tanous66173382018-08-15 18:20:59 -0700507
508 const std::string *s = mapbox::getPtr<const std::string>(hostState);
509 BMCWEB_LOG_DEBUG << "Host state: " << *s;
510 if (s != nullptr)
Ed Tanous6c34de42018-08-29 13:37:36 -0700511 {
Ed Tanous66173382018-08-15 18:20:59 -0700512 // Verify Host State
513 if (*s == "xyz.openbmc_project.State.Host.Running")
Ed Tanous6c34de42018-08-29 13:37:36 -0700514 {
Ed Tanous66173382018-08-15 18:20:59 -0700515 aResp->res.jsonValue["PowerState"] = "On";
516 aResp->res.jsonValue["Status"]["State"] = "Enabled";
517 }
518 else
519 {
520 aResp->res.jsonValue["PowerState"] = "Off";
521 aResp->res.jsonValue["Status"]["State"] = "Disabled";
Ed Tanous6c34de42018-08-29 13:37:36 -0700522 }
523 }
524 },
525 "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
Ed Tanous66173382018-08-15 18:20:59 -0700526 "org.freedesktop.DBus.Properties", "Get",
527 "xyz.openbmc_project.State.Host", "CurrentHostState");
Ed Tanous6c34de42018-08-29 13:37:36 -0700528}
529
530/**
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200531 * SystemsCollection derived class for delivering ComputerSystems Collection
532 * Schema
533 */
Ed Tanous1abe55e2018-09-05 08:30:59 -0700534class SystemsCollection : public Node
535{
536 public:
537 SystemsCollection(CrowApp &app) : Node(app, "/redfish/v1/Systems/")
538 {
539 Node::json["@odata.type"] =
540 "#ComputerSystemCollection.ComputerSystemCollection";
541 Node::json["@odata.id"] = "/redfish/v1/Systems";
542 Node::json["@odata.context"] =
543 "/redfish/v1/"
544 "$metadata#ComputerSystemCollection.ComputerSystemCollection";
545 Node::json["Name"] = "Computer System Collection";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200546
Ed Tanous1abe55e2018-09-05 08:30:59 -0700547 entityPrivileges = {
548 {boost::beast::http::verb::get, {{"Login"}}},
549 {boost::beast::http::verb::head, {{"Login"}}},
550 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
551 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
552 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
553 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
554 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200555
Ed Tanous1abe55e2018-09-05 08:30:59 -0700556 private:
Ed Tanous1abe55e2018-09-05 08:30:59 -0700557 void doGet(crow::Response &res, const crow::Request &req,
558 const std::vector<std::string> &params) override
559 {
Ed Tanous66173382018-08-15 18:20:59 -0700560 BMCWEB_LOG_DEBUG << "Get list of available boards.";
561 std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
562 res.jsonValue = Node::json;
563 crow::connections::systemBus->async_method_call(
564 [asyncResp](const boost::system::error_code ec,
565 const std::vector<std::string> &resp) {
566 if (ec)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700567 {
Ed Tanous66173382018-08-15 18:20:59 -0700568 asyncResp->res.result(
569 boost::beast::http::status::internal_server_error);
570 return;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700571 }
Ed Tanous66173382018-08-15 18:20:59 -0700572 BMCWEB_LOG_DEBUG << "Got " << resp.size() << " boards.";
573
574 // ... prepare json array with appropriate @odata.id links
575 nlohmann::json &boardArray =
576 asyncResp->res.jsonValue["Members"];
577 boardArray = nlohmann::json::array();
578
579 // Iterate over all retrieved ObjectPaths.
580 for (const std::string &objpath : resp)
581 {
582 std::size_t lastPos = objpath.rfind("/");
583 if (lastPos != std::string::npos)
584 {
585 boardArray.push_back(
586 {{"@odata.id", "/redfish/v1/Systems/" +
587 objpath.substr(lastPos + 1)}});
588 }
589 }
590
591 asyncResp->res.jsonValue["Members@odata.count"] =
592 boardArray.size();
593 },
594 "xyz.openbmc_project.ObjectMapper",
595 "/xyz/openbmc_project/object_mapper",
596 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
597 "/xyz/openbmc_project/inventory", int32_t(0),
598 std::array<const char *, 1>{
599 "xyz.openbmc_project.Inventory.Item.Board"});
Ed Tanous1abe55e2018-09-05 08:30:59 -0700600 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200601};
602
603/**
Ed Tanouscc340dd2018-08-29 13:43:38 -0700604 * SystemActionsReset class supports handle POST method for Reset action.
605 * The class retrieves and sends data directly to D-Bus.
606 */
607class SystemActionsReset : public Node
608{
609 public:
610 SystemActionsReset(CrowApp &app) :
611 Node(app, "/redfish/v1/Systems/<str>/Actions/ComputerSystem.Reset/",
612 std::string())
613 {
614 entityPrivileges = {
615 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
616 }
617
618 private:
619 /**
620 * Function handles POST method request.
621 * Analyzes POST body message before sends Reset request data to D-Bus.
622 */
623 void doPost(crow::Response &res, const crow::Request &req,
624 const std::vector<std::string> &params) override
625 {
626 // Parse JSON request body.
627 nlohmann::json post;
628 if (!json_util::processJsonFromRequest(res, req, post))
629 {
630 return;
631 }
632
633 auto asyncResp = std::make_shared<AsyncResp>(res);
634
635 for (const auto &item : post.items())
636 {
637 if (item.key() == "ResetType")
638 {
639 const std::string *reqResetType =
640 item.value().get_ptr<const std::string *>();
641 if (reqResetType == nullptr)
642 {
643 res.result(boost::beast::http::status::bad_request);
644 messages::addMessageToErrorJson(
645 asyncResp->res.jsonValue,
646 messages::actionParameterValueFormatError(
647 item.value().dump(), "ResetType",
648 "ComputerSystem.Reset"));
649 res.end();
650 return;
651 }
652
653 if (*reqResetType == "ForceOff")
654 {
655 // Force off acts on the chassis
656 crow::connections::systemBus->async_method_call(
657 [asyncResp](const boost::system::error_code ec) {
658 if (ec)
659 {
660 BMCWEB_LOG_ERROR << "D-Bus responses error: "
661 << ec;
662 asyncResp->res.result(
663 boost::beast::http::status::
664 internal_server_error);
665 return;
666 }
667 // TODO Consider support polling mechanism to verify
668 // status of host and chassis after execute the
669 // requested action.
670 BMCWEB_LOG_DEBUG << "Response with no content";
671 asyncResp->res.result(
672 boost::beast::http::status::no_content);
673 },
674 "xyz.openbmc_project.State.Chassis",
675 "/xyz/openbmc_project/state/chassis0",
676 "org.freedesktop.DBus.Properties", "Set",
677 "RequestedPowerTransition",
678 "xyz.openbmc_project.State.Chassis",
679 sdbusplus::message::variant<std::string>{
680 "xyz.openbmc_project.State.Chassis.Transition."
681 "Off"});
682 return;
683 }
684 // all other actions operate on the host
685 std::string command;
686 // Execute Reset Action regarding to each reset type.
687 if (*reqResetType == "On")
688 {
689 command = "xyz.openbmc_project.State.Host.Transition.On";
690 }
691 else if (*reqResetType == "GracefulShutdown")
692 {
693 command = "xyz.openbmc_project.State.Host.Transition.Off";
694 }
695 else if (*reqResetType == "GracefulRestart")
696 {
697 command =
698 "xyz.openbmc_project.State.Host.Transition.Reboot";
699 }
700 else
701 {
702 res.result(boost::beast::http::status::bad_request);
703 messages::addMessageToErrorJson(
704 asyncResp->res.jsonValue,
705 messages::actionParameterUnknown("Reset",
706 *reqResetType));
707 res.end();
708 return;
709 }
710
711 crow::connections::systemBus->async_method_call(
712 [asyncResp](const boost::system::error_code ec) {
713 if (ec)
714 {
715 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
716 asyncResp->res.result(boost::beast::http::status::
717 internal_server_error);
718 return;
719 }
720 // TODO Consider support polling mechanism to verify
721 // status of host and chassis after execute the
722 // requested action.
723 BMCWEB_LOG_DEBUG << "Response with no content";
724 asyncResp->res.result(
725 boost::beast::http::status::no_content);
726 },
727 "xyz.openbmc_project.State.Host",
728 "/xyz/openbmc_project/state/host0",
729 "org.freedesktop.DBus.Properties", "Set",
730 "RequestedHostTransition", "xyz.openbmc_project.State.Host",
731 sdbusplus::message::variant<std::string>{command});
732 }
733 else
734 {
735 messages::addMessageToErrorJson(
736 asyncResp->res.jsonValue,
737 messages::actionParameterUnknown("ComputerSystem.Reset",
738 item.key()));
739 }
740 }
741 }
742};
743
744/**
Ed Tanous66173382018-08-15 18:20:59 -0700745 * Systems derived class for delivering Computer Systems Schema.
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200746 */
Ed Tanous1abe55e2018-09-05 08:30:59 -0700747class Systems : public Node
748{
749 public:
750 /*
751 * Default Constructor
752 */
753 Systems(CrowApp &app) :
754 Node(app, "/redfish/v1/Systems/<str>/", std::string())
755 {
756 Node::json["@odata.type"] = "#ComputerSystem.v1_3_0.ComputerSystem";
757 Node::json["@odata.context"] =
758 "/redfish/v1/$metadata#ComputerSystem.ComputerSystem";
759 Node::json["SystemType"] = "Physical";
760 Node::json["Description"] = "Computer System";
761 Node::json["Boot"]["BootSourceOverrideEnabled"] =
762 "Disabled"; // TODO(Dawid), get real boot data
763 Node::json["Boot"]["BootSourceOverrideTarget"] =
764 "None"; // TODO(Dawid), get real boot data
765 Node::json["Boot"]["BootSourceOverrideMode"] =
766 "Legacy"; // TODO(Dawid), get real boot data
767 Node::json["Boot"]["BootSourceOverrideTarget@Redfish.AllowableValues"] =
768 {"None", "Pxe", "Hdd", "Cd",
769 "BiosSetup", "UefiShell", "Usb"}; // TODO(Dawid), get real boot
770 // data
771 Node::json["ProcessorSummary"]["Count"] = int(0);
772 Node::json["ProcessorSummary"]["Status"]["State"] = "Disabled";
773 Node::json["MemorySummary"]["TotalSystemMemoryGiB"] = int(0);
774 Node::json["MemorySummary"]["Status"]["State"] = "Disabled";
Ed Tanous1abe55e2018-09-05 08:30:59 -0700775 entityPrivileges = {
776 {boost::beast::http::verb::get, {{"Login"}}},
777 {boost::beast::http::verb::head, {{"Login"}}},
778 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
779 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
780 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
781 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200782 }
783
Ed Tanous1abe55e2018-09-05 08:30:59 -0700784 private:
Ed Tanous1abe55e2018-09-05 08:30:59 -0700785 /**
786 * Functions triggers appropriate requests on DBus
787 */
788 void doGet(crow::Response &res, const crow::Request &req,
789 const std::vector<std::string> &params) override
790 {
791 // Check if there is required param, truly entering this shall be
792 // impossible
793 if (params.size() != 1)
794 {
795 res.result(boost::beast::http::status::internal_server_error);
796 res.end();
797 return;
798 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200799
Ed Tanous1abe55e2018-09-05 08:30:59 -0700800 const std::string &name = params[0];
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200801
Ed Tanouscc340dd2018-08-29 13:43:38 -0700802 // TODO Need to support ForceRestart.
803 res.jsonValue["Actions"]["#ComputerSystem.Reset"] = {
804 {"target",
805 "/redfish/v1/Systems/" + name + "/Actions/ComputerSystem.Reset"},
806 {"ResetType@Redfish.AllowableValues",
807 {"On", "ForceOff", "GracefulRestart", "GracefulShutdown"}}};
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200808
Ed Tanousa0803ef2018-08-29 13:29:23 -0700809 auto asyncResp = std::make_shared<AsyncResp>(res);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700810
Ed Tanous6c34de42018-08-29 13:37:36 -0700811 getLedGroupIdentify(
Ed Tanousa0803ef2018-08-29 13:29:23 -0700812 asyncResp,
813 [&](const bool &asserted, const std::shared_ptr<AsyncResp> &aResp) {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700814 if (asserted)
815 {
816 // If led group is asserted, then another call is needed to
817 // get led status
Ed Tanous6c34de42018-08-29 13:37:36 -0700818 getLedIdentify(
Ed Tanousa0803ef2018-08-29 13:29:23 -0700819 aResp, [](const std::string &ledStatus,
820 const std::shared_ptr<AsyncResp> &aResp) {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700821 if (!ledStatus.empty())
822 {
823 aResp->res.jsonValue["IndicatorLED"] =
824 ledStatus;
825 }
826 });
827 }
828 else
829 {
830 aResp->res.jsonValue["IndicatorLED"] = "Off";
831 }
832 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700833 getComputerSystem(asyncResp, name);
834 getHostState(asyncResp);
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200835 }
836
Ed Tanous1abe55e2018-09-05 08:30:59 -0700837 void doPatch(crow::Response &res, const crow::Request &req,
838 const std::vector<std::string> &params) override
839 {
840 // Check if there is required param, truly entering this shall be
841 // impossible
Ed Tanous66173382018-08-15 18:20:59 -0700842 auto asyncResp = std::make_shared<AsyncResp>(res);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700843 if (params.size() != 1)
844 {
845 res.result(boost::beast::http::status::internal_server_error);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700846 return;
847 }
848 // Parse JSON request body
849 nlohmann::json patch;
850 if (!json_util::processJsonFromRequest(res, req, patch))
851 {
852 return;
853 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700854
Ed Tanous66173382018-08-15 18:20:59 -0700855 const std::string &name = params[0];
856
Ed Tanous1abe55e2018-09-05 08:30:59 -0700857 res.jsonValue = Node::json;
858 res.jsonValue["@odata.id"] = "/redfish/v1/Systems/" + name;
859
Ed Tanous66173382018-08-15 18:20:59 -0700860 for (const auto &item : patch.items())
861 {
862 if (item.key() == "IndicatorLed")
863 {
864 const std::string *reqLedState =
865 item.value().get_ptr<const std::string *>();
866 if (reqLedState == nullptr)
867 {
868 messages::addMessageToErrorJson(
869 asyncResp->res.jsonValue,
870 messages::propertyValueFormatError(item.value().dump(),
871 item.key()));
872 return;
873 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700874
Ed Tanous66173382018-08-15 18:20:59 -0700875 // Verify key value
876 std::string dbusLedState;
877 if (*reqLedState == "On")
878 {
879 dbusLedState =
880 "xyz.openbmc_project.Led.Physical.Action.Lit";
881 }
882 else if (*reqLedState == "Blink")
883 {
884 dbusLedState =
885 "xyz.openbmc_project.Led.Physical.Action.Blinking";
886 }
887 else if (*reqLedState == "Off")
888 {
889 dbusLedState =
890 "xyz.openbmc_project.Led.Physical.Action.Off";
891 }
892 else
893 {
894 messages::addMessageToJsonRoot(
895 res.jsonValue, messages::propertyValueNotInList(
896 *reqLedState, "IndicatorLED"));
897 return;
898 }
899
900 getHostState(asyncResp);
901 getComputerSystem(asyncResp, name);
902
903 // Update led group
904 BMCWEB_LOG_DEBUG << "Update led group.";
905 crow::connections::systemBus->async_method_call(
906 [asyncResp{std::move(asyncResp)}](
907 const boost::system::error_code ec) {
908 if (ec)
909 {
910 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
911 asyncResp->res.result(boost::beast::http::status::
912 internal_server_error);
913 return;
914 }
915 BMCWEB_LOG_DEBUG << "Led group update done.";
916 },
917 "xyz.openbmc_project.LED.GroupManager",
918 "/xyz/openbmc_project/led/groups/enclosure_identify",
919 "org.freedesktop.DBus.Properties", "Set",
920 "xyz.openbmc_project.Led.Group", "Asserted",
921 sdbusplus::message::variant<bool>(
922 (dbusLedState ==
923 "xyz.openbmc_project.Led.Physical.Action.Off"
924 ? false
925 : true)));
926 // Update identify led status
927 BMCWEB_LOG_DEBUG << "Update led SoftwareInventoryCollection.";
928 crow::connections::systemBus->async_method_call(
929 [asyncResp{std::move(asyncResp)},
930 reqLedState{std::move(*reqLedState)}](
931 const boost::system::error_code ec) {
932 if (ec)
933 {
934 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
935 asyncResp->res.result(boost::beast::http::status::
936 internal_server_error);
937 return;
938 }
939 BMCWEB_LOG_DEBUG << "Led state update done.";
940 asyncResp->res.jsonValue["IndicatorLED"] =
941 std::move(reqLedState);
942 },
943 "xyz.openbmc_project.LED.Controller.identify",
944 "/xyz/openbmc_project/led/physical/identify",
945 "org.freedesktop.DBus.Properties", "Set",
946 "xyz.openbmc_project.Led.Physical", "State",
947 sdbusplus::message::variant<std::string>(dbusLedState));
948 }
949 else
950 {
951 messages::addMessageToErrorJson(
952 asyncResp->res.jsonValue,
953 messages::propertyNotWritable(item.key()));
954 return;
955 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700956 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200957 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200958};
Ed Tanous1abe55e2018-09-05 08:30:59 -0700959} // namespace redfish