diff options
-rw-r--r-- | include/ibm/locks.hpp | 140 | ||||
-rw-r--r-- | include/ibm/management_console_rest.hpp | 85 |
2 files changed, 220 insertions, 5 deletions
diff --git a/include/ibm/locks.hpp b/include/ibm/locks.hpp index 60c55bffa4..dcd110f8dc 100644 --- a/include/ibm/locks.hpp +++ b/include/ibm/locks.hpp @@ -23,16 +23,17 @@ using SegmentFlags = std::vector<std::pair<SType, uint32_t>>; // Lockrequest = session-id | hmc-id | locktype | resourceid | segmentinfo using LockRequest = std::tuple<SType, SType, SType, uint64_t, SegmentFlags>; - using LockRequests = std::vector<LockRequest>; using Rc = std::pair<bool, std::variant<uint32_t, std::pair<uint32_t, LockRequest>>>; -using RcRelaseLock = std::pair<bool, LockRequest>; +using RcRelaseLock = std::pair<bool, std::pair<uint32_t, LockRequest>>; using RcGetLocklist = std::pair< bool, std::variant<std::string, std::vector<std::pair<uint32_t, LockRequests>>>>; - +using ListOfTransactionIds = std::vector<uint32_t>; using RcAcquireLock = std::pair<bool, std::variant<Rc, std::pair<bool, int>>>; +using RcReleaseLockApi = std::pair<bool, std::variant<bool, RcRelaseLock>>; +using SessionFlags = std::pair<SType, SType>; class Lock { @@ -78,6 +79,29 @@ class Lock */ Rc isConflictWithTable(const LockRequests); + /* + * This function implements the logic of checking the ownership of the + * lock from the releaselock request. + * + * Returns : True (if the requesting HMC & Session owns the lock(s)) + * Returns : False (if the request HMC or Session does not own the lock(s)) + */ + + RcRelaseLock isItMyLock(const ListOfTransactionIds &, const SessionFlags &); + + /* + * This function validates the the list of transactionID's and returns false + * if the transaction ID is not valid & not present in the lock table + */ + + bool validateRids(const ListOfTransactionIds &); + + /* + * This function releases the locks that are already obtained by the + * requesting Management console. + */ + + void releaseLock(const ListOfTransactionIds &); /* * This function implements the algorithm for checking the respective @@ -104,7 +128,20 @@ class Lock RcAcquireLock acquireLock(const LockRequests); - public: + /* + * This function implements the logic for releasing the lock that are + * owned by a management console session. + * + * The locks can be released by two ways + * - Using list of transaction ID's + * - Using a Session ID + * + * Client can choose either of the ways by using `Type` JSON key. + * + */ + RcReleaseLockApi releaseLock(const ListOfTransactionIds &, + const SessionFlags &); + Lock() { transactionId = 0; @@ -112,6 +149,34 @@ class Lock } lockObject; +RcReleaseLockApi Lock::releaseLock(const ListOfTransactionIds &p, + const SessionFlags &ids) +{ + + bool status = validateRids(p); + + if (!status) + { + // Validation of rids failed + BMCWEB_LOG_DEBUG << "Not a Valid request id"; + return std::make_pair(false, status); + } + else + { + // Validation passed, check if all the locks are owned by the + // requesting HMC + auto status = isItMyLock(p, ids); + if (status.first) + { + // The current hmc owns all the locks, so we can release + // them + releaseLock(p); + } + return std::make_pair(true, status); + } + return std::make_pair(false, status); +} + RcAcquireLock Lock::acquireLock(const LockRequests lockRequestStructure) { @@ -152,6 +217,72 @@ RcAcquireLock Lock::acquireLock(const LockRequests lockRequestStructure) return std::make_pair(true, std::make_pair(true, 1)); } +void Lock::releaseLock(const ListOfTransactionIds &refRids) +{ + for (const auto &id : refRids) + { + if (lockTable.erase(id)) + { + BMCWEB_LOG_DEBUG << "Removing the locks with transaction ID : " + << id; + } + + else + { + BMCWEB_LOG_DEBUG << "Removing the locks from the lock table " + "failed, tranasction ID: " + << id; + } + } +} + +RcRelaseLock Lock::isItMyLock(const ListOfTransactionIds &refRids, + const SessionFlags &ids) +{ + for (const auto &id : refRids) + { + // Just need to compare the client id of the first lock records in the + // complete lock row(in the map), because the rest of the lock records + // would have the same client id + + std::string expectedClientId = std::get<1>(lockTable[id][0]); + std::string expectedSessionId = std::get<0>(lockTable[id][0]); + + if ((expectedClientId == ids.first) && + (expectedSessionId == ids.second)) + { + // It is owned by the currently request hmc + BMCWEB_LOG_DEBUG << "Lock is owned by the current hmc"; + } + else + { + BMCWEB_LOG_DEBUG << "Lock is not owned by the current hmc"; + return std::make_pair(false, std::make_pair(id, lockTable[id][0])); + } + } + return std::make_pair(true, std::make_pair(0, LockRequest())); +} + +bool Lock::validateRids(const ListOfTransactionIds &refRids) +{ + for (const auto &id : refRids) + { + auto search = lockTable.find(id); + + if (search != lockTable.end()) + { + BMCWEB_LOG_DEBUG << "Valid Transaction id"; + // continue for the next rid + } + else + { + BMCWEB_LOG_DEBUG << "Atleast 1 inValid Request id"; + return false; + } + } + return true; +} + bool Lock::isValidLockRequest(const LockRequest refLockRecord) { @@ -217,7 +348,6 @@ bool Lock::isValidLockRequest(const LockRequest refLockRecord) } } - // validate the segment length return true; } diff --git a/include/ibm/management_console_rest.hpp b/include/ibm/management_console_rest.hpp index a4dcf4a61c..a4bf31ea72 100644 --- a/include/ibm/management_console_rest.hpp +++ b/include/ibm/management_console_rest.hpp @@ -406,6 +406,74 @@ void handleAcquireLockAPI(const crow::Request &req, crow::Response &res, } } +void handleReleaseLockAPI(const crow::Request &req, crow::Response &res, + const std::vector<uint32_t> &listTransactionIds) +{ + BMCWEB_LOG_DEBUG << listTransactionIds.size(); + BMCWEB_LOG_DEBUG << "Data is present"; + for (uint32_t i = 0; i < listTransactionIds.size(); i++) + { + BMCWEB_LOG_DEBUG << listTransactionIds[i]; + } + + std::string clientId = "hmc-id"; + std::string sessionId = req.session->uniqueId; + + // validate the request ids + + auto varReleaselock = crow::ibm_mc_lock::lockObject.releaseLock( + listTransactionIds, std::make_pair(clientId, sessionId)); + + if (!varReleaselock.first) + { + // validation Failed + res.result(boost::beast::http::status::bad_request); + res.end(); + return; + } + else + { + auto statusRelease = + std::get<crow::ibm_mc_lock::RcRelaseLock>(varReleaselock.second); + if (statusRelease.first) + { + // The current hmc owns all the locks, so we already released + // them + res.result(boost::beast::http::status::ok); + res.end(); + return; + } + + else + { + // valid rid, but the current hmc does not own all the locks + BMCWEB_LOG_DEBUG << "Current HMC does not own all the locks"; + res.result(boost::beast::http::status::unauthorized); + + auto var = statusRelease.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) { @@ -469,6 +537,23 @@ template <typename... Middlewares> void requestRoutes(Crow<Middlewares...> &app) } handleAcquireLockAPI(req, res, body); }); + + BMCWEB_ROUTE(app, "/ibm/v1/HMC/LockService/Actions/LockService.ReleaseLock") + .requires({"ConfigureComponents", "ConfigureManager"}) + .methods("POST"_method)( + [](const crow::Request &req, crow::Response &res) { + std::vector<uint32_t> listTransactionIds; + + if (!redfish::json_util::readJson(req, res, "TransactionIDs", + listTransactionIds)) + { + res.result(boost::beast::http::status::bad_request); + res.end(); + return; + } + + handleReleaseLockAPI(req, res, listTransactionIds); + }); } } // namespace ibm_mc |