blob: aaaf85baf447d4eea6a3457ca0f38a048afc559f [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
Jennifer Leeacb7cfb2018-06-07 16:08:15 -070027static std::unique_ptr<sdbusplus::bus::match::match> fwUpdateMatcher;
Jennifer Lee729dae72018-04-24 15:59:34 -070028
Ed Tanous1abe55e2018-09-05 08:30:59 -070029class UpdateService : public Node
30{
31 public:
32 UpdateService(CrowApp &app) : Node(app, "/redfish/v1/UpdateService/")
33 {
Ed Tanous1abe55e2018-09-05 08:30:59 -070034 entityPrivileges = {
35 {boost::beast::http::verb::get, {{"Login"}}},
36 {boost::beast::http::verb::head, {{"Login"}}},
37 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
38 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
39 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
40 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
Jennifer Leeacb7cfb2018-06-07 16:08:15 -070041 }
Jennifer Leeacb7cfb2018-06-07 16:08:15 -070042
Ed Tanous1abe55e2018-09-05 08:30:59 -070043 private:
44 void doGet(crow::Response &res, const crow::Request &req,
45 const std::vector<std::string> &params) override
46 {
Ed Tanous0f74e642018-11-12 15:17:05 -080047 res.jsonValue["@odata.type"] = "#UpdateService.v1_2_0.UpdateService";
48 res.jsonValue["@odata.id"] = "/redfish/v1/UpdateService";
49 res.jsonValue["@odata.context"] =
50 "/redfish/v1/$metadata#UpdateService.UpdateService";
51 res.jsonValue["Id"] = "UpdateService";
52 res.jsonValue["Description"] = "Service for Software Update";
53 res.jsonValue["Name"] = "Update Service";
54 res.jsonValue["HttpPushUri"] = "/redfish/v1/UpdateService";
55 // UpdateService cannot be disabled
56 res.jsonValue["ServiceEnabled"] = true;
57 res.jsonValue["FirmwareInventory"] = {
58 {"@odata.id", "/redfish/v1/UpdateService/FirmwareInventory"}};
Jennifer Leeacb7cfb2018-06-07 16:08:15 -070059 res.end();
Ed Tanous1abe55e2018-09-05 08:30:59 -070060 }
61 static void activateImage(const std::string &objPath)
62 {
63 crow::connections::systemBus->async_method_call(
64 [objPath](const boost::system::error_code error_code) {
65 if (error_code)
66 {
67 BMCWEB_LOG_DEBUG << "error_code = " << error_code;
68 BMCWEB_LOG_DEBUG << "error msg = " << error_code.message();
69 }
70 },
71 "xyz.openbmc_project.Software.BMC.Updater", objPath,
72 "org.freedesktop.DBus.Properties", "Set",
73 "xyz.openbmc_project.Software.Activation", "RequestedActivation",
Ed Tanousabf2add2019-01-22 16:40:12 -080074 std::variant<std::string>(
Ed Tanous1abe55e2018-09-05 08:30:59 -070075 "xyz.openbmc_project.Software.Activation.RequestedActivations."
76 "Active"));
77 }
78 void doPost(crow::Response &res, const crow::Request &req,
79 const std::vector<std::string> &params) override
80 {
81 BMCWEB_LOG_DEBUG << "doPost...";
Jennifer Leeacb7cfb2018-06-07 16:08:15 -070082
Ed Tanous1abe55e2018-09-05 08:30:59 -070083 // Only allow one FW update at a time
84 if (fwUpdateMatcher != nullptr)
85 {
86 res.addHeader("Retry-After", "30");
Jason M. Billsf12894f2018-10-09 12:45:45 -070087 messages::serviceTemporarilyUnavailable(res, "3");
Ed Tanous1abe55e2018-09-05 08:30:59 -070088 res.end();
Jennifer Lee6c4eb9d2018-05-22 10:58:31 -070089 return;
Ed Tanous1abe55e2018-09-05 08:30:59 -070090 }
91 // Make this const static so it survives outside this method
92 static boost::asio::deadline_timer timeout(
93 *req.ioService, boost::posix_time::seconds(5));
Jennifer Lee6c4eb9d2018-05-22 10:58:31 -070094
Ed Tanous1abe55e2018-09-05 08:30:59 -070095 timeout.expires_from_now(boost::posix_time::seconds(5));
Jennifer Lee6c4eb9d2018-05-22 10:58:31 -070096
Ed Tanous1abe55e2018-09-05 08:30:59 -070097 timeout.async_wait([&res](const boost::system::error_code &ec) {
98 fwUpdateMatcher = nullptr;
99 if (ec == boost::asio::error::operation_aborted)
100 {
101 // expected, we were canceled before the timer completed.
102 return;
Jennifer Lee6c4eb9d2018-05-22 10:58:31 -0700103 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700104 BMCWEB_LOG_ERROR
105 << "Timed out waiting for firmware object being created";
106 BMCWEB_LOG_ERROR
107 << "FW image may has already been uploaded to server";
108 if (ec)
109 {
110 BMCWEB_LOG_ERROR << "Async_wait failed" << ec;
111 return;
112 }
113
Jason M. Billsf12894f2018-10-09 12:45:45 -0700114 redfish::messages::internalError(res);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700115 res.end();
116 });
117
118 auto callback = [&res](sdbusplus::message::message &m) {
119 BMCWEB_LOG_DEBUG << "Match fired";
Ed Tanous1abe55e2018-09-05 08:30:59 -0700120
121 if (m.is_method_error())
122 {
123 BMCWEB_LOG_DEBUG << "Dbus method error!!!";
124 res.end();
125 return;
126 }
127 std::vector<std::pair<
128 std::string,
Ed Tanousabf2add2019-01-22 16:40:12 -0800129 std::vector<std::pair<std::string, std::variant<std::string>>>>>
Ed Tanous3ae837c2018-08-07 14:41:19 -0700130 interfacesProperties;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700131
132 sdbusplus::message::object_path objPath;
133
Ed Tanous3ae837c2018-08-07 14:41:19 -0700134 m.read(objPath, interfacesProperties); // Read in the object path
135 // that was just created
Ed Tanous1abe55e2018-09-05 08:30:59 -0700136 // std::string str_objpath = objPath.str; // keep a copy for
137 // constructing response message
138 BMCWEB_LOG_DEBUG << "obj path = " << objPath.str; // str_objpath;
Ed Tanous3ae837c2018-08-07 14:41:19 -0700139 for (auto &interface : interfacesProperties)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700140 {
141 BMCWEB_LOG_DEBUG << "interface = " << interface.first;
142
143 if (interface.first ==
144 "xyz.openbmc_project.Software.Activation")
145 {
146 // cancel timer only when
147 // xyz.openbmc_project.Software.Activation interface is
148 // added
149 boost::system::error_code ec;
150 timeout.cancel(ec);
151 if (ec)
152 {
153 BMCWEB_LOG_ERROR << "error canceling timer " << ec;
154 }
155 UpdateService::activateImage(objPath.str); // str_objpath);
Jason M. Billsf12894f2018-10-09 12:45:45 -0700156 redfish::messages::success(res);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700157 BMCWEB_LOG_DEBUG << "ending response";
158 res.end();
159 fwUpdateMatcher = nullptr;
160 }
161 }
162 };
163
164 fwUpdateMatcher = std::make_unique<sdbusplus::bus::match::match>(
165 *crow::connections::systemBus,
166 "interface='org.freedesktop.DBus.ObjectManager',type='signal',"
167 "member='InterfacesAdded',path='/xyz/openbmc_project/software'",
168 callback);
169
170 std::string filepath(
171 "/tmp/images/" +
172 boost::uuids::to_string(boost::uuids::random_generator()()));
173 BMCWEB_LOG_DEBUG << "Writing file to " << filepath;
174 std::ofstream out(filepath, std::ofstream::out | std::ofstream::binary |
175 std::ofstream::trunc);
176 out << req.body;
177 out.close();
178 BMCWEB_LOG_DEBUG << "file upload complete!!";
179 }
Jennifer Lee729dae72018-04-24 15:59:34 -0700180};
Ed Tanousc711bf82018-07-30 16:31:33 -0700181
Ed Tanous1abe55e2018-09-05 08:30:59 -0700182class SoftwareInventoryCollection : public Node
183{
184 public:
185 template <typename CrowApp>
186 SoftwareInventoryCollection(CrowApp &app) :
187 Node(app, "/redfish/v1/UpdateService/FirmwareInventory/")
188 {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700189 entityPrivileges = {
190 {boost::beast::http::verb::get, {{"Login"}}},
191 {boost::beast::http::verb::head, {{"Login"}}},
192 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
193 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
194 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
195 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
Jennifer Lee729dae72018-04-24 15:59:34 -0700196 }
Jennifer Lee729dae72018-04-24 15:59:34 -0700197
Ed Tanous1abe55e2018-09-05 08:30:59 -0700198 private:
199 void doGet(crow::Response &res, const crow::Request &req,
200 const std::vector<std::string> &params) override
201 {
202 std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
Ed Tanous0f74e642018-11-12 15:17:05 -0800203 res.jsonValue["@odata.type"] =
204 "#SoftwareInventoryCollection.SoftwareInventoryCollection";
205 res.jsonValue["@odata.id"] =
206 "/redfish/v1/UpdateService/FirmwareInventory";
207 res.jsonValue["@odata.context"] =
208 "/redfish/v1/"
209 "$metadata#SoftwareInventoryCollection.SoftwareInventoryCollection";
210 res.jsonValue["Name"] = "Software Inventory Collection";
Ed Tanousc711bf82018-07-30 16:31:33 -0700211
Ed Tanous1abe55e2018-09-05 08:30:59 -0700212 crow::connections::systemBus->async_method_call(
213 [asyncResp](
214 const boost::system::error_code ec,
215 const std::vector<std::pair<
216 std::string, std::vector<std::pair<
217 std::string, std::vector<std::string>>>>>
218 &subtree) {
219 if (ec)
220 {
Jason M. Billsf12894f2018-10-09 12:45:45 -0700221 messages::internalError(asyncResp->res);
Ed Tanousc711bf82018-07-30 16:31:33 -0700222 return;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700223 }
224 asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
225 asyncResp->res.jsonValue["Members@odata.count"] = 0;
Jennifer Lee6c4eb9d2018-05-22 10:58:31 -0700226
Ed Tanous1abe55e2018-09-05 08:30:59 -0700227 for (auto &obj : subtree)
228 {
229 const std::vector<
230 std::pair<std::string, std::vector<std::string>>>
231 &connections = obj.second;
232
Jennifer Leef4b65ab2018-09-18 12:00:13 -0700233 // if can't parse fw id then return
Ed Tanous27826b52018-10-29 11:40:58 -0700234 std::size_t idPos;
235 if ((idPos = obj.first.rfind("/")) == std::string::npos)
Jennifer Leef4b65ab2018-09-18 12:00:13 -0700236 {
Jason M. Billsf12894f2018-10-09 12:45:45 -0700237 messages::internalError(asyncResp->res);
Jennifer Leef4b65ab2018-09-18 12:00:13 -0700238 BMCWEB_LOG_DEBUG << "Can't parse firmware ID!!";
239 return;
240 }
Jennifer Leef4b65ab2018-09-18 12:00:13 -0700241 std::string swId = obj.first.substr(idPos + 1);
242
Ed Tanous1abe55e2018-09-05 08:30:59 -0700243 for (auto &conn : connections)
244 {
245 const std::string &connectionName = conn.first;
246 BMCWEB_LOG_DEBUG << "connectionName = "
247 << connectionName;
248 BMCWEB_LOG_DEBUG << "obj.first = " << obj.first;
249
250 crow::connections::systemBus->async_method_call(
Jennifer Leef4b65ab2018-09-18 12:00:13 -0700251 [asyncResp,
252 swId](const boost::system::error_code error_code,
253 const VariantType &activation) {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700254 BMCWEB_LOG_DEBUG
255 << "safe returned in lambda function";
256 if (error_code)
257 {
Jason M. Billsf12894f2018-10-09 12:45:45 -0700258 messages::internalError(asyncResp->res);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700259 return;
260 }
261
Jennifer Leef4b65ab2018-09-18 12:00:13 -0700262 const std::string *swActivationStatus =
Ed Tanousabf2add2019-01-22 16:40:12 -0800263 std::get_if<std::string>(&activation);
Jennifer Leef4b65ab2018-09-18 12:00:13 -0700264 if (swActivationStatus == nullptr)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700265 {
Jason M. Billsf12894f2018-10-09 12:45:45 -0700266 messages::internalError(asyncResp->res);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700267 return;
268 }
Jennifer Leef4b65ab2018-09-18 12:00:13 -0700269 if (swActivationStatus != nullptr &&
270 *swActivationStatus !=
271 "xyz.openbmc_project.Software."
272 "Activation."
273 "Activations.Active")
Ed Tanous1abe55e2018-09-05 08:30:59 -0700274 {
Jennifer Leef4b65ab2018-09-18 12:00:13 -0700275 // The activation status of this software is
276 // not currently active, so does not need to
277 // be listed in the response
Ed Tanous1abe55e2018-09-05 08:30:59 -0700278 return;
279 }
280 nlohmann::json &members =
281 asyncResp->res.jsonValue["Members"];
282 members.push_back(
Jennifer Leef4b65ab2018-09-18 12:00:13 -0700283 {{"@odata.id", "/redfish/v1/UpdateService/"
284 "FirmwareInventory/" +
285 swId}});
Ed Tanous1abe55e2018-09-05 08:30:59 -0700286 asyncResp->res
287 .jsonValue["Members@odata.count"] =
288 members.size();
289 },
290 connectionName, obj.first,
291 "org.freedesktop.DBus.Properties", "Get",
292 "xyz.openbmc_project.Software.Activation",
293 "Activation");
Ed Tanousc711bf82018-07-30 16:31:33 -0700294 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700295 }
296 },
297 "xyz.openbmc_project.ObjectMapper",
298 "/xyz/openbmc_project/object_mapper",
299 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
300 "/xyz/openbmc_project/software", int32_t(1),
301 std::array<const char *, 1>{
302 "xyz.openbmc_project.Software.Version"});
303 }
Jennifer Lee729dae72018-04-24 15:59:34 -0700304};
305
Ed Tanous1abe55e2018-09-05 08:30:59 -0700306class SoftwareInventory : public Node
307{
308 public:
309 template <typename CrowApp>
310 SoftwareInventory(CrowApp &app) :
311 Node(app, "/redfish/v1/UpdateService/FirmwareInventory/<str>/",
312 std::string())
313 {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700314 entityPrivileges = {
315 {boost::beast::http::verb::get, {{"Login"}}},
316 {boost::beast::http::verb::head, {{"Login"}}},
317 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
318 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
319 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
320 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
321 }
322
323 private:
Andrew Geissler87d84722019-02-28 14:28:39 -0600324 /* Fill related item links (i.e. bmc, bios) in for inventory */
325 static void getRelatedItems(std::shared_ptr<AsyncResp> aResp,
326 const std::string &purpose)
327 {
328 if (purpose == fw_util::bmcPurpose)
329 {
330 nlohmann::json &members = aResp->res.jsonValue["RelatedItem"];
331 members.push_back({{"@odata.id", "/redfish/v1/Managers/bmc"}});
332 aResp->res.jsonValue["Members@odata.count"] = members.size();
333 }
334 else if (purpose == fw_util::biosPurpose)
335 {
336 // TODO(geissonator) Need BIOS schema support added for this
337 // to be valid
338 // nlohmann::json &members = aResp->res.jsonValue["RelatedItem"];
339 // members.push_back(
340 // {{"@odata.id", "/redfish/v1/Systems/system/BIOS"}});
341 // aResp->res.jsonValue["Members@odata.count"] = members.size();
342 }
343 else
344 {
345 BMCWEB_LOG_ERROR << "Unknown software purpose " << purpose;
346 }
347 }
348
Ed Tanous1abe55e2018-09-05 08:30:59 -0700349 void doGet(crow::Response &res, const crow::Request &req,
350 const std::vector<std::string> &params) override
351 {
352 std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
Ed Tanous0f74e642018-11-12 15:17:05 -0800353 res.jsonValue["@odata.type"] =
354 "#SoftwareInventory.v1_1_0.SoftwareInventory";
355 res.jsonValue["@odata.context"] =
356 "/redfish/v1/$metadata#SoftwareInventory.SoftwareInventory";
357 res.jsonValue["Name"] = "Software Inventory";
358 res.jsonValue["Updateable"] = false;
359 res.jsonValue["Status"]["Health"] = "OK";
360 res.jsonValue["Status"]["HealthRollup"] = "OK";
361 res.jsonValue["Status"]["State"] = "Enabled";
Ed Tanous1abe55e2018-09-05 08:30:59 -0700362
363 if (params.size() != 1)
364 {
Jason M. Billsf12894f2018-10-09 12:45:45 -0700365 messages::internalError(res);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700366 res.end();
367 return;
368 }
369
Ed Tanous3ae837c2018-08-07 14:41:19 -0700370 std::shared_ptr<std::string> swId =
Ed Tanous1abe55e2018-09-05 08:30:59 -0700371 std::make_shared<std::string>(params[0]);
372
373 res.jsonValue["@odata.id"] =
Ed Tanous3ae837c2018-08-07 14:41:19 -0700374 "/redfish/v1/UpdateService/FirmwareInventory/" + *swId;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700375
376 crow::connections::systemBus->async_method_call(
Ed Tanous3ae837c2018-08-07 14:41:19 -0700377 [asyncResp, swId](
Ed Tanous1abe55e2018-09-05 08:30:59 -0700378 const boost::system::error_code ec,
379 const std::vector<std::pair<
380 std::string, std::vector<std::pair<
381 std::string, std::vector<std::string>>>>>
382 &subtree) {
383 BMCWEB_LOG_DEBUG << "doGet callback...";
384 if (ec)
385 {
Jason M. Billsf12894f2018-10-09 12:45:45 -0700386 messages::internalError(asyncResp->res);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700387 return;
388 }
389
390 for (const std::pair<
391 std::string,
392 std::vector<
393 std::pair<std::string, std::vector<std::string>>>>
394 &obj : subtree)
395 {
Ed Tanous3ae837c2018-08-07 14:41:19 -0700396 if (boost::ends_with(obj.first, *swId) != true)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700397 {
398 continue;
399 }
400
Jennifer Leef4b65ab2018-09-18 12:00:13 -0700401 if (obj.second.size() < 1)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700402 {
403 continue;
404 }
405
406 crow::connections::systemBus->async_method_call(
407 [asyncResp,
Ed Tanous3ae837c2018-08-07 14:41:19 -0700408 swId](const boost::system::error_code error_code,
409 const boost::container::flat_map<
410 std::string, VariantType> &propertiesList) {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700411 if (error_code)
412 {
Jason M. Billsf12894f2018-10-09 12:45:45 -0700413 messages::internalError(asyncResp->res);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700414 return;
415 }
416 boost::container::flat_map<
417 std::string, VariantType>::const_iterator it =
418 propertiesList.find("Purpose");
419 if (it == propertiesList.end())
420 {
421 BMCWEB_LOG_DEBUG
422 << "Can't find property \"Purpose\"!";
Jason M. Billsf12894f2018-10-09 12:45:45 -0700423 messages::propertyMissing(asyncResp->res,
424 "Purpose");
Ed Tanous1abe55e2018-09-05 08:30:59 -0700425 return;
426 }
Ed Tanous3ae837c2018-08-07 14:41:19 -0700427 const std::string *swInvPurpose =
Ed Tanousabf2add2019-01-22 16:40:12 -0800428 std::get_if<std::string>(&it->second);
Ed Tanous3ae837c2018-08-07 14:41:19 -0700429 if (swInvPurpose == nullptr)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700430 {
431 BMCWEB_LOG_DEBUG
432 << "wrong types for property\"Purpose\"!";
Jason M. Billsf12894f2018-10-09 12:45:45 -0700433 messages::propertyValueTypeError(asyncResp->res,
434 "", "Purpose");
Ed Tanous1abe55e2018-09-05 08:30:59 -0700435 return;
436 }
437
Ed Tanous3ae837c2018-08-07 14:41:19 -0700438 BMCWEB_LOG_DEBUG << "swInvPurpose = "
439 << *swInvPurpose;
Jennifer Leef4b65ab2018-09-18 12:00:13 -0700440 it = propertiesList.find("Version");
441 if (it == propertiesList.end())
Ed Tanous1abe55e2018-09-05 08:30:59 -0700442 {
Jennifer Leef4b65ab2018-09-18 12:00:13 -0700443 BMCWEB_LOG_DEBUG
444 << "Can't find property \"Version\"!";
Jason M. Billsf12894f2018-10-09 12:45:45 -0700445 messages::propertyMissing(asyncResp->res,
446 "Version");
Jennifer Leef4b65ab2018-09-18 12:00:13 -0700447 return;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700448 }
Jennifer Leef4b65ab2018-09-18 12:00:13 -0700449
450 BMCWEB_LOG_DEBUG << "Version found!";
451
452 const std::string *version =
Ed Tanousabf2add2019-01-22 16:40:12 -0800453 std::get_if<std::string>(&it->second);
Jennifer Leef4b65ab2018-09-18 12:00:13 -0700454
455 if (version == nullptr)
456 {
457 BMCWEB_LOG_DEBUG
458 << "Can't find property \"Version\"!";
Jason M. Billsf12894f2018-10-09 12:45:45 -0700459
460 messages::propertyValueTypeError(asyncResp->res,
461 "", "Version");
Jennifer Leef4b65ab2018-09-18 12:00:13 -0700462 return;
463 }
464 asyncResp->res.jsonValue["Version"] = *version;
465 asyncResp->res.jsonValue["Id"] = *swId;
Andrew Geissler54daabe2019-02-13 13:54:15 -0600466
467 // swInvPurpose is of format:
468 // xyz.openbmc_project.Software.Version.VersionPurpose.ABC
469 // Translate this to "ABC update"
470 size_t endDesc = swInvPurpose->rfind(".");
471 if (endDesc == std::string::npos)
472 {
473 messages::internalError(asyncResp->res);
474 return;
475 }
476 endDesc++;
477 if (endDesc >= swInvPurpose->size())
478 {
479 messages::internalError(asyncResp->res);
480 return;
481 }
482
483 std::string formatDesc =
484 swInvPurpose->substr(endDesc);
485 asyncResp->res.jsonValue["Description"] =
486 formatDesc + " update";
Andrew Geissler87d84722019-02-28 14:28:39 -0600487 getRelatedItems(asyncResp, *swInvPurpose);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700488 },
489 obj.second[0].first, obj.first,
490 "org.freedesktop.DBus.Properties", "GetAll",
491 "xyz.openbmc_project.Software.Version");
492 }
493 },
494 "xyz.openbmc_project.ObjectMapper",
495 "/xyz/openbmc_project/object_mapper",
496 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
497 "/xyz/openbmc_project/software", int32_t(1),
498 std::array<const char *, 1>{
499 "xyz.openbmc_project.Software.Version"});
500 }
501};
502
503} // namespace redfish