blob: 3786c309900a6ff1401f473fc6ab5a0d734113cb [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>
Gunnar Mills1214b7e2020-06-04 10:11:30 -05008
9#include <cstdio>
Ed Tanous1abe55e2018-09-05 08:30:59 -070010#include <fstream>
11#include <memory>
Ed Tanousc3ee5222018-05-01 12:58:27 -070012
Ed Tanous1abe55e2018-09-05 08:30:59 -070013namespace crow
14{
15namespace image_upload
16{
Ed Tanousc3ee5222018-05-01 12:58:27 -070017
Ed Tanous23a21a12020-07-25 04:45:05 +000018static std::unique_ptr<sdbusplus::bus::match::match> fwUpdateMatcher;
Ed Tanousc3ee5222018-05-01 12:58:27 -070019
Ed Tanouscb13a392020-07-25 19:02:03 +000020inline void uploadImageHandler(const crow::Request& req, crow::Response& res)
Ed Tanous1abe55e2018-09-05 08:30:59 -070021{
22 // Only allow one FW update at a time
23 if (fwUpdateMatcher != nullptr)
24 {
25 res.addHeader("Retry-After", "30");
26 res.result(boost::beast::http::status::service_unavailable);
Ed Tanousc3ee5222018-05-01 12:58:27 -070027 res.end();
Ed Tanous1abe55e2018-09-05 08:30:59 -070028 return;
29 }
30 // Make this const static so it survives outside this method
Ed Tanous271584a2019-07-09 16:24:22 -070031 static boost::asio::steady_timer timeout(*req.ioService,
32 std::chrono::seconds(5));
Ed Tanous1abe55e2018-09-05 08:30:59 -070033
Ed Tanous271584a2019-07-09 16:24:22 -070034 timeout.expires_after(std::chrono::seconds(15));
Ed Tanous1abe55e2018-09-05 08:30:59 -070035
Lei YU9f898f82019-03-08 16:52:10 +080036 auto timeoutHandler = [&res](const boost::system::error_code& ec) {
Ed Tanousc3ee5222018-05-01 12:58:27 -070037 fwUpdateMatcher = nullptr;
Ed Tanous23e64202020-09-15 19:21:30 -070038 if (ec == boost::asio::error::operation_aborted)
Ed Tanous1abe55e2018-09-05 08:30:59 -070039 {
40 // expected, we were canceled before the timer completed.
41 return;
42 }
Matt Spinlerc9008502019-01-21 12:21:25 -060043 BMCWEB_LOG_ERROR << "Timed out waiting for Version interface";
Ed Tanousc3ee5222018-05-01 12:58:27 -070044
Ed Tanous1abe55e2018-09-05 08:30:59 -070045 if (ec)
46 {
47 BMCWEB_LOG_ERROR << "Async_wait failed " << ec;
48 return;
49 }
50
Matt Spinlerc9008502019-01-21 12:21:25 -060051 res.result(boost::beast::http::status::bad_request);
52 res.jsonValue = {
53 {"data",
54 {{"description",
55 "Version already exists or failed to be extracted"}}},
56 {"message", "400 Bad Request"},
57 {"status", "error"}};
Ed Tanous1abe55e2018-09-05 08:30:59 -070058 res.end();
Lei YU9f898f82019-03-08 16:52:10 +080059 };
Ed Tanous1abe55e2018-09-05 08:30:59 -070060
61 std::function<void(sdbusplus::message::message&)> callback =
62 [&res](sdbusplus::message::message& m) {
63 BMCWEB_LOG_DEBUG << "Match fired";
Ed Tanous1abe55e2018-09-05 08:30:59 -070064
Matt Spinlerc9008502019-01-21 12:21:25 -060065 sdbusplus::message::object_path path;
66 std::vector<std::pair<
67 std::string,
Ed Tanousabf2add2019-01-22 16:40:12 -080068 std::vector<std::pair<std::string, std::variant<std::string>>>>>
Matt Spinlerc9008502019-01-21 12:21:25 -060069 interfaces;
70 m.read(path, interfaces);
71
72 if (std::find_if(interfaces.begin(), interfaces.end(),
73 [](const auto& i) {
74 return i.first ==
75 "xyz.openbmc_project.Software.Version";
76 }) != interfaces.end())
Ed Tanous1abe55e2018-09-05 08:30:59 -070077 {
Ed Tanous271584a2019-07-09 16:24:22 -070078 timeout.cancel();
Ed Tanous2dfd18e2020-12-18 00:41:31 +000079 std::string leaf = path.filename();
80 if (leaf.empty())
Matt Spinlerc9008502019-01-21 12:21:25 -060081 {
Ed Tanous2dfd18e2020-12-18 00:41:31 +000082 leaf = path.str;
Matt Spinlerc9008502019-01-21 12:21:25 -060083 }
Ed Tanous2dfd18e2020-12-18 00:41:31 +000084
85 res.jsonValue = {
86 {"data", leaf}, {"message", "200 OK"}, {"status", "ok"}};
Matt Spinlerc9008502019-01-21 12:21:25 -060087 BMCWEB_LOG_DEBUG << "ending response";
88 res.end();
89 fwUpdateMatcher = nullptr;
Ed Tanous1abe55e2018-09-05 08:30:59 -070090 }
Ed Tanous1abe55e2018-09-05 08:30:59 -070091 };
92 fwUpdateMatcher = std::make_unique<sdbusplus::bus::match::match>(
93 *crow::connections::systemBus,
94 "interface='org.freedesktop.DBus.ObjectManager',type='signal',"
Matt Spinlerc9008502019-01-21 12:21:25 -060095 "member='InterfacesAdded',path='/xyz/openbmc_project/software'",
Ed Tanous1abe55e2018-09-05 08:30:59 -070096 callback);
97
98 std::string filepath(
99 "/tmp/images/" +
100 boost::uuids::to_string(boost::uuids::random_generator()()));
101 BMCWEB_LOG_DEBUG << "Writing file to " << filepath;
102 std::ofstream out(filepath, std::ofstream::out | std::ofstream::binary |
103 std::ofstream::trunc);
104 out << req.body;
105 out.close();
Lei YU9f898f82019-03-08 16:52:10 +0800106 timeout.async_wait(timeoutHandler);
Ed Tanousc3ee5222018-05-01 12:58:27 -0700107}
108
Ed Tanous23a21a12020-07-25 04:45:05 +0000109inline void requestRoutes(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700110{
111 BMCWEB_ROUTE(app, "/upload/image/<str>")
Ed Tanous23a21a12020-07-25 04:45:05 +0000112 .privileges({"ConfigureComponents", "ConfigureManager"})
Ed Tanousb41187f2019-10-24 16:30:02 -0700113 .methods(boost::beast::http::verb::post, boost::beast::http::verb::put)(
114 [](const crow::Request& req, crow::Response& res,
Ed Tanouscb13a392020-07-25 19:02:03 +0000115 const std::string&) { uploadImageHandler(req, res); });
Ed Tanousc3ee5222018-05-01 12:58:27 -0700116
Ed Tanous1abe55e2018-09-05 08:30:59 -0700117 BMCWEB_ROUTE(app, "/upload/image")
Ed Tanous23a21a12020-07-25 04:45:05 +0000118 .privileges({"ConfigureComponents", "ConfigureManager"})
Ed Tanousb41187f2019-10-24 16:30:02 -0700119 .methods(boost::beast::http::verb::post, boost::beast::http::verb::put)(
Ed Tanous1abe55e2018-09-05 08:30:59 -0700120 [](const crow::Request& req, crow::Response& res) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000121 uploadImageHandler(req, res);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700122 });
Ed Tanousc3ee5222018-05-01 12:58:27 -0700123}
Ed Tanous1abe55e2018-09-05 08:30:59 -0700124} // namespace image_upload
125} // namespace crow