blob: cd49883859669a7082c88705bcc842ce2fa7bd28 [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
27/**
28 * SystemAsyncResp
29 * Gathers data needed for response processing after async calls are done
30 */
Ed Tanous1abe55e2018-09-05 08:30:59 -070031class SystemAsyncResp
32{
33 public:
34 SystemAsyncResp(crow::Response &response) : res(response)
35 {
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020036 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020037
Ed Tanous1abe55e2018-09-05 08:30:59 -070038 ~SystemAsyncResp()
39 {
40 if (res.result() != (boost::beast::http::status::ok))
41 {
42 // Reset the json object to clear out any data that made it in
43 // before the error happened todo(ed) handle error condition with
44 // proper code
45 res.jsonValue = messages::internalError();
46 }
47 res.end();
48 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020049
Ed Tanous1abe55e2018-09-05 08:30:59 -070050 void setErrorStatus()
51 {
52 res.result(boost::beast::http::status::internal_server_error);
53 }
54
55 crow::Response &res;
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020056};
57
58/**
59 * OnDemandSystemsProvider
60 * Board provider class that retrieves data directly from dbus, before seting
61 * it into JSON output. This does not cache any data.
62 *
63 * Class can be a good example on how to scale different data providing
64 * solutions to produce single schema output.
65 *
66 * TODO(Pawel)
67 * This perhaps shall be different file, which has to be chosen on compile time
68 * depending on OEM needs
69 */
Ed Tanous1abe55e2018-09-05 08:30:59 -070070class OnDemandSystemsProvider
71{
72 public:
73 template <typename CallbackFunc>
74 void getBaseboardList(CallbackFunc &&callback)
75 {
76 BMCWEB_LOG_DEBUG << "Get list of available boards.";
77 crow::connections::systemBus->async_method_call(
78 [callback{std::move(callback)}](
79 const boost::system::error_code ec,
80 const std::vector<std::string> &resp) {
81 // Callback requires vector<string> to retrieve all available
82 // board list.
83 std::vector<std::string> boardList;
84 if (ec)
85 {
86 // Something wrong on DBus, the error_code is not important
87 // at this moment, just return success=false, and empty
88 // output. Since size of vector may vary depending on
89 // information from Entity Manager, and empty output could
90 // not be treated same way as error.
91 callback(false, boardList);
92 return;
93 }
94 BMCWEB_LOG_DEBUG << "Got " << resp.size() << " boards.";
95 // Iterate over all retrieved ObjectPaths.
96 for (const std::string &objpath : resp)
97 {
98 std::size_t lastPos = objpath.rfind("/");
99 if (lastPos != std::string::npos)
100 {
101 boardList.emplace_back(objpath.substr(lastPos + 1));
102 }
103 }
104 // Finally make a callback with useful data
105 callback(true, boardList);
106 },
107 "xyz.openbmc_project.ObjectMapper",
108 "/xyz/openbmc_project/object_mapper",
109 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
110 "/xyz/openbmc_project/inventory", int32_t(0),
111 std::array<const char *, 1>{
112 "xyz.openbmc_project.Inventory.Item.Board"});
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200113 };
Ed Tanous1abe55e2018-09-05 08:30:59 -0700114
115 /**
116 * @brief Retrieves computer system properties over dbus
117 *
118 * @param[in] aResp Shared pointer for completing asynchronous calls
119 * @param[in] name Computer system name from request
120 *
121 * @return None.
122 */
123 void getComputerSystem(std::shared_ptr<SystemAsyncResp> aResp,
124 const std::string &name)
125 {
126 const std::array<const char *, 5> interfaces = {
127 "xyz.openbmc_project.Inventory.Decorator.Asset",
128 "xyz.openbmc_project.Inventory.Item.Cpu",
129 "xyz.openbmc_project.Inventory.Item.Dimm",
130 "xyz.openbmc_project.Inventory.Item.System",
131 "xyz.openbmc_project.Common.UUID",
132 };
133 BMCWEB_LOG_DEBUG << "Get available system components.";
134 crow::connections::systemBus->async_method_call(
135 [name, aResp{std::move(aResp)}](
136 const boost::system::error_code ec,
137 const std::vector<std::pair<
138 std::string, std::vector<std::pair<
139 std::string, std::vector<std::string>>>>>
140 &subtree) {
141 if (ec)
142 {
143 BMCWEB_LOG_DEBUG << "DBUS response error";
144 aResp->setErrorStatus();
145 return;
146 }
147 bool foundName = false;
148 // Iterate over all retrieved ObjectPaths.
149 for (const std::pair<
150 std::string,
151 std::vector<
152 std::pair<std::string, std::vector<std::string>>>>
153 &object : subtree)
154 {
155 const std::string &path = object.first;
156 BMCWEB_LOG_DEBUG << "Got path: " << path;
157 const std::vector<
158 std::pair<std::string, std::vector<std::string>>>
159 &connectionNames = object.second;
160 if (connectionNames.size() < 1)
161 {
162 continue;
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200163 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700164 // Check if computer system exist
165 if (boost::ends_with(path, name))
166 {
167 foundName = true;
168 BMCWEB_LOG_DEBUG << "Found name: " << name;
169 const std::string connectionName =
170 connectionNames[0].first;
171 crow::connections::systemBus->async_method_call(
172 [aResp, name(std::string(name))](
173 const boost::system::error_code ec,
174 const std::vector<
175 std::pair<std::string, VariantType>>
176 &propertiesList) {
177 if (ec)
178 {
179 BMCWEB_LOG_ERROR << "DBUS response error: "
180 << ec;
181 aResp->setErrorStatus();
182 return;
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200183 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700184 BMCWEB_LOG_DEBUG << "Got "
185 << propertiesList.size()
186 << "properties for system";
187 for (const std::pair<std::string, VariantType>
188 &property : propertiesList)
189 {
190 const std::string *value =
191 mapbox::getPtr<const std::string>(
192 property.second);
193 if (value != nullptr)
194 {
195 aResp->res.jsonValue[property.first] =
196 *value;
197 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200198 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700199 aResp->res.jsonValue["Name"] = name;
200 aResp->res.jsonValue["Id"] =
201 aResp->res.jsonValue["SerialNumber"];
202 },
203 connectionName, path,
204 "org.freedesktop.DBus.Properties", "GetAll",
205 "xyz.openbmc_project.Inventory.Decorator.Asset");
206 }
207 else
208 {
209 // This is not system, so check if it's cpu, dimm, UUID
210 // or BiosVer
211 for (auto const &s : connectionNames)
212 {
213 for (auto const &i : s.second)
214 {
215 if (boost::ends_with(i, "Dimm"))
216 {
217 BMCWEB_LOG_DEBUG
218 << "Found Dimm, now get it properties.";
219 crow::connections::systemBus->async_method_call(
220 [&, aResp](
221 const boost::system::error_code ec,
222 const std::vector<std::pair<
223 std::string, VariantType>>
224 &properties) {
225 if (ec)
226 {
227 BMCWEB_LOG_ERROR
228 << "DBUS response error "
229 << ec;
230 aResp->setErrorStatus();
231 return;
232 }
233 BMCWEB_LOG_DEBUG
234 << "Got " << properties.size()
235 << "Dimm properties.";
236 for (const auto &p : properties)
237 {
238 if (p.first == "MemorySize")
239 {
240 const std::string *value =
241 mapbox::getPtr<
242 const std::string>(
243 p.second);
244 if ((value != nullptr) &&
245 (*value != "NULL"))
246 {
247 // Remove units char
248 int32_t unitCoeff;
249 if (boost::ends_with(
250 *value, "MB"))
251 {
252 unitCoeff = 1000;
253 }
254 else if (boost::
255 ends_with(
256 *value,
257 "KB"))
258 {
259 unitCoeff = 1000000;
260 }
261 else
262 {
263 BMCWEB_LOG_ERROR
264 << "Unsupported"
265 " memory "
266 "units";
267 aResp
268 ->setErrorStatus();
269 return;
270 }
271
272 auto memSize =
273 boost::lexical_cast<
274 int>(value->substr(
275 0,
276 value->length() -
277 2));
278 aResp->res.jsonValue
279 ["TotalSystemMemory"
280 "GiB"] +=
281 memSize * unitCoeff;
282 aResp->res.jsonValue
283 ["MemorySummary"]
284 ["Status"]
285 ["State"] =
286 "Enabled";
287 }
288 }
289 }
290 },
291 s.first, path,
292 "org.freedesktop.DBus.Properties",
293 "GetAll",
294 "xyz.openbmc_project.Inventory.Item."
295 "Dimm");
296 }
297 else if (boost::ends_with(i, "Cpu"))
298 {
299 BMCWEB_LOG_DEBUG
300 << "Found Cpu, now get it properties.";
301 crow::connections::systemBus
302 ->async_method_call(
303 [&, aResp](
304 const boost::system::error_code
305 ec,
306 const std::vector<std::pair<
307 std::string, VariantType>>
308 &properties) {
309 if (ec)
310 {
311 BMCWEB_LOG_ERROR
312 << "DBUS response "
313 "error "
314 << ec;
315 aResp->setErrorStatus();
316 return;
317 }
318 BMCWEB_LOG_DEBUG
319 << "Got "
320 << properties.size()
321 << "Cpu properties.";
322 for (const auto &p : properties)
323 {
324 if (p.first ==
325 "ProcessorFamily")
326 {
327 const std::string
328 *value =
329 mapbox::getPtr<
330 const std::
331 string>(
332 p.second);
333 if (value != nullptr)
334 {
335 aResp->res.jsonValue
336 ["ProcessorSumm"
337 "ary"]
338 ["Count"] =
339 aResp->res
340 .jsonValue
341 ["Proce"
342 "ssorS"
343 "ummar"
344 "y"]
345 ["Coun"
346 "t"]
347 .get<
348 int>() +
349 1;
350 aResp->res.jsonValue
351 ["ProcessorSumm"
352 "ary"]
353 ["Status"]
354 ["State"] =
355 "Enabled";
356 aResp->res.jsonValue
357 ["ProcessorSumm"
358 "ary"]
359 ["Model"] =
360 *value;
361 }
362 }
363 }
364 },
365 s.first, path,
366 "org.freedesktop.DBus.Properties",
367 "GetAll",
368 "xyz.openbmc_project.Inventory."
369 "Item.Cpu");
370 }
371 else if (boost::ends_with(i, "UUID"))
372 {
373 BMCWEB_LOG_DEBUG
374 << "Found UUID, now get it properties.";
375 crow::connections::systemBus->async_method_call(
376 [aResp](
377 const boost::system::error_code ec,
378 const std::vector<std::pair<
379 std::string, VariantType>>
380 &properties) {
381 if (ec)
382 {
383 BMCWEB_LOG_DEBUG
384 << "DBUS response error "
385 << ec;
386 aResp->setErrorStatus();
387 return;
388 }
389 BMCWEB_LOG_DEBUG
390 << "Got " << properties.size()
391 << "UUID properties.";
392 for (const std::pair<std::string,
393 VariantType>
394 &p : properties)
395 {
396 if (p.first == "BIOSVer")
397 {
398 const std::string *value =
399 mapbox::getPtr<
400 const std::string>(
401 p.second);
402 if (value != nullptr)
403 {
404 aResp->res.jsonValue
405 ["BiosVersion"] =
406 *value;
407 }
408 }
409 if (p.first == "UUID")
410 {
411 const std::string *value =
412 mapbox::getPtr<
413 const std::string>(
414 p.second);
415 BMCWEB_LOG_DEBUG
416 << "UUID = " << *value
417 << " length "
418 << value->length();
419 if (value != nullptr)
420 {
421 // Workaround for to
422 // short return str in
423 // smbios demo app, 32
424 // bytes are described
425 // by spec
426 if (value->length() >
427 0 &&
428 value->length() <
429 32)
430 {
431 std::string
432 correctedValue =
433 *value;
434 correctedValue.append(
435 32 -
436 value
437 ->length(),
438 '0');
439 value =
440 &correctedValue;
441 }
442 else if (
443 value->length() ==
444 32)
445 {
446 aResp->res.jsonValue
447 ["UUID"] =
448 value->substr(
449 0, 8) +
450 "-" +
451 value->substr(
452 8, 4) +
453 "-" +
454 value->substr(
455 12, 4) +
456 "-" +
457 value->substr(
458 16, 4) +
459 "-" +
460 value->substr(
461 20, 12);
462 }
463 }
464 }
465 }
466 },
467 s.first, path,
468 "org.freedesktop.DBus.Properties",
469 "GetAll",
470 "xyz.openbmc_project.Common.UUID");
471 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200472 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700473 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200474 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200475 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700476 if (foundName == false)
477 {
478 aResp->setErrorStatus();
479 }
480 },
481 "xyz.openbmc_project.ObjectMapper",
482 "/xyz/openbmc_project/object_mapper",
483 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
484 "/xyz/openbmc_project/inventory", int32_t(0), interfaces);
485 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200486
Ed Tanous1abe55e2018-09-05 08:30:59 -0700487 /**
488 * @brief Retrieves identify led group properties over dbus
489 *
490 * @param[in] aResp Shared pointer for completing asynchronous calls.
491 * @param[in] callback Callback for process retrieved data.
492 *
493 * @return None.
494 */
495 template <typename CallbackFunc>
496 void getLedGroupIdentify(std::shared_ptr<SystemAsyncResp> aResp,
497 CallbackFunc &&callback)
498 {
499 BMCWEB_LOG_DEBUG << "Get led groups";
500 crow::connections::systemBus->async_method_call(
501 [aResp{std::move(aResp)},
502 &callback](const boost::system::error_code &ec,
503 const ManagedObjectsType &resp) {
504 if (ec)
505 {
506 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
507 aResp->setErrorStatus();
508 return;
509 }
510 BMCWEB_LOG_DEBUG << "Got " << resp.size()
511 << "led group objects.";
512 for (const auto &objPath : resp)
513 {
514 const std::string &path = objPath.first;
515 if (path.rfind("enclosure_identify") != std::string::npos)
516 {
517 for (const auto &interface : objPath.second)
518 {
519 if (interface.first ==
520 "xyz.openbmc_project.Led.Group")
521 {
522 for (const auto &property : interface.second)
523 {
524 if (property.first == "Asserted")
525 {
526 const bool *asserted =
527 mapbox::getPtr<const bool>(
528 property.second);
529 if (nullptr != asserted)
530 {
531 callback(*asserted, aResp);
532 }
533 else
534 {
535 callback(false, aResp);
536 }
537 }
538 }
539 }
540 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200541 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200542 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700543 },
544 "xyz.openbmc_project.LED.GroupManager",
545 "/xyz/openbmc_project/led/groups",
546 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
547 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200548
Ed Tanous1abe55e2018-09-05 08:30:59 -0700549 template <typename CallbackFunc>
550 void getLedIdentify(std::shared_ptr<SystemAsyncResp> aResp,
551 CallbackFunc &&callback)
552 {
553 BMCWEB_LOG_DEBUG << "Get identify led properties";
554 crow::connections::systemBus->async_method_call(
555 [aResp{std::move(aResp)},
556 &callback](const boost::system::error_code ec,
557 const PropertiesType &properties) {
558 if (ec)
559 {
560 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
561 aResp->setErrorStatus();
562 return;
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200563 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700564 BMCWEB_LOG_DEBUG << "Got " << properties.size()
565 << "led properties.";
566 std::string output;
567 for (const auto &property : properties)
568 {
569 if (property.first == "State")
570 {
571 const std::string *s =
572 mapbox::getPtr<std::string>(property.second);
573 if (nullptr != s)
574 {
575 BMCWEB_LOG_DEBUG << "Identify Led State: " << *s;
576 const auto pos = s->rfind('.');
577 if (pos != std::string::npos)
578 {
579 auto led = s->substr(pos + 1);
580 for (const std::pair<const char *, const char *>
581 &p :
582 std::array<
583 std::pair<const char *, const char *>,
584 3>{{{"On", "Lit"},
585 {"Blink", "Blinking"},
586 {"Off", "Off"}}})
587 {
588 if (led == p.first)
589 {
590 output = p.second;
591 }
592 }
593 }
594 }
595 }
596 }
597 callback(output, aResp);
598 },
599 "xyz.openbmc_project.LED.Controller.identify",
600 "/xyz/openbmc_project/led/physical/identify",
601 "org.freedesktop.DBus.Properties", "GetAll",
602 "xyz.openbmc_project.Led.Physical");
603 }
604
605 /**
606 * @brief Retrieves host state properties over dbus
607 *
608 * @param[in] aResp Shared pointer for completing asynchronous calls.
609 *
610 * @return None.
611 */
612 void getHostState(std::shared_ptr<SystemAsyncResp> aResp)
613 {
614 BMCWEB_LOG_DEBUG << "Get host information.";
615 crow::connections::systemBus->async_method_call(
616 [aResp{std::move(aResp)}](const boost::system::error_code ec,
617 const PropertiesType &properties) {
618 if (ec)
619 {
620 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
621 aResp->setErrorStatus();
622 return;
623 }
624 BMCWEB_LOG_DEBUG << "Got " << properties.size()
625 << "host properties.";
626 for (const auto &property : properties)
627 {
628 if (property.first == "CurrentHostState")
629 {
630 const std::string *s =
631 mapbox::getPtr<const std::string>(property.second);
632 BMCWEB_LOG_DEBUG << "Host state: " << *s;
633 if (nullptr != s)
634 {
635 const auto pos = s->rfind('.');
636 if (pos != std::string::npos)
637 {
638 // Verify Host State
639 if (s->substr(pos + 1) == "Running")
640 {
641 aResp->res.jsonValue["PowerState"] = "On";
642 aResp->res.jsonValue["Status"]["State"] =
643 "Enabled";
644 }
645 else
646 {
647 aResp->res.jsonValue["PowerState"] = "Off";
648 aResp->res.jsonValue["Status"]["State"] =
649 "Disabled";
650 }
651 }
652 }
653 }
654 }
655 },
656 "xyz.openbmc_project.State.Host",
657 "/xyz/openbmc_project/state/host0",
658 "org.freedesktop.DBus.Properties", "GetAll",
659 "xyz.openbmc_project.State.Host");
660 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200661};
662
663/**
664 * SystemsCollection derived class for delivering ComputerSystems Collection
665 * Schema
666 */
Ed Tanous1abe55e2018-09-05 08:30:59 -0700667class SystemsCollection : public Node
668{
669 public:
670 SystemsCollection(CrowApp &app) : Node(app, "/redfish/v1/Systems/")
671 {
672 Node::json["@odata.type"] =
673 "#ComputerSystemCollection.ComputerSystemCollection";
674 Node::json["@odata.id"] = "/redfish/v1/Systems";
675 Node::json["@odata.context"] =
676 "/redfish/v1/"
677 "$metadata#ComputerSystemCollection.ComputerSystemCollection";
678 Node::json["Name"] = "Computer System Collection";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200679
Ed Tanous1abe55e2018-09-05 08:30:59 -0700680 entityPrivileges = {
681 {boost::beast::http::verb::get, {{"Login"}}},
682 {boost::beast::http::verb::head, {{"Login"}}},
683 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
684 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
685 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
686 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
687 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200688
Ed Tanous1abe55e2018-09-05 08:30:59 -0700689 private:
690 /**
691 * Functions triggers appropriate requests on DBus
692 */
693 void doGet(crow::Response &res, const crow::Request &req,
694 const std::vector<std::string> &params) override
695 {
696 // Get board list, and call the below callback for JSON preparation
697 provider.getBaseboardList([&](const bool &success,
698 const std::vector<std::string> &output) {
699 if (success)
700 {
701 // ... prepare json array with appropriate @odata.id links
702 nlohmann::json boardArray = nlohmann::json::array();
703 for (const std::string &boardItem : output)
704 {
705 boardArray.push_back(
706 {{"@odata.id", "/redfish/v1/Systems/" + boardItem}});
707 }
708 // Then attach members, count size and return,
709 Node::json["Members"] = boardArray;
710 Node::json["Members@odata.count"] = boardArray.size();
711 res.jsonValue = Node::json;
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200712 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700713 else
714 {
715 // ... otherwise, return INTERNALL ERROR
716 res.result(boost::beast::http::status::internal_server_error);
717 }
718 res.end();
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200719 });
Ed Tanous1abe55e2018-09-05 08:30:59 -0700720 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200721
Ed Tanous1abe55e2018-09-05 08:30:59 -0700722 OnDemandSystemsProvider provider;
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200723};
724
725/**
726 * Systems override class for delivering ComputerSystems Schema
727 */
Ed Tanous1abe55e2018-09-05 08:30:59 -0700728class Systems : public Node
729{
730 public:
731 /*
732 * Default Constructor
733 */
734 Systems(CrowApp &app) :
735 Node(app, "/redfish/v1/Systems/<str>/", std::string())
736 {
737 Node::json["@odata.type"] = "#ComputerSystem.v1_3_0.ComputerSystem";
738 Node::json["@odata.context"] =
739 "/redfish/v1/$metadata#ComputerSystem.ComputerSystem";
740 Node::json["SystemType"] = "Physical";
741 Node::json["Description"] = "Computer System";
742 Node::json["Boot"]["BootSourceOverrideEnabled"] =
743 "Disabled"; // TODO(Dawid), get real boot data
744 Node::json["Boot"]["BootSourceOverrideTarget"] =
745 "None"; // TODO(Dawid), get real boot data
746 Node::json["Boot"]["BootSourceOverrideMode"] =
747 "Legacy"; // TODO(Dawid), get real boot data
748 Node::json["Boot"]["BootSourceOverrideTarget@Redfish.AllowableValues"] =
749 {"None", "Pxe", "Hdd", "Cd",
750 "BiosSetup", "UefiShell", "Usb"}; // TODO(Dawid), get real boot
751 // data
752 Node::json["ProcessorSummary"]["Count"] = int(0);
753 Node::json["ProcessorSummary"]["Status"]["State"] = "Disabled";
754 Node::json["MemorySummary"]["TotalSystemMemoryGiB"] = int(0);
755 Node::json["MemorySummary"]["Status"]["State"] = "Disabled";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200756
Ed Tanous1abe55e2018-09-05 08:30:59 -0700757 entityPrivileges = {
758 {boost::beast::http::verb::get, {{"Login"}}},
759 {boost::beast::http::verb::head, {{"Login"}}},
760 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
761 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
762 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
763 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200764 }
765
Ed Tanous1abe55e2018-09-05 08:30:59 -0700766 private:
767 OnDemandSystemsProvider provider;
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200768
Ed Tanous1abe55e2018-09-05 08:30:59 -0700769 /**
770 * Functions triggers appropriate requests on DBus
771 */
772 void doGet(crow::Response &res, const crow::Request &req,
773 const std::vector<std::string> &params) override
774 {
775 // Check if there is required param, truly entering this shall be
776 // impossible
777 if (params.size() != 1)
778 {
779 res.result(boost::beast::http::status::internal_server_error);
780 res.end();
781 return;
782 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200783
Ed Tanous1abe55e2018-09-05 08:30:59 -0700784 const std::string &name = params[0];
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200785
Ed Tanous1abe55e2018-09-05 08:30:59 -0700786 res.jsonValue = Node::json;
787 res.jsonValue["@odata.id"] = "/redfish/v1/Systems/" + name;
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200788
Ed Tanous1abe55e2018-09-05 08:30:59 -0700789 auto asyncResp = std::make_shared<SystemAsyncResp>(res);
790
791 provider.getLedGroupIdentify(
792 asyncResp, [&](const bool &asserted,
793 const std::shared_ptr<SystemAsyncResp> &aResp) {
794 if (asserted)
795 {
796 // If led group is asserted, then another call is needed to
797 // get led status
798 provider.getLedIdentify(
799 aResp,
800 [](const std::string &ledStatus,
801 const std::shared_ptr<SystemAsyncResp> &aResp) {
802 if (!ledStatus.empty())
803 {
804 aResp->res.jsonValue["IndicatorLED"] =
805 ledStatus;
806 }
807 });
808 }
809 else
810 {
811 aResp->res.jsonValue["IndicatorLED"] = "Off";
812 }
813 });
814 provider.getComputerSystem(asyncResp, name);
815 provider.getHostState(asyncResp);
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200816 }
817
Ed Tanous1abe55e2018-09-05 08:30:59 -0700818 void doPatch(crow::Response &res, const crow::Request &req,
819 const std::vector<std::string> &params) override
820 {
821 // Check if there is required param, truly entering this shall be
822 // impossible
823 if (params.size() != 1)
824 {
825 res.result(boost::beast::http::status::internal_server_error);
826 res.end();
827 return;
828 }
829 // Parse JSON request body
830 nlohmann::json patch;
831 if (!json_util::processJsonFromRequest(res, req, patch))
832 {
833 return;
834 }
835 // Find key with new led value
836 const std::string &name = params[0];
837 const std::string *reqLedState = nullptr;
838 json_util::Result r = json_util::getString(
839 "IndicatorLED", patch, reqLedState,
840 static_cast<int>(json_util::MessageSetting::TYPE_ERROR) |
841 static_cast<int>(json_util::MessageSetting::MISSING),
842 res.jsonValue, std::string("/" + name + "/IndicatorLED"));
843 if ((r != json_util::Result::SUCCESS) || (reqLedState == nullptr))
844 {
845 res.result(boost::beast::http::status::bad_request);
846 res.end();
847 return;
848 }
849 // Verify key value
850 std::string dbusLedState;
851 for (const auto &p :
852 boost::container::flat_map<const char *, const char *>{
853 {"On", "Lit"}, {"Blink", "Blinking"}, {"Off", "Off"}})
854 {
855 if (*reqLedState == p.second)
856 {
857 dbusLedState = p.first;
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200858 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700859 }
860
861 // Update led status
862 auto asyncResp = std::make_shared<SystemAsyncResp>(res);
863 res.jsonValue = Node::json;
864 res.jsonValue["@odata.id"] = "/redfish/v1/Systems/" + name;
865
866 provider.getHostState(asyncResp);
867 provider.getComputerSystem(asyncResp, name);
868
869 if (dbusLedState.empty())
870 {
871 messages::addMessageToJsonRoot(
872 res.jsonValue,
873 messages::propertyValueNotInList(*reqLedState, "IndicatorLED"));
874 }
875 else
876 {
877 // Update led group
878 BMCWEB_LOG_DEBUG << "Update led group.";
879 crow::connections::systemBus->async_method_call(
880 [&, asyncResp{std::move(asyncResp)}](
881 const boost::system::error_code ec) {
882 if (ec)
883 {
884 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
885 asyncResp->setErrorStatus();
886 return;
887 }
888 BMCWEB_LOG_DEBUG << "Led group update done.";
889 },
890 "xyz.openbmc_project.LED.GroupManager",
891 "/xyz/openbmc_project/led/groups/enclosure_identify",
892 "org.freedesktop.DBus.Properties", "Set",
893 "xyz.openbmc_project.Led.Group", "Asserted",
894 sdbusplus::message::variant<bool>(
895 (dbusLedState == "Off" ? false : true)));
896 // Update identify led status
897 BMCWEB_LOG_DEBUG << "Update led SoftwareInventoryCollection.";
898 crow::connections::systemBus->async_method_call(
899 [&, asyncResp{std::move(asyncResp)}](
900 const boost::system::error_code ec) {
901 if (ec)
902 {
903 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
904 asyncResp->setErrorStatus();
905 return;
906 }
907 BMCWEB_LOG_DEBUG << "Led state update done.";
908 res.jsonValue["IndicatorLED"] = *reqLedState;
909 },
910 "xyz.openbmc_project.LED.Controller.identify",
911 "/xyz/openbmc_project/led/physical/identify",
912 "org.freedesktop.DBus.Properties", "Set",
913 "xyz.openbmc_project.Led.Physical", "State",
914 sdbusplus::message::variant<std::string>(
915 "xyz.openbmc_project.Led.Physical.Action." + dbusLedState));
916 }
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