xref: /openbmc/bmcweb/features/redfish/lib/update_service.hpp (revision f12894f8bd7fc26ffa16e5a89072e6c19095f866)
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"
191abe55efSEd Tanous 
20729dae72SJennifer Lee #include <boost/container/flat_map.hpp>
21729dae72SJennifer Lee 
221abe55efSEd Tanous namespace redfish
231abe55efSEd Tanous {
24acb7cfb4SJennifer Lee static std::unique_ptr<sdbusplus::bus::match::match> fwUpdateMatcher;
25729dae72SJennifer Lee 
261abe55efSEd Tanous class UpdateService : public Node
271abe55efSEd Tanous {
28729dae72SJennifer Lee   public:
291abe55efSEd Tanous     UpdateService(CrowApp &app) : Node(app, "/redfish/v1/UpdateService/")
301abe55efSEd 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,
551abe55efSEd Tanous                const std::vector<std::string> &params) override
561abe55efSEd Tanous     {
5755c7b7a2SEd Tanous         res.jsonValue = Node::json;
58729dae72SJennifer Lee         res.end();
59729dae72SJennifer Lee     }
601abe55efSEd Tanous     static void activateImage(const std::string &objPath)
611abe55efSEd Tanous     {
62acb7cfb4SJennifer Lee         crow::connections::systemBus->async_method_call(
63c711bf86SEd Tanous             [objPath](const boost::system::error_code error_code) {
641abe55efSEd Tanous                 if (error_code)
651abe55efSEd 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,
781abe55efSEd Tanous                 const std::vector<std::string> &params) override
791abe55efSEd Tanous     {
80acb7cfb4SJennifer Lee         BMCWEB_LOG_DEBUG << "doPost...";
81acb7cfb4SJennifer Lee 
82acb7cfb4SJennifer Lee         // Only allow one FW update at a time
831abe55efSEd Tanous         if (fwUpdateMatcher != nullptr)
841abe55efSEd Tanous         {
85acb7cfb4SJennifer Lee             res.addHeader("Retry-After", "30");
86*f12894f8SJason M. Bills             messages::serviceTemporarilyUnavailable(res, "3");
87acb7cfb4SJennifer Lee             res.end();
88acb7cfb4SJennifer Lee             return;
89acb7cfb4SJennifer Lee         }
90acb7cfb4SJennifer Lee         // Make this const static so it survives outside this method
911abe55efSEd Tanous         static boost::asio::deadline_timer timeout(
921abe55efSEd Tanous             *req.ioService, boost::posix_time::seconds(5));
93acb7cfb4SJennifer Lee 
94acb7cfb4SJennifer Lee         timeout.expires_from_now(boost::posix_time::seconds(5));
95acb7cfb4SJennifer Lee 
96acb7cfb4SJennifer Lee         timeout.async_wait([&res](const boost::system::error_code &ec) {
97acb7cfb4SJennifer Lee             fwUpdateMatcher = nullptr;
981abe55efSEd Tanous             if (ec == boost::asio::error::operation_aborted)
991abe55efSEd Tanous             {
100acb7cfb4SJennifer Lee                 // expected, we were canceled before the timer completed.
101acb7cfb4SJennifer Lee                 return;
102acb7cfb4SJennifer Lee             }
1031abe55efSEd Tanous             BMCWEB_LOG_ERROR
1041abe55efSEd Tanous                 << "Timed out waiting for firmware object being created";
1051abe55efSEd Tanous             BMCWEB_LOG_ERROR
1061abe55efSEd Tanous                 << "FW image may has already been uploaded to server";
1071abe55efSEd Tanous             if (ec)
1081abe55efSEd Tanous             {
109acb7cfb4SJennifer Lee                 BMCWEB_LOG_ERROR << "Async_wait failed" << ec;
110acb7cfb4SJennifer Lee                 return;
111acb7cfb4SJennifer Lee             }
112acb7cfb4SJennifer Lee 
113*f12894f8SJason M. Bills             redfish::messages::internalError(res);
114acb7cfb4SJennifer Lee             res.end();
115acb7cfb4SJennifer Lee         });
116acb7cfb4SJennifer Lee 
117acb7cfb4SJennifer Lee         auto callback = [&res](sdbusplus::message::message &m) {
118acb7cfb4SJennifer Lee             BMCWEB_LOG_DEBUG << "Match fired";
119acb7cfb4SJennifer Lee             bool flag = false;
120acb7cfb4SJennifer Lee 
1211abe55efSEd Tanous             if (m.is_method_error())
1221abe55efSEd Tanous             {
123acb7cfb4SJennifer Lee                 BMCWEB_LOG_DEBUG << "Dbus method error!!!";
124acb7cfb4SJennifer Lee                 res.end();
125acb7cfb4SJennifer Lee                 return;
126acb7cfb4SJennifer Lee             }
127acb7cfb4SJennifer Lee             std::vector<std::pair<
128acb7cfb4SJennifer Lee                 std::string,
1291abe55efSEd Tanous                 std::vector<std::pair<
1301abe55efSEd Tanous                     std::string, sdbusplus::message::variant<std::string>>>>>
1313ae837c9SEd Tanous                 interfacesProperties;
132acb7cfb4SJennifer Lee 
133c711bf86SEd Tanous             sdbusplus::message::object_path objPath;
134acb7cfb4SJennifer Lee 
1353ae837c9SEd Tanous             m.read(objPath, interfacesProperties); // Read in the object path
136acb7cfb4SJennifer Lee                                                    // that was just created
137c711bf86SEd Tanous             // std::string str_objpath = objPath.str;  // keep a copy for
138acb7cfb4SJennifer Lee             // constructing response message
139c711bf86SEd Tanous             BMCWEB_LOG_DEBUG << "obj path = " << objPath.str; // str_objpath;
1403ae837c9SEd Tanous             for (auto &interface : interfacesProperties)
1411abe55efSEd Tanous             {
142acb7cfb4SJennifer Lee                 BMCWEB_LOG_DEBUG << "interface = " << interface.first;
143acb7cfb4SJennifer Lee 
1441abe55efSEd Tanous                 if (interface.first ==
1451abe55efSEd Tanous                     "xyz.openbmc_project.Software.Activation")
1461abe55efSEd Tanous                 {
1471abe55efSEd Tanous                     // cancel timer only when
1481abe55efSEd Tanous                     // xyz.openbmc_project.Software.Activation interface is
1491abe55efSEd Tanous                     // added
150acb7cfb4SJennifer Lee                     boost::system::error_code ec;
151acb7cfb4SJennifer Lee                     timeout.cancel(ec);
1521abe55efSEd Tanous                     if (ec)
1531abe55efSEd Tanous                     {
154acb7cfb4SJennifer Lee                         BMCWEB_LOG_ERROR << "error canceling timer " << ec;
155acb7cfb4SJennifer Lee                     }
156c711bf86SEd Tanous                     UpdateService::activateImage(objPath.str); // str_objpath);
157*f12894f8SJason M. Bills                     redfish::messages::success(res);
158acb7cfb4SJennifer Lee                     BMCWEB_LOG_DEBUG << "ending response";
159acb7cfb4SJennifer Lee                     res.end();
160acb7cfb4SJennifer Lee                     fwUpdateMatcher = nullptr;
161acb7cfb4SJennifer Lee                 }
162acb7cfb4SJennifer Lee             }
163acb7cfb4SJennifer Lee         };
164acb7cfb4SJennifer Lee 
165acb7cfb4SJennifer Lee         fwUpdateMatcher = std::make_unique<sdbusplus::bus::match::match>(
166acb7cfb4SJennifer Lee             *crow::connections::systemBus,
167acb7cfb4SJennifer Lee             "interface='org.freedesktop.DBus.ObjectManager',type='signal',"
168acb7cfb4SJennifer Lee             "member='InterfacesAdded',path='/xyz/openbmc_project/software'",
169acb7cfb4SJennifer Lee             callback);
170acb7cfb4SJennifer Lee 
171acb7cfb4SJennifer Lee         std::string filepath(
172acb7cfb4SJennifer Lee             "/tmp/images/" +
173acb7cfb4SJennifer Lee             boost::uuids::to_string(boost::uuids::random_generator()()));
174acb7cfb4SJennifer Lee         BMCWEB_LOG_DEBUG << "Writing file to " << filepath;
175acb7cfb4SJennifer Lee         std::ofstream out(filepath, std::ofstream::out | std::ofstream::binary |
176acb7cfb4SJennifer Lee                                         std::ofstream::trunc);
177acb7cfb4SJennifer Lee         out << req.body;
178acb7cfb4SJennifer Lee         out.close();
179acb7cfb4SJennifer Lee         BMCWEB_LOG_DEBUG << "file upload complete!!";
180acb7cfb4SJennifer Lee     }
181729dae72SJennifer Lee };
182729dae72SJennifer Lee 
1831abe55efSEd Tanous class SoftwareInventoryCollection : public Node
1841abe55efSEd Tanous {
185729dae72SJennifer Lee   public:
186729dae72SJennifer Lee     template <typename CrowApp>
1871abe55efSEd Tanous     SoftwareInventoryCollection(CrowApp &app) :
1881abe55efSEd Tanous         Node(app, "/redfish/v1/UpdateService/FirmwareInventory/")
1891abe55efSEd Tanous     {
190729dae72SJennifer Lee         Node::json["@odata.type"] =
191729dae72SJennifer Lee             "#SoftwareInventoryCollection.SoftwareInventoryCollection";
1926c4eb9deSJennifer Lee         Node::json["@odata.id"] = "/redfish/v1/UpdateService/FirmwareInventory";
193729dae72SJennifer Lee         Node::json["@odata.context"] =
194729dae72SJennifer Lee             "/redfish/v1/"
195729dae72SJennifer Lee             "$metadata#SoftwareInventoryCollection.SoftwareInventoryCollection";
196729dae72SJennifer Lee         Node::json["Name"] = "Software Inventory Collection";
197729dae72SJennifer Lee 
198729dae72SJennifer Lee         entityPrivileges = {
199729dae72SJennifer Lee             {boost::beast::http::verb::get, {{"Login"}}},
200729dae72SJennifer Lee             {boost::beast::http::verb::head, {{"Login"}}},
201729dae72SJennifer Lee             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
202729dae72SJennifer Lee             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
203729dae72SJennifer Lee             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
204729dae72SJennifer Lee             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
205729dae72SJennifer Lee     }
206729dae72SJennifer Lee 
207729dae72SJennifer Lee   private:
20855c7b7a2SEd Tanous     void doGet(crow::Response &res, const crow::Request &req,
2091abe55efSEd Tanous                const std::vector<std::string> &params) override
2101abe55efSEd Tanous     {
211c711bf86SEd Tanous         std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
21255c7b7a2SEd Tanous         res.jsonValue = Node::json;
213c711bf86SEd Tanous 
214c711bf86SEd Tanous         crow::connections::systemBus->async_method_call(
215c711bf86SEd Tanous             [asyncResp](
216c711bf86SEd Tanous                 const boost::system::error_code ec,
2176c4eb9deSJennifer Lee                 const std::vector<std::pair<
2181abe55efSEd Tanous                     std::string, std::vector<std::pair<
2191abe55efSEd Tanous                                      std::string, std::vector<std::string>>>>>
2206c4eb9deSJennifer Lee                     &subtree) {
2211abe55efSEd Tanous                 if (ec)
2221abe55efSEd Tanous                 {
223*f12894f8SJason M. Bills                     messages::internalError(asyncResp->res);
2246c4eb9deSJennifer Lee                     return;
225729dae72SJennifer Lee                 }
226c711bf86SEd Tanous                 asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
227c711bf86SEd Tanous                 asyncResp->res.jsonValue["Members@odata.count"] = 0;
2286c4eb9deSJennifer Lee 
2291abe55efSEd Tanous                 for (auto &obj : subtree)
2301abe55efSEd Tanous                 {
2311abe55efSEd Tanous                     const std::vector<
2321abe55efSEd Tanous                         std::pair<std::string, std::vector<std::string>>>
2336c4eb9deSJennifer Lee                         &connections = obj.second;
2346c4eb9deSJennifer Lee 
235f4b65ab1SJennifer Lee                     // if can't parse fw id then return
236f4b65ab1SJennifer Lee                     std::size_t idPos = obj.first.rfind("/");
237f4b65ab1SJennifer Lee                     if (idPos == std::string::npos ||
238f4b65ab1SJennifer Lee                         idPos + 1 == obj.first.size())
239f4b65ab1SJennifer Lee                     {
240*f12894f8SJason M. Bills                         messages::internalError(asyncResp->res);
241f4b65ab1SJennifer Lee                         BMCWEB_LOG_DEBUG << "Can't parse firmware ID!!";
242f4b65ab1SJennifer Lee                         return;
243f4b65ab1SJennifer Lee                     }
244f4b65ab1SJennifer Lee 
245f4b65ab1SJennifer Lee                     std::string swId = obj.first.substr(idPos + 1);
246f4b65ab1SJennifer Lee 
2471abe55efSEd Tanous                     for (auto &conn : connections)
2481abe55efSEd Tanous                     {
249c711bf86SEd Tanous                         const std::string &connectionName = conn.first;
2501abe55efSEd Tanous                         BMCWEB_LOG_DEBUG << "connectionName = "
2511abe55efSEd Tanous                                          << connectionName;
25255c7b7a2SEd Tanous                         BMCWEB_LOG_DEBUG << "obj.first = " << obj.first;
2536c4eb9deSJennifer Lee 
25455c7b7a2SEd Tanous                         crow::connections::systemBus->async_method_call(
255f4b65ab1SJennifer Lee                             [asyncResp,
256f4b65ab1SJennifer Lee                              swId](const boost::system::error_code error_code,
257c711bf86SEd Tanous                                    const VariantType &activation) {
2581abe55efSEd Tanous                                 BMCWEB_LOG_DEBUG
2591abe55efSEd Tanous                                     << "safe returned in lambda function";
2601abe55efSEd Tanous                                 if (error_code)
2611abe55efSEd Tanous                                 {
262*f12894f8SJason M. Bills                                     messages::internalError(asyncResp->res);
2636c4eb9deSJennifer Lee                                     return;
2646c4eb9deSJennifer Lee                                 }
265c711bf86SEd Tanous 
266f4b65ab1SJennifer Lee                                 const std::string *swActivationStatus =
2671abe55efSEd Tanous                                     mapbox::getPtr<const std::string>(
2681abe55efSEd Tanous                                         activation);
269f4b65ab1SJennifer Lee                                 if (swActivationStatus == nullptr)
2701abe55efSEd Tanous                                 {
271*f12894f8SJason M. Bills                                     messages::internalError(asyncResp->res);
272acb7cfb4SJennifer Lee                                     return;
273acb7cfb4SJennifer Lee                                 }
274f4b65ab1SJennifer Lee                                 if (swActivationStatus != nullptr &&
275f4b65ab1SJennifer Lee                                     *swActivationStatus !=
276f4b65ab1SJennifer Lee                                         "xyz.openbmc_project.Software."
277f4b65ab1SJennifer Lee                                         "Activation."
278f4b65ab1SJennifer Lee                                         "Activations.Active")
2791abe55efSEd Tanous                                 {
280f4b65ab1SJennifer Lee                                     // The activation status of this software is
281f4b65ab1SJennifer Lee                                     // not currently active, so does not need to
282f4b65ab1SJennifer Lee                                     // be listed in the response
283c711bf86SEd Tanous                                     return;
284c711bf86SEd Tanous                                 }
285c711bf86SEd Tanous                                 nlohmann::json &members =
286c711bf86SEd Tanous                                     asyncResp->res.jsonValue["Members"];
287c711bf86SEd Tanous                                 members.push_back(
288f4b65ab1SJennifer Lee                                     {{"@odata.id", "/redfish/v1/UpdateService/"
2891abe55efSEd Tanous                                                    "FirmwareInventory/" +
290f4b65ab1SJennifer Lee                                                        swId}});
2911abe55efSEd Tanous                                 asyncResp->res
2921abe55efSEd Tanous                                     .jsonValue["Members@odata.count"] =
293c711bf86SEd Tanous                                     members.size();
2946c4eb9deSJennifer Lee                             },
2951abe55efSEd Tanous                             connectionName, obj.first,
2961abe55efSEd Tanous                             "org.freedesktop.DBus.Properties", "Get",
2971abe55efSEd Tanous                             "xyz.openbmc_project.Software.Activation",
298acb7cfb4SJennifer Lee                             "Activation");
2996c4eb9deSJennifer Lee                     }
3006c4eb9deSJennifer Lee                 }
301c711bf86SEd Tanous             },
302c711bf86SEd Tanous             "xyz.openbmc_project.ObjectMapper",
303c711bf86SEd Tanous             "/xyz/openbmc_project/object_mapper",
304c711bf86SEd Tanous             "xyz.openbmc_project.ObjectMapper", "GetSubTree",
305c711bf86SEd Tanous             "/xyz/openbmc_project/software", int32_t(1),
3061abe55efSEd Tanous             std::array<const char *, 1>{
3071abe55efSEd Tanous                 "xyz.openbmc_project.Software.Version"});
308729dae72SJennifer Lee     }
309729dae72SJennifer Lee };
310c711bf86SEd Tanous 
3111abe55efSEd Tanous class SoftwareInventory : public Node
3121abe55efSEd Tanous {
313729dae72SJennifer Lee   public:
314729dae72SJennifer Lee     template <typename CrowApp>
3151abe55efSEd Tanous     SoftwareInventory(CrowApp &app) :
3161abe55efSEd Tanous         Node(app, "/redfish/v1/UpdateService/FirmwareInventory/<str>/",
3171abe55efSEd Tanous              std::string())
3181abe55efSEd Tanous     {
3191abe55efSEd Tanous         Node::json["@odata.type"] =
3201abe55efSEd Tanous             "#SoftwareInventory.v1_1_0.SoftwareInventory";
321729dae72SJennifer Lee         Node::json["@odata.context"] =
322729dae72SJennifer Lee             "/redfish/v1/$metadata#SoftwareInventory.SoftwareInventory";
323729dae72SJennifer Lee         Node::json["Name"] = "Software Inventory";
3246c4eb9deSJennifer Lee         Node::json["Updateable"] = false;
325acb7cfb4SJennifer Lee         Node::json["Status"]["Health"] = "OK";
326acb7cfb4SJennifer Lee         Node::json["Status"]["HealthRollup"] = "OK";
327acb7cfb4SJennifer Lee         Node::json["Status"]["State"] = "Enabled";
328729dae72SJennifer Lee         entityPrivileges = {
329729dae72SJennifer Lee             {boost::beast::http::verb::get, {{"Login"}}},
330729dae72SJennifer Lee             {boost::beast::http::verb::head, {{"Login"}}},
331729dae72SJennifer Lee             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
332729dae72SJennifer Lee             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
333729dae72SJennifer Lee             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
334729dae72SJennifer Lee             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
335729dae72SJennifer Lee     }
336729dae72SJennifer Lee 
337729dae72SJennifer Lee   private:
33855c7b7a2SEd Tanous     void doGet(crow::Response &res, const crow::Request &req,
3391abe55efSEd Tanous                const std::vector<std::string> &params) override
3401abe55efSEd Tanous     {
341c711bf86SEd Tanous         std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
34255c7b7a2SEd Tanous         res.jsonValue = Node::json;
3436c4eb9deSJennifer Lee 
3441abe55efSEd Tanous         if (params.size() != 1)
3451abe55efSEd Tanous         {
346*f12894f8SJason M. Bills             messages::internalError(res);
347729dae72SJennifer Lee             res.end();
348729dae72SJennifer Lee             return;
349729dae72SJennifer Lee         }
350729dae72SJennifer Lee 
3513ae837c9SEd Tanous         std::shared_ptr<std::string> swId =
352c711bf86SEd Tanous             std::make_shared<std::string>(params[0]);
353c711bf86SEd Tanous 
35455c7b7a2SEd Tanous         res.jsonValue["@odata.id"] =
3553ae837c9SEd Tanous             "/redfish/v1/UpdateService/FirmwareInventory/" + *swId;
356c711bf86SEd Tanous 
357c711bf86SEd Tanous         crow::connections::systemBus->async_method_call(
3583ae837c9SEd Tanous             [asyncResp, swId](
359c711bf86SEd Tanous                 const boost::system::error_code ec,
3606c4eb9deSJennifer Lee                 const std::vector<std::pair<
3611abe55efSEd Tanous                     std::string, std::vector<std::pair<
3621abe55efSEd Tanous                                      std::string, std::vector<std::string>>>>>
3636c4eb9deSJennifer Lee                     &subtree) {
36455c7b7a2SEd Tanous                 BMCWEB_LOG_DEBUG << "doGet callback...";
3651abe55efSEd Tanous                 if (ec)
3661abe55efSEd Tanous                 {
367*f12894f8SJason M. Bills                     messages::internalError(asyncResp->res);
3686c4eb9deSJennifer Lee                     return;
3696c4eb9deSJennifer Lee                 }
3706c4eb9deSJennifer Lee 
3711abe55efSEd Tanous                 for (const std::pair<
3721abe55efSEd Tanous                          std::string,
3731abe55efSEd Tanous                          std::vector<
3741abe55efSEd Tanous                              std::pair<std::string, std::vector<std::string>>>>
3751abe55efSEd Tanous                          &obj : subtree)
3761abe55efSEd Tanous                 {
3773ae837c9SEd Tanous                     if (boost::ends_with(obj.first, *swId) != true)
3781abe55efSEd Tanous                     {
379acb7cfb4SJennifer Lee                         continue;
380acb7cfb4SJennifer Lee                     }
381acb7cfb4SJennifer Lee 
382f4b65ab1SJennifer Lee                     if (obj.second.size() < 1)
3831abe55efSEd Tanous                     {
384acb7cfb4SJennifer Lee                         continue;
385acb7cfb4SJennifer Lee                     }
3866c4eb9deSJennifer Lee 
38755c7b7a2SEd Tanous                     crow::connections::systemBus->async_method_call(
3881abe55efSEd Tanous                         [asyncResp,
3893ae837c9SEd Tanous                          swId](const boost::system::error_code error_code,
3901abe55efSEd Tanous                                const boost::container::flat_map<
3911abe55efSEd Tanous                                    std::string, VariantType> &propertiesList) {
3921abe55efSEd Tanous                             if (error_code)
3931abe55efSEd Tanous                             {
394*f12894f8SJason M. Bills                                 messages::internalError(asyncResp->res);
3956c4eb9deSJennifer Lee                                 return;
3966c4eb9deSJennifer Lee                             }
3971abe55efSEd Tanous                             boost::container::flat_map<
3981abe55efSEd Tanous                                 std::string, VariantType>::const_iterator it =
3996c4eb9deSJennifer Lee                                 propertiesList.find("Purpose");
4001abe55efSEd Tanous                             if (it == propertiesList.end())
4011abe55efSEd Tanous                             {
4021abe55efSEd Tanous                                 BMCWEB_LOG_DEBUG
4031abe55efSEd Tanous                                     << "Can't find property \"Purpose\"!";
404*f12894f8SJason M. Bills                                 messages::propertyMissing(asyncResp->res,
405*f12894f8SJason M. Bills                                                           "Purpose");
4066c4eb9deSJennifer Lee                                 return;
4076c4eb9deSJennifer Lee                             }
4083ae837c9SEd Tanous                             const std::string *swInvPurpose =
409acb7cfb4SJennifer Lee                                 mapbox::getPtr<const std::string>(it->second);
4103ae837c9SEd Tanous                             if (swInvPurpose == nullptr)
4111abe55efSEd Tanous                             {
4121abe55efSEd Tanous                                 BMCWEB_LOG_DEBUG
4131abe55efSEd Tanous                                     << "wrong types for property\"Purpose\"!";
414*f12894f8SJason M. Bills                                 messages::propertyValueTypeError(asyncResp->res,
415*f12894f8SJason M. Bills                                                                  "", "Purpose");
416acb7cfb4SJennifer Lee                                 return;
417acb7cfb4SJennifer Lee                             }
418c711bf86SEd Tanous 
4193ae837c9SEd Tanous                             BMCWEB_LOG_DEBUG << "swInvPurpose = "
4203ae837c9SEd Tanous                                              << *swInvPurpose;
421c711bf86SEd Tanous                             it = propertiesList.find("Version");
4221abe55efSEd Tanous                             if (it == propertiesList.end())
4231abe55efSEd Tanous                             {
4241abe55efSEd Tanous                                 BMCWEB_LOG_DEBUG
4251abe55efSEd Tanous                                     << "Can't find property \"Version\"!";
426*f12894f8SJason M. Bills                                 messages::propertyMissing(asyncResp->res,
427*f12894f8SJason M. Bills                                                           "Version");
428c711bf86SEd Tanous                                 return;
429acb7cfb4SJennifer Lee                             }
430acb7cfb4SJennifer Lee 
431f4b65ab1SJennifer Lee                             BMCWEB_LOG_DEBUG << "Version found!";
432c711bf86SEd Tanous 
433f4b65ab1SJennifer Lee                             const std::string *version =
434f4b65ab1SJennifer Lee                                 mapbox::getPtr<const std::string>(it->second);
435f4b65ab1SJennifer Lee 
436f4b65ab1SJennifer Lee                             if (version == nullptr)
4371abe55efSEd Tanous                             {
4381abe55efSEd Tanous                                 BMCWEB_LOG_DEBUG
4391abe55efSEd Tanous                                     << "Can't find property \"Version\"!";
440*f12894f8SJason M. Bills 
441*f12894f8SJason M. Bills                                 messages::propertyValueTypeError(asyncResp->res,
442*f12894f8SJason M. Bills                                                                  "", "Version");
4436c4eb9deSJennifer Lee                                 return;
4446c4eb9deSJennifer Lee                             }
445c711bf86SEd Tanous                             asyncResp->res.jsonValue["Version"] = *version;
4463ae837c9SEd Tanous                             asyncResp->res.jsonValue["Id"] = *swId;
4476c4eb9deSJennifer Lee                         },
448c711bf86SEd Tanous                         obj.second[0].first, obj.first,
449c711bf86SEd Tanous                         "org.freedesktop.DBus.Properties", "GetAll",
450c711bf86SEd Tanous                         "xyz.openbmc_project.Software.Version");
4516c4eb9deSJennifer Lee                 }
452c711bf86SEd Tanous             },
453c711bf86SEd Tanous             "xyz.openbmc_project.ObjectMapper",
454c711bf86SEd Tanous             "/xyz/openbmc_project/object_mapper",
455c711bf86SEd Tanous             "xyz.openbmc_project.ObjectMapper", "GetSubTree",
456c711bf86SEd Tanous             "/xyz/openbmc_project/software", int32_t(1),
4571abe55efSEd Tanous             std::array<const char *, 1>{
4581abe55efSEd Tanous                 "xyz.openbmc_project.Software.Version"});
4596c4eb9deSJennifer Lee     }
460729dae72SJennifer Lee };
461729dae72SJennifer Lee 
462729dae72SJennifer Lee } // namespace redfish
463