blob: 0ce0d5bacbf9e078ef5ee3254004755ba07ee8f4 [file] [log] [blame]
Ratan Gupta453fed02019-12-14 09:39:47 +05301#pragma once
Ratan Gupta453fed02019-12-14 09:39:47 +05302#include <tinyxml2.h>
3
Ed Tanous04e438c2020-10-03 08:06:26 -07004#include <app.hpp>
Ratan Gupta453fed02019-12-14 09:39:47 +05305#include <async_resp.hpp>
Sunitha Harish97b0e432019-11-21 04:59:29 -06006#include <boost/algorithm/string.hpp>
7#include <boost/container/flat_set.hpp>
Manojkiran Eda5bb0ece2020-01-20 20:22:36 +05308#include <error_messages.hpp>
Sunitha Harish96330b92020-06-26 05:42:14 -05009#include <event_service_manager.hpp>
manojkiraneda0b631ae2019-12-03 17:54:28 +053010#include <ibm/locks.hpp>
11#include <nlohmann/json.hpp>
Sunitha Harish96330b92020-06-26 05:42:14 -050012#include <resource_messages.hpp>
Sunitha Harish97b0e432019-11-21 04:59:29 -060013#include <sdbusplus/message/types.hpp>
manojkiraneda0b631ae2019-12-03 17:54:28 +053014#include <utils/json_utils.hpp>
Sunitha Harish97b0e432019-11-21 04:59:29 -060015
Gunnar Mills1214b7e2020-06-04 10:11:30 -050016#include <filesystem>
17#include <fstream>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050018
manojkiraneda0b631ae2019-12-03 17:54:28 +053019using SType = std::string;
20using SegmentFlags = std::vector<std::pair<std::string, uint32_t>>;
21using LockRequest = std::tuple<SType, SType, SType, uint64_t, SegmentFlags>;
22using LockRequests = std::vector<LockRequest>;
23using Rc = std::pair<bool, std::variant<uint32_t, LockRequest>>;
manojkiraneda402b5712019-12-13 17:07:09 +053024using RcGetLockList =
25 std::variant<std::string, std::vector<std::pair<uint32_t, LockRequests>>>;
26using ListOfSessionIds = std::vector<std::string>;
Ratan Gupta453fed02019-12-14 09:39:47 +053027namespace crow
28{
29namespace ibm_mc
30{
Gunnar Mills1214b7e2020-06-04 10:11:30 -050031constexpr const char* methodNotAllowedMsg = "Method Not Allowed";
32constexpr const char* resourceNotFoundMsg = "Resource Not Found";
33constexpr const char* contentNotAcceptableMsg = "Content Not Acceptable";
34constexpr const char* internalServerError = "Internal Server Error";
Sunitha Harish97b0e432019-11-21 04:59:29 -060035
Sunitha Harish7c0bbe72020-07-30 08:25:28 -050036constexpr size_t maxSaveareaDirSize =
37 10000000; // Allow save area dir size to be max 10MB
38constexpr size_t minSaveareaFileSize =
39 100; // Allow save area file size of minimum 100B
Asmitha Karunanithi5738de52020-07-17 02:03:31 -050040constexpr size_t maxSaveareaFileSize =
41 500000; // Allow save area file size upto 500KB
42constexpr size_t maxBroadcastMsgSize =
43 1000; // Allow Broadcast message size upto 1KB
44
Ed Tanous02379d32020-09-15 21:15:44 -070045inline bool createSaveAreaPath(crow::Response& res)
Sunitha Harish97b0e432019-11-21 04:59:29 -060046{
47 // The path /var/lib/obmc will be created by initrdscripts
48 // Create the directories for the save-area files, when we get
49 // first file upload request
50 std::error_code ec;
51 if (!std::filesystem::is_directory("/var/lib/obmc/bmc-console-mgmt", ec))
52 {
53 std::filesystem::create_directory("/var/lib/obmc/bmc-console-mgmt", ec);
54 }
55 if (ec)
56 {
57 res.result(boost::beast::http::status::internal_server_error);
58 res.jsonValue["Description"] = internalServerError;
59 BMCWEB_LOG_DEBUG
60 << "handleIbmPost: Failed to prepare save-area directory. ec : "
61 << ec;
62 return false;
63 }
64
65 if (!std::filesystem::is_directory(
66 "/var/lib/obmc/bmc-console-mgmt/save-area", ec))
67 {
68 std::filesystem::create_directory(
69 "/var/lib/obmc/bmc-console-mgmt/save-area", ec);
70 }
71 if (ec)
72 {
73 res.result(boost::beast::http::status::internal_server_error);
74 res.jsonValue["Description"] = internalServerError;
75 BMCWEB_LOG_DEBUG
76 << "handleIbmPost: Failed to prepare save-area directory. ec : "
77 << ec;
78 return false;
79 }
80 return true;
81}
Ed Tanous02379d32020-09-15 21:15:44 -070082
83inline void handleFilePut(const crow::Request& req, crow::Response& res,
84 const std::string& fileID)
Sunitha Harish97b0e432019-11-21 04:59:29 -060085{
Sunitha Harish7c0bbe72020-07-30 08:25:28 -050086 std::error_code ec;
Sunitha Harish97b0e432019-11-21 04:59:29 -060087 // Check the content-type of the request
88 std::string_view contentType = req.getHeaderValue("content-type");
89 if (boost::starts_with(contentType, "multipart/form-data"))
90 {
91 BMCWEB_LOG_DEBUG
92 << "This is multipart/form-data. Invalid content for PUT";
93
94 res.result(boost::beast::http::status::not_acceptable);
95 res.jsonValue["Description"] = contentNotAcceptableMsg;
96 return;
97 }
Ed Tanous3174e4d2020-10-07 11:41:22 -070098 BMCWEB_LOG_DEBUG << "Not a multipart/form-data. Continue..";
asmithakarun1c7b07c2019-09-09 03:42:59 -050099
100 BMCWEB_LOG_DEBUG
101 << "handleIbmPut: Request to create/update the save-area file";
102 if (!createSaveAreaPath(res))
Sunitha Harish97b0e432019-11-21 04:59:29 -0600103 {
asmithakarun1c7b07c2019-09-09 03:42:59 -0500104 res.result(boost::beast::http::status::not_found);
105 res.jsonValue["Description"] = resourceNotFoundMsg;
106 return;
107 }
Sunitha Harish7c0bbe72020-07-30 08:25:28 -0500108
asmithakarun1c7b07c2019-09-09 03:42:59 -0500109 std::ofstream file;
110 std::filesystem::path loc("/var/lib/obmc/bmc-console-mgmt/save-area");
Sunitha Harish97b0e432019-11-21 04:59:29 -0600111
Sunitha Harish7c0bbe72020-07-30 08:25:28 -0500112 // Get the current size of the savearea directory
113 std::filesystem::recursive_directory_iterator iter(loc, ec);
114 if (ec)
115 {
116 res.result(boost::beast::http::status::internal_server_error);
117 res.jsonValue["Description"] = internalServerError;
118 BMCWEB_LOG_DEBUG << "handleIbmPut: Failed to prepare save-area "
119 "directory iterator. ec : "
120 << ec;
121 return;
122 }
123 std::uintmax_t saveAreaDirSize = 0;
124 for (auto& it : iter)
125 {
126 if (!std::filesystem::is_directory(it, ec))
127 {
128 if (ec)
129 {
130 res.result(boost::beast::http::status::internal_server_error);
131 res.jsonValue["Description"] = internalServerError;
132 BMCWEB_LOG_DEBUG << "handleIbmPut: Failed to find save-area "
133 "directory . ec : "
134 << ec;
135 return;
136 }
137 std::uintmax_t fileSize = std::filesystem::file_size(it, ec);
138 if (ec)
139 {
140 res.result(boost::beast::http::status::internal_server_error);
141 res.jsonValue["Description"] = internalServerError;
142 BMCWEB_LOG_DEBUG << "handleIbmPut: Failed to find save-area "
143 "file size inside the directory . ec : "
144 << ec;
145 return;
146 }
147 saveAreaDirSize += fileSize;
148 }
149 }
150 BMCWEB_LOG_DEBUG << "saveAreaDirSize: " << saveAreaDirSize;
151
152 // Get the file size getting uploaded
Ed Tanous3174e4d2020-10-07 11:41:22 -0700153 const std::string& data = req.body;
Sunitha Harish7c0bbe72020-07-30 08:25:28 -0500154 BMCWEB_LOG_DEBUG << "data length: " << data.length();
155
156 if (data.length() < minSaveareaFileSize)
157 {
158 res.result(boost::beast::http::status::bad_request);
159 res.jsonValue["Description"] =
160 "File size is less than minimum allowed size[100B]";
161 return;
162 }
163 if (data.length() > maxSaveareaFileSize)
asmithakarun1c7b07c2019-09-09 03:42:59 -0500164 {
165 res.result(boost::beast::http::status::bad_request);
166 res.jsonValue["Description"] =
Ratan Guptae46946a2020-05-11 13:22:59 +0530167 "File size exceeds maximum allowed size[500KB]";
asmithakarun1c7b07c2019-09-09 03:42:59 -0500168 return;
169 }
Sunitha Harish7c0bbe72020-07-30 08:25:28 -0500170
171 // Form the file path
172 loc /= fileID;
Asmitha Karunanithi10693fa2020-07-27 02:27:49 -0500173 BMCWEB_LOG_DEBUG << "Writing to the file: " << loc;
174
Sunitha Harish7c0bbe72020-07-30 08:25:28 -0500175 // Check if the same file exists in the directory
176 bool fileExists = std::filesystem::exists(loc, ec);
177 if (ec)
Asmitha Karunanithi10693fa2020-07-27 02:27:49 -0500178 {
Sunitha Harish7c0bbe72020-07-30 08:25:28 -0500179 res.result(boost::beast::http::status::internal_server_error);
180 res.jsonValue["Description"] = internalServerError;
181 BMCWEB_LOG_DEBUG << "handleIbmPut: Failed to find if file exists. ec : "
182 << ec;
183 return;
Asmitha Karunanithi10693fa2020-07-27 02:27:49 -0500184 }
Sunitha Harish7c0bbe72020-07-30 08:25:28 -0500185
186 std::uintmax_t newSizeToWrite = 0;
187 if (fileExists)
188 {
189 // File exists. Get the current file size
190 std::uintmax_t currentFileSize = std::filesystem::file_size(loc, ec);
191 if (ec)
192 {
193 res.result(boost::beast::http::status::internal_server_error);
194 res.jsonValue["Description"] = internalServerError;
195 BMCWEB_LOG_DEBUG << "handleIbmPut: Failed to find file size. ec : "
196 << ec;
197 return;
198 }
199 // Calculate the difference in the file size.
200 // If the data.length is greater than the existing file size, then
201 // calculate the difference. Else consider the delta size as zero -
202 // because there is no increase in the total directory size.
203 // We need to add the diff only if the incoming data is larger than the
204 // existing filesize
205 if (data.length() > currentFileSize)
206 {
207 newSizeToWrite = data.length() - currentFileSize;
208 }
209 BMCWEB_LOG_DEBUG << "newSizeToWrite: " << newSizeToWrite;
210 }
211 else
212 {
213 // This is a new file upload
214 newSizeToWrite = data.length();
215 }
216
217 // Calculate the total dir size before writing the new file
218 BMCWEB_LOG_DEBUG << "total new size: " << saveAreaDirSize + newSizeToWrite;
219
220 if ((saveAreaDirSize + newSizeToWrite) > maxSaveareaDirSize)
221 {
222 res.result(boost::beast::http::status::bad_request);
223 res.jsonValue["Description"] = "File size does not fit in the savearea "
224 "directory maximum allowed size[10MB]";
225 return;
226 }
227
asmithakarun1c7b07c2019-09-09 03:42:59 -0500228 file.open(loc, std::ofstream::out);
229 if (file.fail())
230 {
231 BMCWEB_LOG_DEBUG << "Error while opening the file for writing";
232 res.result(boost::beast::http::status::internal_server_error);
233 res.jsonValue["Description"] = "Error while creating the file";
234 return;
Sunitha Harish97b0e432019-11-21 04:59:29 -0600235 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700236 file << data;
237 std::string origin = "/ibm/v1/Host/ConfigFiles/" + fileID;
238 // Push an event
239 if (fileExists)
240 {
241 BMCWEB_LOG_DEBUG << "config file is updated";
242 res.jsonValue["Description"] = "File Updated";
243
244 redfish::EventServiceManager::getInstance().sendEvent(
245 redfish::messages::resourceChanged(), origin, "IBMConfigFile");
246 }
Sunitha Harish97b0e432019-11-21 04:59:29 -0600247 else
248 {
Ed Tanous3174e4d2020-10-07 11:41:22 -0700249 BMCWEB_LOG_DEBUG << "config file is created";
250 res.jsonValue["Description"] = "File Created";
Asmitha Karunanithi10693fa2020-07-27 02:27:49 -0500251
Ed Tanous3174e4d2020-10-07 11:41:22 -0700252 redfish::EventServiceManager::getInstance().sendEvent(
253 redfish::messages::resourceCreated(), origin, "IBMConfigFile");
asmithakarun1c7b07c2019-09-09 03:42:59 -0500254 }
Ratan Guptad3630cb2019-12-14 11:21:35 +0530255}
asmithakarun1c7b07c2019-09-09 03:42:59 -0500256
Ed Tanous02379d32020-09-15 21:15:44 -0700257inline void handleConfigFileList(crow::Response& res)
Ratan Guptad3630cb2019-12-14 11:21:35 +0530258{
259 std::vector<std::string> pathObjList;
260 std::filesystem::path loc("/var/lib/obmc/bmc-console-mgmt/save-area");
261 if (std::filesystem::exists(loc) && std::filesystem::is_directory(loc))
262 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500263 for (const auto& file : std::filesystem::directory_iterator(loc))
Ratan Guptad3630cb2019-12-14 11:21:35 +0530264 {
Ed Tanous3174e4d2020-10-07 11:41:22 -0700265 const std::filesystem::path& pathObj = file.path();
Ratan Guptad3630cb2019-12-14 11:21:35 +0530266 pathObjList.push_back("/ibm/v1/Host/ConfigFiles/" +
267 pathObj.filename().string());
268 }
269 }
Sunitha Harishe56f2542020-07-22 02:38:59 -0500270 res.jsonValue["@odata.type"] = "#IBMConfigFile.v1_0_0.IBMConfigFile";
Ratan Guptad3630cb2019-12-14 11:21:35 +0530271 res.jsonValue["@odata.id"] = "/ibm/v1/Host/ConfigFiles/";
272 res.jsonValue["Id"] = "ConfigFiles";
273 res.jsonValue["Name"] = "ConfigFiles";
274
275 res.jsonValue["Members"] = std::move(pathObjList);
Sunitha Harishe56f2542020-07-22 02:38:59 -0500276 res.jsonValue["Actions"]["#IBMConfigFiles.DeleteAll"] = {
Ratan Guptad3630cb2019-12-14 11:21:35 +0530277 {"target",
Sunitha Harishe56f2542020-07-22 02:38:59 -0500278 "/ibm/v1/Host/ConfigFiles/Actions/IBMConfigFiles.DeleteAll"}};
Ratan Guptad3630cb2019-12-14 11:21:35 +0530279 res.end();
280}
281
Ed Tanous02379d32020-09-15 21:15:44 -0700282inline void deleteConfigFiles(crow::Response& res)
Ratan Guptad3630cb2019-12-14 11:21:35 +0530283{
284 std::vector<std::string> pathObjList;
285 std::error_code ec;
286 std::filesystem::path loc("/var/lib/obmc/bmc-console-mgmt/save-area");
287 if (std::filesystem::exists(loc) && std::filesystem::is_directory(loc))
288 {
289 std::filesystem::remove_all(loc, ec);
290 if (ec)
291 {
292 res.result(boost::beast::http::status::internal_server_error);
293 res.jsonValue["Description"] = internalServerError;
294 BMCWEB_LOG_DEBUG << "deleteConfigFiles: Failed to delete the "
295 "config files directory. ec : "
296 << ec;
297 }
298 }
299 res.end();
asmithakarun1c7b07c2019-09-09 03:42:59 -0500300}
301
Ed Tanous02379d32020-09-15 21:15:44 -0700302inline void getLockServiceData(crow::Response& res)
Ratan Gupta734a1c32019-12-14 11:53:48 +0530303{
304 res.jsonValue["@odata.type"] = "#LockService.v1_0_0.LockService";
305 res.jsonValue["@odata.id"] = "/ibm/v1/HMC/LockService/";
306 res.jsonValue["Id"] = "LockService";
307 res.jsonValue["Name"] = "LockService";
308
309 res.jsonValue["Actions"]["#LockService.AcquireLock"] = {
310 {"target", "/ibm/v1/HMC/LockService/Actions/LockService.AcquireLock"}};
311 res.jsonValue["Actions"]["#LockService.ReleaseLock"] = {
312 {"target", "/ibm/v1/HMC/LockService/Actions/LockService.ReleaseLock"}};
313 res.jsonValue["Actions"]["#LockService.GetLockList"] = {
314 {"target", "/ibm/v1/HMC/LockService/Actions/LockService.GetLockList"}};
315 res.end();
316}
317
Ed Tanous02379d32020-09-15 21:15:44 -0700318inline void handleFileGet(crow::Response& res, const std::string& fileID)
asmithakarun1c7b07c2019-09-09 03:42:59 -0500319{
320 BMCWEB_LOG_DEBUG << "HandleGet on SaveArea files on path: " << fileID;
321 std::filesystem::path loc("/var/lib/obmc/bmc-console-mgmt/save-area/" +
322 fileID);
323 if (!std::filesystem::exists(loc))
324 {
325 BMCWEB_LOG_ERROR << loc << "Not found";
326 res.result(boost::beast::http::status::not_found);
327 res.jsonValue["Description"] = resourceNotFoundMsg;
328 return;
329 }
330
331 std::ifstream readfile(loc.string());
332 if (!readfile)
333 {
334 BMCWEB_LOG_ERROR << loc.string() << "Not found";
335 res.result(boost::beast::http::status::not_found);
336 res.jsonValue["Description"] = resourceNotFoundMsg;
337 return;
338 }
339
340 std::string contentDispositionParam =
341 "attachment; filename=\"" + fileID + "\"";
342 res.addHeader("Content-Disposition", contentDispositionParam);
343 std::string fileData;
344 fileData = {std::istreambuf_iterator<char>(readfile),
345 std::istreambuf_iterator<char>()};
346 res.jsonValue["Data"] = fileData;
347 return;
348}
349
Ed Tanous02379d32020-09-15 21:15:44 -0700350inline void handleFileDelete(crow::Response& res, const std::string& fileID)
asmithakarun1c7b07c2019-09-09 03:42:59 -0500351{
352 std::string filePath("/var/lib/obmc/bmc-console-mgmt/save-area/" + fileID);
353 BMCWEB_LOG_DEBUG << "Removing the file : " << filePath << "\n";
354
Ed Tanous2c70f802020-09-28 14:29:23 -0700355 std::ifstream fileOpen(filePath.c_str());
356 if (static_cast<bool>(fileOpen))
Ed Tanous3174e4d2020-10-07 11:41:22 -0700357 {
asmithakarun1c7b07c2019-09-09 03:42:59 -0500358 if (remove(filePath.c_str()) == 0)
359 {
360 BMCWEB_LOG_DEBUG << "File removed!\n";
361 res.jsonValue["Description"] = "File Deleted";
362 }
363 else
364 {
365 BMCWEB_LOG_ERROR << "File not removed!\n";
366 res.result(boost::beast::http::status::internal_server_error);
367 res.jsonValue["Description"] = internalServerError;
368 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700369 }
asmithakarun1c7b07c2019-09-09 03:42:59 -0500370 else
371 {
372 BMCWEB_LOG_ERROR << "File not found!\n";
Sunitha Harish97b0e432019-11-21 04:59:29 -0600373 res.result(boost::beast::http::status::not_found);
374 res.jsonValue["Description"] = resourceNotFoundMsg;
375 }
376 return;
377}
378
Asmitha Karunanithi5738de52020-07-17 02:03:31 -0500379inline void handleBroadcastService(const crow::Request& req,
380 crow::Response& res)
381{
382 std::string broadcastMsg;
383
384 if (!redfish::json_util::readJson(req, res, "Message", broadcastMsg))
385 {
386 BMCWEB_LOG_DEBUG << "Not a Valid JSON";
387 res.result(boost::beast::http::status::bad_request);
388 return;
389 }
390 if (broadcastMsg.size() > maxBroadcastMsgSize)
391 {
392 BMCWEB_LOG_ERROR << "Message size exceeds maximum allowed size[1KB]";
393 res.result(boost::beast::http::status::bad_request);
394 return;
395 }
396 redfish::EventServiceManager::getInstance().sendBroadcastMsg(broadcastMsg);
397 res.end();
398 return;
399}
400
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500401inline void handleFileUrl(const crow::Request& req, crow::Response& res,
402 const std::string& fileID)
Sunitha Harish97b0e432019-11-21 04:59:29 -0600403{
Ed Tanousb41187f2019-10-24 16:30:02 -0700404 if (req.method() == boost::beast::http::verb::put)
Sunitha Harish97b0e432019-11-21 04:59:29 -0600405 {
asmithakarun1c7b07c2019-09-09 03:42:59 -0500406 handleFilePut(req, res, fileID);
Sunitha Harish97b0e432019-11-21 04:59:29 -0600407 res.end();
408 return;
409 }
Ed Tanousb41187f2019-10-24 16:30:02 -0700410 if (req.method() == boost::beast::http::verb::get)
asmithakarun1c7b07c2019-09-09 03:42:59 -0500411 {
412 handleFileGet(res, fileID);
413 res.end();
414 return;
415 }
Ed Tanousb41187f2019-10-24 16:30:02 -0700416 if (req.method() == boost::beast::http::verb::delete_)
asmithakarun1c7b07c2019-09-09 03:42:59 -0500417 {
418 handleFileDelete(res, fileID);
419 res.end();
420 return;
421 }
Sunitha Harish97b0e432019-11-21 04:59:29 -0600422}
Ratan Gupta453fed02019-12-14 09:39:47 +0530423
Ed Tanous02379d32020-09-15 21:15:44 -0700424inline void handleAcquireLockAPI(const crow::Request& req, crow::Response& res,
425 std::vector<nlohmann::json> body)
manojkiraneda0b631ae2019-12-03 17:54:28 +0530426{
427 LockRequests lockRequestStructure;
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500428 for (auto& element : body)
manojkiraneda0b631ae2019-12-03 17:54:28 +0530429 {
430 std::string lockType;
431 uint64_t resourceId;
432
433 SegmentFlags segInfo;
434 std::vector<nlohmann::json> segmentFlags;
435
436 if (!redfish::json_util::readJson(element, res, "LockType", lockType,
437 "ResourceID", resourceId,
438 "SegmentFlags", segmentFlags))
439 {
440 BMCWEB_LOG_DEBUG << "Not a Valid JSON";
441 res.result(boost::beast::http::status::bad_request);
442 res.end();
443 return;
444 }
445 BMCWEB_LOG_DEBUG << lockType;
446 BMCWEB_LOG_DEBUG << resourceId;
447
448 BMCWEB_LOG_DEBUG << "Segment Flags are present";
449
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500450 for (auto& e : segmentFlags)
manojkiraneda0b631ae2019-12-03 17:54:28 +0530451 {
452 std::string lockFlags;
453 uint32_t segmentLength;
454
455 if (!redfish::json_util::readJson(e, res, "LockFlag", lockFlags,
456 "SegmentLength", segmentLength))
457 {
458 res.result(boost::beast::http::status::bad_request);
459 res.end();
460 return;
461 }
462
463 BMCWEB_LOG_DEBUG << "Lockflag : " << lockFlags;
464 BMCWEB_LOG_DEBUG << "SegmentLength : " << segmentLength;
465
466 segInfo.push_back(std::make_pair(lockFlags, segmentLength));
467 }
Manojkiran Eda566329e2020-05-22 12:36:17 +0530468 lockRequestStructure.push_back(
469 make_tuple(req.session->uniqueId, req.session->clientId, lockType,
470 resourceId, segInfo));
manojkiraneda0b631ae2019-12-03 17:54:28 +0530471 }
472
473 // print lock request into journal
474
Ed Tanous4e087512020-09-28 18:41:25 -0700475 for (auto& i : lockRequestStructure)
manojkiraneda0b631ae2019-12-03 17:54:28 +0530476 {
Ed Tanous4e087512020-09-28 18:41:25 -0700477 BMCWEB_LOG_DEBUG << std::get<0>(i);
478 BMCWEB_LOG_DEBUG << std::get<1>(i);
479 BMCWEB_LOG_DEBUG << std::get<2>(i);
480 BMCWEB_LOG_DEBUG << std::get<3>(i);
manojkiraneda0b631ae2019-12-03 17:54:28 +0530481
Ed Tanous4e087512020-09-28 18:41:25 -0700482 for (const auto& p : std::get<4>(i))
manojkiraneda0b631ae2019-12-03 17:54:28 +0530483 {
484 BMCWEB_LOG_DEBUG << p.first << ", " << p.second;
485 }
486 }
487
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500488 const LockRequests& t = lockRequestStructure;
manojkiraneda0b631ae2019-12-03 17:54:28 +0530489
Ratan Gupta07386c62019-12-14 14:06:09 +0530490 auto varAcquireLock = crow::ibm_mc_lock::Lock::getInstance().acquireLock(t);
manojkiraneda0b631ae2019-12-03 17:54:28 +0530491
492 if (varAcquireLock.first)
493 {
494 // Either validity failure of there is a conflict with itself
495
496 auto validityStatus =
497 std::get<std::pair<bool, int>>(varAcquireLock.second);
498
499 if ((!validityStatus.first) && (validityStatus.second == 0))
500 {
501 BMCWEB_LOG_DEBUG << "Not a Valid record";
502 BMCWEB_LOG_DEBUG << "Bad json in request";
503 res.result(boost::beast::http::status::bad_request);
504 res.end();
505 return;
506 }
507 if (validityStatus.first && (validityStatus.second == 1))
508 {
509 BMCWEB_LOG_DEBUG << "There is a conflict within itself";
510 res.result(boost::beast::http::status::bad_request);
511 res.end();
512 return;
513 }
514 }
515 else
516 {
517 auto conflictStatus =
518 std::get<crow::ibm_mc_lock::Rc>(varAcquireLock.second);
519 if (!conflictStatus.first)
520 {
521 BMCWEB_LOG_DEBUG << "There is no conflict with the locktable";
522 res.result(boost::beast::http::status::ok);
523
524 auto var = std::get<uint32_t>(conflictStatus.second);
525 nlohmann::json returnJson;
526 returnJson["id"] = var;
527 res.jsonValue["TransactionID"] = var;
528 res.end();
529 return;
530 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700531 BMCWEB_LOG_DEBUG << "There is a conflict with the lock table";
532 res.result(boost::beast::http::status::conflict);
533 auto var =
534 std::get<std::pair<uint32_t, LockRequest>>(conflictStatus.second);
535 nlohmann::json returnJson, segments;
536 nlohmann::json myarray = nlohmann::json::array();
537 returnJson["TransactionID"] = var.first;
538 returnJson["SessionID"] = std::get<0>(var.second);
539 returnJson["HMCID"] = std::get<1>(var.second);
540 returnJson["LockType"] = std::get<2>(var.second);
541 returnJson["ResourceID"] = std::get<3>(var.second);
542
543 for (auto& i : std::get<4>(var.second))
manojkiraneda0b631ae2019-12-03 17:54:28 +0530544 {
Ed Tanous3174e4d2020-10-07 11:41:22 -0700545 segments["LockFlag"] = i.first;
546 segments["SegmentLength"] = i.second;
547 myarray.push_back(segments);
manojkiraneda0b631ae2019-12-03 17:54:28 +0530548 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700549
550 returnJson["SegmentFlags"] = myarray;
551
552 res.jsonValue["Record"] = returnJson;
553 res.end();
554 return;
manojkiraneda0b631ae2019-12-03 17:54:28 +0530555 }
556}
Ed Tanous02379d32020-09-15 21:15:44 -0700557inline void handleRelaseAllAPI(const crow::Request& req, crow::Response& res)
Manojkiran Eda5bb0ece2020-01-20 20:22:36 +0530558{
559 crow::ibm_mc_lock::Lock::getInstance().releaseLock(req.session->uniqueId);
560 res.result(boost::beast::http::status::ok);
561 res.end();
562 return;
563}
manojkiraneda0b631ae2019-12-03 17:54:28 +0530564
Ed Tanous02379d32020-09-15 21:15:44 -0700565inline void
566 handleReleaseLockAPI(const crow::Request& req, crow::Response& res,
567 const std::vector<uint32_t>& listTransactionIds)
manojkiraneda3b6dea62019-12-13 17:05:36 +0530568{
569 BMCWEB_LOG_DEBUG << listTransactionIds.size();
570 BMCWEB_LOG_DEBUG << "Data is present";
Ed Tanous4e087512020-09-28 18:41:25 -0700571 for (unsigned int listTransactionId : listTransactionIds)
manojkiraneda3b6dea62019-12-13 17:05:36 +0530572 {
Ed Tanous4e087512020-09-28 18:41:25 -0700573 BMCWEB_LOG_DEBUG << listTransactionId;
manojkiraneda3b6dea62019-12-13 17:05:36 +0530574 }
575
manojkiraneda3b6dea62019-12-13 17:05:36 +0530576 // validate the request ids
577
Ratan Gupta07386c62019-12-14 14:06:09 +0530578 auto varReleaselock = crow::ibm_mc_lock::Lock::getInstance().releaseLock(
Manojkiran Eda566329e2020-05-22 12:36:17 +0530579 listTransactionIds,
580 std::make_pair(req.session->clientId, req.session->uniqueId));
manojkiraneda3b6dea62019-12-13 17:05:36 +0530581
582 if (!varReleaselock.first)
583 {
584 // validation Failed
585 res.result(boost::beast::http::status::bad_request);
586 res.end();
587 return;
588 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700589 auto statusRelease =
590 std::get<crow::ibm_mc_lock::RcRelaseLock>(varReleaselock.second);
591 if (statusRelease.first)
manojkiraneda3b6dea62019-12-13 17:05:36 +0530592 {
Ed Tanous3174e4d2020-10-07 11:41:22 -0700593 // The current hmc owns all the locks, so we already released
594 // them
595 res.result(boost::beast::http::status::ok);
596 res.end();
597 return;
manojkiraneda3b6dea62019-12-13 17:05:36 +0530598 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700599
600 // valid rid, but the current hmc does not own all the locks
601 BMCWEB_LOG_DEBUG << "Current HMC does not own all the locks";
602 res.result(boost::beast::http::status::unauthorized);
603
604 auto var = statusRelease.second;
605 nlohmann::json returnJson, segments;
606 nlohmann::json myArray = nlohmann::json::array();
607 returnJson["TransactionID"] = var.first;
608 returnJson["SessionID"] = std::get<0>(var.second);
609 returnJson["HMCID"] = std::get<1>(var.second);
610 returnJson["LockType"] = std::get<2>(var.second);
611 returnJson["ResourceID"] = std::get<3>(var.second);
612
613 for (auto& i : std::get<4>(var.second))
614 {
615 segments["LockFlag"] = i.first;
616 segments["SegmentLength"] = i.second;
617 myArray.push_back(segments);
618 }
619
620 returnJson["SegmentFlags"] = myArray;
621 res.jsonValue["Record"] = returnJson;
622 res.end();
623 return;
manojkiraneda3b6dea62019-12-13 17:05:36 +0530624}
625
Ed Tanous02379d32020-09-15 21:15:44 -0700626inline void handleGetLockListAPI(crow::Response& res,
627 const ListOfSessionIds& listSessionIds)
manojkiraneda402b5712019-12-13 17:07:09 +0530628{
629 BMCWEB_LOG_DEBUG << listSessionIds.size();
630
Ratan Gupta07386c62019-12-14 14:06:09 +0530631 auto status =
632 crow::ibm_mc_lock::Lock::getInstance().getLockList(listSessionIds);
manojkiraneda402b5712019-12-13 17:07:09 +0530633 auto var = std::get<std::vector<std::pair<uint32_t, LockRequests>>>(status);
634
635 nlohmann::json lockRecords = nlohmann::json::array();
636
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500637 for (const auto& transactionId : var)
manojkiraneda402b5712019-12-13 17:07:09 +0530638 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500639 for (const auto& lockRecord : transactionId.second)
manojkiraneda402b5712019-12-13 17:07:09 +0530640 {
641 nlohmann::json returnJson;
642
643 returnJson["TransactionID"] = transactionId.first;
644 returnJson["SessionID"] = std::get<0>(lockRecord);
645 returnJson["HMCID"] = std::get<1>(lockRecord);
646 returnJson["LockType"] = std::get<2>(lockRecord);
647 returnJson["ResourceID"] = std::get<3>(lockRecord);
648
649 nlohmann::json segments;
650 nlohmann::json segmentInfoArray = nlohmann::json::array();
651
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500652 for (const auto& segment : std::get<4>(lockRecord))
manojkiraneda402b5712019-12-13 17:07:09 +0530653 {
654 segments["LockFlag"] = segment.first;
655 segments["SegmentLength"] = segment.second;
656 segmentInfoArray.push_back(segments);
657 }
658
659 returnJson["SegmentFlags"] = segmentInfoArray;
660 lockRecords.push_back(returnJson);
661 }
662 }
663 res.result(boost::beast::http::status::ok);
664 res.jsonValue["Records"] = lockRecords;
665 res.end();
666}
667
Sunitha Harish7c0bbe72020-07-30 08:25:28 -0500668inline bool isValidConfigFileName(const std::string& fileName,
669 crow::Response& res)
670{
671 if (fileName.empty())
672 {
673 BMCWEB_LOG_ERROR << "Empty filename";
674 res.jsonValue["Description"] = "Empty file path in the url";
675 return false;
676 }
677
678 // ConfigFile name is allowed to take upper and lowercase letters,
679 // numbers and hyphen
680 std::size_t found = fileName.find_first_not_of(
681 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-");
682 if (found != std::string::npos)
683 {
684 BMCWEB_LOG_ERROR << "Unsupported character in filename: " << fileName;
685 res.jsonValue["Description"] = "Unsupported character in filename";
686 return false;
687 }
688
689 // Check the filename length
690 if (fileName.length() > 20)
691 {
692 BMCWEB_LOG_ERROR << "Name must be maximum 20 characters. "
693 "Input filename length is: "
694 << fileName.length();
695 res.jsonValue["Description"] = "Filename must be maximum 20 characters";
696 return false;
697 }
698
699 return true;
700}
701
Ed Tanous02379d32020-09-15 21:15:44 -0700702inline void requestRoutes(App& app)
Ratan Gupta453fed02019-12-14 09:39:47 +0530703{
704
705 // allowed only for admin
706 BMCWEB_ROUTE(app, "/ibm/v1/")
Ed Tanous23a21a12020-07-25 04:45:05 +0000707 .privileges({"ConfigureComponents", "ConfigureManager"})
Ed Tanousb41187f2019-10-24 16:30:02 -0700708 .methods(boost::beast::http::verb::get)(
Ed Tanouscb13a392020-07-25 19:02:03 +0000709 [](const crow::Request&, crow::Response& res) {
Ratan Gupta453fed02019-12-14 09:39:47 +0530710 res.jsonValue["@odata.type"] =
711 "#ibmServiceRoot.v1_0_0.ibmServiceRoot";
712 res.jsonValue["@odata.id"] = "/ibm/v1/";
713 res.jsonValue["Id"] = "IBM Rest RootService";
714 res.jsonValue["Name"] = "IBM Service Root";
715 res.jsonValue["ConfigFiles"] = {
716 {"@odata.id", "/ibm/v1/Host/ConfigFiles"}};
717 res.jsonValue["LockService"] = {
718 {"@odata.id", "/ibm/v1/HMC/LockService"}};
Asmitha Karunanithi5738de52020-07-17 02:03:31 -0500719 res.jsonValue["BroadcastService"] = {
720 {"@odata.id", "/ibm/v1/HMC/BroadcastService"}};
Ratan Gupta453fed02019-12-14 09:39:47 +0530721 res.end();
722 });
Sunitha Harish97b0e432019-11-21 04:59:29 -0600723
Ratan Guptad3630cb2019-12-14 11:21:35 +0530724 BMCWEB_ROUTE(app, "/ibm/v1/Host/ConfigFiles")
Ed Tanous23a21a12020-07-25 04:45:05 +0000725 .privileges({"ConfigureComponents", "ConfigureManager"})
Ed Tanousb41187f2019-10-24 16:30:02 -0700726 .methods(boost::beast::http::verb::get)(
Ed Tanouscb13a392020-07-25 19:02:03 +0000727 [](const crow::Request&, crow::Response& res) {
Ratan Guptad3630cb2019-12-14 11:21:35 +0530728 handleConfigFileList(res);
729 });
730
731 BMCWEB_ROUTE(app,
Sunitha Harishe56f2542020-07-22 02:38:59 -0500732 "/ibm/v1/Host/ConfigFiles/Actions/IBMConfigFiles.DeleteAll")
Ed Tanous23a21a12020-07-25 04:45:05 +0000733 .privileges({"ConfigureComponents", "ConfigureManager"})
Ed Tanousb41187f2019-10-24 16:30:02 -0700734 .methods(boost::beast::http::verb::post)(
Ed Tanouscb13a392020-07-25 19:02:03 +0000735 [](const crow::Request&, crow::Response& res) {
Ratan Guptad3630cb2019-12-14 11:21:35 +0530736 deleteConfigFiles(res);
737 });
738
Sunitha Harish7c0bbe72020-07-30 08:25:28 -0500739 BMCWEB_ROUTE(app, "/ibm/v1/Host/ConfigFiles/<str>")
Ed Tanous23a21a12020-07-25 04:45:05 +0000740 .privileges({"ConfigureComponents", "ConfigureManager"})
Sunitha Harish7c0bbe72020-07-30 08:25:28 -0500741 .methods(
742 boost::beast::http::verb::put, boost::beast::http::verb::get,
743 boost::beast::http::verb::delete_)([](const crow::Request& req,
744 crow::Response& res,
745 const std::string& fileName) {
746 std::shared_ptr<bmcweb::AsyncResp> asyncResp =
747 std::make_shared<bmcweb::AsyncResp>(res);
748 BMCWEB_LOG_DEBUG << "ConfigFile : " << fileName;
749 // Validate the incoming fileName
750 if (!isValidConfigFileName(fileName, res))
751 {
752 asyncResp->res.result(boost::beast::http::status::bad_request);
753 return;
754 }
755 handleFileUrl(req, res, fileName);
756 });
Ratan Gupta734a1c32019-12-14 11:53:48 +0530757
758 BMCWEB_ROUTE(app, "/ibm/v1/HMC/LockService")
Ed Tanous23a21a12020-07-25 04:45:05 +0000759 .privileges({"ConfigureComponents", "ConfigureManager"})
Ed Tanousb41187f2019-10-24 16:30:02 -0700760 .methods(boost::beast::http::verb::get)(
Ed Tanouscb13a392020-07-25 19:02:03 +0000761 [](const crow::Request&, crow::Response& res) {
Ratan Gupta734a1c32019-12-14 11:53:48 +0530762 getLockServiceData(res);
763 });
manojkiraneda0b631ae2019-12-03 17:54:28 +0530764
765 BMCWEB_ROUTE(app, "/ibm/v1/HMC/LockService/Actions/LockService.AcquireLock")
Ed Tanous23a21a12020-07-25 04:45:05 +0000766 .privileges({"ConfigureComponents", "ConfigureManager"})
Ed Tanousb41187f2019-10-24 16:30:02 -0700767 .methods(boost::beast::http::verb::post)(
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500768 [](const crow::Request& req, crow::Response& res) {
manojkiraneda0b631ae2019-12-03 17:54:28 +0530769 std::vector<nlohmann::json> body;
manojkiraneda0b631ae2019-12-03 17:54:28 +0530770 if (!redfish::json_util::readJson(req, res, "Request", body))
771 {
772 BMCWEB_LOG_DEBUG << "Not a Valid JSON";
773 res.result(boost::beast::http::status::bad_request);
774 res.end();
775 return;
776 }
777 handleAcquireLockAPI(req, res, body);
778 });
manojkiraneda3b6dea62019-12-13 17:05:36 +0530779 BMCWEB_ROUTE(app, "/ibm/v1/HMC/LockService/Actions/LockService.ReleaseLock")
Ed Tanous23a21a12020-07-25 04:45:05 +0000780 .privileges({"ConfigureComponents", "ConfigureManager"})
Ed Tanousb41187f2019-10-24 16:30:02 -0700781 .methods(boost::beast::http::verb::post)([](const crow::Request& req,
782 crow::Response& res) {
Manojkiran Eda5bb0ece2020-01-20 20:22:36 +0530783 std::string type;
784 std::vector<uint32_t> listTransactionIds;
manojkiraneda3b6dea62019-12-13 17:05:36 +0530785
Manojkiran Eda5bb0ece2020-01-20 20:22:36 +0530786 if (!redfish::json_util::readJson(req, res, "Type", type,
787 "TransactionIDs",
788 listTransactionIds))
789 {
790 res.result(boost::beast::http::status::bad_request);
791 res.end();
792 return;
793 }
794 if (type == "Transaction")
795 {
manojkiraneda3b6dea62019-12-13 17:05:36 +0530796 handleReleaseLockAPI(req, res, listTransactionIds);
Manojkiran Eda5bb0ece2020-01-20 20:22:36 +0530797 }
798 else if (type == "Session")
799 {
800 handleRelaseAllAPI(req, res);
801 }
802 else
803 {
804 BMCWEB_LOG_DEBUG << " Value of Type : " << type
805 << "is Not a Valid key";
806 redfish::messages::propertyValueNotInList(res, type, "Type");
807 }
808 });
manojkiraneda402b5712019-12-13 17:07:09 +0530809 BMCWEB_ROUTE(app, "/ibm/v1/HMC/LockService/Actions/LockService.GetLockList")
Ed Tanous23a21a12020-07-25 04:45:05 +0000810 .privileges({"ConfigureComponents", "ConfigureManager"})
Ed Tanousb41187f2019-10-24 16:30:02 -0700811 .methods(boost::beast::http::verb::post)(
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500812 [](const crow::Request& req, crow::Response& res) {
manojkiraneda402b5712019-12-13 17:07:09 +0530813 ListOfSessionIds listSessionIds;
814
815 if (!redfish::json_util::readJson(req, res, "SessionIDs",
816 listSessionIds))
817 {
818 res.result(boost::beast::http::status::bad_request);
819 res.end();
820 return;
821 }
Ed Tanouscb13a392020-07-25 19:02:03 +0000822 handleGetLockListAPI(res, listSessionIds);
manojkiraneda402b5712019-12-13 17:07:09 +0530823 });
Asmitha Karunanithi5738de52020-07-17 02:03:31 -0500824
825 BMCWEB_ROUTE(app, "/ibm/v1/HMC/BroadcastService")
Ed Tanous23a21a12020-07-25 04:45:05 +0000826 .privileges({"ConfigureComponents", "ConfigureManager"})
Asmitha Karunanithi5738de52020-07-17 02:03:31 -0500827 .methods(boost::beast::http::verb::post)(
828 [](const crow::Request& req, crow::Response& res) {
829 handleBroadcastService(req, res);
830 });
Ratan Gupta453fed02019-12-14 09:39:47 +0530831}
832
833} // namespace ibm_mc
834} // namespace crow