Implement Acquire Lock Function in Lock Service
- This commit implements the rest API by which any external
client(Ex: Hardware Management Console) can request for a
single/multiple locks as per the design specification mentioned
in `docs/designs/management-console/hmc-lock-management.md`
Tested By:
1. curl -k -H "X-Auth-Token:$bmc_tokens" -XPOST -H "Content-type: application/json" -d '{
"Request" :[
{
"LockType":"Read",
"SegmentFlags":
[
{"LockFlag":"LockSame","SegmentLength":3},
{"LockFlag":"DontLock","SegmentLength":4}
],
"ResourceID": 256
}
]
}' https://<ip>/ibm/v1/HMC/LockService/Actions/LockService.AcquireLock
2.curl -k -H "X-Auth-Token:$bmc_tokens" -XPOST -H "Content-type: application/json" -d '{
"Request" :[
{
"LockType":"Read",
"SegmentFlags":
[
{"LockFlag":"LockAll","SegmentLength":2},
{"LockFlag":"DontLock","SegmentLength":1}
],
"ResourceID": 234
},
{
"LockType" : "Read",
"SegmentFlags":
[
{"LockFlag":"DontLock","SegmentLength":2},
{"LockFlag":"DontLock","SegmentLength":1}
],
"ResourceID": 234
}
]}' https://<ip>/ibm/v1/HMC/LockService/Actions/LockService.AcquireLock
Signed-off-by: manojkiraneda <manojkiran.eda@gmail.com>
Change-Id: Ia173878702afe7c00160b7935d6a03099b7df622
diff --git a/include/ibm/management_console_rest.hpp b/include/ibm/management_console_rest.hpp
index 225861d..a4dcf4a 100644
--- a/include/ibm/management_console_rest.hpp
+++ b/include/ibm/management_console_rest.hpp
@@ -7,10 +7,21 @@
#include <boost/container/flat_set.hpp>
#include <filesystem>
#include <fstream>
+#include <ibm/locks.hpp>
+#include <nlohmann/json.hpp>
#include <regex>
#include <sdbusplus/message/types.hpp>
+#include <utils/json_utils.hpp>
#define MAX_SAVE_AREA_FILESIZE 200000
+using SType = std::string;
+using SegmentFlags = std::vector<std::pair<std::string, uint32_t>>;
+using LockRequest = std::tuple<SType, SType, SType, uint64_t, SegmentFlags>;
+using LockRequests = std::vector<LockRequest>;
+using Rc = std::pair<bool, std::variant<uint32_t, LockRequest>>;
+using RcGetLockList = std::pair<
+ bool,
+ std::variant<std::string, std::vector<std::pair<uint32_t, LockRequests>>>>;
namespace crow
{
@@ -259,6 +270,142 @@
}
}
+void handleAcquireLockAPI(const crow::Request &req, crow::Response &res,
+ std::vector<nlohmann::json> body)
+{
+ LockRequests lockRequestStructure;
+ for (auto &element : body)
+ {
+ std::string lockType;
+ uint64_t resourceId;
+
+ SegmentFlags segInfo;
+ std::vector<nlohmann::json> segmentFlags;
+
+ if (!redfish::json_util::readJson(element, res, "LockType", lockType,
+ "ResourceID", resourceId,
+ "SegmentFlags", segmentFlags))
+ {
+ BMCWEB_LOG_DEBUG << "Not a Valid JSON";
+ res.result(boost::beast::http::status::bad_request);
+ res.end();
+ return;
+ }
+ BMCWEB_LOG_DEBUG << lockType;
+ BMCWEB_LOG_DEBUG << resourceId;
+
+ BMCWEB_LOG_DEBUG << "Segment Flags are present";
+
+ for (auto &e : segmentFlags)
+ {
+ std::string lockFlags;
+ uint32_t segmentLength;
+
+ if (!redfish::json_util::readJson(e, res, "LockFlag", lockFlags,
+ "SegmentLength", segmentLength))
+ {
+ res.result(boost::beast::http::status::bad_request);
+ res.end();
+ return;
+ }
+
+ BMCWEB_LOG_DEBUG << "Lockflag : " << lockFlags;
+ BMCWEB_LOG_DEBUG << "SegmentLength : " << segmentLength;
+
+ segInfo.push_back(std::make_pair(lockFlags, segmentLength));
+ }
+ lockRequestStructure.push_back(make_tuple(
+ req.session->uniqueId, "hmc-id", lockType, resourceId, segInfo));
+ }
+
+ // print lock request into journal
+
+ for (uint32_t i = 0; i < lockRequestStructure.size(); i++)
+ {
+ BMCWEB_LOG_DEBUG << std::get<0>(lockRequestStructure[i]);
+ BMCWEB_LOG_DEBUG << std::get<1>(lockRequestStructure[i]);
+ BMCWEB_LOG_DEBUG << std::get<2>(lockRequestStructure[i]);
+ BMCWEB_LOG_DEBUG << std::get<3>(lockRequestStructure[i]);
+
+ for (const auto &p : std::get<4>(lockRequestStructure[i]))
+ {
+ BMCWEB_LOG_DEBUG << p.first << ", " << p.second;
+ }
+ }
+
+ const LockRequests &t = lockRequestStructure;
+
+ auto varAcquireLock = crow::ibm_mc_lock::lockObject.acquireLock(t);
+
+ if (varAcquireLock.first)
+ {
+ // Either validity failure of there is a conflict with itself
+
+ auto validityStatus =
+ std::get<std::pair<bool, int>>(varAcquireLock.second);
+
+ if ((!validityStatus.first) && (validityStatus.second == 0))
+ {
+ BMCWEB_LOG_DEBUG << "Not a Valid record";
+ BMCWEB_LOG_DEBUG << "Bad json in request";
+ res.result(boost::beast::http::status::bad_request);
+ res.end();
+ return;
+ }
+ if (validityStatus.first && (validityStatus.second == 1))
+ {
+ BMCWEB_LOG_DEBUG << "There is a conflict within itself";
+ res.result(boost::beast::http::status::bad_request);
+ res.end();
+ return;
+ }
+ }
+ else
+ {
+ auto conflictStatus =
+ std::get<crow::ibm_mc_lock::Rc>(varAcquireLock.second);
+ if (!conflictStatus.first)
+ {
+ BMCWEB_LOG_DEBUG << "There is no conflict with the locktable";
+ res.result(boost::beast::http::status::ok);
+
+ auto var = std::get<uint32_t>(conflictStatus.second);
+ nlohmann::json returnJson;
+ returnJson["id"] = var;
+ res.jsonValue["TransactionID"] = var;
+ res.end();
+ return;
+ }
+ else
+ {
+ BMCWEB_LOG_DEBUG << "There is a conflict with the lock table";
+ res.result(boost::beast::http::status::conflict);
+ auto var = std::get<std::pair<uint32_t, LockRequest>>(
+ conflictStatus.second);
+ nlohmann::json returnJson, segments;
+ nlohmann::json myarray = nlohmann::json::array();
+ returnJson["TransactionID"] = var.first;
+ returnJson["SessionID"] = std::get<0>(var.second);
+ returnJson["HMCID"] = std::get<1>(var.second);
+ returnJson["LockType"] = std::get<2>(var.second);
+ returnJson["ResourceID"] = std::get<3>(var.second);
+
+ for (uint32_t i = 0; i < std::get<4>(var.second).size(); i++)
+ {
+ segments["LockFlag"] = std::get<4>(var.second)[i].first;
+ segments["SegmentLength"] = std::get<4>(var.second)[i].second;
+ myarray.push_back(segments);
+ }
+
+ returnJson["SegmentFlags"] = myarray;
+
+ res.jsonValue["Record"] = returnJson;
+ res.end();
+ return;
+ }
+ }
+}
+
template <typename... Middlewares> void requestRoutes(Crow<Middlewares...> &app)
{
@@ -306,6 +453,22 @@
[](const crow::Request &req, crow::Response &res) {
getLockServiceData(res);
});
+
+ BMCWEB_ROUTE(app, "/ibm/v1/HMC/LockService/Actions/LockService.AcquireLock")
+ .requires({"ConfigureComponents", "ConfigureManager"})
+ .methods("POST"_method)(
+ [](const crow::Request &req, crow::Response &res) {
+ std::vector<nlohmann::json> body;
+
+ if (!redfish::json_util::readJson(req, res, "Request", body))
+ {
+ BMCWEB_LOG_DEBUG << "Not a Valid JSON";
+ res.result(boost::beast::http::status::bad_request);
+ res.end();
+ return;
+ }
+ handleAcquireLockAPI(req, res, body);
+ });
}
} // namespace ibm_mc