blob: cdd7dd47d29bc7d96066511d2e5a342a4dee983b [file] [log] [blame]
Ed Tanousc3ee5222018-05-01 12:58:27 -07001#pragma once
2
Ed Tanous3ccb3ad2023-01-13 17:40:03 -08003#include "app.hpp"
4#include "dbus_singleton.hpp"
5#include "dbus_utility.hpp"
Ed Tanous2c6ffdb2023-06-28 11:28:38 -07006#include "ossl_random.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -08007
Ed Tanous3ccb3ad2023-01-13 17:40:03 -08008#include <sdbusplus/bus/match.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -05009
10#include <cstdio>
Ed Tanous1abe55e2018-09-05 08:30:59 -070011#include <fstream>
12#include <memory>
Ed Tanousc3ee5222018-05-01 12:58:27 -070013
Ed Tanous1abe55e2018-09-05 08:30:59 -070014namespace crow
15{
16namespace image_upload
17{
Ed Tanousc3ee5222018-05-01 12:58:27 -070018
Ed Tanouscf9e4172022-12-21 09:30:16 -080019// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
Patrick Williams59d494e2022-07-22 19:26:55 -050020static std::unique_ptr<sdbusplus::bus::match_t> fwUpdateMatcher;
Ed Tanousc3ee5222018-05-01 12:58:27 -070021
zhanghch058d1b46d2021-04-01 11:18:24 +080022inline void
23 uploadImageHandler(const crow::Request& req,
24 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanous1abe55e2018-09-05 08:30:59 -070025{
26 // Only allow one FW update at a time
27 if (fwUpdateMatcher != nullptr)
28 {
zhanghch058d1b46d2021-04-01 11:18:24 +080029 asyncResp->res.addHeader("Retry-After", "30");
30 asyncResp->res.result(boost::beast::http::status::service_unavailable);
Ed Tanous1abe55e2018-09-05 08:30:59 -070031 return;
32 }
33 // Make this const static so it survives outside this method
Ed Tanous271584a2019-07-09 16:24:22 -070034 static boost::asio::steady_timer timeout(*req.ioService,
35 std::chrono::seconds(5));
Ed Tanous1abe55e2018-09-05 08:30:59 -070036
Ed Tanous271584a2019-07-09 16:24:22 -070037 timeout.expires_after(std::chrono::seconds(15));
Ed Tanous1abe55e2018-09-05 08:30:59 -070038
zhanghch058d1b46d2021-04-01 11:18:24 +080039 auto timeoutHandler = [asyncResp](const boost::system::error_code& ec) {
Ed Tanousc3ee5222018-05-01 12:58:27 -070040 fwUpdateMatcher = nullptr;
Ed Tanous23e64202020-09-15 19:21:30 -070041 if (ec == boost::asio::error::operation_aborted)
Ed Tanous1abe55e2018-09-05 08:30:59 -070042 {
43 // expected, we were canceled before the timer completed.
44 return;
45 }
Matt Spinlerc9008502019-01-21 12:21:25 -060046 BMCWEB_LOG_ERROR << "Timed out waiting for Version interface";
Ed Tanousc3ee5222018-05-01 12:58:27 -070047
Ed Tanous1abe55e2018-09-05 08:30:59 -070048 if (ec)
49 {
50 BMCWEB_LOG_ERROR << "Async_wait failed " << ec;
51 return;
52 }
53
zhanghch058d1b46d2021-04-01 11:18:24 +080054 asyncResp->res.result(boost::beast::http::status::bad_request);
Ed Tanous14766872022-03-15 10:44:42 -070055 asyncResp->res.jsonValue["data"]["description"] =
56 "Version already exists or failed to be extracted";
57 asyncResp->res.jsonValue["message"] = "400 Bad Request";
58 asyncResp->res.jsonValue["status"] = "error";
Lei YU9f898f82019-03-08 16:52:10 +080059 };
Ed Tanous1abe55e2018-09-05 08:30:59 -070060
Patrick Williams59d494e2022-07-22 19:26:55 -050061 std::function<void(sdbusplus::message_t&)> callback =
62 [asyncResp](sdbusplus::message_t& m) {
Ed Tanous002d39b2022-05-31 08:59:27 -070063 BMCWEB_LOG_DEBUG << "Match fired";
Ed Tanous1abe55e2018-09-05 08:30:59 -070064
Ed Tanous002d39b2022-05-31 08:59:27 -070065 sdbusplus::message::object_path path;
66 dbus::utility::DBusInteracesMap interfaces;
67 m.read(path, interfaces);
Matt Spinlerc9008502019-01-21 12:21:25 -060068
Ed Tanous002d39b2022-05-31 08:59:27 -070069 if (std::find_if(interfaces.begin(), interfaces.end(),
70 [](const auto& i) {
71 return i.first == "xyz.openbmc_project.Software.Version";
72 }) != interfaces.end())
73 {
74 timeout.cancel();
75 std::string leaf = path.filename();
76 if (leaf.empty())
Ed Tanous1abe55e2018-09-05 08:30:59 -070077 {
Ed Tanous002d39b2022-05-31 08:59:27 -070078 leaf = path.str;
Ed Tanous1abe55e2018-09-05 08:30:59 -070079 }
Ed Tanous002d39b2022-05-31 08:59:27 -070080
81 asyncResp->res.jsonValue["data"] = leaf;
82 asyncResp->res.jsonValue["message"] = "200 OK";
83 asyncResp->res.jsonValue["status"] = "ok";
84 BMCWEB_LOG_DEBUG << "ending response";
85 fwUpdateMatcher = nullptr;
86 }
87 };
Patrick Williams59d494e2022-07-22 19:26:55 -050088 fwUpdateMatcher = std::make_unique<sdbusplus::bus::match_t>(
Ed Tanous1abe55e2018-09-05 08:30:59 -070089 *crow::connections::systemBus,
90 "interface='org.freedesktop.DBus.ObjectManager',type='signal',"
Matt Spinlerc9008502019-01-21 12:21:25 -060091 "member='InterfacesAdded',path='/xyz/openbmc_project/software'",
Ed Tanous1abe55e2018-09-05 08:30:59 -070092 callback);
93
Ed Tanous2c6ffdb2023-06-28 11:28:38 -070094 std::string filepath("/tmp/images/" + bmcweb::getRandomUUID());
Ed Tanous1abe55e2018-09-05 08:30:59 -070095 BMCWEB_LOG_DEBUG << "Writing file to " << filepath;
96 std::ofstream out(filepath, std::ofstream::out | std::ofstream::binary |
97 std::ofstream::trunc);
Ed Tanous33c6b582023-02-14 15:05:48 -080098 out << req.body();
Ed Tanous1abe55e2018-09-05 08:30:59 -070099 out.close();
Lei YU9f898f82019-03-08 16:52:10 +0800100 timeout.async_wait(timeoutHandler);
Ed Tanousc3ee5222018-05-01 12:58:27 -0700101}
102
Ed Tanous23a21a12020-07-25 04:45:05 +0000103inline void requestRoutes(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700104{
105 BMCWEB_ROUTE(app, "/upload/image/<str>")
Ed Tanous432a8902021-06-14 15:28:56 -0700106 .privileges({{"ConfigureComponents", "ConfigureManager"}})
Ed Tanousb41187f2019-10-24 16:30:02 -0700107 .methods(boost::beast::http::verb::post, boost::beast::http::verb::put)(
zhanghch058d1b46d2021-04-01 11:18:24 +0800108 [](const crow::Request& req,
109 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
110 const std::string&) { uploadImageHandler(req, asyncResp); });
Ed Tanousc3ee5222018-05-01 12:58:27 -0700111
Ed Tanous1abe55e2018-09-05 08:30:59 -0700112 BMCWEB_ROUTE(app, "/upload/image")
Ed Tanous432a8902021-06-14 15:28:56 -0700113 .privileges({{"ConfigureComponents", "ConfigureManager"}})
Ed Tanousb41187f2019-10-24 16:30:02 -0700114 .methods(boost::beast::http::verb::post, boost::beast::http::verb::put)(
zhanghch058d1b46d2021-04-01 11:18:24 +0800115 [](const crow::Request& req,
116 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700117 uploadImageHandler(req, asyncResp);
118 });
Ed Tanousc3ee5222018-05-01 12:58:27 -0700119}
Ed Tanous1abe55e2018-09-05 08:30:59 -0700120} // namespace image_upload
121} // namespace crow