blob: 44c117028f43ff13e2c4ecf27d4dbc0803dbb70d [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 <error_messages.hpp>
22#include <utils/json_utils.hpp>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020023
Ed Tanous1abe55e2018-09-05 08:30:59 -070024namespace redfish
25{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020026
Ed Tanous6c34de42018-08-29 13:37:36 -070027template <typename CallbackFunc> void getBaseboardList(CallbackFunc &&callback)
Ed Tanous1abe55e2018-09-05 08:30:59 -070028{
Ed Tanous6c34de42018-08-29 13:37:36 -070029 BMCWEB_LOG_DEBUG << "Get list of available boards.";
30 crow::connections::systemBus->async_method_call(
31 [callback{std::move(callback)}](const boost::system::error_code ec,
32 const std::vector<std::string> &resp) {
33 // Callback requires vector<string> to retrieve all available board
34 // list.
35 std::vector<std::string> boardList;
36 if (ec)
37 {
38 // Something wrong on DBus, the error_code is not important at
39 // this moment, just return success=false, and empty output.
40 // Since size of vector may vary depending on information from
41 // Entity Manager, and empty output could not be treated same
42 // way as error.
43 callback(false, boardList);
44 return;
45 }
46 BMCWEB_LOG_DEBUG << "Got " << resp.size() << " boards.";
47 // Iterate over all retrieved ObjectPaths.
48 for (const std::string &objpath : resp)
49 {
50 std::size_t lastPos = objpath.rfind("/");
51 if (lastPos != std::string::npos)
Ed Tanous1abe55e2018-09-05 08:30:59 -070052 {
Ed Tanous6c34de42018-08-29 13:37:36 -070053 boardList.emplace_back(objpath.substr(lastPos + 1));
Ed Tanous1abe55e2018-09-05 08:30:59 -070054 }
Ed Tanous6c34de42018-08-29 13:37:36 -070055 }
56 // Finally make a callback with useful data
57 callback(true, boardList);
58 },
59 "xyz.openbmc_project.ObjectMapper",
60 "/xyz/openbmc_project/object_mapper",
61 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
62 "/xyz/openbmc_project/inventory", int32_t(0),
63 std::array<const char *, 1>{
64 "xyz.openbmc_project.Inventory.Item.Board"});
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020065};
66
67/**
Ed Tanous6c34de42018-08-29 13:37:36 -070068 * @brief Retrieves computer system properties over dbus
69 *
70 * @param[in] aResp Shared pointer for completing asynchronous calls
71 * @param[in] name Computer system name from request
72 *
73 * @return None.
74 */
75void getComputerSystem(std::shared_ptr<AsyncResp> aResp,
76 const std::string &name)
77{
78 const std::array<const char *, 5> interfaces = {
79 "xyz.openbmc_project.Inventory.Decorator.Asset",
80 "xyz.openbmc_project.Inventory.Item.Cpu",
81 "xyz.openbmc_project.Inventory.Item.Dimm",
82 "xyz.openbmc_project.Inventory.Item.System",
83 "xyz.openbmc_project.Common.UUID",
84 };
85 BMCWEB_LOG_DEBUG << "Get available system components.";
86 crow::connections::systemBus->async_method_call(
87 [name, aResp{std::move(aResp)}](
88 const boost::system::error_code ec,
89 const std::vector<std::pair<
90 std::string,
91 std::vector<std::pair<std::string, std::vector<std::string>>>>>
92 &subtree) {
93 if (ec)
94 {
95 BMCWEB_LOG_DEBUG << "DBUS response error";
96 aResp->res.result(
97 boost::beast::http::status::internal_server_error);
98 return;
99 }
100 bool foundName = false;
101 // Iterate over all retrieved ObjectPaths.
102 for (const std::pair<std::string,
103 std::vector<std::pair<
104 std::string, std::vector<std::string>>>>
105 &object : subtree)
106 {
107 const std::string &path = object.first;
108 BMCWEB_LOG_DEBUG << "Got path: " << path;
109 const std::vector<
110 std::pair<std::string, std::vector<std::string>>>
111 &connectionNames = object.second;
112 if (connectionNames.size() < 1)
113 {
114 continue;
115 }
116 // Check if computer system exist
117 if (boost::ends_with(path, name))
118 {
119 foundName = true;
120 BMCWEB_LOG_DEBUG << "Found name: " << name;
121 const std::string connectionName = connectionNames[0].first;
122 crow::connections::systemBus->async_method_call(
123 [aResp, name(std::string(name))](
124 const boost::system::error_code ec,
125 const std::vector<std::pair<
126 std::string, VariantType>> &propertiesList) {
127 if (ec)
128 {
129 BMCWEB_LOG_ERROR << "DBUS response error: "
130 << ec;
131 aResp->res.result(boost::beast::http::status::
132 internal_server_error);
133 return;
134 }
135 BMCWEB_LOG_DEBUG << "Got " << propertiesList.size()
136 << "properties for system";
137 for (const std::pair<std::string, VariantType>
138 &property : propertiesList)
139 {
140 const std::string *value =
141 mapbox::getPtr<const std::string>(
142 property.second);
143 if (value != nullptr)
144 {
145 aResp->res.jsonValue[property.first] =
146 *value;
147 }
148 }
149 aResp->res.jsonValue["Name"] = name;
150 aResp->res.jsonValue["Id"] =
151 aResp->res.jsonValue["SerialNumber"];
152 },
153 connectionName, path, "org.freedesktop.DBus.Properties",
154 "GetAll",
155 "xyz.openbmc_project.Inventory.Decorator.Asset");
156 }
157 else
158 {
159 // This is not system, so check if it's cpu, dimm, UUID or
160 // BiosVer
161 for (auto const &s : connectionNames)
162 {
163 for (auto const &i : s.second)
164 {
165 if (boost::ends_with(i, "Dimm"))
166 {
167 BMCWEB_LOG_DEBUG
168 << "Found Dimm, now get it properties.";
169 crow::connections::systemBus->async_method_call(
170 [&, aResp](
171 const boost::system::error_code ec,
172 const std::vector<
173 std::pair<std::string, VariantType>>
174 &properties) {
175 if (ec)
176 {
177 BMCWEB_LOG_ERROR
178 << "DBUS response error " << ec;
179 aResp->res.result(
180 boost::beast::http::status::
181 internal_server_error);
182 return;
183 }
184 BMCWEB_LOG_DEBUG << "Got "
185 << properties.size()
186 << "Dimm properties.";
187 for (const auto &p : properties)
188 {
189 if (p.first == "MemorySize")
190 {
191 const std::string *value =
192 mapbox::getPtr<
193 const std::string>(
194 p.second);
195 if ((value != nullptr) &&
196 (*value != "NULL"))
197 {
198 // Remove units char
199 int32_t unitCoeff;
200 if (boost::ends_with(*value,
201 "MB"))
202 {
203 unitCoeff = 1000;
204 }
205 else if (boost::ends_with(
206 *value, "KB"))
207 {
208 unitCoeff = 1000000;
209 }
210 else
211 {
212 BMCWEB_LOG_ERROR
213 << "Unsupported "
214 "memory units";
215 aResp->res.result(
216 boost::beast::http::
217 status::
218 internal_server_error);
219 return;
220 }
221
222 auto memSize =
223 boost::lexical_cast<
224 int>(value->substr(
225 0, value->length() -
226 2));
227 aResp->res.jsonValue
228 ["TotalSystemMemoryGi"
229 "B"] +=
230 memSize * unitCoeff;
231 aResp->res.jsonValue
232 ["MemorySummary"]
233 ["Status"]["State"] =
234 "Enabled";
235 }
236 }
237 }
238 },
239 s.first, path,
240 "org.freedesktop.DBus.Properties", "GetAll",
241 "xyz.openbmc_project.Inventory.Item.Dimm");
242 }
243 else if (boost::ends_with(i, "Cpu"))
244 {
245 BMCWEB_LOG_DEBUG
246 << "Found Cpu, now get it properties.";
247 crow::connections::systemBus->async_method_call(
248 [&, aResp](
249 const boost::system::error_code ec,
250 const std::vector<
251 std::pair<std::string, VariantType>>
252 &properties) {
253 if (ec)
254 {
255 BMCWEB_LOG_ERROR
256 << "DBUS response error " << ec;
257 aResp->res.result(
258 boost::beast::http::status::
259 internal_server_error);
260 return;
261 }
262 BMCWEB_LOG_DEBUG << "Got "
263 << properties.size()
264 << "Cpu properties.";
265 for (const auto &p : properties)
266 {
267 if (p.first == "ProcessorFamily")
268 {
269 const std::string *value =
270 mapbox::getPtr<
271 const std::string>(
272 p.second);
273 if (value != nullptr)
274 {
275 aResp->res.jsonValue
276 ["ProcessorSummary"]
277 ["Count"] =
278 aResp->res
279 .jsonValue
280 ["ProcessorSumm"
281 "ary"]["Count"]
282 .get<int>() +
283 1;
284 aResp->res.jsonValue
285 ["ProcessorSummary"]
286 ["Status"]["State"] =
287 "Enabled";
288 aResp->res.jsonValue
289 ["ProcessorSummary"]
290 ["Model"] = *value;
291 }
292 }
293 }
294 },
295 s.first, path,
296 "org.freedesktop.DBus.Properties", "GetAll",
297 "xyz.openbmc_project.Inventory.Item.Cpu");
298 }
299 else if (boost::ends_with(i, "UUID"))
300 {
301 BMCWEB_LOG_DEBUG
302 << "Found UUID, now get it properties.";
303 crow::connections::systemBus->async_method_call(
304 [aResp](
305 const boost::system::error_code ec,
306 const std::vector<
307 std::pair<std::string, VariantType>>
308 &properties) {
309 if (ec)
310 {
311 BMCWEB_LOG_DEBUG
312 << "DBUS response error " << ec;
313 aResp->res.result(
314 boost::beast::http::status::
315 internal_server_error);
316 return;
317 }
318 BMCWEB_LOG_DEBUG << "Got "
319 << properties.size()
320 << "UUID properties.";
321 for (const std::pair<std::string,
322 VariantType> &p :
323 properties)
324 {
325 if (p.first == "BIOSVer")
326 {
327 const std::string *value =
328 mapbox::getPtr<
329 const std::string>(
330 p.second);
331 if (value != nullptr)
332 {
333 aResp->res.jsonValue
334 ["BiosVersion"] =
335 *value;
336 }
337 }
338 if (p.first == "UUID")
339 {
340 const std::string *value =
341 mapbox::getPtr<
342 const std::string>(
343 p.second);
344 BMCWEB_LOG_DEBUG
345 << "UUID = " << *value
346 << " length "
347 << value->length();
348 if (value != nullptr)
349 {
350 // Workaround for to short
351 // return str in smbios demo
352 // app, 32 bytes are
353 // described by spec
354 if (value->length() > 0 &&
355 value->length() < 32)
356 {
357 std::string
358 correctedValue =
359 *value;
360 correctedValue.append(
361 32 -
362 value->length(),
363 '0');
364 value = &correctedValue;
365 }
366 else if (value->length() ==
367 32)
368 {
369 aResp->res
370 .jsonValue["UUID"] =
371 value->substr(0,
372 8) +
373 "-" +
374 value->substr(8,
375 4) +
376 "-" +
377 value->substr(12,
378 4) +
379 "-" +
380 value->substr(16,
381 4) +
382 "-" +
383 value->substr(20,
384 12);
385 }
386 }
387 }
388 }
389 },
390 s.first, path,
391 "org.freedesktop.DBus.Properties", "GetAll",
392 "xyz.openbmc_project.Common.UUID");
393 }
394 }
395 }
396 }
397 }
398 if (foundName == false)
399 {
400 aResp->res.result(
401 boost::beast::http::status::internal_server_error);
402 }
403 },
404 "xyz.openbmc_project.ObjectMapper",
405 "/xyz/openbmc_project/object_mapper",
406 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
407 "/xyz/openbmc_project/inventory", int32_t(0), interfaces);
408}
409
410/**
411 * @brief Retrieves identify led group properties over dbus
412 *
413 * @param[in] aResp Shared pointer for completing asynchronous calls.
414 * @param[in] callback Callback for process retrieved data.
415 *
416 * @return None.
417 */
418template <typename CallbackFunc>
419void getLedGroupIdentify(std::shared_ptr<AsyncResp> aResp,
420 CallbackFunc &&callback)
421{
422 BMCWEB_LOG_DEBUG << "Get led groups";
423 crow::connections::systemBus->async_method_call(
424 [aResp{std::move(aResp)},
425 &callback](const boost::system::error_code &ec,
426 const ManagedObjectsType &resp) {
427 if (ec)
428 {
429 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
430 aResp->res.result(
431 boost::beast::http::status::internal_server_error);
432 return;
433 }
434 BMCWEB_LOG_DEBUG << "Got " << resp.size() << "led group objects.";
435 for (const auto &objPath : resp)
436 {
437 const std::string &path = objPath.first;
438 if (path.rfind("enclosure_identify") != std::string::npos)
439 {
440 for (const auto &interface : objPath.second)
441 {
442 if (interface.first == "xyz.openbmc_project.Led.Group")
443 {
444 for (const auto &property : interface.second)
445 {
446 if (property.first == "Asserted")
447 {
448 const bool *asserted =
449 mapbox::getPtr<const bool>(
450 property.second);
451 if (nullptr != asserted)
452 {
453 callback(*asserted, aResp);
454 }
455 else
456 {
457 callback(false, aResp);
458 }
459 }
460 }
461 }
462 }
463 }
464 }
465 },
466 "xyz.openbmc_project.LED.GroupManager",
467 "/xyz/openbmc_project/led/groups", "org.freedesktop.DBus.ObjectManager",
468 "GetManagedObjects");
469}
470
471template <typename CallbackFunc>
472void getLedIdentify(std::shared_ptr<AsyncResp> aResp, CallbackFunc &&callback)
473{
474 BMCWEB_LOG_DEBUG << "Get identify led properties";
475 crow::connections::systemBus->async_method_call(
476 [aResp{std::move(aResp)}, &callback](const boost::system::error_code ec,
477 const PropertiesType &properties) {
478 if (ec)
479 {
480 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
481 aResp->res.result(
482 boost::beast::http::status::internal_server_error);
483 return;
484 }
485 BMCWEB_LOG_DEBUG << "Got " << properties.size()
486 << "led properties.";
487 std::string output;
488 for (const auto &property : properties)
489 {
490 if (property.first == "State")
491 {
492 const std::string *s =
493 mapbox::getPtr<std::string>(property.second);
494 if (nullptr != s)
495 {
496 BMCWEB_LOG_DEBUG << "Identify Led State: " << *s;
497 const auto pos = s->rfind('.');
498 if (pos != std::string::npos)
499 {
500 auto led = s->substr(pos + 1);
501 for (const std::pair<const char *, const char *>
502 &p :
503 std::array<
504 std::pair<const char *, const char *>, 3>{
505 {{"On", "Lit"},
506 {"Blink", "Blinking"},
507 {"Off", "Off"}}})
508 {
509 if (led == p.first)
510 {
511 output = p.second;
512 }
513 }
514 }
515 }
516 }
517 }
518 callback(output, aResp);
519 },
520 "xyz.openbmc_project.LED.Controller.identify",
521 "/xyz/openbmc_project/led/physical/identify",
522 "org.freedesktop.DBus.Properties", "GetAll",
523 "xyz.openbmc_project.Led.Physical");
524}
525
526/**
527 * @brief Retrieves host state properties over dbus
528 *
529 * @param[in] aResp Shared pointer for completing asynchronous calls.
530 *
531 * @return None.
532 */
533void getHostState(std::shared_ptr<AsyncResp> aResp)
534{
535 BMCWEB_LOG_DEBUG << "Get host information.";
536 crow::connections::systemBus->async_method_call(
537 [aResp{std::move(aResp)}](const boost::system::error_code ec,
538 const PropertiesType &properties) {
539 if (ec)
540 {
541 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
542 aResp->res.result(
543 boost::beast::http::status::internal_server_error);
544 return;
545 }
546 BMCWEB_LOG_DEBUG << "Got " << properties.size()
547 << "host properties.";
548 for (const auto &property : properties)
549 {
550 if (property.first == "CurrentHostState")
551 {
552 const std::string *s =
553 mapbox::getPtr<const std::string>(property.second);
554 BMCWEB_LOG_DEBUG << "Host state: " << *s;
555 if (nullptr != s)
556 {
557 const auto pos = s->rfind('.');
558 if (pos != std::string::npos)
559 {
560 // Verify Host State
561 if (s->substr(pos + 1) == "Running")
562 {
563 aResp->res.jsonValue["PowerState"] = "On";
564 aResp->res.jsonValue["Status"]["State"] =
565 "Enabled";
566 }
567 else
568 {
569 aResp->res.jsonValue["PowerState"] = "Off";
570 aResp->res.jsonValue["Status"]["State"] =
571 "Disabled";
572 }
573 }
574 }
575 }
576 }
577 },
578 "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
579 "org.freedesktop.DBus.Properties", "GetAll",
580 "xyz.openbmc_project.State.Host");
581}
582
583/**
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200584 * SystemsCollection derived class for delivering ComputerSystems Collection
585 * Schema
586 */
Ed Tanous1abe55e2018-09-05 08:30:59 -0700587class SystemsCollection : public Node
588{
589 public:
590 SystemsCollection(CrowApp &app) : Node(app, "/redfish/v1/Systems/")
591 {
592 Node::json["@odata.type"] =
593 "#ComputerSystemCollection.ComputerSystemCollection";
594 Node::json["@odata.id"] = "/redfish/v1/Systems";
595 Node::json["@odata.context"] =
596 "/redfish/v1/"
597 "$metadata#ComputerSystemCollection.ComputerSystemCollection";
598 Node::json["Name"] = "Computer System Collection";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200599
Ed Tanous1abe55e2018-09-05 08:30:59 -0700600 entityPrivileges = {
601 {boost::beast::http::verb::get, {{"Login"}}},
602 {boost::beast::http::verb::head, {{"Login"}}},
603 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
604 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
605 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
606 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
607 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200608
Ed Tanous1abe55e2018-09-05 08:30:59 -0700609 private:
610 /**
611 * Functions triggers appropriate requests on DBus
612 */
613 void doGet(crow::Response &res, const crow::Request &req,
614 const std::vector<std::string> &params) override
615 {
616 // Get board list, and call the below callback for JSON preparation
Ed Tanous6c34de42018-08-29 13:37:36 -0700617 getBaseboardList([&](const bool &success,
618 const std::vector<std::string> &output) {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700619 if (success)
620 {
621 // ... prepare json array with appropriate @odata.id links
622 nlohmann::json boardArray = nlohmann::json::array();
623 for (const std::string &boardItem : output)
624 {
625 boardArray.push_back(
626 {{"@odata.id", "/redfish/v1/Systems/" + boardItem}});
627 }
628 // Then attach members, count size and return,
629 Node::json["Members"] = boardArray;
630 Node::json["Members@odata.count"] = boardArray.size();
631 res.jsonValue = Node::json;
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200632 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700633 else
634 {
635 // ... otherwise, return INTERNALL ERROR
636 res.result(boost::beast::http::status::internal_server_error);
637 }
638 res.end();
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200639 });
Ed Tanous1abe55e2018-09-05 08:30:59 -0700640 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200641};
642
643/**
644 * Systems override class for delivering ComputerSystems Schema
645 */
Ed Tanous1abe55e2018-09-05 08:30:59 -0700646class Systems : public Node
647{
648 public:
649 /*
650 * Default Constructor
651 */
652 Systems(CrowApp &app) :
653 Node(app, "/redfish/v1/Systems/<str>/", std::string())
654 {
655 Node::json["@odata.type"] = "#ComputerSystem.v1_3_0.ComputerSystem";
656 Node::json["@odata.context"] =
657 "/redfish/v1/$metadata#ComputerSystem.ComputerSystem";
658 Node::json["SystemType"] = "Physical";
659 Node::json["Description"] = "Computer System";
660 Node::json["Boot"]["BootSourceOverrideEnabled"] =
661 "Disabled"; // TODO(Dawid), get real boot data
662 Node::json["Boot"]["BootSourceOverrideTarget"] =
663 "None"; // TODO(Dawid), get real boot data
664 Node::json["Boot"]["BootSourceOverrideMode"] =
665 "Legacy"; // TODO(Dawid), get real boot data
666 Node::json["Boot"]["BootSourceOverrideTarget@Redfish.AllowableValues"] =
667 {"None", "Pxe", "Hdd", "Cd",
668 "BiosSetup", "UefiShell", "Usb"}; // TODO(Dawid), get real boot
669 // data
670 Node::json["ProcessorSummary"]["Count"] = int(0);
671 Node::json["ProcessorSummary"]["Status"]["State"] = "Disabled";
672 Node::json["MemorySummary"]["TotalSystemMemoryGiB"] = int(0);
673 Node::json["MemorySummary"]["Status"]["State"] = "Disabled";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200674
Ed Tanous1abe55e2018-09-05 08:30:59 -0700675 entityPrivileges = {
676 {boost::beast::http::verb::get, {{"Login"}}},
677 {boost::beast::http::verb::head, {{"Login"}}},
678 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
679 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
680 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
681 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200682 }
683
Ed Tanous1abe55e2018-09-05 08:30:59 -0700684 private:
Ed Tanous1abe55e2018-09-05 08:30:59 -0700685 /**
686 * Functions triggers appropriate requests on DBus
687 */
688 void doGet(crow::Response &res, const crow::Request &req,
689 const std::vector<std::string> &params) override
690 {
691 // Check if there is required param, truly entering this shall be
692 // impossible
693 if (params.size() != 1)
694 {
695 res.result(boost::beast::http::status::internal_server_error);
696 res.end();
697 return;
698 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200699
Ed Tanous1abe55e2018-09-05 08:30:59 -0700700 const std::string &name = params[0];
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200701
Ed Tanous1abe55e2018-09-05 08:30:59 -0700702 res.jsonValue = Node::json;
703 res.jsonValue["@odata.id"] = "/redfish/v1/Systems/" + name;
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200704
Ed Tanousa0803ef2018-08-29 13:29:23 -0700705 auto asyncResp = std::make_shared<AsyncResp>(res);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700706
Ed Tanous6c34de42018-08-29 13:37:36 -0700707 getLedGroupIdentify(
Ed Tanousa0803ef2018-08-29 13:29:23 -0700708 asyncResp,
709 [&](const bool &asserted, const std::shared_ptr<AsyncResp> &aResp) {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700710 if (asserted)
711 {
712 // If led group is asserted, then another call is needed to
713 // get led status
Ed Tanous6c34de42018-08-29 13:37:36 -0700714 getLedIdentify(
Ed Tanousa0803ef2018-08-29 13:29:23 -0700715 aResp, [](const std::string &ledStatus,
716 const std::shared_ptr<AsyncResp> &aResp) {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700717 if (!ledStatus.empty())
718 {
719 aResp->res.jsonValue["IndicatorLED"] =
720 ledStatus;
721 }
722 });
723 }
724 else
725 {
726 aResp->res.jsonValue["IndicatorLED"] = "Off";
727 }
728 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700729 getComputerSystem(asyncResp, name);
730 getHostState(asyncResp);
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200731 }
732
Ed Tanous1abe55e2018-09-05 08:30:59 -0700733 void doPatch(crow::Response &res, const crow::Request &req,
734 const std::vector<std::string> &params) override
735 {
736 // Check if there is required param, truly entering this shall be
737 // impossible
738 if (params.size() != 1)
739 {
740 res.result(boost::beast::http::status::internal_server_error);
741 res.end();
742 return;
743 }
744 // Parse JSON request body
745 nlohmann::json patch;
746 if (!json_util::processJsonFromRequest(res, req, patch))
747 {
748 return;
749 }
750 // Find key with new led value
751 const std::string &name = params[0];
752 const std::string *reqLedState = nullptr;
753 json_util::Result r = json_util::getString(
754 "IndicatorLED", patch, reqLedState,
755 static_cast<int>(json_util::MessageSetting::TYPE_ERROR) |
756 static_cast<int>(json_util::MessageSetting::MISSING),
757 res.jsonValue, std::string("/" + name + "/IndicatorLED"));
758 if ((r != json_util::Result::SUCCESS) || (reqLedState == nullptr))
759 {
760 res.result(boost::beast::http::status::bad_request);
761 res.end();
762 return;
763 }
764 // Verify key value
765 std::string dbusLedState;
766 for (const auto &p :
767 boost::container::flat_map<const char *, const char *>{
768 {"On", "Lit"}, {"Blink", "Blinking"}, {"Off", "Off"}})
769 {
770 if (*reqLedState == p.second)
771 {
772 dbusLedState = p.first;
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200773 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700774 }
775
776 // Update led status
Ed Tanousa0803ef2018-08-29 13:29:23 -0700777 auto asyncResp = std::make_shared<AsyncResp>(res);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700778 res.jsonValue = Node::json;
779 res.jsonValue["@odata.id"] = "/redfish/v1/Systems/" + name;
780
Ed Tanous6c34de42018-08-29 13:37:36 -0700781 getHostState(asyncResp);
782 getComputerSystem(asyncResp, name);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700783
784 if (dbusLedState.empty())
785 {
786 messages::addMessageToJsonRoot(
787 res.jsonValue,
788 messages::propertyValueNotInList(*reqLedState, "IndicatorLED"));
789 }
790 else
791 {
792 // Update led group
793 BMCWEB_LOG_DEBUG << "Update led group.";
794 crow::connections::systemBus->async_method_call(
795 [&, asyncResp{std::move(asyncResp)}](
796 const boost::system::error_code ec) {
797 if (ec)
798 {
799 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Ed Tanousa0803ef2018-08-29 13:29:23 -0700800 asyncResp->res.result(
801 boost::beast::http::status::internal_server_error);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700802 return;
803 }
804 BMCWEB_LOG_DEBUG << "Led group update done.";
805 },
806 "xyz.openbmc_project.LED.GroupManager",
807 "/xyz/openbmc_project/led/groups/enclosure_identify",
808 "org.freedesktop.DBus.Properties", "Set",
809 "xyz.openbmc_project.Led.Group", "Asserted",
810 sdbusplus::message::variant<bool>(
811 (dbusLedState == "Off" ? false : true)));
812 // Update identify led status
813 BMCWEB_LOG_DEBUG << "Update led SoftwareInventoryCollection.";
814 crow::connections::systemBus->async_method_call(
815 [&, asyncResp{std::move(asyncResp)}](
816 const boost::system::error_code ec) {
817 if (ec)
818 {
819 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Ed Tanousa0803ef2018-08-29 13:29:23 -0700820 asyncResp->res.result(
821 boost::beast::http::status::internal_server_error);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700822 return;
823 }
824 BMCWEB_LOG_DEBUG << "Led state update done.";
825 res.jsonValue["IndicatorLED"] = *reqLedState;
826 },
827 "xyz.openbmc_project.LED.Controller.identify",
828 "/xyz/openbmc_project/led/physical/identify",
829 "org.freedesktop.DBus.Properties", "Set",
830 "xyz.openbmc_project.Led.Physical", "State",
831 sdbusplus::message::variant<std::string>(
832 "xyz.openbmc_project.Led.Physical.Action." + dbusLedState));
833 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200834 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200835};
Ed Tanous1abe55e2018-09-05 08:30:59 -0700836} // namespace redfish