xref: /openbmc/bmcweb/redfish-core/lib/systems.hpp (revision 530520ea)
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 #include <utils/json_utils.hpp>
21 
22 namespace redfish
23 {
24 
25 /**
26  * @brief Retrieves computer system properties over dbus
27  *
28  * @param[in] aResp Shared pointer for completing asynchronous calls
29  * @param[in] name  Computer system name from request
30  *
31  * @return None.
32  */
33 void getComputerSystem(std::shared_ptr<AsyncResp> aResp,
34                        const std::string &name)
35 {
36     BMCWEB_LOG_DEBUG << "Get available system components.";
37     crow::connections::systemBus->async_method_call(
38         [name, aResp{std::move(aResp)}](
39             const boost::system::error_code ec,
40             const std::vector<std::pair<
41                 std::string,
42                 std::vector<std::pair<std::string, std::vector<std::string>>>>>
43                 &subtree) {
44             if (ec)
45             {
46                 BMCWEB_LOG_DEBUG << "DBUS response error";
47                 messages::internalError(aResp->res);
48                 return;
49             }
50             bool foundName = false;
51             // Iterate over all retrieved ObjectPaths.
52             for (const std::pair<std::string,
53                                  std::vector<std::pair<
54                                      std::string, std::vector<std::string>>>>
55                      &object : subtree)
56             {
57                 const std::string &path = object.first;
58                 BMCWEB_LOG_DEBUG << "Got path: " << path;
59                 const std::vector<
60                     std::pair<std::string, std::vector<std::string>>>
61                     &connectionNames = object.second;
62                 if (connectionNames.size() < 1)
63                 {
64                     continue;
65                 }
66                 // Check if computer system exist
67                 if (boost::ends_with(path, name))
68                 {
69                     foundName = true;
70                     BMCWEB_LOG_DEBUG << "Found name: " << name;
71                     const std::string connectionName = connectionNames[0].first;
72                     crow::connections::systemBus->async_method_call(
73                         [aResp, name(std::string(name))](
74                             const boost::system::error_code ec,
75                             const std::vector<std::pair<
76                                 std::string, VariantType>> &propertiesList) {
77                             if (ec)
78                             {
79                                 BMCWEB_LOG_ERROR << "DBUS response error: "
80                                                  << ec;
81                                 messages::internalError(aResp->res);
82                                 return;
83                             }
84                             BMCWEB_LOG_DEBUG << "Got " << propertiesList.size()
85                                              << "properties for system";
86                             for (const std::pair<std::string, VariantType>
87                                      &property : propertiesList)
88                             {
89                                 const std::string *value =
90                                     sdbusplus::message::variant_ns::get_if<
91                                         std::string>(&property.second);
92                                 if (value != nullptr)
93                                 {
94                                     aResp->res.jsonValue[property.first] =
95                                         *value;
96                                 }
97                             }
98                             aResp->res.jsonValue["Name"] = name;
99                             aResp->res.jsonValue["Id"] =
100                                 aResp->res.jsonValue["SerialNumber"];
101                         },
102                         connectionName, path, "org.freedesktop.DBus.Properties",
103                         "GetAll",
104                         "xyz.openbmc_project.Inventory.Decorator.Asset");
105                 }
106                 else
107                 {
108                     // This is not system, so check if it's cpu, dimm, UUID or
109                     // BiosVer
110                     for (const auto &connection : connectionNames)
111                     {
112                         for (const auto &interfaceName : connection.second)
113                         {
114                             if (interfaceName ==
115                                 "xyz.openbmc_project.Inventory.Item.Dimm")
116                             {
117                                 BMCWEB_LOG_DEBUG
118                                     << "Found Dimm, now get its properties.";
119                                 crow::connections::systemBus->async_method_call(
120                                     [aResp](
121                                         const boost::system::error_code ec,
122                                         const std::vector<
123                                             std::pair<std::string, VariantType>>
124                                             &properties) {
125                                         if (ec)
126                                         {
127                                             BMCWEB_LOG_ERROR
128                                                 << "DBUS response error " << ec;
129                                             messages::internalError(aResp->res);
130                                             return;
131                                         }
132                                         BMCWEB_LOG_DEBUG << "Got "
133                                                          << properties.size()
134                                                          << "Dimm properties.";
135                                         for (const std::pair<std::string,
136                                                              VariantType>
137                                                  &property : properties)
138                                         {
139                                             if (property.first ==
140                                                 "MemorySizeInKb")
141                                             {
142                                                 const uint64_t *value =
143                                                     sdbusplus::message::
144                                                         variant_ns::get_if<
145                                                             uint64_t>(
146                                                             &property.second);
147                                                 if (value != nullptr)
148                                                 {
149                                                     aResp->res.jsonValue
150                                                         ["TotalSystemMemoryGi"
151                                                          "B"] +=
152                                                         *value / (1024 * 1024);
153                                                     aResp->res.jsonValue
154                                                         ["MemorySummary"]
155                                                         ["Status"]["State"] =
156                                                         "Enabled";
157                                                 }
158                                             }
159                                         }
160                                     },
161                                     connection.first, path,
162                                     "org.freedesktop.DBus.Properties", "GetAll",
163                                     "xyz.openbmc_project.Inventory.Item.Dimm");
164                             }
165                             else if (interfaceName ==
166                                      "xyz.openbmc_project.Inventory.Item.Cpu")
167                             {
168                                 BMCWEB_LOG_DEBUG
169                                     << "Found Cpu, now get its properties.";
170                                 crow::connections::systemBus->async_method_call(
171                                     [aResp](
172                                         const boost::system::error_code ec,
173                                         const std::vector<
174                                             std::pair<std::string, VariantType>>
175                                             &properties) {
176                                         if (ec)
177                                         {
178                                             BMCWEB_LOG_ERROR
179                                                 << "DBUS response error " << ec;
180                                             messages::internalError(aResp->res);
181                                             return;
182                                         }
183                                         BMCWEB_LOG_DEBUG << "Got "
184                                                          << properties.size()
185                                                          << "Cpu properties.";
186                                         for (const auto &property : properties)
187                                         {
188                                             if (property.first ==
189                                                 "ProcessorFamily")
190                                             {
191                                                 const std::string *value =
192                                                     sdbusplus::message::
193                                                         variant_ns::get_if<
194                                                             std::string>(
195                                                             &property.second);
196                                                 if (value != nullptr)
197                                                 {
198                                                     nlohmann::json
199                                                         &procSummary =
200                                                             aResp->res.jsonValue
201                                                                 ["ProcessorSumm"
202                                                                  "ary"];
203                                                     nlohmann::json &procCount =
204                                                         procSummary["Count"];
205 
206                                                     procCount =
207                                                         procCount.get<int>() +
208                                                         1;
209                                                     procSummary["Status"]
210                                                                ["State"] =
211                                                                    "Enabled";
212                                                     procSummary["Model"] =
213                                                         *value;
214                                                 }
215                                             }
216                                         }
217                                     },
218                                     connection.first, path,
219                                     "org.freedesktop.DBus.Properties", "GetAll",
220                                     "xyz.openbmc_project.Inventory.Item.Cpu");
221                             }
222                             else if (interfaceName ==
223                                      "xyz.openbmc_project.Common.UUID")
224                             {
225                                 BMCWEB_LOG_DEBUG
226                                     << "Found UUID, now get its properties.";
227                                 crow::connections::systemBus->async_method_call(
228                                     [aResp](
229                                         const boost::system::error_code ec,
230                                         const std::vector<
231                                             std::pair<std::string, VariantType>>
232                                             &properties) {
233                                         if (ec)
234                                         {
235                                             BMCWEB_LOG_DEBUG
236                                                 << "DBUS response error " << ec;
237                                             messages::internalError(aResp->res);
238                                             return;
239                                         }
240                                         BMCWEB_LOG_DEBUG << "Got "
241                                                          << properties.size()
242                                                          << "UUID properties.";
243                                         for (const std::pair<std::string,
244                                                              VariantType>
245                                                  &property : properties)
246                                         {
247                                             if (property.first == "BIOSVer")
248                                             {
249                                                 const std::string *value =
250                                                     sdbusplus::message::
251                                                         variant_ns::get_if<
252                                                             std::string>(
253                                                             &property.second);
254                                                 if (value != nullptr)
255                                                 {
256                                                     aResp->res.jsonValue
257                                                         ["BiosVersion"] =
258                                                         *value;
259                                                 }
260                                             }
261                                             if (property.first == "UUID")
262                                             {
263                                                 const std::string *value =
264                                                     sdbusplus::message::
265                                                         variant_ns::get_if<
266                                                             std::string>(
267                                                             &property.second);
268 
269                                                 if (value != nullptr)
270                                                 {
271                                                     std::string valueStr =
272                                                         *value;
273                                                     if (valueStr.size() == 32)
274                                                     {
275                                                         valueStr.insert(8, 1,
276                                                                         '-');
277                                                         valueStr.insert(13, 1,
278                                                                         '-');
279                                                         valueStr.insert(18, 1,
280                                                                         '-');
281                                                         valueStr.insert(23, 1,
282                                                                         '-');
283                                                     }
284                                                     BMCWEB_LOG_DEBUG
285                                                         << "UUID = "
286                                                         << valueStr;
287                                                     aResp->res
288                                                         .jsonValue["UUID"] =
289                                                         valueStr;
290                                                 }
291                                             }
292                                         }
293                                     },
294                                     connection.first, path,
295                                     "org.freedesktop.DBus.Properties", "GetAll",
296                                     "xyz.openbmc_project.Common.UUID");
297                             }
298                         }
299                     }
300                 }
301             }
302             if (foundName == false)
303             {
304                 messages::internalError(aResp->res);
305             }
306         },
307         "xyz.openbmc_project.ObjectMapper",
308         "/xyz/openbmc_project/object_mapper",
309         "xyz.openbmc_project.ObjectMapper", "GetSubTree",
310         "/xyz/openbmc_project/inventory", int32_t(0),
311         std::array<const char *, 5>{
312             "xyz.openbmc_project.Inventory.Decorator.Asset",
313             "xyz.openbmc_project.Inventory.Item.Cpu",
314             "xyz.openbmc_project.Inventory.Item.Dimm",
315             "xyz.openbmc_project.Inventory.Item.System",
316             "xyz.openbmc_project.Common.UUID",
317         });
318 }
319 
320 /**
321  * @brief Retrieves identify led group properties over dbus
322  *
323  * @param[in] aResp     Shared pointer for completing asynchronous calls.
324  * @param[in] callback  Callback for process retrieved data.
325  *
326  * @return None.
327  */
328 template <typename CallbackFunc>
329 void getLedGroupIdentify(std::shared_ptr<AsyncResp> aResp,
330                          CallbackFunc &&callback)
331 {
332     BMCWEB_LOG_DEBUG << "Get led groups";
333     crow::connections::systemBus->async_method_call(
334         [aResp{std::move(aResp)},
335          callback{std::move(callback)}](const boost::system::error_code &ec,
336                                         const ManagedObjectsType &resp) {
337             if (ec)
338             {
339                 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
340                 messages::internalError(aResp->res);
341                 return;
342             }
343             BMCWEB_LOG_DEBUG << "Got " << resp.size() << "led group objects.";
344             for (const auto &objPath : resp)
345             {
346                 const std::string &path = objPath.first;
347                 if (path.rfind("enclosure_identify") != std::string::npos)
348                 {
349                     for (const auto &interface : objPath.second)
350                     {
351                         if (interface.first == "xyz.openbmc_project.Led.Group")
352                         {
353                             for (const auto &property : interface.second)
354                             {
355                                 if (property.first == "Asserted")
356                                 {
357                                     const bool *asserted =
358                                         sdbusplus::message::variant_ns::get_if<
359                                             bool>(&property.second);
360                                     if (nullptr != asserted)
361                                     {
362                                         callback(*asserted, aResp);
363                                     }
364                                     else
365                                     {
366                                         callback(false, aResp);
367                                     }
368                                 }
369                             }
370                         }
371                     }
372                 }
373             }
374         },
375         "xyz.openbmc_project.LED.GroupManager",
376         "/xyz/openbmc_project/led/groups", "org.freedesktop.DBus.ObjectManager",
377         "GetManagedObjects");
378 }
379 
380 template <typename CallbackFunc>
381 void getLedIdentify(std::shared_ptr<AsyncResp> aResp, CallbackFunc &&callback)
382 {
383     BMCWEB_LOG_DEBUG << "Get identify led properties";
384     crow::connections::systemBus->async_method_call(
385         [aResp,
386          callback{std::move(callback)}](const boost::system::error_code ec,
387                                         const PropertiesType &properties) {
388             if (ec)
389             {
390                 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
391                 messages::internalError(aResp->res);
392                 return;
393             }
394             BMCWEB_LOG_DEBUG << "Got " << properties.size()
395                              << "led properties.";
396             std::string output;
397             for (const auto &property : properties)
398             {
399                 if (property.first == "State")
400                 {
401                     const std::string *s =
402                         sdbusplus::message::variant_ns::get_if<std::string>(
403                             &property.second);
404                     if (nullptr != s)
405                     {
406                         BMCWEB_LOG_DEBUG << "Identify Led State: " << *s;
407                         const auto pos = s->rfind('.');
408                         if (pos != std::string::npos)
409                         {
410                             auto led = s->substr(pos + 1);
411                             for (const std::pair<const char *, const char *>
412                                      &p :
413                                  std::array<
414                                      std::pair<const char *, const char *>, 3>{
415                                      {{"On", "Lit"},
416                                       {"Blink", "Blinking"},
417                                       {"Off", "Off"}}})
418                             {
419                                 if (led == p.first)
420                                 {
421                                     output = p.second;
422                                 }
423                             }
424                         }
425                     }
426                 }
427             }
428             callback(output, aResp);
429         },
430         "xyz.openbmc_project.LED.Controller.identify",
431         "/xyz/openbmc_project/led/physical/identify",
432         "org.freedesktop.DBus.Properties", "GetAll",
433         "xyz.openbmc_project.Led.Physical");
434 }
435 
436 /**
437  * @brief Retrieves host state properties over dbus
438  *
439  * @param[in] aResp     Shared pointer for completing asynchronous calls.
440  *
441  * @return None.
442  */
443 void getHostState(std::shared_ptr<AsyncResp> aResp)
444 {
445     BMCWEB_LOG_DEBUG << "Get host information.";
446     crow::connections::systemBus->async_method_call(
447         [aResp{std::move(aResp)}](
448             const boost::system::error_code ec,
449             const sdbusplus::message::variant<std::string> &hostState) {
450             if (ec)
451             {
452                 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
453                 messages::internalError(aResp->res);
454                 return;
455             }
456 
457             const std::string *s =
458                 sdbusplus::message::variant_ns::get_if<std::string>(&hostState);
459             BMCWEB_LOG_DEBUG << "Host state: " << *s;
460             if (s != nullptr)
461             {
462                 // Verify Host State
463                 if (*s == "xyz.openbmc_project.State.Host.Running")
464                 {
465                     aResp->res.jsonValue["PowerState"] = "On";
466                     aResp->res.jsonValue["Status"]["State"] = "Enabled";
467                 }
468                 else
469                 {
470                     aResp->res.jsonValue["PowerState"] = "Off";
471                     aResp->res.jsonValue["Status"]["State"] = "Disabled";
472                 }
473             }
474         },
475         "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
476         "org.freedesktop.DBus.Properties", "Get",
477         "xyz.openbmc_project.State.Host", "CurrentHostState");
478 }
479 
480 /**
481  * SystemsCollection derived class for delivering ComputerSystems Collection
482  * Schema
483  */
484 class SystemsCollection : public Node
485 {
486   public:
487     SystemsCollection(CrowApp &app) : Node(app, "/redfish/v1/Systems/")
488     {
489         entityPrivileges = {
490             {boost::beast::http::verb::get, {{"Login"}}},
491             {boost::beast::http::verb::head, {{"Login"}}},
492             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
493             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
494             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
495             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
496     }
497 
498   private:
499     void doGet(crow::Response &res, const crow::Request &req,
500                const std::vector<std::string> &params) override
501     {
502         BMCWEB_LOG_DEBUG << "Get list of available boards.";
503         std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
504         res.jsonValue["@odata.type"] =
505             "#ComputerSystemCollection.ComputerSystemCollection";
506         res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
507         res.jsonValue["@odata.context"] =
508             "/redfish/v1/"
509             "$metadata#ComputerSystemCollection.ComputerSystemCollection";
510         res.jsonValue["Name"] = "Computer System Collection";
511         crow::connections::systemBus->async_method_call(
512             [asyncResp](const boost::system::error_code ec,
513                         const std::vector<std::string> &resp) {
514                 if (ec)
515                 {
516                     messages::internalError(asyncResp->res);
517                     return;
518                 }
519                 BMCWEB_LOG_DEBUG << "Got " << resp.size() << " boards.";
520 
521                 // ... prepare json array with appropriate @odata.id links
522                 nlohmann::json &boardArray =
523                     asyncResp->res.jsonValue["Members"];
524                 boardArray = nlohmann::json::array();
525 
526                 // Iterate over all retrieved ObjectPaths.
527                 for (const std::string &objpath : resp)
528                 {
529                     std::size_t lastPos = objpath.rfind("/");
530                     if (lastPos != std::string::npos)
531                     {
532                         boardArray.push_back(
533                             {{"@odata.id", "/redfish/v1/Systems/" +
534                                                objpath.substr(lastPos + 1)}});
535                     }
536                 }
537 
538                 asyncResp->res.jsonValue["Members@odata.count"] =
539                     boardArray.size();
540             },
541             "xyz.openbmc_project.ObjectMapper",
542             "/xyz/openbmc_project/object_mapper",
543             "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
544             "/xyz/openbmc_project/inventory", int32_t(0),
545             std::array<const char *, 1>{
546                 "xyz.openbmc_project.Inventory.Item.Board"});
547     }
548 };
549 
550 /**
551  * SystemActionsReset class supports handle POST method for Reset action.
552  * The class retrieves and sends data directly to D-Bus.
553  */
554 class SystemActionsReset : public Node
555 {
556   public:
557     SystemActionsReset(CrowApp &app) :
558         Node(app, "/redfish/v1/Systems/<str>/Actions/ComputerSystem.Reset/",
559              std::string())
560     {
561         entityPrivileges = {
562             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
563     }
564 
565   private:
566     /**
567      * Function handles POST method request.
568      * Analyzes POST body message before sends Reset request data to D-Bus.
569      */
570     void doPost(crow::Response &res, const crow::Request &req,
571                 const std::vector<std::string> &params) override
572     {
573         auto asyncResp = std::make_shared<AsyncResp>(res);
574 
575         std::string resetType;
576         if (!json_util::readJson(req, res, "ResetType", resetType))
577         {
578             return;
579         }
580 
581         if (resetType == "ForceOff")
582         {
583             // Force off acts on the chassis
584             crow::connections::systemBus->async_method_call(
585                 [asyncResp](const boost::system::error_code ec) {
586                     if (ec)
587                     {
588                         BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
589                         messages::internalError(asyncResp->res);
590                         return;
591                     }
592                     // TODO Consider support polling mechanism to verify
593                     // status of host and chassis after execute the
594                     // requested action.
595                     messages::success(asyncResp->res);
596                 },
597                 "xyz.openbmc_project.State.Chassis",
598                 "/xyz/openbmc_project/state/chassis0",
599                 "org.freedesktop.DBus.Properties", "Set",
600                 "xyz.openbmc_project.State.Chassis", "RequestedPowerTransition",
601                 sdbusplus::message::variant<std::string>{
602                     "xyz.openbmc_project.State.Chassis.Transition.Off"});
603             return;
604         }
605         // all other actions operate on the host
606         std::string command;
607         // Execute Reset Action regarding to each reset type.
608         if (resetType == "On")
609         {
610             command = "xyz.openbmc_project.State.Host.Transition.On";
611         }
612         else if (resetType == "GracefulShutdown")
613         {
614             command = "xyz.openbmc_project.State.Host.Transition.Off";
615         }
616         else if (resetType == "GracefulRestart")
617         {
618             command = "xyz.openbmc_project.State.Host.Transition.Reboot";
619         }
620         else
621         {
622             messages::actionParameterUnknown(res, "Reset", resetType);
623             return;
624         }
625 
626         crow::connections::systemBus->async_method_call(
627             [asyncResp](const boost::system::error_code ec) {
628                 if (ec)
629                 {
630                     BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
631                     messages::internalError(asyncResp->res);
632                     return;
633                 }
634                 // TODO Consider support polling mechanism to verify
635                 // status of host and chassis after execute the
636                 // requested action.
637                 messages::success(asyncResp->res);
638             },
639             "xyz.openbmc_project.State.Host",
640             "/xyz/openbmc_project/state/host0",
641             "org.freedesktop.DBus.Properties", "Set",
642             "xyz.openbmc_project.State.Host", "RequestedHostTransition",
643             sdbusplus::message::variant<std::string>{command});
644     }
645 };
646 
647 /**
648  * Systems derived class for delivering Computer Systems Schema.
649  */
650 class Systems : public Node
651 {
652   public:
653     /*
654      * Default Constructor
655      */
656     Systems(CrowApp &app) :
657         Node(app, "/redfish/v1/Systems/<str>/", std::string())
658     {
659         entityPrivileges = {
660             {boost::beast::http::verb::get, {{"Login"}}},
661             {boost::beast::http::verb::head, {{"Login"}}},
662             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
663             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
664             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
665             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
666     }
667 
668   private:
669     /**
670      * Functions triggers appropriate requests on DBus
671      */
672     void doGet(crow::Response &res, const crow::Request &req,
673                const std::vector<std::string> &params) override
674     {
675         // Check if there is required param, truly entering this shall be
676         // impossible
677         if (params.size() != 1)
678         {
679             messages::internalError(res);
680             res.end();
681             return;
682         }
683 
684         const std::string &name = params[0];
685 
686         res.jsonValue["@odata.type"] = "#ComputerSystem.v1_3_0.ComputerSystem";
687         res.jsonValue["@odata.context"] =
688             "/redfish/v1/$metadata#ComputerSystem.ComputerSystem";
689         res.jsonValue["SystemType"] = "Physical";
690         res.jsonValue["Description"] = "Computer System";
691         res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
692             "Disabled"; // TODO(Dawid), get real boot data
693         res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
694             "None"; // TODO(Dawid), get real boot data
695         res.jsonValue["Boot"]["BootSourceOverrideMode"] =
696             "Legacy"; // TODO(Dawid), get real boot data
697         res.jsonValue["Boot"]
698                      ["BootSourceOverrideTarget@Redfish.AllowableValues"] = {
699             "None",      "Pxe",       "Hdd", "Cd",
700             "BiosSetup", "UefiShell", "Usb"}; // TODO(Dawid), get real boot
701                                               // data
702         res.jsonValue["ProcessorSummary"]["Count"] = 0;
703         res.jsonValue["ProcessorSummary"]["Status"]["State"] = "Disabled";
704         res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] = int(0);
705         res.jsonValue["MemorySummary"]["Status"]["State"] = "Disabled";
706         res.jsonValue["@odata.id"] = "/redfish/v1/Systems/" + name;
707 
708         res.jsonValue["Processors"] = {
709             {"@odata.id", "/redfish/v1/Systems/" + name + "/Processors"}};
710         res.jsonValue["Memory"] = {
711             {"@odata.id", "/redfish/v1/Systems/" + name + "/Memory"}};
712         // TODO Need to support ForceRestart.
713         res.jsonValue["Actions"]["#ComputerSystem.Reset"] = {
714             {"target",
715              "/redfish/v1/Systems/" + name + "/Actions/ComputerSystem.Reset"},
716             {"ResetType@Redfish.AllowableValues",
717              {"On", "ForceOff", "GracefulRestart", "GracefulShutdown"}}};
718 
719         res.jsonValue["LogServices"] = {
720             {"@odata.id", "/redfish/v1/Systems/" + name + "/LogServices"}};
721 
722         auto asyncResp = std::make_shared<AsyncResp>(res);
723 
724         getLedGroupIdentify(
725             asyncResp,
726             [&](const bool &asserted, const std::shared_ptr<AsyncResp> &aResp) {
727                 if (asserted)
728                 {
729                     // If led group is asserted, then another call is needed to
730                     // get led status
731                     getLedIdentify(
732                         aResp, [](const std::string &ledStatus,
733                                   const std::shared_ptr<AsyncResp> &aResp) {
734                             if (!ledStatus.empty())
735                             {
736                                 aResp->res.jsonValue["IndicatorLED"] =
737                                     ledStatus;
738                             }
739                         });
740                 }
741                 else
742                 {
743                     aResp->res.jsonValue["IndicatorLED"] = "Off";
744                 }
745             });
746         getComputerSystem(asyncResp, name);
747         getHostState(asyncResp);
748     }
749 
750     void doPatch(crow::Response &res, const crow::Request &req,
751                  const std::vector<std::string> &params) override
752     {
753         // Check if there is required param, truly entering this shall be
754         // impossible
755         auto asyncResp = std::make_shared<AsyncResp>(res);
756         if (params.size() != 1)
757         {
758             messages::internalError(asyncResp->res);
759             return;
760         }
761 
762         const std::string &name = params[0];
763 
764         messages::success(asyncResp->res);
765 
766         std::string indicatorLedTemp;
767         std::optional<std::string> indicatorLed = indicatorLedTemp;
768         if (!json_util::readJson(req, res, "IndicatorLed", indicatorLed))
769         {
770             return;
771         }
772 
773         if (indicatorLed)
774         {
775             std::string dbusLedState;
776             if (*indicatorLed == "On")
777             {
778                 dbusLedState = "xyz.openbmc_project.Led.Physical.Action.Lit";
779             }
780             else if (*indicatorLed == "Blink")
781             {
782                 dbusLedState =
783                     "xyz.openbmc_project.Led.Physical.Action.Blinking";
784             }
785             else if (*indicatorLed == "Off")
786             {
787                 dbusLedState = "xyz.openbmc_project.Led.Physical.Action.Off";
788             }
789             else
790             {
791                 messages::propertyValueNotInList(res, *indicatorLed,
792                                                  "IndicatorLED");
793                 return;
794             }
795 
796             getHostState(asyncResp);
797             getComputerSystem(asyncResp, name);
798 
799             // Update led group
800             BMCWEB_LOG_DEBUG << "Update led group.";
801             crow::connections::systemBus->async_method_call(
802                 [asyncResp{std::move(asyncResp)}](
803                     const boost::system::error_code ec) {
804                     if (ec)
805                     {
806                         BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
807                         messages::internalError(asyncResp->res);
808                         return;
809                     }
810                     BMCWEB_LOG_DEBUG << "Led group update done.";
811                 },
812                 "xyz.openbmc_project.LED.GroupManager",
813                 "/xyz/openbmc_project/led/groups/enclosure_identify",
814                 "org.freedesktop.DBus.Properties", "Set",
815                 "xyz.openbmc_project.Led.Group", "Asserted",
816                 sdbusplus::message::variant<bool>(
817                     (dbusLedState ==
818                              "xyz.openbmc_project.Led.Physical.Action.Off"
819                          ? false
820                          : true)));
821             // Update identify led status
822             BMCWEB_LOG_DEBUG << "Update led SoftwareInventoryCollection.";
823             crow::connections::systemBus->async_method_call(
824                 [asyncResp{std::move(asyncResp)},
825                  indicatorLed{std::move(*indicatorLed)}](
826                     const boost::system::error_code ec) {
827                     if (ec)
828                     {
829                         BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
830                         messages::internalError(asyncResp->res);
831                         return;
832                     }
833                     BMCWEB_LOG_DEBUG << "Led state update done.";
834                 },
835                 "xyz.openbmc_project.LED.Controller.identify",
836                 "/xyz/openbmc_project/led/physical/identify",
837                 "org.freedesktop.DBus.Properties", "Set",
838                 "xyz.openbmc_project.Led.Physical", "State",
839                 sdbusplus::message::variant<std::string>(dbusLedState));
840         }
841     }
842 };
843 } // namespace redfish
844