blob: 225861dea32d95dae9e60ae1734de9dbcc4ec5b3 [file] [log] [blame]
Ratan Gupta453fed02019-12-14 09:39:47 +05301#pragma once
2#include <app.h>
3#include <tinyxml2.h>
4
5#include <async_resp.hpp>
Sunitha Harish97b0e432019-11-21 04:59:29 -06006#include <boost/algorithm/string.hpp>
7#include <boost/container/flat_set.hpp>
8#include <filesystem>
9#include <fstream>
10#include <regex>
11#include <sdbusplus/message/types.hpp>
12
13#define MAX_SAVE_AREA_FILESIZE 200000
Ratan Gupta453fed02019-12-14 09:39:47 +053014
15namespace crow
16{
17namespace ibm_mc
18{
Sunitha Harish97b0e432019-11-21 04:59:29 -060019constexpr const char *methodNotAllowedMsg = "Method Not Allowed";
20constexpr const char *resourceNotFoundMsg = "Resource Not Found";
21constexpr const char *contentNotAcceptableMsg = "Content Not Acceptable";
22constexpr const char *internalServerError = "Internal Server Error";
23
24bool createSaveAreaPath(crow::Response &res)
25{
26 // The path /var/lib/obmc will be created by initrdscripts
27 // Create the directories for the save-area files, when we get
28 // first file upload request
29 std::error_code ec;
30 if (!std::filesystem::is_directory("/var/lib/obmc/bmc-console-mgmt", ec))
31 {
32 std::filesystem::create_directory("/var/lib/obmc/bmc-console-mgmt", ec);
33 }
34 if (ec)
35 {
36 res.result(boost::beast::http::status::internal_server_error);
37 res.jsonValue["Description"] = internalServerError;
38 BMCWEB_LOG_DEBUG
39 << "handleIbmPost: Failed to prepare save-area directory. ec : "
40 << ec;
41 return false;
42 }
43
44 if (!std::filesystem::is_directory(
45 "/var/lib/obmc/bmc-console-mgmt/save-area", ec))
46 {
47 std::filesystem::create_directory(
48 "/var/lib/obmc/bmc-console-mgmt/save-area", ec);
49 }
50 if (ec)
51 {
52 res.result(boost::beast::http::status::internal_server_error);
53 res.jsonValue["Description"] = internalServerError;
54 BMCWEB_LOG_DEBUG
55 << "handleIbmPost: Failed to prepare save-area directory. ec : "
56 << ec;
57 return false;
58 }
59 return true;
60}
61void handleFilePut(const crow::Request &req, crow::Response &res,
asmithakarun1c7b07c2019-09-09 03:42:59 -050062 const std::string &fileID)
Sunitha Harish97b0e432019-11-21 04:59:29 -060063{
64 // Check the content-type of the request
65 std::string_view contentType = req.getHeaderValue("content-type");
66 if (boost::starts_with(contentType, "multipart/form-data"))
67 {
68 BMCWEB_LOG_DEBUG
69 << "This is multipart/form-data. Invalid content for PUT";
70
71 res.result(boost::beast::http::status::not_acceptable);
72 res.jsonValue["Description"] = contentNotAcceptableMsg;
73 return;
74 }
75 else
76 {
77 BMCWEB_LOG_DEBUG << "Not a multipart/form-data. Continue..";
78 }
asmithakarun1c7b07c2019-09-09 03:42:59 -050079
80 BMCWEB_LOG_DEBUG
81 << "handleIbmPut: Request to create/update the save-area file";
82 if (!createSaveAreaPath(res))
Sunitha Harish97b0e432019-11-21 04:59:29 -060083 {
asmithakarun1c7b07c2019-09-09 03:42:59 -050084 res.result(boost::beast::http::status::not_found);
85 res.jsonValue["Description"] = resourceNotFoundMsg;
86 return;
87 }
88 // Create the file
89 std::ofstream file;
90 std::filesystem::path loc("/var/lib/obmc/bmc-console-mgmt/save-area");
91 loc /= fileID;
Sunitha Harish97b0e432019-11-21 04:59:29 -060092
asmithakarun1c7b07c2019-09-09 03:42:59 -050093 std::string data = std::move(req.body);
94 BMCWEB_LOG_DEBUG << "data capaticty : " << data.capacity();
95 if (data.capacity() > MAX_SAVE_AREA_FILESIZE)
96 {
97 res.result(boost::beast::http::status::bad_request);
98 res.jsonValue["Description"] =
99 "File size exceeds 200KB. Maximum allowed size is 200KB";
100 return;
101 }
asmithakarun1c7b07c2019-09-09 03:42:59 -0500102 BMCWEB_LOG_DEBUG << "Creating file " << loc;
103 file.open(loc, std::ofstream::out);
104 if (file.fail())
105 {
106 BMCWEB_LOG_DEBUG << "Error while opening the file for writing";
107 res.result(boost::beast::http::status::internal_server_error);
108 res.jsonValue["Description"] = "Error while creating the file";
109 return;
Sunitha Harish97b0e432019-11-21 04:59:29 -0600110 }
111 else
112 {
asmithakarun1c7b07c2019-09-09 03:42:59 -0500113 file << data;
114 BMCWEB_LOG_DEBUG << "save-area file is created";
115 res.jsonValue["Description"] = "File Created";
116 }
Ratan Guptad3630cb2019-12-14 11:21:35 +0530117}
asmithakarun1c7b07c2019-09-09 03:42:59 -0500118
Ratan Guptad3630cb2019-12-14 11:21:35 +0530119void handleConfigFileList(crow::Response &res)
120{
121 std::vector<std::string> pathObjList;
122 std::filesystem::path loc("/var/lib/obmc/bmc-console-mgmt/save-area");
123 if (std::filesystem::exists(loc) && std::filesystem::is_directory(loc))
124 {
125 for (const auto &file : std::filesystem::directory_iterator(loc))
126 {
127 std::filesystem::path pathObj(file.path());
128 pathObjList.push_back("/ibm/v1/Host/ConfigFiles/" +
129 pathObj.filename().string());
130 }
131 }
132 res.jsonValue["@odata.type"] = "#FileCollection.v1_0_0.FileCollection";
133 res.jsonValue["@odata.id"] = "/ibm/v1/Host/ConfigFiles/";
134 res.jsonValue["Id"] = "ConfigFiles";
135 res.jsonValue["Name"] = "ConfigFiles";
136
137 res.jsonValue["Members"] = std::move(pathObjList);
138 res.jsonValue["Actions"]["#FileCollection.DeleteAll"] = {
139 {"target",
140 "/ibm/v1/Host/ConfigFiles/Actions/FileCollection.DeleteAll"}};
141 res.end();
142}
143
144void deleteConfigFiles(crow::Response &res)
145{
146 std::vector<std::string> pathObjList;
147 std::error_code ec;
148 std::filesystem::path loc("/var/lib/obmc/bmc-console-mgmt/save-area");
149 if (std::filesystem::exists(loc) && std::filesystem::is_directory(loc))
150 {
151 std::filesystem::remove_all(loc, ec);
152 if (ec)
153 {
154 res.result(boost::beast::http::status::internal_server_error);
155 res.jsonValue["Description"] = internalServerError;
156 BMCWEB_LOG_DEBUG << "deleteConfigFiles: Failed to delete the "
157 "config files directory. ec : "
158 << ec;
159 }
160 }
161 res.end();
asmithakarun1c7b07c2019-09-09 03:42:59 -0500162}
163
Ratan Gupta734a1c32019-12-14 11:53:48 +0530164void getLockServiceData(crow::Response &res)
165{
166 res.jsonValue["@odata.type"] = "#LockService.v1_0_0.LockService";
167 res.jsonValue["@odata.id"] = "/ibm/v1/HMC/LockService/";
168 res.jsonValue["Id"] = "LockService";
169 res.jsonValue["Name"] = "LockService";
170
171 res.jsonValue["Actions"]["#LockService.AcquireLock"] = {
172 {"target", "/ibm/v1/HMC/LockService/Actions/LockService.AcquireLock"}};
173 res.jsonValue["Actions"]["#LockService.ReleaseLock"] = {
174 {"target", "/ibm/v1/HMC/LockService/Actions/LockService.ReleaseLock"}};
175 res.jsonValue["Actions"]["#LockService.GetLockList"] = {
176 {"target", "/ibm/v1/HMC/LockService/Actions/LockService.GetLockList"}};
177 res.end();
178}
179
asmithakarun1c7b07c2019-09-09 03:42:59 -0500180void handleFileGet(crow::Response &res, const std::string &fileID)
181{
182 BMCWEB_LOG_DEBUG << "HandleGet on SaveArea files on path: " << fileID;
183 std::filesystem::path loc("/var/lib/obmc/bmc-console-mgmt/save-area/" +
184 fileID);
185 if (!std::filesystem::exists(loc))
186 {
187 BMCWEB_LOG_ERROR << loc << "Not found";
188 res.result(boost::beast::http::status::not_found);
189 res.jsonValue["Description"] = resourceNotFoundMsg;
190 return;
191 }
192
193 std::ifstream readfile(loc.string());
194 if (!readfile)
195 {
196 BMCWEB_LOG_ERROR << loc.string() << "Not found";
197 res.result(boost::beast::http::status::not_found);
198 res.jsonValue["Description"] = resourceNotFoundMsg;
199 return;
200 }
201
202 std::string contentDispositionParam =
203 "attachment; filename=\"" + fileID + "\"";
204 res.addHeader("Content-Disposition", contentDispositionParam);
205 std::string fileData;
206 fileData = {std::istreambuf_iterator<char>(readfile),
207 std::istreambuf_iterator<char>()};
208 res.jsonValue["Data"] = fileData;
209 return;
210}
211
212void handleFileDelete(crow::Response &res, const std::string &fileID)
213{
214 std::string filePath("/var/lib/obmc/bmc-console-mgmt/save-area/" + fileID);
215 BMCWEB_LOG_DEBUG << "Removing the file : " << filePath << "\n";
216
217 std::ifstream file_open(filePath.c_str());
218 if (static_cast<bool>(file_open))
219 if (remove(filePath.c_str()) == 0)
220 {
221 BMCWEB_LOG_DEBUG << "File removed!\n";
222 res.jsonValue["Description"] = "File Deleted";
223 }
224 else
225 {
226 BMCWEB_LOG_ERROR << "File not removed!\n";
227 res.result(boost::beast::http::status::internal_server_error);
228 res.jsonValue["Description"] = internalServerError;
229 }
230 else
231 {
232 BMCWEB_LOG_ERROR << "File not found!\n";
Sunitha Harish97b0e432019-11-21 04:59:29 -0600233 res.result(boost::beast::http::status::not_found);
234 res.jsonValue["Description"] = resourceNotFoundMsg;
235 }
236 return;
237}
238
239inline void handleFileUrl(const crow::Request &req, crow::Response &res,
asmithakarun1c7b07c2019-09-09 03:42:59 -0500240 const std::string &fileID)
Sunitha Harish97b0e432019-11-21 04:59:29 -0600241{
Sunitha Harish97b0e432019-11-21 04:59:29 -0600242 if (req.method() == "PUT"_method)
243 {
asmithakarun1c7b07c2019-09-09 03:42:59 -0500244 handleFilePut(req, res, fileID);
Sunitha Harish97b0e432019-11-21 04:59:29 -0600245 res.end();
246 return;
247 }
asmithakarun1c7b07c2019-09-09 03:42:59 -0500248 if (req.method() == "GET"_method)
249 {
250 handleFileGet(res, fileID);
251 res.end();
252 return;
253 }
254 if (req.method() == "DELETE"_method)
255 {
256 handleFileDelete(res, fileID);
257 res.end();
258 return;
259 }
Sunitha Harish97b0e432019-11-21 04:59:29 -0600260}
Ratan Gupta453fed02019-12-14 09:39:47 +0530261
262template <typename... Middlewares> void requestRoutes(Crow<Middlewares...> &app)
263{
264
265 // allowed only for admin
266 BMCWEB_ROUTE(app, "/ibm/v1/")
267 .requires({"ConfigureComponents", "ConfigureManager"})
268 .methods("GET"_method)(
269 [](const crow::Request &req, crow::Response &res) {
270 res.jsonValue["@odata.type"] =
271 "#ibmServiceRoot.v1_0_0.ibmServiceRoot";
272 res.jsonValue["@odata.id"] = "/ibm/v1/";
273 res.jsonValue["Id"] = "IBM Rest RootService";
274 res.jsonValue["Name"] = "IBM Service Root";
275 res.jsonValue["ConfigFiles"] = {
276 {"@odata.id", "/ibm/v1/Host/ConfigFiles"}};
277 res.jsonValue["LockService"] = {
278 {"@odata.id", "/ibm/v1/HMC/LockService"}};
279 res.end();
280 });
Sunitha Harish97b0e432019-11-21 04:59:29 -0600281
Ratan Guptad3630cb2019-12-14 11:21:35 +0530282 BMCWEB_ROUTE(app, "/ibm/v1/Host/ConfigFiles")
283 .requires({"ConfigureComponents", "ConfigureManager"})
284 .methods("GET"_method)(
285 [](const crow::Request &req, crow::Response &res) {
286 handleConfigFileList(res);
287 });
288
289 BMCWEB_ROUTE(app,
290 "/ibm/v1/Host/ConfigFiles/Actions/FileCollection.DeleteAll")
291 .requires({"ConfigureComponents", "ConfigureManager"})
292 .methods("POST"_method)(
293 [](const crow::Request &req, crow::Response &res) {
294 deleteConfigFiles(res);
295 });
296
asmithakarun1c7b07c2019-09-09 03:42:59 -0500297 BMCWEB_ROUTE(app, "/ibm/v1/Host/ConfigFiles/<path>")
Sunitha Harish97b0e432019-11-21 04:59:29 -0600298 .requires({"ConfigureComponents", "ConfigureManager"})
asmithakarun1c7b07c2019-09-09 03:42:59 -0500299 .methods("PUT"_method, "GET"_method, "DELETE"_method)(
300 [](const crow::Request &req, crow::Response &res,
301 const std::string &path) { handleFileUrl(req, res, path); });
Ratan Gupta734a1c32019-12-14 11:53:48 +0530302
303 BMCWEB_ROUTE(app, "/ibm/v1/HMC/LockService")
304 .requires({"ConfigureComponents", "ConfigureManager"})
305 .methods("GET"_method)(
306 [](const crow::Request &req, crow::Response &res) {
307 getLockServiceData(res);
308 });
Ratan Gupta453fed02019-12-14 09:39:47 +0530309}
310
311} // namespace ibm_mc
312} // namespace crow