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