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