xref: /openbmc/bmcweb/features/redfish/lib/systems.hpp (revision a434f2bde1f80e1a0ddcda0961a7ff102de152d6)
1c5b2abe0SLewanczyk, Dawid /*
2c5b2abe0SLewanczyk, Dawid // Copyright (c) 2018 Intel Corporation
3c5b2abe0SLewanczyk, Dawid //
4c5b2abe0SLewanczyk, Dawid // Licensed under the Apache License, Version 2.0 (the "License");
5c5b2abe0SLewanczyk, Dawid // you may not use this file except in compliance with the License.
6c5b2abe0SLewanczyk, Dawid // You may obtain a copy of the License at
7c5b2abe0SLewanczyk, Dawid //
8c5b2abe0SLewanczyk, Dawid //      http://www.apache.org/licenses/LICENSE-2.0
9c5b2abe0SLewanczyk, Dawid //
10c5b2abe0SLewanczyk, Dawid // Unless required by applicable law or agreed to in writing, software
11c5b2abe0SLewanczyk, Dawid // distributed under the License is distributed on an "AS IS" BASIS,
12c5b2abe0SLewanczyk, Dawid // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c5b2abe0SLewanczyk, Dawid // See the License for the specific language governing permissions and
14c5b2abe0SLewanczyk, Dawid // limitations under the License.
15c5b2abe0SLewanczyk, Dawid */
16c5b2abe0SLewanczyk, Dawid #pragma once
17c5b2abe0SLewanczyk, Dawid 
18c5b2abe0SLewanczyk, Dawid #include <error_messages.hpp>
19c5b2abe0SLewanczyk, Dawid #include <utils/json_utils.hpp>
20c5b2abe0SLewanczyk, Dawid #include "node.hpp"
21c5b2abe0SLewanczyk, Dawid #include "boost/container/flat_map.hpp"
22c5b2abe0SLewanczyk, Dawid 
23c5b2abe0SLewanczyk, Dawid namespace redfish {
24c5b2abe0SLewanczyk, Dawid 
25c5b2abe0SLewanczyk, Dawid /**
26c5b2abe0SLewanczyk, Dawid  * SystemAsyncResp
27c5b2abe0SLewanczyk, Dawid  * Gathers data needed for response processing after async calls are done
28c5b2abe0SLewanczyk, Dawid  */
29c5b2abe0SLewanczyk, Dawid class SystemAsyncResp {
30c5b2abe0SLewanczyk, Dawid  public:
3155c7b7a2SEd Tanous   SystemAsyncResp(crow::Response &response) : res(response) {}
32c5b2abe0SLewanczyk, Dawid 
33c5b2abe0SLewanczyk, Dawid   ~SystemAsyncResp() {
34c5b2abe0SLewanczyk, Dawid     if (res.result() != (boost::beast::http::status::ok)) {
35c5b2abe0SLewanczyk, Dawid       // Reset the json object to clear out any data that made it in before the
36c5b2abe0SLewanczyk, Dawid       // error happened
37c5b2abe0SLewanczyk, Dawid       // todo(ed) handle error condition with proper code
3855c7b7a2SEd Tanous       res.jsonValue = messages::internalError();
39c5b2abe0SLewanczyk, Dawid     }
40c5b2abe0SLewanczyk, Dawid     res.end();
41c5b2abe0SLewanczyk, Dawid   }
42c5b2abe0SLewanczyk, Dawid 
43c5b2abe0SLewanczyk, Dawid   void setErrorStatus() {
44c5b2abe0SLewanczyk, Dawid     res.result(boost::beast::http::status::internal_server_error);
45c5b2abe0SLewanczyk, Dawid   }
46c5b2abe0SLewanczyk, Dawid 
4755c7b7a2SEd Tanous   crow::Response &res;
48c5b2abe0SLewanczyk, Dawid };
49c5b2abe0SLewanczyk, Dawid 
50c5b2abe0SLewanczyk, Dawid /**
51c5b2abe0SLewanczyk, Dawid  * OnDemandSystemsProvider
52c5b2abe0SLewanczyk, Dawid  * Board provider class that retrieves data directly from dbus, before seting
53c5b2abe0SLewanczyk, Dawid  * it into JSON output. This does not cache any data.
54c5b2abe0SLewanczyk, Dawid  *
55c5b2abe0SLewanczyk, Dawid  * Class can be a good example on how to scale different data providing
56c5b2abe0SLewanczyk, Dawid  * solutions to produce single schema output.
57c5b2abe0SLewanczyk, Dawid  *
58c5b2abe0SLewanczyk, Dawid  * TODO(Pawel)
59c5b2abe0SLewanczyk, Dawid  * This perhaps shall be different file, which has to be chosen on compile time
60c5b2abe0SLewanczyk, Dawid  * depending on OEM needs
61c5b2abe0SLewanczyk, Dawid  */
62c5b2abe0SLewanczyk, Dawid class OnDemandSystemsProvider {
63c5b2abe0SLewanczyk, Dawid  public:
64c5b2abe0SLewanczyk, Dawid   template <typename CallbackFunc>
65c5b2abe0SLewanczyk, Dawid   void getBaseboardList(CallbackFunc &&callback) {
6655c7b7a2SEd Tanous     BMCWEB_LOG_DEBUG << "Get list of available boards.";
6755c7b7a2SEd Tanous     crow::connections::systemBus->async_method_call(
68c5b2abe0SLewanczyk, Dawid         [callback{std::move(callback)}](const boost::system::error_code ec,
69c5b2abe0SLewanczyk, Dawid                                         const std::vector<std::string> &resp) {
70c5b2abe0SLewanczyk, Dawid           // Callback requires vector<string> to retrieve all available board
71c5b2abe0SLewanczyk, Dawid           // list.
72c5b2abe0SLewanczyk, Dawid           std::vector<std::string> board_list;
73c5b2abe0SLewanczyk, Dawid           if (ec) {
74c5b2abe0SLewanczyk, Dawid             // Something wrong on DBus, the error_code is not important at this
75c5b2abe0SLewanczyk, Dawid             // moment, just return success=false, and empty output. Since size
76c5b2abe0SLewanczyk, Dawid             // of vector may vary depending on information from Entity Manager,
77c5b2abe0SLewanczyk, Dawid             // and empty output could not be treated same way as error.
78c5b2abe0SLewanczyk, Dawid             callback(false, board_list);
79c5b2abe0SLewanczyk, Dawid             return;
80c5b2abe0SLewanczyk, Dawid           }
8155c7b7a2SEd Tanous           BMCWEB_LOG_DEBUG << "Got " << resp.size() << " boards.";
82c5b2abe0SLewanczyk, Dawid           // Iterate over all retrieved ObjectPaths.
83c5b2abe0SLewanczyk, Dawid           for (const std::string &objpath : resp) {
84c5b2abe0SLewanczyk, Dawid             std::size_t last_pos = objpath.rfind("/");
85c5b2abe0SLewanczyk, Dawid             if (last_pos != std::string::npos) {
86c5b2abe0SLewanczyk, Dawid               board_list.emplace_back(objpath.substr(last_pos + 1));
87c5b2abe0SLewanczyk, Dawid             }
88c5b2abe0SLewanczyk, Dawid           }
89c5b2abe0SLewanczyk, Dawid           // Finally make a callback with useful data
90c5b2abe0SLewanczyk, Dawid           callback(true, board_list);
91c5b2abe0SLewanczyk, Dawid         },
92c5b2abe0SLewanczyk, Dawid         "xyz.openbmc_project.ObjectMapper",
93c5b2abe0SLewanczyk, Dawid         "/xyz/openbmc_project/object_mapper",
94c5b2abe0SLewanczyk, Dawid         "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
95c5b2abe0SLewanczyk, Dawid         "/xyz/openbmc_project/inventory", int32_t(0),
96c5b2abe0SLewanczyk, Dawid         std::array<const char *, 1>{
97c5b2abe0SLewanczyk, Dawid             "xyz.openbmc_project.Inventory.Item.Board"});
98c5b2abe0SLewanczyk, Dawid   };
99c5b2abe0SLewanczyk, Dawid 
100c5b2abe0SLewanczyk, Dawid   /**
101c5b2abe0SLewanczyk, Dawid    * @brief Retrieves computer system properties over dbus
102c5b2abe0SLewanczyk, Dawid    *
103c5b2abe0SLewanczyk, Dawid    * @param[in] aResp Shared pointer for completing asynchronous calls
104c5b2abe0SLewanczyk, Dawid    * @param[in] name  Computer system name from request
105c5b2abe0SLewanczyk, Dawid    *
106c5b2abe0SLewanczyk, Dawid    * @return None.
107c5b2abe0SLewanczyk, Dawid    */
108c5b2abe0SLewanczyk, Dawid   void getComputerSystem(std::shared_ptr<SystemAsyncResp> aResp,
109c5b2abe0SLewanczyk, Dawid                          const std::string &name) {
110c5b2abe0SLewanczyk, Dawid     const std::array<const char *, 5> interfaces = {
111c5b2abe0SLewanczyk, Dawid         "xyz.openbmc_project.Inventory.Decorator.Asset",
112c5b2abe0SLewanczyk, Dawid         "xyz.openbmc_project.Inventory.Item.Cpu",
113c5b2abe0SLewanczyk, Dawid         "xyz.openbmc_project.Inventory.Item.Dimm",
114c5b2abe0SLewanczyk, Dawid         "xyz.openbmc_project.Inventory.Item.System",
115c5b2abe0SLewanczyk, Dawid         "xyz.openbmc_project.Common.UUID",
116c5b2abe0SLewanczyk, Dawid     };
11755c7b7a2SEd Tanous     BMCWEB_LOG_DEBUG << "Get available system components.";
11855c7b7a2SEd Tanous     crow::connections::systemBus->async_method_call(
119c5b2abe0SLewanczyk, Dawid         [name, aResp{std::move(aResp)}](
120c5b2abe0SLewanczyk, Dawid             const boost::system::error_code ec,
121c5b2abe0SLewanczyk, Dawid             const std::vector<std::pair<
122c5b2abe0SLewanczyk, Dawid                 std::string,
123c5b2abe0SLewanczyk, Dawid                 std::vector<std::pair<std::string, std::vector<std::string>>>>>
124c5b2abe0SLewanczyk, Dawid                 &subtree) {
125c5b2abe0SLewanczyk, Dawid           if (ec) {
12655c7b7a2SEd Tanous             BMCWEB_LOG_DEBUG << "DBUS response error";
127c5b2abe0SLewanczyk, Dawid             aResp->setErrorStatus();
128c5b2abe0SLewanczyk, Dawid             return;
129c5b2abe0SLewanczyk, Dawid           }
130c5b2abe0SLewanczyk, Dawid           bool foundName = false;
131c5b2abe0SLewanczyk, Dawid           // Iterate over all retrieved ObjectPaths.
132c5b2abe0SLewanczyk, Dawid           for (const std::pair<std::string,
133c5b2abe0SLewanczyk, Dawid                                std::vector<std::pair<std::string,
134c5b2abe0SLewanczyk, Dawid                                                      std::vector<std::string>>>>
135c5b2abe0SLewanczyk, Dawid                    &object : subtree) {
136c5b2abe0SLewanczyk, Dawid             const std::string &path = object.first;
13755c7b7a2SEd Tanous             BMCWEB_LOG_DEBUG << "Got path: " << path;
138c5b2abe0SLewanczyk, Dawid             const std::vector<std::pair<std::string, std::vector<std::string>>>
139c5b2abe0SLewanczyk, Dawid                 &connectionNames = object.second;
140c5b2abe0SLewanczyk, Dawid             if (connectionNames.size() < 1) {
141c5b2abe0SLewanczyk, Dawid               continue;
142c5b2abe0SLewanczyk, Dawid             }
143c5b2abe0SLewanczyk, Dawid             // Check if computer system exist
144c5b2abe0SLewanczyk, Dawid             if (boost::ends_with(path, name)) {
145c5b2abe0SLewanczyk, Dawid               foundName = true;
14655c7b7a2SEd Tanous               BMCWEB_LOG_DEBUG << "Found name: " << name;
147c5b2abe0SLewanczyk, Dawid               const std::string connectionName = connectionNames[0].first;
14855c7b7a2SEd Tanous               crow::connections::systemBus->async_method_call(
149c5b2abe0SLewanczyk, Dawid                   [aResp, name(std::string(name))](
150c5b2abe0SLewanczyk, Dawid                       const boost::system::error_code ec,
151c5b2abe0SLewanczyk, Dawid                       const std::vector<std::pair<std::string, VariantType>>
152c5b2abe0SLewanczyk, Dawid                           &propertiesList) {
153c5b2abe0SLewanczyk, Dawid                     if (ec) {
15455c7b7a2SEd Tanous                       BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
155c5b2abe0SLewanczyk, Dawid                       aResp->setErrorStatus();
156c5b2abe0SLewanczyk, Dawid                       return;
157c5b2abe0SLewanczyk, Dawid                     }
15855c7b7a2SEd Tanous                     BMCWEB_LOG_DEBUG << "Got " << propertiesList.size()
159c5b2abe0SLewanczyk, Dawid                                      << "properties for system";
160c5b2abe0SLewanczyk, Dawid                     for (const std::pair<std::string, VariantType> &property :
161c5b2abe0SLewanczyk, Dawid                          propertiesList) {
162c5b2abe0SLewanczyk, Dawid                       const std::string *value =
16355c7b7a2SEd Tanous                           mapbox::getPtr<const std::string>(property.second);
164c5b2abe0SLewanczyk, Dawid                       if (value != nullptr) {
16555c7b7a2SEd Tanous                         aResp->res.jsonValue[property.first] = *value;
166c5b2abe0SLewanczyk, Dawid                       }
167c5b2abe0SLewanczyk, Dawid                     }
16855c7b7a2SEd Tanous                     aResp->res.jsonValue["Name"] = name;
16955c7b7a2SEd Tanous                     aResp->res.jsonValue["Id"] =
17055c7b7a2SEd Tanous                         aResp->res.jsonValue["SerialNumber"];
171c5b2abe0SLewanczyk, Dawid                   },
172c5b2abe0SLewanczyk, Dawid                   connectionName, path, "org.freedesktop.DBus.Properties",
173c5b2abe0SLewanczyk, Dawid                   "GetAll", "xyz.openbmc_project.Inventory.Decorator.Asset");
174c5b2abe0SLewanczyk, Dawid             } else {
175c5b2abe0SLewanczyk, Dawid               // This is not system, so check if it's cpu, dimm, UUID or BiosVer
176c5b2abe0SLewanczyk, Dawid               for (auto const &s : connectionNames) {
177c5b2abe0SLewanczyk, Dawid                 for (auto const &i : s.second) {
178c5b2abe0SLewanczyk, Dawid                   if (boost::ends_with(i, "Dimm")) {
17955c7b7a2SEd Tanous                     BMCWEB_LOG_DEBUG << "Found Dimm, now get it properties.";
18055c7b7a2SEd Tanous                     crow::connections::systemBus->async_method_call(
181c5b2abe0SLewanczyk, Dawid                         [&, aResp](const boost::system::error_code ec,
182c5b2abe0SLewanczyk, Dawid                                    const std::vector<std::pair<
183c5b2abe0SLewanczyk, Dawid                                        std::string, VariantType>> &properties) {
184c5b2abe0SLewanczyk, Dawid                           if (ec) {
18555c7b7a2SEd Tanous                             BMCWEB_LOG_ERROR << "DBUS response error " << ec;
186c5b2abe0SLewanczyk, Dawid                             aResp->setErrorStatus();
187c5b2abe0SLewanczyk, Dawid                             return;
188c5b2abe0SLewanczyk, Dawid                           }
18955c7b7a2SEd Tanous                           BMCWEB_LOG_DEBUG << "Got " << properties.size()
190c5b2abe0SLewanczyk, Dawid                                            << "Dimm properties.";
191c5b2abe0SLewanczyk, Dawid                           for (const auto &p : properties) {
192c5b2abe0SLewanczyk, Dawid                             if (p.first == "MemorySize") {
193c5b2abe0SLewanczyk, Dawid                               const std::string *value =
19455c7b7a2SEd Tanous                                   mapbox::getPtr<const std::string>(p.second);
195c5b2abe0SLewanczyk, Dawid                               if ((value != nullptr) && (*value != "NULL")) {
196c5b2abe0SLewanczyk, Dawid                                 // Remove units char
197c5b2abe0SLewanczyk, Dawid                                 int32_t unitCoeff;
198c5b2abe0SLewanczyk, Dawid                                 if (boost::ends_with(*value, "MB")) {
199c5b2abe0SLewanczyk, Dawid                                   unitCoeff = 1000;
200c5b2abe0SLewanczyk, Dawid                                 } else if (boost::ends_with(*value, "KB")) {
201c5b2abe0SLewanczyk, Dawid                                   unitCoeff = 1000000;
202c5b2abe0SLewanczyk, Dawid                                 } else {
203*a434f2bdSEd Tanous                                   BMCWEB_LOG_ERROR
204*a434f2bdSEd Tanous                                       << "Unsupported memory units";
205c5b2abe0SLewanczyk, Dawid                                   aResp->setErrorStatus();
206c5b2abe0SLewanczyk, Dawid                                   return;
207c5b2abe0SLewanczyk, Dawid                                 }
208c5b2abe0SLewanczyk, Dawid 
209c5b2abe0SLewanczyk, Dawid                                 auto memSize = boost::lexical_cast<int>(
210c5b2abe0SLewanczyk, Dawid                                     value->substr(0, value->length() - 2));
21155c7b7a2SEd Tanous                                 aResp->res.jsonValue["TotalSystemMemoryGiB"] +=
212c5b2abe0SLewanczyk, Dawid                                     memSize * unitCoeff;
21355c7b7a2SEd Tanous                                 aResp->res.jsonValue["MemorySummary"]["Status"]
214c5b2abe0SLewanczyk, Dawid                                                     ["State"] = "Enabled";
215c5b2abe0SLewanczyk, Dawid                               }
216c5b2abe0SLewanczyk, Dawid                             }
217c5b2abe0SLewanczyk, Dawid                           }
218c5b2abe0SLewanczyk, Dawid                         },
219c5b2abe0SLewanczyk, Dawid                         s.first, path, "org.freedesktop.DBus.Properties",
220c5b2abe0SLewanczyk, Dawid                         "GetAll", "xyz.openbmc_project.Inventory.Item.Dimm");
221c5b2abe0SLewanczyk, Dawid                   } else if (boost::ends_with(i, "Cpu")) {
22255c7b7a2SEd Tanous                     BMCWEB_LOG_DEBUG << "Found Cpu, now get it properties.";
22355c7b7a2SEd Tanous                     crow::connections::systemBus->async_method_call(
224c5b2abe0SLewanczyk, Dawid                         [&, aResp](const boost::system::error_code ec,
225c5b2abe0SLewanczyk, Dawid                                    const std::vector<std::pair<
226c5b2abe0SLewanczyk, Dawid                                        std::string, VariantType>> &properties) {
227c5b2abe0SLewanczyk, Dawid                           if (ec) {
22855c7b7a2SEd Tanous                             BMCWEB_LOG_ERROR << "DBUS response error " << ec;
229c5b2abe0SLewanczyk, Dawid                             aResp->setErrorStatus();
230c5b2abe0SLewanczyk, Dawid                             return;
231c5b2abe0SLewanczyk, Dawid                           }
23255c7b7a2SEd Tanous                           BMCWEB_LOG_DEBUG << "Got " << properties.size()
233c5b2abe0SLewanczyk, Dawid                                            << "Cpu properties.";
234c5b2abe0SLewanczyk, Dawid                           for (const auto &p : properties) {
235c5b2abe0SLewanczyk, Dawid                             if (p.first == "ProcessorFamily") {
236c5b2abe0SLewanczyk, Dawid                               const std::string *value =
23755c7b7a2SEd Tanous                                   mapbox::getPtr<const std::string>(p.second);
238c5b2abe0SLewanczyk, Dawid                               if (value != nullptr) {
239c5b2abe0SLewanczyk, Dawid                                 aResp->res
24055c7b7a2SEd Tanous                                     .jsonValue["ProcessorSummary"]["Count"] =
241c5b2abe0SLewanczyk, Dawid                                     aResp->res
24255c7b7a2SEd Tanous                                         .jsonValue["ProcessorSummary"]["Count"]
243c5b2abe0SLewanczyk, Dawid                                         .get<int>() +
244c5b2abe0SLewanczyk, Dawid                                     1;
24555c7b7a2SEd Tanous                                 aResp->res.jsonValue["ProcessorSummary"]
246c5b2abe0SLewanczyk, Dawid                                                     ["Status"]["State"] =
247c5b2abe0SLewanczyk, Dawid                                     "Enabled";
248c5b2abe0SLewanczyk, Dawid                                 aResp->res
24955c7b7a2SEd Tanous                                     .jsonValue["ProcessorSummary"]["Model"] =
250c5b2abe0SLewanczyk, Dawid                                     *value;
251c5b2abe0SLewanczyk, Dawid                               }
252c5b2abe0SLewanczyk, Dawid                             }
253c5b2abe0SLewanczyk, Dawid                           }
254c5b2abe0SLewanczyk, Dawid                         },
255c5b2abe0SLewanczyk, Dawid                         s.first, path, "org.freedesktop.DBus.Properties",
256c5b2abe0SLewanczyk, Dawid                         "GetAll", "xyz.openbmc_project.Inventory.Item.Cpu");
257c5b2abe0SLewanczyk, Dawid                   } else if (boost::ends_with(i, "UUID")) {
25855c7b7a2SEd Tanous                     BMCWEB_LOG_DEBUG << "Found UUID, now get it properties.";
25955c7b7a2SEd Tanous                     crow::connections::systemBus->async_method_call(
260c5b2abe0SLewanczyk, Dawid                         [aResp](const boost::system::error_code ec,
261c5b2abe0SLewanczyk, Dawid                                 const std::vector<std::pair<
262c5b2abe0SLewanczyk, Dawid                                     std::string, VariantType>> &properties) {
263c5b2abe0SLewanczyk, Dawid                           if (ec) {
26455c7b7a2SEd Tanous                             BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
265c5b2abe0SLewanczyk, Dawid                             aResp->setErrorStatus();
266c5b2abe0SLewanczyk, Dawid                             return;
267c5b2abe0SLewanczyk, Dawid                           }
26855c7b7a2SEd Tanous                           BMCWEB_LOG_DEBUG << "Got " << properties.size()
269c5b2abe0SLewanczyk, Dawid                                            << "UUID properties.";
270c5b2abe0SLewanczyk, Dawid                           for (const std::pair<std::string, VariantType> &p :
271c5b2abe0SLewanczyk, Dawid                                properties) {
272c5b2abe0SLewanczyk, Dawid                             if (p.first == "BIOSVer") {
273c5b2abe0SLewanczyk, Dawid                               const std::string *value =
27455c7b7a2SEd Tanous                                   mapbox::getPtr<const std::string>(p.second);
275c5b2abe0SLewanczyk, Dawid                               if (value != nullptr) {
27655c7b7a2SEd Tanous                                 aResp->res.jsonValue["BiosVersion"] = *value;
277c5b2abe0SLewanczyk, Dawid                               }
278c5b2abe0SLewanczyk, Dawid                             }
279c5b2abe0SLewanczyk, Dawid                             if (p.first == "UUID") {
280c5b2abe0SLewanczyk, Dawid                               const std::string *value =
28155c7b7a2SEd Tanous                                   mapbox::getPtr<const std::string>(p.second);
28255c7b7a2SEd Tanous                               BMCWEB_LOG_DEBUG << "UUID = " << *value
283c5b2abe0SLewanczyk, Dawid                                                << " length " << value->length();
284c5b2abe0SLewanczyk, Dawid                               if (value != nullptr) {
285c5b2abe0SLewanczyk, Dawid                                 // Workaround for to short return str in smbios
286c5b2abe0SLewanczyk, Dawid                                 // demo app, 32 bytes are described by spec
287c5b2abe0SLewanczyk, Dawid                                 if (value->length() > 0 &&
288c5b2abe0SLewanczyk, Dawid                                     value->length() < 32) {
289c5b2abe0SLewanczyk, Dawid                                   std::string correctedValue = *value;
290c5b2abe0SLewanczyk, Dawid                                   correctedValue.append(32 - value->length(),
291c5b2abe0SLewanczyk, Dawid                                                         '0');
292c5b2abe0SLewanczyk, Dawid                                   value = &correctedValue;
293c5b2abe0SLewanczyk, Dawid                                 } else if (value->length() == 32) {
29455c7b7a2SEd Tanous                                   aResp->res.jsonValue["UUID"] =
295c5b2abe0SLewanczyk, Dawid                                       value->substr(0, 8) + "-" +
296c5b2abe0SLewanczyk, Dawid                                       value->substr(8, 4) + "-" +
297c5b2abe0SLewanczyk, Dawid                                       value->substr(12, 4) + "-" +
298c5b2abe0SLewanczyk, Dawid                                       value->substr(16, 4) + "-" +
299c5b2abe0SLewanczyk, Dawid                                       value->substr(20, 12);
300c5b2abe0SLewanczyk, Dawid                                 }
301c5b2abe0SLewanczyk, Dawid                               }
302c5b2abe0SLewanczyk, Dawid                             }
303c5b2abe0SLewanczyk, Dawid                           }
304c5b2abe0SLewanczyk, Dawid                         },
305c5b2abe0SLewanczyk, Dawid                         s.first, path, "org.freedesktop.DBus.Properties",
306c5b2abe0SLewanczyk, Dawid                         "GetAll", "xyz.openbmc_project.Common.UUID");
307c5b2abe0SLewanczyk, Dawid                   }
308c5b2abe0SLewanczyk, Dawid                 }
309c5b2abe0SLewanczyk, Dawid               }
310c5b2abe0SLewanczyk, Dawid             }
311c5b2abe0SLewanczyk, Dawid           }
312c5b2abe0SLewanczyk, Dawid           if (foundName == false) {
313c5b2abe0SLewanczyk, Dawid             aResp->setErrorStatus();
314c5b2abe0SLewanczyk, Dawid           }
315c5b2abe0SLewanczyk, Dawid         },
316c5b2abe0SLewanczyk, Dawid         "xyz.openbmc_project.ObjectMapper",
317c5b2abe0SLewanczyk, Dawid         "/xyz/openbmc_project/object_mapper",
318c5b2abe0SLewanczyk, Dawid         "xyz.openbmc_project.ObjectMapper", "GetSubTree",
319c5b2abe0SLewanczyk, Dawid         "/xyz/openbmc_project/inventory", int32_t(0), interfaces);
320c5b2abe0SLewanczyk, Dawid   }
321c5b2abe0SLewanczyk, Dawid 
322c5b2abe0SLewanczyk, Dawid   /**
323c5b2abe0SLewanczyk, Dawid    * @brief Retrieves identify led group properties over dbus
324c5b2abe0SLewanczyk, Dawid    *
325c5b2abe0SLewanczyk, Dawid    * @param[in] aResp     Shared pointer for completing asynchronous calls.
326c5b2abe0SLewanczyk, Dawid    * @param[in] callback  Callback for process retrieved data.
327c5b2abe0SLewanczyk, Dawid    *
328c5b2abe0SLewanczyk, Dawid    * @return None.
329c5b2abe0SLewanczyk, Dawid    */
330c5b2abe0SLewanczyk, Dawid   template <typename CallbackFunc>
331c5b2abe0SLewanczyk, Dawid   void getLedGroupIdentify(std::shared_ptr<SystemAsyncResp> aResp,
332c5b2abe0SLewanczyk, Dawid                            CallbackFunc &&callback) {
33355c7b7a2SEd Tanous     BMCWEB_LOG_DEBUG << "Get led groups";
33455c7b7a2SEd Tanous     crow::connections::systemBus->async_method_call(
335*a434f2bdSEd Tanous         [aResp{std::move(aResp)}, &callback](
336*a434f2bdSEd Tanous             const boost::system::error_code &ec,
337*a434f2bdSEd Tanous             const ManagedObjectsType &resp) {
338c5b2abe0SLewanczyk, Dawid           if (ec) {
33955c7b7a2SEd Tanous             BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
340c5b2abe0SLewanczyk, Dawid             aResp->setErrorStatus();
341c5b2abe0SLewanczyk, Dawid             return;
342c5b2abe0SLewanczyk, Dawid           }
34355c7b7a2SEd Tanous           BMCWEB_LOG_DEBUG << "Got " << resp.size() << "led group objects.";
344c5b2abe0SLewanczyk, Dawid           for (const auto &objPath : resp) {
345c5b2abe0SLewanczyk, Dawid             const std::string &path = objPath.first;
346c5b2abe0SLewanczyk, Dawid             if (path.rfind("enclosure_identify") != std::string::npos) {
347c5b2abe0SLewanczyk, Dawid               for (const auto &interface : objPath.second) {
348c5b2abe0SLewanczyk, Dawid                 if (interface.first == "xyz.openbmc_project.Led.Group") {
349c5b2abe0SLewanczyk, Dawid                   for (const auto &property : interface.second) {
350c5b2abe0SLewanczyk, Dawid                     if (property.first == "Asserted") {
351c5b2abe0SLewanczyk, Dawid                       const bool *asserted =
35255c7b7a2SEd Tanous                           mapbox::getPtr<const bool>(property.second);
353c5b2abe0SLewanczyk, Dawid                       if (nullptr != asserted) {
354c5b2abe0SLewanczyk, Dawid                         callback(*asserted, aResp);
355c5b2abe0SLewanczyk, Dawid                       } else {
356c5b2abe0SLewanczyk, Dawid                         callback(false, aResp);
357c5b2abe0SLewanczyk, Dawid                       }
358c5b2abe0SLewanczyk, Dawid                     }
359c5b2abe0SLewanczyk, Dawid                   }
360c5b2abe0SLewanczyk, Dawid                 }
361c5b2abe0SLewanczyk, Dawid               }
362c5b2abe0SLewanczyk, Dawid             }
363c5b2abe0SLewanczyk, Dawid           }
364c5b2abe0SLewanczyk, Dawid         },
365c5b2abe0SLewanczyk, Dawid         "xyz.openbmc_project.LED.GroupManager",
366c5b2abe0SLewanczyk, Dawid         "/xyz/openbmc_project/led/groups", "org.freedesktop.DBus.ObjectManager",
367c5b2abe0SLewanczyk, Dawid         "GetManagedObjects");
368c5b2abe0SLewanczyk, Dawid   }
369c5b2abe0SLewanczyk, Dawid 
370c5b2abe0SLewanczyk, Dawid   template <typename CallbackFunc>
371c5b2abe0SLewanczyk, Dawid   void getLedIdentify(std::shared_ptr<SystemAsyncResp> aResp,
372c5b2abe0SLewanczyk, Dawid                       CallbackFunc &&callback) {
37355c7b7a2SEd Tanous     BMCWEB_LOG_DEBUG << "Get identify led properties";
37455c7b7a2SEd Tanous     crow::connections::systemBus->async_method_call(
375*a434f2bdSEd Tanous         [aResp{std::move(aResp)}, &callback](const boost::system::error_code ec,
376c5b2abe0SLewanczyk, Dawid                                              const PropertiesType &properties) {
377c5b2abe0SLewanczyk, Dawid           if (ec) {
37855c7b7a2SEd Tanous             BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
379c5b2abe0SLewanczyk, Dawid             aResp->setErrorStatus();
380c5b2abe0SLewanczyk, Dawid             return;
381c5b2abe0SLewanczyk, Dawid           }
38255c7b7a2SEd Tanous           BMCWEB_LOG_DEBUG << "Got " << properties.size() << "led properties.";
383c5b2abe0SLewanczyk, Dawid           std::string output;
384c5b2abe0SLewanczyk, Dawid           for (const auto &property : properties) {
385c5b2abe0SLewanczyk, Dawid             if (property.first == "State") {
386c5b2abe0SLewanczyk, Dawid               const std::string *s =
38755c7b7a2SEd Tanous                   mapbox::getPtr<std::string>(property.second);
388c5b2abe0SLewanczyk, Dawid               if (nullptr != s) {
38955c7b7a2SEd Tanous                 BMCWEB_LOG_DEBUG << "Identify Led State: " << *s;
390c5b2abe0SLewanczyk, Dawid                 const auto pos = s->rfind('.');
391c5b2abe0SLewanczyk, Dawid                 if (pos != std::string::npos) {
392c5b2abe0SLewanczyk, Dawid                   auto led = s->substr(pos + 1);
393c5b2abe0SLewanczyk, Dawid                   for (const std::pair<const char *, const char *> &p :
394c5b2abe0SLewanczyk, Dawid                        std::array<std::pair<const char *, const char *>, 3>{
395c5b2abe0SLewanczyk, Dawid                            {{"On", "Lit"},
396c5b2abe0SLewanczyk, Dawid                             {"Blink", "Blinking"},
397c5b2abe0SLewanczyk, Dawid                             {"Off", "Off"}}}) {
398c5b2abe0SLewanczyk, Dawid                     if (led == p.first) {
399c5b2abe0SLewanczyk, Dawid                       output = p.second;
400c5b2abe0SLewanczyk, Dawid                     }
401c5b2abe0SLewanczyk, Dawid                   }
402c5b2abe0SLewanczyk, Dawid                 }
403c5b2abe0SLewanczyk, Dawid               }
404c5b2abe0SLewanczyk, Dawid             }
405c5b2abe0SLewanczyk, Dawid           }
406c5b2abe0SLewanczyk, Dawid           callback(output, aResp);
407c5b2abe0SLewanczyk, Dawid         },
408c5b2abe0SLewanczyk, Dawid         "xyz.openbmc_project.LED.Controller.identify",
409c5b2abe0SLewanczyk, Dawid         "/xyz/openbmc_project/led/physical/identify",
410c5b2abe0SLewanczyk, Dawid         "org.freedesktop.DBus.Properties", "GetAll",
411c5b2abe0SLewanczyk, Dawid         "xyz.openbmc_project.Led.Physical");
412c5b2abe0SLewanczyk, Dawid   }
413c5b2abe0SLewanczyk, Dawid 
414c5b2abe0SLewanczyk, Dawid   /**
415c5b2abe0SLewanczyk, Dawid    * @brief Retrieves host state properties over dbus
416c5b2abe0SLewanczyk, Dawid    *
417c5b2abe0SLewanczyk, Dawid    * @param[in] aResp     Shared pointer for completing asynchronous calls.
418c5b2abe0SLewanczyk, Dawid    *
419c5b2abe0SLewanczyk, Dawid    * @return None.
420c5b2abe0SLewanczyk, Dawid    */
421c5b2abe0SLewanczyk, Dawid   void getHostState(std::shared_ptr<SystemAsyncResp> aResp) {
42255c7b7a2SEd Tanous     BMCWEB_LOG_DEBUG << "Get host information.";
42355c7b7a2SEd Tanous     crow::connections::systemBus->async_method_call(
424c5b2abe0SLewanczyk, Dawid         [aResp{std::move(aResp)}](const boost::system::error_code ec,
425c5b2abe0SLewanczyk, Dawid                                   const PropertiesType &properties) {
426c5b2abe0SLewanczyk, Dawid           if (ec) {
42755c7b7a2SEd Tanous             BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
428c5b2abe0SLewanczyk, Dawid             aResp->setErrorStatus();
429c5b2abe0SLewanczyk, Dawid             return;
430c5b2abe0SLewanczyk, Dawid           }
43155c7b7a2SEd Tanous           BMCWEB_LOG_DEBUG << "Got " << properties.size() << "host properties.";
432c5b2abe0SLewanczyk, Dawid           for (const auto &property : properties) {
433c5b2abe0SLewanczyk, Dawid             if (property.first == "CurrentHostState") {
434c5b2abe0SLewanczyk, Dawid               const std::string *s =
43555c7b7a2SEd Tanous                   mapbox::getPtr<const std::string>(property.second);
43655c7b7a2SEd Tanous               BMCWEB_LOG_DEBUG << "Host state: " << *s;
437c5b2abe0SLewanczyk, Dawid               if (nullptr != s) {
438c5b2abe0SLewanczyk, Dawid                 const auto pos = s->rfind('.');
439c5b2abe0SLewanczyk, Dawid                 if (pos != std::string::npos) {
440c5b2abe0SLewanczyk, Dawid                   // Verify Host State
441c5b2abe0SLewanczyk, Dawid                   if (s->substr(pos + 1) == "Running") {
44255c7b7a2SEd Tanous                     aResp->res.jsonValue["PowerState"] = "On";
44355c7b7a2SEd Tanous                     aResp->res.jsonValue["Status"]["State"] = "Enabled";
444c5b2abe0SLewanczyk, Dawid                   } else {
44555c7b7a2SEd Tanous                     aResp->res.jsonValue["PowerState"] = "Off";
44655c7b7a2SEd Tanous                     aResp->res.jsonValue["Status"]["State"] = "Disabled";
447c5b2abe0SLewanczyk, Dawid                   }
448c5b2abe0SLewanczyk, Dawid                 }
449c5b2abe0SLewanczyk, Dawid               }
450c5b2abe0SLewanczyk, Dawid             }
451c5b2abe0SLewanczyk, Dawid           }
452c5b2abe0SLewanczyk, Dawid         },
453c5b2abe0SLewanczyk, Dawid         "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
454c5b2abe0SLewanczyk, Dawid         "org.freedesktop.DBus.Properties", "GetAll",
455c5b2abe0SLewanczyk, Dawid         "xyz.openbmc_project.State.Host");
456c5b2abe0SLewanczyk, Dawid   }
457c5b2abe0SLewanczyk, Dawid };
458c5b2abe0SLewanczyk, Dawid 
459c5b2abe0SLewanczyk, Dawid /**
460c5b2abe0SLewanczyk, Dawid  * SystemsCollection derived class for delivering ComputerSystems Collection
461c5b2abe0SLewanczyk, Dawid  * Schema
462c5b2abe0SLewanczyk, Dawid  */
463c5b2abe0SLewanczyk, Dawid class SystemsCollection : public Node {
464c5b2abe0SLewanczyk, Dawid  public:
465c5b2abe0SLewanczyk, Dawid   SystemsCollection(CrowApp &app) : Node(app, "/redfish/v1/Systems/") {
466c5b2abe0SLewanczyk, Dawid     Node::json["@odata.type"] =
467c5b2abe0SLewanczyk, Dawid         "#ComputerSystemCollection.ComputerSystemCollection";
468c5b2abe0SLewanczyk, Dawid     Node::json["@odata.id"] = "/redfish/v1/Systems";
469c5b2abe0SLewanczyk, Dawid     Node::json["@odata.context"] =
470c5b2abe0SLewanczyk, Dawid         "/redfish/v1/"
471c5b2abe0SLewanczyk, Dawid         "$metadata#ComputerSystemCollection.ComputerSystemCollection";
472c5b2abe0SLewanczyk, Dawid     Node::json["Name"] = "Computer System Collection";
473c5b2abe0SLewanczyk, Dawid 
474c5b2abe0SLewanczyk, Dawid     entityPrivileges = {
475c5b2abe0SLewanczyk, Dawid         {boost::beast::http::verb::get, {{"Login"}}},
476c5b2abe0SLewanczyk, Dawid         {boost::beast::http::verb::head, {{"Login"}}},
477c5b2abe0SLewanczyk, Dawid         {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
478c5b2abe0SLewanczyk, Dawid         {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
479c5b2abe0SLewanczyk, Dawid         {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
480c5b2abe0SLewanczyk, Dawid         {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
481c5b2abe0SLewanczyk, Dawid   }
482c5b2abe0SLewanczyk, Dawid 
483c5b2abe0SLewanczyk, Dawid  private:
484c5b2abe0SLewanczyk, Dawid   /**
485c5b2abe0SLewanczyk, Dawid    * Functions triggers appropriate requests on DBus
486c5b2abe0SLewanczyk, Dawid    */
48755c7b7a2SEd Tanous   void doGet(crow::Response &res, const crow::Request &req,
488c5b2abe0SLewanczyk, Dawid              const std::vector<std::string> &params) override {
489c5b2abe0SLewanczyk, Dawid     // Get board list, and call the below callback for JSON preparation
490c5b2abe0SLewanczyk, Dawid     provider.getBaseboardList(
491c5b2abe0SLewanczyk, Dawid         [&](const bool &success, const std::vector<std::string> &output) {
492c5b2abe0SLewanczyk, Dawid           if (success) {
493c5b2abe0SLewanczyk, Dawid             // ... prepare json array with appropriate @odata.id links
494c5b2abe0SLewanczyk, Dawid             nlohmann::json boardArray = nlohmann::json::array();
495c5b2abe0SLewanczyk, Dawid             for (const std::string &board_item : output) {
496c5b2abe0SLewanczyk, Dawid               boardArray.push_back(
497c5b2abe0SLewanczyk, Dawid                   {{"@odata.id", "/redfish/v1/Systems/" + board_item}});
498c5b2abe0SLewanczyk, Dawid             }
499c5b2abe0SLewanczyk, Dawid             // Then attach members, count size and return,
500c5b2abe0SLewanczyk, Dawid             Node::json["Members"] = boardArray;
501c5b2abe0SLewanczyk, Dawid             Node::json["Members@odata.count"] = boardArray.size();
50255c7b7a2SEd Tanous             res.jsonValue = Node::json;
503c5b2abe0SLewanczyk, Dawid           } else {
504c5b2abe0SLewanczyk, Dawid             // ... otherwise, return INTERNALL ERROR
505c5b2abe0SLewanczyk, Dawid             res.result(boost::beast::http::status::internal_server_error);
506c5b2abe0SLewanczyk, Dawid           }
507c5b2abe0SLewanczyk, Dawid           res.end();
508c5b2abe0SLewanczyk, Dawid         });
509c5b2abe0SLewanczyk, Dawid   }
510c5b2abe0SLewanczyk, Dawid 
511c5b2abe0SLewanczyk, Dawid   OnDemandSystemsProvider provider;
512c5b2abe0SLewanczyk, Dawid };
513c5b2abe0SLewanczyk, Dawid 
514c5b2abe0SLewanczyk, Dawid /**
515c5b2abe0SLewanczyk, Dawid  * Systems override class for delivering ComputerSystems Schema
516c5b2abe0SLewanczyk, Dawid  */
517c5b2abe0SLewanczyk, Dawid class Systems : public Node {
518c5b2abe0SLewanczyk, Dawid  public:
519c5b2abe0SLewanczyk, Dawid   /*
520c5b2abe0SLewanczyk, Dawid    * Default Constructor
521c5b2abe0SLewanczyk, Dawid    */
522c5b2abe0SLewanczyk, Dawid   Systems(CrowApp &app)
523c5b2abe0SLewanczyk, Dawid       : Node(app, "/redfish/v1/Systems/<str>/", std::string()) {
524c5b2abe0SLewanczyk, Dawid     Node::json["@odata.type"] = "#ComputerSystem.v1_3_0.ComputerSystem";
525c5b2abe0SLewanczyk, Dawid     Node::json["@odata.context"] =
526c5b2abe0SLewanczyk, Dawid         "/redfish/v1/$metadata#ComputerSystem.ComputerSystem";
527c5b2abe0SLewanczyk, Dawid     Node::json["SystemType"] = "Physical";
528c5b2abe0SLewanczyk, Dawid     Node::json["Description"] = "Computer System";
529c5b2abe0SLewanczyk, Dawid     Node::json["Boot"]["BootSourceOverrideEnabled"] =
530c5b2abe0SLewanczyk, Dawid         "Disabled";  // TODO(Dawid), get real boot data
531c5b2abe0SLewanczyk, Dawid     Node::json["Boot"]["BootSourceOverrideTarget"] =
532c5b2abe0SLewanczyk, Dawid         "None";  // TODO(Dawid), get real boot data
533c5b2abe0SLewanczyk, Dawid     Node::json["Boot"]["BootSourceOverrideMode"] =
534c5b2abe0SLewanczyk, Dawid         "Legacy";  // TODO(Dawid), get real boot data
535c5b2abe0SLewanczyk, Dawid     Node::json["Boot"]["BootSourceOverrideTarget@Redfish.AllowableValues"] = {
536c5b2abe0SLewanczyk, Dawid         "None",      "Pxe",       "Hdd", "Cd",
537c5b2abe0SLewanczyk, Dawid         "BiosSetup", "UefiShell", "Usb"};  // TODO(Dawid), get real boot data
538c5b2abe0SLewanczyk, Dawid     Node::json["ProcessorSummary"]["Count"] = int(0);
539c5b2abe0SLewanczyk, Dawid     Node::json["ProcessorSummary"]["Status"]["State"] = "Disabled";
540c5b2abe0SLewanczyk, Dawid     Node::json["MemorySummary"]["TotalSystemMemoryGiB"] = int(0);
541c5b2abe0SLewanczyk, Dawid     Node::json["MemorySummary"]["Status"]["State"] = "Disabled";
542c5b2abe0SLewanczyk, Dawid 
543c5b2abe0SLewanczyk, Dawid     entityPrivileges = {
544c5b2abe0SLewanczyk, Dawid         {boost::beast::http::verb::get, {{"Login"}}},
545c5b2abe0SLewanczyk, Dawid         {boost::beast::http::verb::head, {{"Login"}}},
546c5b2abe0SLewanczyk, Dawid         {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
547c5b2abe0SLewanczyk, Dawid         {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
548c5b2abe0SLewanczyk, Dawid         {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
549c5b2abe0SLewanczyk, Dawid         {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
550c5b2abe0SLewanczyk, Dawid   }
551c5b2abe0SLewanczyk, Dawid 
552c5b2abe0SLewanczyk, Dawid  private:
553c5b2abe0SLewanczyk, Dawid   OnDemandSystemsProvider provider;
554c5b2abe0SLewanczyk, Dawid 
555c5b2abe0SLewanczyk, Dawid   /**
556c5b2abe0SLewanczyk, Dawid    * Functions triggers appropriate requests on DBus
557c5b2abe0SLewanczyk, Dawid    */
55855c7b7a2SEd Tanous   void doGet(crow::Response &res, const crow::Request &req,
559c5b2abe0SLewanczyk, Dawid              const std::vector<std::string> &params) override {
560c5b2abe0SLewanczyk, Dawid     // Check if there is required param, truly entering this shall be
561c5b2abe0SLewanczyk, Dawid     // impossible
562c5b2abe0SLewanczyk, Dawid     if (params.size() != 1) {
563c5b2abe0SLewanczyk, Dawid       res.result(boost::beast::http::status::internal_server_error);
564c5b2abe0SLewanczyk, Dawid       res.end();
565c5b2abe0SLewanczyk, Dawid       return;
566c5b2abe0SLewanczyk, Dawid     }
567c5b2abe0SLewanczyk, Dawid 
568c5b2abe0SLewanczyk, Dawid     const std::string &name = params[0];
569c5b2abe0SLewanczyk, Dawid 
57055c7b7a2SEd Tanous     res.jsonValue = Node::json;
57155c7b7a2SEd Tanous     res.jsonValue["@odata.id"] = "/redfish/v1/Systems/" + name;
572c5b2abe0SLewanczyk, Dawid 
573c5b2abe0SLewanczyk, Dawid     auto asyncResp = std::make_shared<SystemAsyncResp>(res);
574c5b2abe0SLewanczyk, Dawid 
575c5b2abe0SLewanczyk, Dawid     provider.getLedGroupIdentify(
576c5b2abe0SLewanczyk, Dawid         asyncResp, [&](const bool &asserted,
577c5b2abe0SLewanczyk, Dawid                        const std::shared_ptr<SystemAsyncResp> &aResp) {
578c5b2abe0SLewanczyk, Dawid           if (asserted) {
579c5b2abe0SLewanczyk, Dawid             // If led group is asserted, then another call is needed to
580c5b2abe0SLewanczyk, Dawid             // get led status
581c5b2abe0SLewanczyk, Dawid             provider.getLedIdentify(
582c5b2abe0SLewanczyk, Dawid                 aResp, [](const std::string &ledStatus,
583c5b2abe0SLewanczyk, Dawid                           const std::shared_ptr<SystemAsyncResp> &aResp) {
584c5b2abe0SLewanczyk, Dawid                   if (!ledStatus.empty()) {
58555c7b7a2SEd Tanous                     aResp->res.jsonValue["IndicatorLED"] = ledStatus;
586c5b2abe0SLewanczyk, Dawid                   }
587c5b2abe0SLewanczyk, Dawid                 });
588c5b2abe0SLewanczyk, Dawid           } else {
58955c7b7a2SEd Tanous             aResp->res.jsonValue["IndicatorLED"] = "Off";
590c5b2abe0SLewanczyk, Dawid           }
591c5b2abe0SLewanczyk, Dawid         });
592c5b2abe0SLewanczyk, Dawid     provider.getComputerSystem(asyncResp, name);
593c5b2abe0SLewanczyk, Dawid     provider.getHostState(asyncResp);
594c5b2abe0SLewanczyk, Dawid   }
595c5b2abe0SLewanczyk, Dawid 
59655c7b7a2SEd Tanous   void doPatch(crow::Response &res, const crow::Request &req,
597c5b2abe0SLewanczyk, Dawid                const std::vector<std::string> &params) override {
598c5b2abe0SLewanczyk, Dawid     // Check if there is required param, truly entering this shall be
599c5b2abe0SLewanczyk, Dawid     // impossible
600c5b2abe0SLewanczyk, Dawid     if (params.size() != 1) {
601c5b2abe0SLewanczyk, Dawid       res.result(boost::beast::http::status::internal_server_error);
602c5b2abe0SLewanczyk, Dawid       res.end();
603c5b2abe0SLewanczyk, Dawid       return;
604c5b2abe0SLewanczyk, Dawid     }
605c5b2abe0SLewanczyk, Dawid     // Parse JSON request body
606c5b2abe0SLewanczyk, Dawid     nlohmann::json patch;
607c5b2abe0SLewanczyk, Dawid     if (!json_util::processJsonFromRequest(res, req, patch)) {
608c5b2abe0SLewanczyk, Dawid       return;
609c5b2abe0SLewanczyk, Dawid     }
610c5b2abe0SLewanczyk, Dawid     // Find key with new led value
611c5b2abe0SLewanczyk, Dawid     const std::string &name = params[0];
612c5b2abe0SLewanczyk, Dawid     const std::string *reqLedState = nullptr;
613c5b2abe0SLewanczyk, Dawid     json_util::Result r = json_util::getString(
614c5b2abe0SLewanczyk, Dawid         "IndicatorLED", patch, reqLedState,
615c5b2abe0SLewanczyk, Dawid         static_cast<int>(json_util::MessageSetting::TYPE_ERROR) |
616c5b2abe0SLewanczyk, Dawid             static_cast<int>(json_util::MessageSetting::MISSING),
61755c7b7a2SEd Tanous         res.jsonValue, std::string("/" + name + "/IndicatorLED"));
618c5b2abe0SLewanczyk, Dawid     if ((r != json_util::Result::SUCCESS) || (reqLedState == nullptr)) {
619c5b2abe0SLewanczyk, Dawid       res.result(boost::beast::http::status::bad_request);
620c5b2abe0SLewanczyk, Dawid       res.end();
621c5b2abe0SLewanczyk, Dawid       return;
622c5b2abe0SLewanczyk, Dawid     }
623c5b2abe0SLewanczyk, Dawid     // Verify key value
624c5b2abe0SLewanczyk, Dawid     std::string dbusLedState;
625c5b2abe0SLewanczyk, Dawid     for (const auto &p : boost::container::flat_map<const char *, const char *>{
626c5b2abe0SLewanczyk, Dawid              {"On", "Lit"}, {"Blink", "Blinking"}, {"Off", "Off"}}) {
627c5b2abe0SLewanczyk, Dawid       if (*reqLedState == p.second) {
628c5b2abe0SLewanczyk, Dawid         dbusLedState = p.first;
629c5b2abe0SLewanczyk, Dawid       }
630c5b2abe0SLewanczyk, Dawid     }
631c5b2abe0SLewanczyk, Dawid 
632c5b2abe0SLewanczyk, Dawid     // Update led status
633c5b2abe0SLewanczyk, Dawid     auto asyncResp = std::make_shared<SystemAsyncResp>(res);
63455c7b7a2SEd Tanous     res.jsonValue = Node::json;
63555c7b7a2SEd Tanous     res.jsonValue["@odata.id"] = "/redfish/v1/Systems/" + name;
636c5b2abe0SLewanczyk, Dawid 
637c5b2abe0SLewanczyk, Dawid     provider.getHostState(asyncResp);
638c5b2abe0SLewanczyk, Dawid     provider.getComputerSystem(asyncResp, name);
639c5b2abe0SLewanczyk, Dawid 
640c5b2abe0SLewanczyk, Dawid     if (dbusLedState.empty()) {
641c5b2abe0SLewanczyk, Dawid       messages::addMessageToJsonRoot(
64255c7b7a2SEd Tanous           res.jsonValue,
643c5b2abe0SLewanczyk, Dawid           messages::propertyValueNotInList(*reqLedState, "IndicatorLED"));
644c5b2abe0SLewanczyk, Dawid     } else {
645c5b2abe0SLewanczyk, Dawid       // Update led group
64655c7b7a2SEd Tanous       BMCWEB_LOG_DEBUG << "Update led group.";
64755c7b7a2SEd Tanous       crow::connections::systemBus->async_method_call(
648c5b2abe0SLewanczyk, Dawid           [&, asyncResp{std::move(asyncResp)}](
649c5b2abe0SLewanczyk, Dawid               const boost::system::error_code ec) {
650c5b2abe0SLewanczyk, Dawid             if (ec) {
65155c7b7a2SEd Tanous               BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
652c5b2abe0SLewanczyk, Dawid               asyncResp->setErrorStatus();
653c5b2abe0SLewanczyk, Dawid               return;
654c5b2abe0SLewanczyk, Dawid             }
65555c7b7a2SEd Tanous             BMCWEB_LOG_DEBUG << "Led group update done.";
656c5b2abe0SLewanczyk, Dawid           },
657c5b2abe0SLewanczyk, Dawid           "xyz.openbmc_project.LED.GroupManager",
658c5b2abe0SLewanczyk, Dawid           "/xyz/openbmc_project/led/groups/enclosure_identify",
659c5b2abe0SLewanczyk, Dawid           "org.freedesktop.DBus.Properties", "Set",
660c5b2abe0SLewanczyk, Dawid           "xyz.openbmc_project.Led.Group", "Asserted",
661c5b2abe0SLewanczyk, Dawid           sdbusplus::message::variant<bool>(
662c5b2abe0SLewanczyk, Dawid               (dbusLedState == "Off" ? false : true)));
663c5b2abe0SLewanczyk, Dawid       // Update identify led status
66455c7b7a2SEd Tanous       BMCWEB_LOG_DEBUG << "Update led SoftwareInventoryCollection.";
66555c7b7a2SEd Tanous       crow::connections::systemBus->async_method_call(
666c5b2abe0SLewanczyk, Dawid           [&, asyncResp{std::move(asyncResp)}](
667c5b2abe0SLewanczyk, Dawid               const boost::system::error_code ec) {
668c5b2abe0SLewanczyk, Dawid             if (ec) {
66955c7b7a2SEd Tanous               BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
670c5b2abe0SLewanczyk, Dawid               asyncResp->setErrorStatus();
671c5b2abe0SLewanczyk, Dawid               return;
672c5b2abe0SLewanczyk, Dawid             }
67355c7b7a2SEd Tanous             BMCWEB_LOG_DEBUG << "Led state update done.";
67455c7b7a2SEd Tanous             res.jsonValue["IndicatorLED"] = *reqLedState;
675c5b2abe0SLewanczyk, Dawid           },
676c5b2abe0SLewanczyk, Dawid           "xyz.openbmc_project.LED.Controller.identify",
677c5b2abe0SLewanczyk, Dawid           "/xyz/openbmc_project/led/physical/identify",
678c5b2abe0SLewanczyk, Dawid           "org.freedesktop.DBus.Properties", "Set",
679c5b2abe0SLewanczyk, Dawid           "xyz.openbmc_project.Led.Physical", "State",
680c5b2abe0SLewanczyk, Dawid           sdbusplus::message::variant<std::string>(
681c5b2abe0SLewanczyk, Dawid               "xyz.openbmc_project.Led.Physical.Action." + dbusLedState));
682c5b2abe0SLewanczyk, Dawid     }
683c5b2abe0SLewanczyk, Dawid   }
684c5b2abe0SLewanczyk, Dawid };
685c5b2abe0SLewanczyk, Dawid }  // namespace redfish
686