xref: /openbmc/bmcweb/features/redfish/lib/update_service.hpp (revision 1abe55ef9844afcddcab9d862ae06118f3a2390c)
1729dae72SJennifer Lee /*
2729dae72SJennifer Lee // Copyright (c) 2018 Intel Corporation
3729dae72SJennifer Lee //
4729dae72SJennifer Lee // Licensed under the Apache License, Version 2.0 (the "License");
5729dae72SJennifer Lee // you may not use this file except in compliance with the License.
6729dae72SJennifer Lee // You may obtain a copy of the License at
7729dae72SJennifer Lee //
8729dae72SJennifer Lee //      http://www.apache.org/licenses/LICENSE-2.0
9729dae72SJennifer Lee //
10729dae72SJennifer Lee // Unless required by applicable law or agreed to in writing, software
11729dae72SJennifer Lee // distributed under the License is distributed on an "AS IS" BASIS,
12729dae72SJennifer Lee // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13729dae72SJennifer Lee // See the License for the specific language governing permissions and
14729dae72SJennifer Lee // limitations under the License.
15729dae72SJennifer Lee */
16729dae72SJennifer Lee #pragma once
17729dae72SJennifer Lee 
18729dae72SJennifer Lee #include "node.hpp"
19*1abe55efSEd Tanous 
20729dae72SJennifer Lee #include <boost/container/flat_map.hpp>
21729dae72SJennifer Lee 
22*1abe55efSEd Tanous namespace redfish
23*1abe55efSEd Tanous {
24acb7cfb4SJennifer Lee static std::unique_ptr<sdbusplus::bus::match::match> fwUpdateMatcher;
25729dae72SJennifer Lee 
26*1abe55efSEd Tanous class UpdateService : public Node
27*1abe55efSEd Tanous {
28729dae72SJennifer Lee   public:
29*1abe55efSEd Tanous     UpdateService(CrowApp &app) : Node(app, "/redfish/v1/UpdateService/")
30*1abe55efSEd Tanous     {
31729dae72SJennifer Lee         Node::json["@odata.type"] = "#UpdateService.v1_2_0.UpdateService";
32729dae72SJennifer Lee         Node::json["@odata.id"] = "/redfish/v1/UpdateService";
33729dae72SJennifer Lee         Node::json["@odata.context"] =
34729dae72SJennifer Lee             "/redfish/v1/$metadata#UpdateService.UpdateService";
35729dae72SJennifer Lee         Node::json["Id"] = "UpdateService";
36729dae72SJennifer Lee         Node::json["Description"] = "Service for Software Update";
37729dae72SJennifer Lee         Node::json["Name"] = "Update Service";
38acb7cfb4SJennifer Lee         Node::json["HttpPushUri"] = "/redfish/v1/UpdateService";
39c711bf86SEd Tanous         // UpdateService cannot be disabled
40c711bf86SEd Tanous         Node::json["ServiceEnabled"] = true;
416c4eb9deSJennifer Lee         Node::json["FirmwareInventory"] = {
426c4eb9deSJennifer Lee             {"@odata.id", "/redfish/v1/UpdateService/FirmwareInventory"}};
43729dae72SJennifer Lee 
44729dae72SJennifer Lee         entityPrivileges = {
45729dae72SJennifer Lee             {boost::beast::http::verb::get, {{"Login"}}},
46729dae72SJennifer Lee             {boost::beast::http::verb::head, {{"Login"}}},
47729dae72SJennifer Lee             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
48729dae72SJennifer Lee             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
49729dae72SJennifer Lee             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
50729dae72SJennifer Lee             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
51729dae72SJennifer Lee     }
52729dae72SJennifer Lee 
53729dae72SJennifer Lee   private:
5455c7b7a2SEd Tanous     void doGet(crow::Response &res, const crow::Request &req,
55*1abe55efSEd Tanous                const std::vector<std::string> &params) override
56*1abe55efSEd Tanous     {
5755c7b7a2SEd Tanous         res.jsonValue = Node::json;
58729dae72SJennifer Lee         res.end();
59729dae72SJennifer Lee     }
60*1abe55efSEd Tanous     static void activateImage(const std::string &objPath)
61*1abe55efSEd Tanous     {
62acb7cfb4SJennifer Lee         crow::connections::systemBus->async_method_call(
63c711bf86SEd Tanous             [objPath](const boost::system::error_code error_code) {
64*1abe55efSEd Tanous                 if (error_code)
65*1abe55efSEd Tanous                 {
66acb7cfb4SJennifer Lee                     BMCWEB_LOG_DEBUG << "error_code = " << error_code;
67acb7cfb4SJennifer Lee                     BMCWEB_LOG_DEBUG << "error msg = " << error_code.message();
68acb7cfb4SJennifer Lee                 }
69acb7cfb4SJennifer Lee             },
70c711bf86SEd Tanous             "xyz.openbmc_project.Software.BMC.Updater", objPath,
71acb7cfb4SJennifer Lee             "org.freedesktop.DBus.Properties", "Set",
72acb7cfb4SJennifer Lee             "xyz.openbmc_project.Software.Activation", "RequestedActivation",
73acb7cfb4SJennifer Lee             sdbusplus::message::variant<std::string>(
74acb7cfb4SJennifer Lee                 "xyz.openbmc_project.Software.Activation.RequestedActivations."
75acb7cfb4SJennifer Lee                 "Active"));
76acb7cfb4SJennifer Lee     }
77acb7cfb4SJennifer Lee     void doPost(crow::Response &res, const crow::Request &req,
78*1abe55efSEd Tanous                 const std::vector<std::string> &params) override
79*1abe55efSEd Tanous     {
80acb7cfb4SJennifer Lee         BMCWEB_LOG_DEBUG << "doPost...";
81acb7cfb4SJennifer Lee 
82acb7cfb4SJennifer Lee         // Only allow one FW update at a time
83*1abe55efSEd Tanous         if (fwUpdateMatcher != nullptr)
84*1abe55efSEd Tanous         {
85acb7cfb4SJennifer Lee             res.addHeader("Retry-After", "30");
86acb7cfb4SJennifer Lee             res.result(boost::beast::http::status::service_unavailable);
87acb7cfb4SJennifer Lee             res.jsonValue = messages::serviceTemporarilyUnavailable("3");
88acb7cfb4SJennifer Lee             res.end();
89acb7cfb4SJennifer Lee             return;
90acb7cfb4SJennifer Lee         }
91acb7cfb4SJennifer Lee         // Make this const static so it survives outside this method
92*1abe55efSEd Tanous         static boost::asio::deadline_timer timeout(
93*1abe55efSEd Tanous             *req.ioService, boost::posix_time::seconds(5));
94acb7cfb4SJennifer Lee 
95acb7cfb4SJennifer Lee         timeout.expires_from_now(boost::posix_time::seconds(5));
96acb7cfb4SJennifer Lee 
97acb7cfb4SJennifer Lee         timeout.async_wait([&res](const boost::system::error_code &ec) {
98acb7cfb4SJennifer Lee             fwUpdateMatcher = nullptr;
99*1abe55efSEd Tanous             if (ec == boost::asio::error::operation_aborted)
100*1abe55efSEd Tanous             {
101acb7cfb4SJennifer Lee                 // expected, we were canceled before the timer completed.
102acb7cfb4SJennifer Lee                 return;
103acb7cfb4SJennifer Lee             }
104*1abe55efSEd Tanous             BMCWEB_LOG_ERROR
105*1abe55efSEd Tanous                 << "Timed out waiting for firmware object being created";
106*1abe55efSEd Tanous             BMCWEB_LOG_ERROR
107*1abe55efSEd Tanous                 << "FW image may has already been uploaded to server";
108*1abe55efSEd Tanous             if (ec)
109*1abe55efSEd Tanous             {
110acb7cfb4SJennifer Lee                 BMCWEB_LOG_ERROR << "Async_wait failed" << ec;
111acb7cfb4SJennifer Lee                 return;
112acb7cfb4SJennifer Lee             }
113acb7cfb4SJennifer Lee 
114acb7cfb4SJennifer Lee             res.result(boost::beast::http::status::internal_server_error);
115acb7cfb4SJennifer Lee             res.jsonValue = redfish::messages::internalError();
116acb7cfb4SJennifer Lee             res.end();
117acb7cfb4SJennifer Lee         });
118acb7cfb4SJennifer Lee 
119acb7cfb4SJennifer Lee         auto callback = [&res](sdbusplus::message::message &m) {
120acb7cfb4SJennifer Lee             BMCWEB_LOG_DEBUG << "Match fired";
121acb7cfb4SJennifer Lee             bool flag = false;
122acb7cfb4SJennifer Lee 
123*1abe55efSEd Tanous             if (m.is_method_error())
124*1abe55efSEd Tanous             {
125acb7cfb4SJennifer Lee                 BMCWEB_LOG_DEBUG << "Dbus method error!!!";
126acb7cfb4SJennifer Lee                 res.end();
127acb7cfb4SJennifer Lee                 return;
128acb7cfb4SJennifer Lee             }
129acb7cfb4SJennifer Lee             std::vector<std::pair<
130acb7cfb4SJennifer Lee                 std::string,
131*1abe55efSEd Tanous                 std::vector<std::pair<
132*1abe55efSEd Tanous                     std::string, sdbusplus::message::variant<std::string>>>>>
133acb7cfb4SJennifer Lee                 interfaces_properties;
134acb7cfb4SJennifer Lee 
135c711bf86SEd Tanous             sdbusplus::message::object_path objPath;
136acb7cfb4SJennifer Lee 
137c711bf86SEd Tanous             m.read(objPath, interfaces_properties); // Read in the object path
138acb7cfb4SJennifer Lee                                                     // that was just created
139c711bf86SEd Tanous             // std::string str_objpath = objPath.str;  // keep a copy for
140acb7cfb4SJennifer Lee             // constructing response message
141c711bf86SEd Tanous             BMCWEB_LOG_DEBUG << "obj path = " << objPath.str; // str_objpath;
142*1abe55efSEd Tanous             for (auto &interface : interfaces_properties)
143*1abe55efSEd Tanous             {
144acb7cfb4SJennifer Lee                 BMCWEB_LOG_DEBUG << "interface = " << interface.first;
145acb7cfb4SJennifer Lee 
146*1abe55efSEd Tanous                 if (interface.first ==
147*1abe55efSEd Tanous                     "xyz.openbmc_project.Software.Activation")
148*1abe55efSEd Tanous                 {
149*1abe55efSEd Tanous                     // cancel timer only when
150*1abe55efSEd Tanous                     // xyz.openbmc_project.Software.Activation interface is
151*1abe55efSEd Tanous                     // added
152acb7cfb4SJennifer Lee                     boost::system::error_code ec;
153acb7cfb4SJennifer Lee                     timeout.cancel(ec);
154*1abe55efSEd Tanous                     if (ec)
155*1abe55efSEd Tanous                     {
156acb7cfb4SJennifer Lee                         BMCWEB_LOG_ERROR << "error canceling timer " << ec;
157acb7cfb4SJennifer Lee                     }
158c711bf86SEd Tanous                     UpdateService::activateImage(objPath.str); // str_objpath);
159acb7cfb4SJennifer Lee                     res.jsonValue = redfish::messages::success();
160acb7cfb4SJennifer Lee                     BMCWEB_LOG_DEBUG << "ending response";
161acb7cfb4SJennifer Lee                     res.end();
162acb7cfb4SJennifer Lee                     fwUpdateMatcher = nullptr;
163acb7cfb4SJennifer Lee                 }
164acb7cfb4SJennifer Lee             }
165acb7cfb4SJennifer Lee         };
166acb7cfb4SJennifer Lee 
167acb7cfb4SJennifer Lee         fwUpdateMatcher = std::make_unique<sdbusplus::bus::match::match>(
168acb7cfb4SJennifer Lee             *crow::connections::systemBus,
169acb7cfb4SJennifer Lee             "interface='org.freedesktop.DBus.ObjectManager',type='signal',"
170acb7cfb4SJennifer Lee             "member='InterfacesAdded',path='/xyz/openbmc_project/software'",
171acb7cfb4SJennifer Lee             callback);
172acb7cfb4SJennifer Lee 
173acb7cfb4SJennifer Lee         std::string filepath(
174acb7cfb4SJennifer Lee             "/tmp/images/" +
175acb7cfb4SJennifer Lee             boost::uuids::to_string(boost::uuids::random_generator()()));
176acb7cfb4SJennifer Lee         BMCWEB_LOG_DEBUG << "Writing file to " << filepath;
177acb7cfb4SJennifer Lee         std::ofstream out(filepath, std::ofstream::out | std::ofstream::binary |
178acb7cfb4SJennifer Lee                                         std::ofstream::trunc);
179acb7cfb4SJennifer Lee         out << req.body;
180acb7cfb4SJennifer Lee         out.close();
181acb7cfb4SJennifer Lee         BMCWEB_LOG_DEBUG << "file upload complete!!";
182acb7cfb4SJennifer Lee     }
183729dae72SJennifer Lee };
184729dae72SJennifer Lee 
185*1abe55efSEd Tanous class SoftwareInventoryCollection : public Node
186*1abe55efSEd Tanous {
187729dae72SJennifer Lee   public:
188729dae72SJennifer Lee     template <typename CrowApp>
189*1abe55efSEd Tanous     SoftwareInventoryCollection(CrowApp &app) :
190*1abe55efSEd Tanous         Node(app, "/redfish/v1/UpdateService/FirmwareInventory/")
191*1abe55efSEd Tanous     {
192729dae72SJennifer Lee         Node::json["@odata.type"] =
193729dae72SJennifer Lee             "#SoftwareInventoryCollection.SoftwareInventoryCollection";
1946c4eb9deSJennifer Lee         Node::json["@odata.id"] = "/redfish/v1/UpdateService/FirmwareInventory";
195729dae72SJennifer Lee         Node::json["@odata.context"] =
196729dae72SJennifer Lee             "/redfish/v1/"
197729dae72SJennifer Lee             "$metadata#SoftwareInventoryCollection.SoftwareInventoryCollection";
198729dae72SJennifer Lee         Node::json["Name"] = "Software Inventory Collection";
199729dae72SJennifer Lee 
200729dae72SJennifer Lee         entityPrivileges = {
201729dae72SJennifer Lee             {boost::beast::http::verb::get, {{"Login"}}},
202729dae72SJennifer Lee             {boost::beast::http::verb::head, {{"Login"}}},
203729dae72SJennifer Lee             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
204729dae72SJennifer Lee             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
205729dae72SJennifer Lee             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
206729dae72SJennifer Lee             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
207729dae72SJennifer Lee     }
208729dae72SJennifer Lee 
209729dae72SJennifer Lee   private:
21055c7b7a2SEd Tanous     void doGet(crow::Response &res, const crow::Request &req,
211*1abe55efSEd Tanous                const std::vector<std::string> &params) override
212*1abe55efSEd Tanous     {
213c711bf86SEd Tanous         std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
21455c7b7a2SEd Tanous         res.jsonValue = Node::json;
215c711bf86SEd Tanous 
216c711bf86SEd Tanous         crow::connections::systemBus->async_method_call(
217c711bf86SEd Tanous             [asyncResp](
218c711bf86SEd Tanous                 const boost::system::error_code ec,
2196c4eb9deSJennifer Lee                 const std::vector<std::pair<
220*1abe55efSEd Tanous                     std::string, std::vector<std::pair<
221*1abe55efSEd Tanous                                      std::string, std::vector<std::string>>>>>
2226c4eb9deSJennifer Lee                     &subtree) {
223*1abe55efSEd Tanous                 if (ec)
224*1abe55efSEd Tanous                 {
225c711bf86SEd Tanous                     asyncResp->res.result(
226c711bf86SEd Tanous                         boost::beast::http::status::internal_server_error);
2276c4eb9deSJennifer Lee                     return;
228729dae72SJennifer Lee                 }
229c711bf86SEd Tanous                 asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
230c711bf86SEd Tanous                 asyncResp->res.jsonValue["Members@odata.count"] = 0;
2316c4eb9deSJennifer Lee 
232*1abe55efSEd Tanous                 for (auto &obj : subtree)
233*1abe55efSEd Tanous                 {
234*1abe55efSEd Tanous                     const std::vector<
235*1abe55efSEd Tanous                         std::pair<std::string, std::vector<std::string>>>
2366c4eb9deSJennifer Lee                         &connections = obj.second;
2376c4eb9deSJennifer Lee 
238*1abe55efSEd Tanous                     for (auto &conn : connections)
239*1abe55efSEd Tanous                     {
240c711bf86SEd Tanous                         const std::string &connectionName = conn.first;
241*1abe55efSEd Tanous                         BMCWEB_LOG_DEBUG << "connectionName = "
242*1abe55efSEd Tanous                                          << connectionName;
24355c7b7a2SEd Tanous                         BMCWEB_LOG_DEBUG << "obj.first = " << obj.first;
2446c4eb9deSJennifer Lee 
24555c7b7a2SEd Tanous                         crow::connections::systemBus->async_method_call(
246*1abe55efSEd Tanous                             [asyncResp](
247*1abe55efSEd Tanous                                 const boost::system::error_code error_code,
248c711bf86SEd Tanous                                 const VariantType &activation) {
249*1abe55efSEd Tanous                                 BMCWEB_LOG_DEBUG
250*1abe55efSEd Tanous                                     << "safe returned in lambda function";
251*1abe55efSEd Tanous                                 if (error_code)
252*1abe55efSEd Tanous                                 {
253acb7cfb4SJennifer Lee                                     asyncResp->res.result(
254*1abe55efSEd Tanous                                         boost::beast::http::status::
255*1abe55efSEd Tanous                                             internal_server_error);
2566c4eb9deSJennifer Lee                                     return;
2576c4eb9deSJennifer Lee                                 }
258c711bf86SEd Tanous 
259c711bf86SEd Tanous                                 const std::string *sw_inv_purpose =
260*1abe55efSEd Tanous                                     mapbox::getPtr<const std::string>(
261*1abe55efSEd Tanous                                         activation);
262*1abe55efSEd Tanous                                 if (sw_inv_purpose == nullptr)
263*1abe55efSEd Tanous                                 {
264c711bf86SEd Tanous                                     asyncResp->res.result(
265*1abe55efSEd Tanous                                         boost::beast::http::status::
266*1abe55efSEd Tanous                                             internal_server_error);
267acb7cfb4SJennifer Lee                                     return;
268acb7cfb4SJennifer Lee                                 }
269*1abe55efSEd Tanous                                 std::size_t last_pos =
270*1abe55efSEd Tanous                                     sw_inv_purpose->rfind(".");
271*1abe55efSEd Tanous                                 if (last_pos == std::string::npos)
272*1abe55efSEd Tanous                                 {
273c711bf86SEd Tanous                                     asyncResp->res.result(
274*1abe55efSEd Tanous                                         boost::beast::http::status::
275*1abe55efSEd Tanous                                             internal_server_error);
276c711bf86SEd Tanous                                     return;
277c711bf86SEd Tanous                                 }
278c711bf86SEd Tanous                                 nlohmann::json &members =
279c711bf86SEd Tanous                                     asyncResp->res.jsonValue["Members"];
280c711bf86SEd Tanous                                 members.push_back(
281*1abe55efSEd Tanous                                     {{"@odata.id", "/redfish/v1/UpdateService/"
282*1abe55efSEd Tanous                                                    "FirmwareInventory/" +
283*1abe55efSEd Tanous                                                        sw_inv_purpose->substr(
284*1abe55efSEd Tanous                                                            last_pos + 1)}});
285*1abe55efSEd Tanous                                 asyncResp->res
286*1abe55efSEd Tanous                                     .jsonValue["Members@odata.count"] =
287c711bf86SEd Tanous                                     members.size();
2886c4eb9deSJennifer Lee                             },
289*1abe55efSEd Tanous                             connectionName, obj.first,
290*1abe55efSEd Tanous                             "org.freedesktop.DBus.Properties", "Get",
291*1abe55efSEd Tanous                             "xyz.openbmc_project.Software.Activation",
292acb7cfb4SJennifer Lee                             "Activation");
2936c4eb9deSJennifer Lee                     }
2946c4eb9deSJennifer Lee                 }
295c711bf86SEd Tanous             },
296c711bf86SEd Tanous             "xyz.openbmc_project.ObjectMapper",
297c711bf86SEd Tanous             "/xyz/openbmc_project/object_mapper",
298c711bf86SEd Tanous             "xyz.openbmc_project.ObjectMapper", "GetSubTree",
299c711bf86SEd Tanous             "/xyz/openbmc_project/software", int32_t(1),
300*1abe55efSEd Tanous             std::array<const char *, 1>{
301*1abe55efSEd Tanous                 "xyz.openbmc_project.Software.Version"});
302729dae72SJennifer Lee     }
303729dae72SJennifer Lee };
304c711bf86SEd Tanous 
305*1abe55efSEd Tanous class SoftwareInventory : public Node
306*1abe55efSEd Tanous {
307729dae72SJennifer Lee   public:
308729dae72SJennifer Lee     template <typename CrowApp>
309*1abe55efSEd Tanous     SoftwareInventory(CrowApp &app) :
310*1abe55efSEd Tanous         Node(app, "/redfish/v1/UpdateService/FirmwareInventory/<str>/",
311*1abe55efSEd Tanous              std::string())
312*1abe55efSEd Tanous     {
313*1abe55efSEd Tanous         Node::json["@odata.type"] =
314*1abe55efSEd Tanous             "#SoftwareInventory.v1_1_0.SoftwareInventory";
315729dae72SJennifer Lee         Node::json["@odata.context"] =
316729dae72SJennifer Lee             "/redfish/v1/$metadata#SoftwareInventory.SoftwareInventory";
317729dae72SJennifer Lee         Node::json["Name"] = "Software Inventory";
3186c4eb9deSJennifer Lee         Node::json["Updateable"] = false;
319acb7cfb4SJennifer Lee         Node::json["Status"]["Health"] = "OK";
320acb7cfb4SJennifer Lee         Node::json["Status"]["HealthRollup"] = "OK";
321acb7cfb4SJennifer Lee         Node::json["Status"]["State"] = "Enabled";
322729dae72SJennifer Lee         entityPrivileges = {
323729dae72SJennifer Lee             {boost::beast::http::verb::get, {{"Login"}}},
324729dae72SJennifer Lee             {boost::beast::http::verb::head, {{"Login"}}},
325729dae72SJennifer Lee             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
326729dae72SJennifer Lee             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
327729dae72SJennifer Lee             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
328729dae72SJennifer Lee             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
329729dae72SJennifer Lee     }
330729dae72SJennifer Lee 
331729dae72SJennifer Lee   private:
33255c7b7a2SEd Tanous     void doGet(crow::Response &res, const crow::Request &req,
333*1abe55efSEd Tanous                const std::vector<std::string> &params) override
334*1abe55efSEd Tanous     {
335c711bf86SEd Tanous         std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
33655c7b7a2SEd Tanous         res.jsonValue = Node::json;
3376c4eb9deSJennifer Lee 
338*1abe55efSEd Tanous         if (params.size() != 1)
339*1abe55efSEd Tanous         {
340729dae72SJennifer Lee             res.result(boost::beast::http::status::internal_server_error);
341acb7cfb4SJennifer Lee             res.jsonValue = messages::internalError();
342729dae72SJennifer Lee             res.end();
343729dae72SJennifer Lee             return;
344729dae72SJennifer Lee         }
345729dae72SJennifer Lee 
346c711bf86SEd Tanous         std::shared_ptr<std::string> sw_id =
347c711bf86SEd Tanous             std::make_shared<std::string>(params[0]);
348c711bf86SEd Tanous 
34955c7b7a2SEd Tanous         res.jsonValue["@odata.id"] =
350c711bf86SEd Tanous             "/redfish/v1/UpdateService/FirmwareInventory/" + *sw_id;
351c711bf86SEd Tanous 
352c711bf86SEd Tanous         crow::connections::systemBus->async_method_call(
353c711bf86SEd Tanous             [asyncResp, sw_id](
354c711bf86SEd Tanous                 const boost::system::error_code ec,
3556c4eb9deSJennifer Lee                 const std::vector<std::pair<
356*1abe55efSEd Tanous                     std::string, std::vector<std::pair<
357*1abe55efSEd Tanous                                      std::string, std::vector<std::string>>>>>
3586c4eb9deSJennifer Lee                     &subtree) {
35955c7b7a2SEd Tanous                 BMCWEB_LOG_DEBUG << "doGet callback...";
360*1abe55efSEd Tanous                 if (ec)
361*1abe55efSEd Tanous                 {
362c711bf86SEd Tanous                     asyncResp->res.result(
363c711bf86SEd Tanous                         boost::beast::http::status::internal_server_error);
3646c4eb9deSJennifer Lee                     return;
3656c4eb9deSJennifer Lee                 }
3666c4eb9deSJennifer Lee 
367*1abe55efSEd Tanous                 for (const std::pair<
368*1abe55efSEd Tanous                          std::string,
369*1abe55efSEd Tanous                          std::vector<
370*1abe55efSEd Tanous                              std::pair<std::string, std::vector<std::string>>>>
371*1abe55efSEd Tanous                          &obj : subtree)
372*1abe55efSEd Tanous                 {
373*1abe55efSEd Tanous                     if (boost::ends_with(obj.first, *sw_id) != true)
374*1abe55efSEd Tanous                     {
375acb7cfb4SJennifer Lee                         continue;
376acb7cfb4SJennifer Lee                     }
377acb7cfb4SJennifer Lee 
378*1abe55efSEd Tanous                     if (obj.second.size() <= 1)
379*1abe55efSEd Tanous                     {
380acb7cfb4SJennifer Lee                         continue;
381acb7cfb4SJennifer Lee                     }
3826c4eb9deSJennifer Lee 
38355c7b7a2SEd Tanous                     crow::connections::systemBus->async_method_call(
384*1abe55efSEd Tanous                         [asyncResp,
385*1abe55efSEd Tanous                          sw_id](const boost::system::error_code error_code,
386*1abe55efSEd Tanous                                 const boost::container::flat_map<
387*1abe55efSEd Tanous                                     std::string, VariantType> &propertiesList) {
388*1abe55efSEd Tanous                             if (error_code)
389*1abe55efSEd Tanous                             {
390c711bf86SEd Tanous                                 asyncResp->res.result(
391*1abe55efSEd Tanous                                     boost::beast::http::status::
392*1abe55efSEd Tanous                                         internal_server_error);
3936c4eb9deSJennifer Lee                                 return;
3946c4eb9deSJennifer Lee                             }
395*1abe55efSEd Tanous                             boost::container::flat_map<
396*1abe55efSEd Tanous                                 std::string, VariantType>::const_iterator it =
3976c4eb9deSJennifer Lee                                 propertiesList.find("Purpose");
398*1abe55efSEd Tanous                             if (it == propertiesList.end())
399*1abe55efSEd Tanous                             {
400*1abe55efSEd Tanous                                 BMCWEB_LOG_DEBUG
401*1abe55efSEd Tanous                                     << "Can't find property \"Purpose\"!";
402c711bf86SEd Tanous                                 asyncResp->res.result(
403*1abe55efSEd Tanous                                     boost::beast::http::status::
404*1abe55efSEd Tanous                                         internal_server_error);
4056c4eb9deSJennifer Lee                                 return;
4066c4eb9deSJennifer Lee                             }
407acb7cfb4SJennifer Lee                             const std::string *sw_inv_purpose =
408acb7cfb4SJennifer Lee                                 mapbox::getPtr<const std::string>(it->second);
409*1abe55efSEd Tanous                             if (sw_inv_purpose == nullptr)
410*1abe55efSEd Tanous                             {
411*1abe55efSEd Tanous                                 BMCWEB_LOG_DEBUG
412*1abe55efSEd Tanous                                     << "wrong types for property\"Purpose\"!";
413c711bf86SEd Tanous                                 asyncResp->res.result(
414*1abe55efSEd Tanous                                     boost::beast::http::status::
415*1abe55efSEd Tanous                                         internal_server_error);
416acb7cfb4SJennifer Lee                                 return;
417acb7cfb4SJennifer Lee                             }
418c711bf86SEd Tanous 
419*1abe55efSEd Tanous                             BMCWEB_LOG_DEBUG << "sw_inv_purpose = "
420*1abe55efSEd Tanous                                              << *sw_inv_purpose;
421*1abe55efSEd Tanous                             if (boost::ends_with(*sw_inv_purpose, "." + *sw_id))
422*1abe55efSEd Tanous                             {
423c711bf86SEd Tanous                                 it = propertiesList.find("Version");
424*1abe55efSEd Tanous                                 if (it == propertiesList.end())
425*1abe55efSEd Tanous                                 {
426*1abe55efSEd Tanous                                     BMCWEB_LOG_DEBUG
427*1abe55efSEd Tanous                                         << "Can't find property \"Version\"!";
428c711bf86SEd Tanous                                     asyncResp->res.result(
429*1abe55efSEd Tanous                                         boost::beast::http::status::
430*1abe55efSEd Tanous                                             internal_server_error);
431c711bf86SEd Tanous                                     return;
432acb7cfb4SJennifer Lee                                 }
433acb7cfb4SJennifer Lee 
434acb7cfb4SJennifer Lee                                 const std::string *version =
435*1abe55efSEd Tanous                                     mapbox::getPtr<const std::string>(
436*1abe55efSEd Tanous                                         it->second);
437c711bf86SEd Tanous 
438*1abe55efSEd Tanous                                 if (version != nullptr)
439*1abe55efSEd Tanous                                 {
440*1abe55efSEd Tanous                                     BMCWEB_LOG_DEBUG
441*1abe55efSEd Tanous                                         << "Can't find property \"Version\"!";
442c711bf86SEd Tanous                                     asyncResp->res.result(
443*1abe55efSEd Tanous                                         boost::beast::http::status::
444*1abe55efSEd Tanous                                             internal_server_error);
4456c4eb9deSJennifer Lee                                     return;
4466c4eb9deSJennifer Lee                                 }
447c711bf86SEd Tanous                                 asyncResp->res.jsonValue["Version"] = *version;
448c711bf86SEd Tanous                                 asyncResp->res.jsonValue["Id"] = *sw_id;
4496c4eb9deSJennifer Lee                             }
4506c4eb9deSJennifer Lee                         },
451c711bf86SEd Tanous                         obj.second[0].first, obj.first,
452c711bf86SEd Tanous                         "org.freedesktop.DBus.Properties", "GetAll",
453c711bf86SEd Tanous                         "xyz.openbmc_project.Software.Version");
4546c4eb9deSJennifer Lee                 }
455c711bf86SEd Tanous             },
456c711bf86SEd Tanous             "xyz.openbmc_project.ObjectMapper",
457c711bf86SEd Tanous             "/xyz/openbmc_project/object_mapper",
458c711bf86SEd Tanous             "xyz.openbmc_project.ObjectMapper", "GetSubTree",
459c711bf86SEd Tanous             "/xyz/openbmc_project/software", int32_t(1),
460*1abe55efSEd Tanous             std::array<const char *, 1>{
461*1abe55efSEd Tanous                 "xyz.openbmc_project.Software.Version"});
4626c4eb9deSJennifer Lee     }
463729dae72SJennifer Lee };
464729dae72SJennifer Lee 
465729dae72SJennifer Lee } // namespace redfish
466