xref: /openbmc/bmcweb/features/redfish/lib/systems.hpp (revision 04a258f40c26565b4042a32b5c9b5f2414dae0df)
1 /*
2 // Copyright (c) 2018 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 */
16 #pragma once
17 
18 #include "boost/container/flat_map.hpp"
19 #include "node.hpp"
20 
21 #include <utils/json_utils.hpp>
22 
23 namespace redfish
24 {
25 
26 /**
27  * @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  */
34 void getComputerSystem(std::shared_ptr<AsyncResp> aResp,
35                        const std::string &name)
36 {
37     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 (const auto &connection : connectionNames)
114                     {
115                         for (const auto &interfaceName : connection.second)
116                         {
117                             if (interfaceName ==
118                                 "xyz.openbmc_project.Inventory.Item.Dimm")
119                             {
120                                 BMCWEB_LOG_DEBUG
121                                     << "Found Dimm, now get its properties.";
122                                 crow::connections::systemBus->async_method_call(
123                                     [aResp](
124                                         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.";
140                                         for (const std::pair<std::string,
141                                                              VariantType>
142                                                  &property : properties)
143                                         {
144                                             if (property.first ==
145                                                 "MemorySizeInKb")
146                                             {
147                                                 const uint64_t *value =
148                                                     mapbox::getPtr<
149                                                         const uint64_t>(
150                                                         property.second);
151                                                 if (value != nullptr)
152                                                 {
153                                                     aResp->res.jsonValue
154                                                         ["TotalSystemMemoryGi"
155                                                          "B"] +=
156                                                         *value / (1024 * 1024);
157                                                     aResp->res.jsonValue
158                                                         ["MemorySummary"]
159                                                         ["Status"]["State"] =
160                                                         "Enabled";
161                                                 }
162                                             }
163                                         }
164                                     },
165                                     connection.first, path,
166                                     "org.freedesktop.DBus.Properties", "GetAll",
167                                     "xyz.openbmc_project.Inventory.Item.Dimm");
168                             }
169                             else if (interfaceName ==
170                                      "xyz.openbmc_project.Inventory.Item.Cpu")
171                             {
172                                 BMCWEB_LOG_DEBUG
173                                     << "Found Cpu, now get its properties.";
174                                 crow::connections::systemBus->async_method_call(
175                                     [aResp](
176                                         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.";
192                                         for (const auto &property : properties)
193                                         {
194                                             if (property.first ==
195                                                 "ProcessorFamily")
196                                             {
197                                                 const std::string *value =
198                                                     mapbox::getPtr<
199                                                         const std::string>(
200                                                         property.second);
201                                                 if (value != nullptr)
202                                                 {
203                                                     nlohmann::json
204                                                         &procSummary =
205                                                             aResp->res.jsonValue
206                                                                 ["ProcessorSumm"
207                                                                  "ary"];
208                                                     nlohmann::json &procCount =
209                                                         procSummary["Count"];
210 
211                                                     procCount =
212                                                         procCount.get<int>() +
213                                                         1;
214                                                     procSummary["Status"]
215                                                                ["State"] =
216                                                                    "Enabled";
217                                                     procSummary["Model"] =
218                                                         *value;
219                                                 }
220                                             }
221                                         }
222                                     },
223                                     connection.first, path,
224                                     "org.freedesktop.DBus.Properties", "GetAll",
225                                     "xyz.openbmc_project.Inventory.Item.Cpu");
226                             }
227                             else if (interfaceName ==
228                                      "xyz.openbmc_project.Common.UUID")
229                             {
230                                 BMCWEB_LOG_DEBUG
231                                     << "Found UUID, now get its properties.";
232                                 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,
251                                                              VariantType>
252                                                  &property : properties)
253                                         {
254                                             if (property.first == "BIOSVer")
255                                             {
256                                                 const std::string *value =
257                                                     mapbox::getPtr<
258                                                         const std::string>(
259                                                         property.second);
260                                                 if (value != nullptr)
261                                                 {
262                                                     aResp->res.jsonValue
263                                                         ["BiosVersion"] =
264                                                         *value;
265                                                 }
266                                             }
267                                             if (property.first == "UUID")
268                                             {
269                                                 const std::string *value =
270                                                     mapbox::getPtr<
271                                                         const std::string>(
272                                                         property.second);
273 
274                                                 if (value != nullptr)
275                                                 {
276                                                     std::string valueStr =
277                                                         *value;
278                                                     if (valueStr.size() == 32)
279                                                     {
280                                                         valueStr.insert(8, 1,
281                                                                         '-');
282                                                         valueStr.insert(13, 1,
283                                                                         '-');
284                                                         valueStr.insert(18, 1,
285                                                                         '-');
286                                                         valueStr.insert(23, 1,
287                                                                         '-');
288                                                     }
289                                                     BMCWEB_LOG_DEBUG
290                                                         << "UUID = "
291                                                         << valueStr;
292                                                     aResp->res
293                                                         .jsonValue["UUID"] =
294                                                         valueStr;
295                                                 }
296                                             }
297                                         }
298                                     },
299                                     connection.first, path,
300                                     "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",
316         "/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         });
324 }
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  */
334 template <typename CallbackFunc>
335 void 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)},
341          callback{std::move(callback)}](const boost::system::error_code &ec,
342                                         const ManagedObjectsType &resp) {
343             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 
387 template <typename CallbackFunc>
388 void getLedIdentify(std::shared_ptr<AsyncResp> aResp, CallbackFunc &&callback)
389 {
390     BMCWEB_LOG_DEBUG << "Get identify led properties";
391     crow::connections::systemBus->async_method_call(
392         [aResp,
393          callback{std::move(callback)}](const boost::system::error_code ec,
394                                         const PropertiesType &properties) {
395             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  */
450 void getHostState(std::shared_ptr<AsyncResp> aResp)
451 {
452     BMCWEB_LOG_DEBUG << "Get host information.";
453     crow::connections::systemBus->async_method_call(
454         [aResp{std::move(aResp)}](
455             const boost::system::error_code ec,
456             const sdbusplus::message::variant<std::string> &hostState) {
457             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             }
464 
465             const std::string *s = mapbox::getPtr<const std::string>(hostState);
466             BMCWEB_LOG_DEBUG << "Host state: " << *s;
467             if (s != nullptr)
468             {
469                 // Verify Host State
470                 if (*s == "xyz.openbmc_project.State.Host.Running")
471                 {
472                     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";
479                 }
480             }
481         },
482         "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
483         "org.freedesktop.DBus.Properties", "Get",
484         "xyz.openbmc_project.State.Host", "CurrentHostState");
485 }
486 
487 /**
488  * SystemsCollection derived class for delivering ComputerSystems Collection
489  * Schema
490  */
491 class 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";
503 
504         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     }
512 
513   private:
514     void doGet(crow::Response &res, const crow::Request &req,
515                const std::vector<std::string> &params) override
516     {
517         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)
524                 {
525                     asyncResp->res.result(
526                         boost::beast::http::status::internal_server_error);
527                     return;
528                 }
529                 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"});
557     }
558 };
559 
560 /**
561  * SystemActionsReset class supports handle POST method for Reset action.
562  * The class retrieves and sends data directly to D-Bus.
563  */
564 class 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 /**
702  * Systems derived class for delivering Computer Systems Schema.
703  */
704 class 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
728         Node::json["ProcessorSummary"]["Count"] = 0;
729         Node::json["ProcessorSummary"]["Status"]["State"] = "Disabled";
730         Node::json["MemorySummary"]["TotalSystemMemoryGiB"] = int(0);
731         Node::json["MemorySummary"]["Status"]["State"] = "Disabled";
732         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"}}}};
739     }
740 
741   private:
742     /**
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         }
756 
757         const std::string &name = params[0];
758 
759         res.jsonValue = Node::json;
760         res.jsonValue["@odata.id"] = "/redfish/v1/Systems/" + name;
761 
762         // 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"}}};
768 
769         auto asyncResp = std::make_shared<AsyncResp>(res);
770 
771         getLedGroupIdentify(
772             asyncResp,
773             [&](const bool &asserted, const std::shared_ptr<AsyncResp> &aResp) {
774                 if (asserted)
775                 {
776                     // If led group is asserted, then another call is needed to
777                     // get led status
778                     getLedIdentify(
779                         aResp, [](const std::string &ledStatus,
780                                   const std::shared_ptr<AsyncResp> &aResp) {
781                             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             });
793         getComputerSystem(asyncResp, name);
794         getHostState(asyncResp);
795     }
796 
797     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
802         auto asyncResp = std::make_shared<AsyncResp>(res);
803         if (params.size() != 1)
804         {
805             res.result(boost::beast::http::status::internal_server_error);
806             return;
807         }
808         // Parse JSON request body
809         nlohmann::json patch;
810         if (!json_util::processJsonFromRequest(res, req, patch))
811         {
812             return;
813         }
814 
815         const std::string &name = params[0];
816 
817         res.jsonValue = Node::json;
818         res.jsonValue["@odata.id"] = "/redfish/v1/Systems/" + name;
819 
820         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                 }
834 
835                 // 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             }
916         }
917     }
918 };
919 } // namespace redfish
920