blob: aefb27e3a88db13509c89f0c0969852287d01984 [file] [log] [blame]
Ed Tanousc3ee5222018-05-01 12:58:27 -07001#pragma once
2
Ed Tanous04e438c2020-10-03 08:06:26 -07003#include <app.hpp>
Ed Tanousc3ee5222018-05-01 12:58:27 -07004#include <boost/uuid/uuid.hpp>
5#include <boost/uuid/uuid_generators.hpp>
6#include <boost/uuid/uuid_io.hpp>
Ed Tanous1abe55e2018-09-05 08:30:59 -07007#include <dbus_singleton.hpp>
Ed Tanous168e20c2021-12-13 14:39:53 -08008#include <dbus_utility.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 Tanous23a21a12020-07-25 04:45:05 +000019static std::unique_ptr<sdbusplus::bus::match::match> fwUpdateMatcher;
Ed Tanousc3ee5222018-05-01 12:58:27 -070020
zhanghch058d1b46d2021-04-01 11:18:24 +080021inline void
22 uploadImageHandler(const crow::Request& req,
23 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanous1abe55e2018-09-05 08:30:59 -070024{
25 // Only allow one FW update at a time
26 if (fwUpdateMatcher != nullptr)
27 {
zhanghch058d1b46d2021-04-01 11:18:24 +080028 asyncResp->res.addHeader("Retry-After", "30");
29 asyncResp->res.result(boost::beast::http::status::service_unavailable);
Ed Tanous1abe55e2018-09-05 08:30:59 -070030 return;
31 }
32 // Make this const static so it survives outside this method
Ed Tanous271584a2019-07-09 16:24:22 -070033 static boost::asio::steady_timer timeout(*req.ioService,
34 std::chrono::seconds(5));
Ed Tanous1abe55e2018-09-05 08:30:59 -070035
Ed Tanous271584a2019-07-09 16:24:22 -070036 timeout.expires_after(std::chrono::seconds(15));
Ed Tanous1abe55e2018-09-05 08:30:59 -070037
zhanghch058d1b46d2021-04-01 11:18:24 +080038 auto timeoutHandler = [asyncResp](const boost::system::error_code& ec) {
Ed Tanousc3ee5222018-05-01 12:58:27 -070039 fwUpdateMatcher = nullptr;
Ed Tanous23e64202020-09-15 19:21:30 -070040 if (ec == boost::asio::error::operation_aborted)
Ed Tanous1abe55e2018-09-05 08:30:59 -070041 {
42 // expected, we were canceled before the timer completed.
43 return;
44 }
Matt Spinlerc9008502019-01-21 12:21:25 -060045 BMCWEB_LOG_ERROR << "Timed out waiting for Version interface";
Ed Tanousc3ee5222018-05-01 12:58:27 -070046
Ed Tanous1abe55e2018-09-05 08:30:59 -070047 if (ec)
48 {
49 BMCWEB_LOG_ERROR << "Async_wait failed " << ec;
50 return;
51 }
52
zhanghch058d1b46d2021-04-01 11:18:24 +080053 asyncResp->res.result(boost::beast::http::status::bad_request);
Ed Tanous14766872022-03-15 10:44:42 -070054 asyncResp->res.jsonValue["data"]["description"] =
55 "Version already exists or failed to be extracted";
56 asyncResp->res.jsonValue["message"] = "400 Bad Request";
57 asyncResp->res.jsonValue["status"] = "error";
Lei YU9f898f82019-03-08 16:52:10 +080058 };
Ed Tanous1abe55e2018-09-05 08:30:59 -070059
60 std::function<void(sdbusplus::message::message&)> callback =
zhanghch058d1b46d2021-04-01 11:18:24 +080061 [asyncResp](sdbusplus::message::message& m) {
Ed Tanous1abe55e2018-09-05 08:30:59 -070062 BMCWEB_LOG_DEBUG << "Match fired";
Ed Tanous1abe55e2018-09-05 08:30:59 -070063
Matt Spinlerc9008502019-01-21 12:21:25 -060064 sdbusplus::message::object_path path;
Ed Tanousb9d36b42022-02-26 21:42:46 -080065 dbus::utility::DBusInteracesMap interfaces;
Matt Spinlerc9008502019-01-21 12:21:25 -060066 m.read(path, interfaces);
67
68 if (std::find_if(interfaces.begin(), interfaces.end(),
69 [](const auto& i) {
70 return i.first ==
71 "xyz.openbmc_project.Software.Version";
72 }) != interfaces.end())
Ed Tanous1abe55e2018-09-05 08:30:59 -070073 {
Ed Tanous271584a2019-07-09 16:24:22 -070074 timeout.cancel();
Ed Tanous2dfd18e2020-12-18 00:41:31 +000075 std::string leaf = path.filename();
76 if (leaf.empty())
Matt Spinlerc9008502019-01-21 12:21:25 -060077 {
Ed Tanous2dfd18e2020-12-18 00:41:31 +000078 leaf = path.str;
Matt Spinlerc9008502019-01-21 12:21:25 -060079 }
Ed Tanous2dfd18e2020-12-18 00:41:31 +000080
Ed Tanous14766872022-03-15 10:44:42 -070081 asyncResp->res.jsonValue["data"] = leaf;
82 asyncResp->res.jsonValue["message"] = "200 OK";
83 asyncResp->res.jsonValue["status"] = "ok";
Matt Spinlerc9008502019-01-21 12:21:25 -060084 BMCWEB_LOG_DEBUG << "ending response";
Matt Spinlerc9008502019-01-21 12:21:25 -060085 fwUpdateMatcher = nullptr;
Ed Tanous1abe55e2018-09-05 08:30:59 -070086 }
Ed Tanous1abe55e2018-09-05 08:30:59 -070087 };
88 fwUpdateMatcher = std::make_unique<sdbusplus::bus::match::match>(
89 *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
94 std::string filepath(
95 "/tmp/images/" +
96 boost::uuids::to_string(boost::uuids::random_generator()()));
97 BMCWEB_LOG_DEBUG << "Writing file to " << filepath;
98 std::ofstream out(filepath, std::ofstream::out | std::ofstream::binary |
99 std::ofstream::trunc);
100 out << req.body;
101 out.close();
Lei YU9f898f82019-03-08 16:52:10 +0800102 timeout.async_wait(timeoutHandler);
Ed Tanousc3ee5222018-05-01 12:58:27 -0700103}
104
Ed Tanous23a21a12020-07-25 04:45:05 +0000105inline void requestRoutes(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700106{
107 BMCWEB_ROUTE(app, "/upload/image/<str>")
Ed Tanous432a8902021-06-14 15:28:56 -0700108 .privileges({{"ConfigureComponents", "ConfigureManager"}})
Ed Tanousb41187f2019-10-24 16:30:02 -0700109 .methods(boost::beast::http::verb::post, boost::beast::http::verb::put)(
zhanghch058d1b46d2021-04-01 11:18:24 +0800110 [](const crow::Request& req,
111 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
112 const std::string&) { uploadImageHandler(req, asyncResp); });
Ed Tanousc3ee5222018-05-01 12:58:27 -0700113
Ed Tanous1abe55e2018-09-05 08:30:59 -0700114 BMCWEB_ROUTE(app, "/upload/image")
Ed Tanous432a8902021-06-14 15:28:56 -0700115 .privileges({{"ConfigureComponents", "ConfigureManager"}})
Ed Tanousb41187f2019-10-24 16:30:02 -0700116 .methods(boost::beast::http::verb::post, boost::beast::http::verb::put)(
zhanghch058d1b46d2021-04-01 11:18:24 +0800117 [](const crow::Request& req,
118 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
119 uploadImageHandler(req, asyncResp);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700120 });
Ed Tanousc3ee5222018-05-01 12:58:27 -0700121}
Ed Tanous1abe55e2018-09-05 08:30:59 -0700122} // namespace image_upload
123} // namespace crow