blob: 9f16e1e95ce97a524f4a53b0d51ab2fe7216ded8 [file] [log] [blame]
Jennifer Lee729dae72018-04-24 15:59:34 -07001/*
2// Copyright (c) 2018 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16#pragma once
17
18#include "node.hpp"
Ed Tanous1abe55e2018-09-05 08:30:59 -070019
Jennifer Lee729dae72018-04-24 15:59:34 -070020#include <boost/container/flat_map.hpp>
Andrew Geissler87d84722019-02-28 14:28:39 -060021#include <utils/fw_utils.hpp>
Ed Tanousabf2add2019-01-22 16:40:12 -080022#include <variant>
Jennifer Lee729dae72018-04-24 15:59:34 -070023
Ed Tanous1abe55e2018-09-05 08:30:59 -070024namespace redfish
25{
Ed Tanous27826b52018-10-29 11:40:58 -070026
Andrew Geissler0e7de462019-03-04 19:11:54 -060027// Match signals added on software path
Jennifer Leeacb7cfb2018-06-07 16:08:15 -070028static std::unique_ptr<sdbusplus::bus::match::match> fwUpdateMatcher;
Andrew Geissler0e7de462019-03-04 19:11:54 -060029// Only allow one update at a time
30static bool fwUpdateInProgress = false;
Jennifer Lee729dae72018-04-24 15:59:34 -070031
Ed Tanous1abe55e2018-09-05 08:30:59 -070032class UpdateService : public Node
33{
34 public:
35 UpdateService(CrowApp &app) : Node(app, "/redfish/v1/UpdateService/")
36 {
Ed Tanous1abe55e2018-09-05 08:30:59 -070037 entityPrivileges = {
38 {boost::beast::http::verb::get, {{"Login"}}},
39 {boost::beast::http::verb::head, {{"Login"}}},
40 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
41 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
42 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
43 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
Jennifer Leeacb7cfb2018-06-07 16:08:15 -070044 }
Jennifer Leeacb7cfb2018-06-07 16:08:15 -070045
Ed Tanous1abe55e2018-09-05 08:30:59 -070046 private:
47 void doGet(crow::Response &res, const crow::Request &req,
48 const std::vector<std::string> &params) override
49 {
Ed Tanous0f74e642018-11-12 15:17:05 -080050 res.jsonValue["@odata.type"] = "#UpdateService.v1_2_0.UpdateService";
51 res.jsonValue["@odata.id"] = "/redfish/v1/UpdateService";
52 res.jsonValue["@odata.context"] =
53 "/redfish/v1/$metadata#UpdateService.UpdateService";
54 res.jsonValue["Id"] = "UpdateService";
55 res.jsonValue["Description"] = "Service for Software Update";
56 res.jsonValue["Name"] = "Update Service";
57 res.jsonValue["HttpPushUri"] = "/redfish/v1/UpdateService";
58 // UpdateService cannot be disabled
59 res.jsonValue["ServiceEnabled"] = true;
60 res.jsonValue["FirmwareInventory"] = {
61 {"@odata.id", "/redfish/v1/UpdateService/FirmwareInventory"}};
Jennifer Leeacb7cfb2018-06-07 16:08:15 -070062 res.end();
Ed Tanous1abe55e2018-09-05 08:30:59 -070063 }
Andrew Geissler0e7de462019-03-04 19:11:54 -060064 static void cleanUp()
Ed Tanous1abe55e2018-09-05 08:30:59 -070065 {
Andrew Geissler0e7de462019-03-04 19:11:54 -060066 fwUpdateInProgress = false;
67 fwUpdateMatcher = nullptr;
68 }
69 static void activateImage(const std::string &objPath,
70 const std::string &service)
71 {
72 BMCWEB_LOG_DEBUG << "Activate image for " << objPath << " " << service;
Ed Tanous1abe55e2018-09-05 08:30:59 -070073 crow::connections::systemBus->async_method_call(
Andrew Geissler0e7de462019-03-04 19:11:54 -060074 [](const boost::system::error_code error_code) {
Ed Tanous1abe55e2018-09-05 08:30:59 -070075 if (error_code)
76 {
77 BMCWEB_LOG_DEBUG << "error_code = " << error_code;
78 BMCWEB_LOG_DEBUG << "error msg = " << error_code.message();
79 }
80 },
Andrew Geissler0e7de462019-03-04 19:11:54 -060081 service, objPath, "org.freedesktop.DBus.Properties", "Set",
Ed Tanous1abe55e2018-09-05 08:30:59 -070082 "xyz.openbmc_project.Software.Activation", "RequestedActivation",
Ed Tanousabf2add2019-01-22 16:40:12 -080083 std::variant<std::string>(
Ed Tanous1abe55e2018-09-05 08:30:59 -070084 "xyz.openbmc_project.Software.Activation.RequestedActivations."
85 "Active"));
86 }
Andrew Geissler0e7de462019-03-04 19:11:54 -060087 static void softwareInterfaceAdded(std::shared_ptr<AsyncResp> asyncResp,
88 boost::asio::deadline_timer &timeout,
89 sdbusplus::message::message &m)
90 {
91 std::vector<std::pair<
92 std::string,
93 std::vector<std::pair<std::string, std::variant<std::string>>>>>
94 interfacesProperties;
95
96 sdbusplus::message::object_path objPath;
97
98 m.read(objPath, interfacesProperties);
99
100 BMCWEB_LOG_DEBUG << "obj path = " << objPath.str;
101 for (auto &interface : interfacesProperties)
102 {
103 BMCWEB_LOG_DEBUG << "interface = " << interface.first;
104
105 if (interface.first == "xyz.openbmc_project.Software.Activation")
106 {
107 // Found our interface, disable callbacks
108 fwUpdateMatcher = nullptr;
109
110 // Retrieve service and activate
111 crow::connections::systemBus->async_method_call(
112 [objPath, asyncResp, &timeout](
113 const boost::system::error_code error_code,
114 const std::vector<std::pair<
115 std::string, std::vector<std::string>>> &objInfo) {
116 if (error_code)
117 {
118 BMCWEB_LOG_DEBUG << "error_code = " << error_code;
119 BMCWEB_LOG_DEBUG << "error msg = "
120 << error_code.message();
121 messages::internalError(asyncResp->res);
122 cleanUp();
123 return;
124 }
125 // Ensure we only got one service back
126 if (objInfo.size() != 1)
127 {
128 BMCWEB_LOG_ERROR << "Invalid Object Size "
129 << objInfo.size();
130 messages::internalError(asyncResp->res);
131 cleanUp();
132 return;
133 }
134 // cancel timer only when
135 // xyz.openbmc_project.Software.Activation interface
136 // is added
137 boost::system::error_code ec;
138 timeout.cancel(ec);
139 if (ec)
140 {
141 BMCWEB_LOG_ERROR << "error canceling timer " << ec;
142 }
143 UpdateService::activateImage(objPath.str,
144 objInfo[0].first);
145 redfish::messages::success(asyncResp->res);
146 fwUpdateInProgress = false;
147 },
148 "xyz.openbmc_project.ObjectMapper",
149 "/xyz/openbmc_project/object_mapper",
150 "xyz.openbmc_project.ObjectMapper", "GetObject",
151 objPath.str,
152 std::array<const char *, 1>{
153 "xyz.openbmc_project.Software.Activation"});
154 }
155 }
156 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700157 void doPost(crow::Response &res, const crow::Request &req,
158 const std::vector<std::string> &params) override
159 {
160 BMCWEB_LOG_DEBUG << "doPost...";
Jennifer Leeacb7cfb2018-06-07 16:08:15 -0700161
Ed Tanous1abe55e2018-09-05 08:30:59 -0700162 // Only allow one FW update at a time
Andrew Geissler0e7de462019-03-04 19:11:54 -0600163 if (fwUpdateInProgress != false)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700164 {
165 res.addHeader("Retry-After", "30");
Andrew Geissler0e7de462019-03-04 19:11:54 -0600166 messages::serviceTemporarilyUnavailable(res, "30");
Ed Tanous1abe55e2018-09-05 08:30:59 -0700167 res.end();
Jennifer Lee6c4eb9d2018-05-22 10:58:31 -0700168 return;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700169 }
Andrew Geissler0e7de462019-03-04 19:11:54 -0600170
Ed Tanous1abe55e2018-09-05 08:30:59 -0700171 // Make this const static so it survives outside this method
172 static boost::asio::deadline_timer timeout(
173 *req.ioService, boost::posix_time::seconds(5));
Jennifer Lee6c4eb9d2018-05-22 10:58:31 -0700174
Ed Tanous1abe55e2018-09-05 08:30:59 -0700175 timeout.expires_from_now(boost::posix_time::seconds(5));
Jennifer Lee6c4eb9d2018-05-22 10:58:31 -0700176
Ed Tanous1abe55e2018-09-05 08:30:59 -0700177 timeout.async_wait([&res](const boost::system::error_code &ec) {
Andrew Geissler0e7de462019-03-04 19:11:54 -0600178 cleanUp();
Ed Tanous1abe55e2018-09-05 08:30:59 -0700179 if (ec == boost::asio::error::operation_aborted)
180 {
181 // expected, we were canceled before the timer completed.
182 return;
Jennifer Lee6c4eb9d2018-05-22 10:58:31 -0700183 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700184 BMCWEB_LOG_ERROR
185 << "Timed out waiting for firmware object being created";
186 BMCWEB_LOG_ERROR
187 << "FW image may has already been uploaded to server";
188 if (ec)
189 {
190 BMCWEB_LOG_ERROR << "Async_wait failed" << ec;
191 return;
192 }
193
Jason M. Billsf12894f2018-10-09 12:45:45 -0700194 redfish::messages::internalError(res);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700195 res.end();
196 });
197
Andrew Geissler0e7de462019-03-04 19:11:54 -0600198 std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
199 auto callback = [asyncResp](sdbusplus::message::message &m) {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700200 BMCWEB_LOG_DEBUG << "Match fired";
Andrew Geissler0e7de462019-03-04 19:11:54 -0600201 softwareInterfaceAdded(asyncResp, timeout, m);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700202 };
203
Andrew Geissler0e7de462019-03-04 19:11:54 -0600204 fwUpdateInProgress = true;
205
Ed Tanous1abe55e2018-09-05 08:30:59 -0700206 fwUpdateMatcher = std::make_unique<sdbusplus::bus::match::match>(
207 *crow::connections::systemBus,
208 "interface='org.freedesktop.DBus.ObjectManager',type='signal',"
209 "member='InterfacesAdded',path='/xyz/openbmc_project/software'",
210 callback);
211
212 std::string filepath(
213 "/tmp/images/" +
214 boost::uuids::to_string(boost::uuids::random_generator()()));
215 BMCWEB_LOG_DEBUG << "Writing file to " << filepath;
216 std::ofstream out(filepath, std::ofstream::out | std::ofstream::binary |
217 std::ofstream::trunc);
218 out << req.body;
219 out.close();
220 BMCWEB_LOG_DEBUG << "file upload complete!!";
221 }
Jennifer Lee729dae72018-04-24 15:59:34 -0700222};
Ed Tanousc711bf82018-07-30 16:31:33 -0700223
Ed Tanous1abe55e2018-09-05 08:30:59 -0700224class SoftwareInventoryCollection : public Node
225{
226 public:
227 template <typename CrowApp>
228 SoftwareInventoryCollection(CrowApp &app) :
229 Node(app, "/redfish/v1/UpdateService/FirmwareInventory/")
230 {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700231 entityPrivileges = {
232 {boost::beast::http::verb::get, {{"Login"}}},
233 {boost::beast::http::verb::head, {{"Login"}}},
234 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
235 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
236 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
237 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
Jennifer Lee729dae72018-04-24 15:59:34 -0700238 }
Jennifer Lee729dae72018-04-24 15:59:34 -0700239
Ed Tanous1abe55e2018-09-05 08:30:59 -0700240 private:
241 void doGet(crow::Response &res, const crow::Request &req,
242 const std::vector<std::string> &params) override
243 {
244 std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
Ed Tanous0f74e642018-11-12 15:17:05 -0800245 res.jsonValue["@odata.type"] =
246 "#SoftwareInventoryCollection.SoftwareInventoryCollection";
247 res.jsonValue["@odata.id"] =
248 "/redfish/v1/UpdateService/FirmwareInventory";
249 res.jsonValue["@odata.context"] =
250 "/redfish/v1/"
251 "$metadata#SoftwareInventoryCollection.SoftwareInventoryCollection";
252 res.jsonValue["Name"] = "Software Inventory Collection";
Ed Tanousc711bf82018-07-30 16:31:33 -0700253
Ed Tanous1abe55e2018-09-05 08:30:59 -0700254 crow::connections::systemBus->async_method_call(
255 [asyncResp](
256 const boost::system::error_code ec,
257 const std::vector<std::pair<
258 std::string, std::vector<std::pair<
259 std::string, std::vector<std::string>>>>>
260 &subtree) {
261 if (ec)
262 {
Jason M. Billsf12894f2018-10-09 12:45:45 -0700263 messages::internalError(asyncResp->res);
Ed Tanousc711bf82018-07-30 16:31:33 -0700264 return;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700265 }
266 asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
267 asyncResp->res.jsonValue["Members@odata.count"] = 0;
Jennifer Lee6c4eb9d2018-05-22 10:58:31 -0700268
Ed Tanous1abe55e2018-09-05 08:30:59 -0700269 for (auto &obj : subtree)
270 {
271 const std::vector<
272 std::pair<std::string, std::vector<std::string>>>
273 &connections = obj.second;
274
Jennifer Leef4b65ab2018-09-18 12:00:13 -0700275 // if can't parse fw id then return
Ed Tanous27826b52018-10-29 11:40:58 -0700276 std::size_t idPos;
277 if ((idPos = obj.first.rfind("/")) == std::string::npos)
Jennifer Leef4b65ab2018-09-18 12:00:13 -0700278 {
Jason M. Billsf12894f2018-10-09 12:45:45 -0700279 messages::internalError(asyncResp->res);
Jennifer Leef4b65ab2018-09-18 12:00:13 -0700280 BMCWEB_LOG_DEBUG << "Can't parse firmware ID!!";
281 return;
282 }
Jennifer Leef4b65ab2018-09-18 12:00:13 -0700283 std::string swId = obj.first.substr(idPos + 1);
284
Ed Tanous1abe55e2018-09-05 08:30:59 -0700285 for (auto &conn : connections)
286 {
287 const std::string &connectionName = conn.first;
288 BMCWEB_LOG_DEBUG << "connectionName = "
289 << connectionName;
290 BMCWEB_LOG_DEBUG << "obj.first = " << obj.first;
291
292 crow::connections::systemBus->async_method_call(
Jennifer Leef4b65ab2018-09-18 12:00:13 -0700293 [asyncResp,
294 swId](const boost::system::error_code error_code,
295 const VariantType &activation) {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700296 BMCWEB_LOG_DEBUG
297 << "safe returned in lambda function";
298 if (error_code)
299 {
Jason M. Billsf12894f2018-10-09 12:45:45 -0700300 messages::internalError(asyncResp->res);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700301 return;
302 }
303
Jennifer Leef4b65ab2018-09-18 12:00:13 -0700304 const std::string *swActivationStatus =
Ed Tanousabf2add2019-01-22 16:40:12 -0800305 std::get_if<std::string>(&activation);
Jennifer Leef4b65ab2018-09-18 12:00:13 -0700306 if (swActivationStatus == nullptr)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700307 {
Jason M. Billsf12894f2018-10-09 12:45:45 -0700308 messages::internalError(asyncResp->res);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700309 return;
310 }
Jennifer Leef4b65ab2018-09-18 12:00:13 -0700311 if (swActivationStatus != nullptr &&
312 *swActivationStatus !=
313 "xyz.openbmc_project.Software."
314 "Activation."
315 "Activations.Active")
Ed Tanous1abe55e2018-09-05 08:30:59 -0700316 {
Jennifer Leef4b65ab2018-09-18 12:00:13 -0700317 // The activation status of this software is
318 // not currently active, so does not need to
319 // be listed in the response
Ed Tanous1abe55e2018-09-05 08:30:59 -0700320 return;
321 }
322 nlohmann::json &members =
323 asyncResp->res.jsonValue["Members"];
324 members.push_back(
Jennifer Leef4b65ab2018-09-18 12:00:13 -0700325 {{"@odata.id", "/redfish/v1/UpdateService/"
326 "FirmwareInventory/" +
327 swId}});
Ed Tanous1abe55e2018-09-05 08:30:59 -0700328 asyncResp->res
329 .jsonValue["Members@odata.count"] =
330 members.size();
331 },
332 connectionName, obj.first,
333 "org.freedesktop.DBus.Properties", "Get",
334 "xyz.openbmc_project.Software.Activation",
335 "Activation");
Ed Tanousc711bf82018-07-30 16:31:33 -0700336 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700337 }
338 },
339 "xyz.openbmc_project.ObjectMapper",
340 "/xyz/openbmc_project/object_mapper",
341 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
342 "/xyz/openbmc_project/software", int32_t(1),
343 std::array<const char *, 1>{
344 "xyz.openbmc_project.Software.Version"});
345 }
Jennifer Lee729dae72018-04-24 15:59:34 -0700346};
347
Ed Tanous1abe55e2018-09-05 08:30:59 -0700348class SoftwareInventory : public Node
349{
350 public:
351 template <typename CrowApp>
352 SoftwareInventory(CrowApp &app) :
353 Node(app, "/redfish/v1/UpdateService/FirmwareInventory/<str>/",
354 std::string())
355 {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700356 entityPrivileges = {
357 {boost::beast::http::verb::get, {{"Login"}}},
358 {boost::beast::http::verb::head, {{"Login"}}},
359 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
360 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
361 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
362 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
363 }
364
365 private:
Andrew Geissler87d84722019-02-28 14:28:39 -0600366 /* Fill related item links (i.e. bmc, bios) in for inventory */
367 static void getRelatedItems(std::shared_ptr<AsyncResp> aResp,
368 const std::string &purpose)
369 {
370 if (purpose == fw_util::bmcPurpose)
371 {
372 nlohmann::json &members = aResp->res.jsonValue["RelatedItem"];
373 members.push_back({{"@odata.id", "/redfish/v1/Managers/bmc"}});
374 aResp->res.jsonValue["Members@odata.count"] = members.size();
375 }
376 else if (purpose == fw_util::biosPurpose)
377 {
378 // TODO(geissonator) Need BIOS schema support added for this
379 // to be valid
380 // nlohmann::json &members = aResp->res.jsonValue["RelatedItem"];
381 // members.push_back(
382 // {{"@odata.id", "/redfish/v1/Systems/system/BIOS"}});
383 // aResp->res.jsonValue["Members@odata.count"] = members.size();
384 }
385 else
386 {
387 BMCWEB_LOG_ERROR << "Unknown software purpose " << purpose;
388 }
389 }
390
Ed Tanous1abe55e2018-09-05 08:30:59 -0700391 void doGet(crow::Response &res, const crow::Request &req,
392 const std::vector<std::string> &params) override
393 {
394 std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
Ed Tanous0f74e642018-11-12 15:17:05 -0800395 res.jsonValue["@odata.type"] =
396 "#SoftwareInventory.v1_1_0.SoftwareInventory";
397 res.jsonValue["@odata.context"] =
398 "/redfish/v1/$metadata#SoftwareInventory.SoftwareInventory";
399 res.jsonValue["Name"] = "Software Inventory";
400 res.jsonValue["Updateable"] = false;
401 res.jsonValue["Status"]["Health"] = "OK";
402 res.jsonValue["Status"]["HealthRollup"] = "OK";
403 res.jsonValue["Status"]["State"] = "Enabled";
Ed Tanous1abe55e2018-09-05 08:30:59 -0700404
405 if (params.size() != 1)
406 {
Jason M. Billsf12894f2018-10-09 12:45:45 -0700407 messages::internalError(res);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700408 res.end();
409 return;
410 }
411
Ed Tanous3ae837c2018-08-07 14:41:19 -0700412 std::shared_ptr<std::string> swId =
Ed Tanous1abe55e2018-09-05 08:30:59 -0700413 std::make_shared<std::string>(params[0]);
414
415 res.jsonValue["@odata.id"] =
Ed Tanous3ae837c2018-08-07 14:41:19 -0700416 "/redfish/v1/UpdateService/FirmwareInventory/" + *swId;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700417
418 crow::connections::systemBus->async_method_call(
Ed Tanous3ae837c2018-08-07 14:41:19 -0700419 [asyncResp, swId](
Ed Tanous1abe55e2018-09-05 08:30:59 -0700420 const boost::system::error_code ec,
421 const std::vector<std::pair<
422 std::string, std::vector<std::pair<
423 std::string, std::vector<std::string>>>>>
424 &subtree) {
425 BMCWEB_LOG_DEBUG << "doGet callback...";
426 if (ec)
427 {
Jason M. Billsf12894f2018-10-09 12:45:45 -0700428 messages::internalError(asyncResp->res);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700429 return;
430 }
431
432 for (const std::pair<
433 std::string,
434 std::vector<
435 std::pair<std::string, std::vector<std::string>>>>
436 &obj : subtree)
437 {
Ed Tanous3ae837c2018-08-07 14:41:19 -0700438 if (boost::ends_with(obj.first, *swId) != true)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700439 {
440 continue;
441 }
442
Jennifer Leef4b65ab2018-09-18 12:00:13 -0700443 if (obj.second.size() < 1)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700444 {
445 continue;
446 }
447
448 crow::connections::systemBus->async_method_call(
449 [asyncResp,
Ed Tanous3ae837c2018-08-07 14:41:19 -0700450 swId](const boost::system::error_code error_code,
451 const boost::container::flat_map<
452 std::string, VariantType> &propertiesList) {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700453 if (error_code)
454 {
Jason M. Billsf12894f2018-10-09 12:45:45 -0700455 messages::internalError(asyncResp->res);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700456 return;
457 }
458 boost::container::flat_map<
459 std::string, VariantType>::const_iterator it =
460 propertiesList.find("Purpose");
461 if (it == propertiesList.end())
462 {
463 BMCWEB_LOG_DEBUG
464 << "Can't find property \"Purpose\"!";
Jason M. Billsf12894f2018-10-09 12:45:45 -0700465 messages::propertyMissing(asyncResp->res,
466 "Purpose");
Ed Tanous1abe55e2018-09-05 08:30:59 -0700467 return;
468 }
Ed Tanous3ae837c2018-08-07 14:41:19 -0700469 const std::string *swInvPurpose =
Ed Tanousabf2add2019-01-22 16:40:12 -0800470 std::get_if<std::string>(&it->second);
Ed Tanous3ae837c2018-08-07 14:41:19 -0700471 if (swInvPurpose == nullptr)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700472 {
473 BMCWEB_LOG_DEBUG
474 << "wrong types for property\"Purpose\"!";
Jason M. Billsf12894f2018-10-09 12:45:45 -0700475 messages::propertyValueTypeError(asyncResp->res,
476 "", "Purpose");
Ed Tanous1abe55e2018-09-05 08:30:59 -0700477 return;
478 }
479
Ed Tanous3ae837c2018-08-07 14:41:19 -0700480 BMCWEB_LOG_DEBUG << "swInvPurpose = "
481 << *swInvPurpose;
Jennifer Leef4b65ab2018-09-18 12:00:13 -0700482 it = propertiesList.find("Version");
483 if (it == propertiesList.end())
Ed Tanous1abe55e2018-09-05 08:30:59 -0700484 {
Jennifer Leef4b65ab2018-09-18 12:00:13 -0700485 BMCWEB_LOG_DEBUG
486 << "Can't find property \"Version\"!";
Jason M. Billsf12894f2018-10-09 12:45:45 -0700487 messages::propertyMissing(asyncResp->res,
488 "Version");
Jennifer Leef4b65ab2018-09-18 12:00:13 -0700489 return;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700490 }
Jennifer Leef4b65ab2018-09-18 12:00:13 -0700491
492 BMCWEB_LOG_DEBUG << "Version found!";
493
494 const std::string *version =
Ed Tanousabf2add2019-01-22 16:40:12 -0800495 std::get_if<std::string>(&it->second);
Jennifer Leef4b65ab2018-09-18 12:00:13 -0700496
497 if (version == nullptr)
498 {
499 BMCWEB_LOG_DEBUG
500 << "Can't find property \"Version\"!";
Jason M. Billsf12894f2018-10-09 12:45:45 -0700501
502 messages::propertyValueTypeError(asyncResp->res,
503 "", "Version");
Jennifer Leef4b65ab2018-09-18 12:00:13 -0700504 return;
505 }
506 asyncResp->res.jsonValue["Version"] = *version;
507 asyncResp->res.jsonValue["Id"] = *swId;
Andrew Geissler54daabe2019-02-13 13:54:15 -0600508
509 // swInvPurpose is of format:
510 // xyz.openbmc_project.Software.Version.VersionPurpose.ABC
511 // Translate this to "ABC update"
512 size_t endDesc = swInvPurpose->rfind(".");
513 if (endDesc == std::string::npos)
514 {
515 messages::internalError(asyncResp->res);
516 return;
517 }
518 endDesc++;
519 if (endDesc >= swInvPurpose->size())
520 {
521 messages::internalError(asyncResp->res);
522 return;
523 }
524
525 std::string formatDesc =
526 swInvPurpose->substr(endDesc);
527 asyncResp->res.jsonValue["Description"] =
528 formatDesc + " update";
Andrew Geissler87d84722019-02-28 14:28:39 -0600529 getRelatedItems(asyncResp, *swInvPurpose);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700530 },
531 obj.second[0].first, obj.first,
532 "org.freedesktop.DBus.Properties", "GetAll",
533 "xyz.openbmc_project.Software.Version");
534 }
535 },
536 "xyz.openbmc_project.ObjectMapper",
537 "/xyz/openbmc_project/object_mapper",
538 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
539 "/xyz/openbmc_project/software", int32_t(1),
540 std::array<const char *, 1>{
541 "xyz.openbmc_project.Software.Version"});
542 }
543};
544
545} // namespace redfish