summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/ibm/locks.hpp610
-rw-r--r--include/ibm/management_console_rest.hpp339
-rw-r--r--include/sessions.hpp10
-rw-r--r--meson.build1
-rw-r--r--src/webserver_run.cpp1
-rw-r--r--test/include/ibm/lock_test.cpp314
6 files changed, 1 insertions, 1274 deletions
diff --git a/include/ibm/locks.hpp b/include/ibm/locks.hpp
deleted file mode 100644
index 3bb82b9479..0000000000
--- a/include/ibm/locks.hpp
+++ /dev/null
@@ -1,610 +0,0 @@
-#pragma once
-
-#include "ibm/utils.hpp"
-#include "logging.hpp"
-
-#include <boost/container/flat_map.hpp>
-#include <boost/endian/conversion.hpp>
-#include <nlohmann/json.hpp>
-
-#include <filesystem>
-#include <fstream>
-#include <variant>
-
-namespace crow
-{
-namespace ibm_mc_lock
-{
-
-using SType = std::string;
-
-/*----------------------------------------
-|Segment flags : LockFlag | SegmentLength|
-------------------------------------------*/
-
-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, std::pair<uint32_t, LockRequest>>;
-using RcGetLockList =
- 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>;
-using ListOfSessionIds = std::vector<std::string>;
-
-class Lock
-{
- uint32_t transactionId = 0;
- boost::container::flat_map<uint32_t, LockRequests> lockTable;
-
- protected:
- /*
- * This function implements the logic for validating an incoming
- * lock request/requests.
- *
- * Returns : True (if Valid)
- * Returns : False (if not a Valid lock request)
- */
-
- virtual bool isValidLockRequest(const LockRequest& refLockRecord);
-
- /*
- * This function implements the logic of checking if the incoming
- * multi-lock request is not having conflicting requirements.
- *
- * Returns : True (if conflicting)
- * Returns : False (if not conflicting)
- */
-
- virtual bool isConflictRequest(const LockRequests& refLockRequestStructure);
- /*
- * Implements the core algorithm to find the conflicting
- * lock requests.
- *
- * This functions takes two lock requests and check if both
- * are conflicting to each other.
- *
- * Returns : True (if conflicting)
- * Returns : False (if not conflicting)
- */
- virtual bool isConflictRecord(const LockRequest& refLockRecord1,
- const LockRequest& refLockRecord2);
-
- /*
- * This function implements the logic of checking the conflicting
- * locks from a incoming single/multi lock requests with the already
- * existing lock request in the lock table.
- *
- */
-
- virtual Rc isConflictWithTable(const LockRequests& refLockRequestStructure);
- /*
- * 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))
- */
-
- virtual RcRelaseLock isItMyLock(const ListOfTransactionIds& refRids,
- const SessionFlags& ids);
-
- /*
- * 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
- */
-
- virtual bool validateRids(const ListOfTransactionIds& refRids);
-
- /*
- * This function releases the locks that are already obtained by the
- * requesting Management console.
- */
-
- void releaseLock(const ListOfTransactionIds& refRids);
-
- Lock()
- {
- transactionId = lockTable.empty() ? 0 : prev(lockTable.end())->first;
- }
-
- /*
- * This function implements the algorithm for checking the respective
- * bytes of the resource id based on the lock management algorithm.
- */
-
- static bool checkByte(uint64_t resourceId1, uint64_t resourceId2,
- uint32_t position);
-
- /*
- * This functions implements a counter that generates a unique 32 bit
- * number for every successful transaction. This number will be used by
- * the Management Console for debug.
- */
- virtual uint32_t generateTransactionId();
-
- public:
- /*
- * Explicitly deleted copy and move constructors
- */
- Lock(const Lock&) = delete;
- Lock(Lock&&) = delete;
- Lock& operator=(const Lock&) = delete;
- Lock& operator=(Lock&&) = delete;
-
- /*
- * This function implements the logic for acquiring a lock on a
- * resource if the incoming request is legitimate without any
- * conflicting requirements & without any conflicting requirement
- * with the existing locks in the lock table.
- *
- */
-
- RcAcquireLock acquireLock(const LockRequests& lockRequestStructure);
-
- /*
- * 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& p,
- const SessionFlags& ids);
-
- /*
- * This function implements the logic for getting the list of locks obtained
- * by a particular management console.
- */
- RcGetLockList getLockList(const ListOfSessionIds& listSessionId);
-
- /*
- * This function is releases all the locks obtained by a particular
- * session.
- */
-
- void releaseLock(const std::string& sessionId);
-
- static Lock& getInstance()
- {
- static Lock lockObject;
- return lockObject;
- }
-
- virtual ~Lock() = default;
-};
-
-inline RcGetLockList Lock::getLockList(const ListOfSessionIds& listSessionId)
-{
- std::vector<std::pair<uint32_t, LockRequests>> lockList{};
-
- if (!lockTable.empty())
- {
- for (const auto& i : listSessionId)
- {
- auto it = lockTable.begin();
- while (it != lockTable.end())
- {
- // Check if session id of this entry matches with session id
- // given
- if (std::get<0>(it->second[0]) == i)
- {
- BMCWEB_LOG_DEBUG("Session id is found in the locktable");
-
- // Push the whole lock record into a vector for returning
- // the json
- lockList.emplace_back(it->first, it->second);
- }
- // Go to next entry in map
- it++;
- }
- }
- }
- // we may have found at least one entry with the given session id
- // return the json list of lock records pertaining to the given
- // session id, or send an empty list if lock table is empty
- return {lockList};
-}
-
-inline RcReleaseLockApi Lock::releaseLock(const ListOfTransactionIds& p,
- const SessionFlags& ids)
-{
- bool status = validateRids(p);
-
- if (!status)
- {
- // Validation of rids failed
- BMCWEB_LOG_ERROR("releaseLock: Contains invalid request id");
- return std::make_pair(false, status);
- }
- // Validation passed, check if all the locks are owned by the
- // requesting HMC
- auto status2 = isItMyLock(p, ids);
- if (!status2.first)
- {
- return std::make_pair(false, status2);
- }
- return std::make_pair(true, status2);
-}
-
-inline RcAcquireLock Lock::acquireLock(const LockRequests& lockRequestStructure)
-{
- // validate the lock request
-
- for (const auto& lockRecord : lockRequestStructure)
- {
- bool status = isValidLockRequest(lockRecord);
- if (!status)
- {
- BMCWEB_LOG_DEBUG("Not a Valid record");
- BMCWEB_LOG_DEBUG("Bad json in request");
- return std::make_pair(true, std::make_pair(status, 0));
- }
- }
- // check for conflict record
-
- const LockRequests& multiRequest = lockRequestStructure;
- bool status = isConflictRequest(multiRequest);
-
- if (status)
- {
- BMCWEB_LOG_DEBUG("There is a conflict within itself");
- return std::make_pair(true, std::make_pair(status, 1));
- }
- BMCWEB_LOG_DEBUG("The request is not conflicting within itself");
-
- // Need to check for conflict with the locktable entries.
-
- auto conflict = isConflictWithTable(multiRequest);
-
- BMCWEB_LOG_DEBUG("Done with checking conflict with the locktable");
- return std::make_pair(false, conflict);
-}
-
-inline void Lock::releaseLock(const std::string& sessionId)
-{
- if (!lockTable.empty())
- {
- auto it = lockTable.begin();
- while (it != lockTable.end())
- {
- if (!it->second.empty())
- {
- // Check if session id of this entry matches with session id
- // given
- if (std::get<0>(it->second[0]) == sessionId)
- {
- BMCWEB_LOG_DEBUG("Remove the lock from the locktable "
- "having sessionID={}",
- sessionId);
- BMCWEB_LOG_DEBUG("TransactionID ={}", it->first);
- it = lockTable.erase(it);
- }
- else
- {
- it++;
- }
- }
- }
- }
-}
-inline 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");
- // remove the lock
- if (lockTable.erase(id) != 0U)
- {
- BMCWEB_LOG_DEBUG("Removing the locks with transaction ID : {}",
- id);
- }
- else
- {
- BMCWEB_LOG_ERROR("Removing the locks from the lock table "
- "failed, transaction ID: {}",
- id);
- }
- }
- 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()));
-}
-
-inline 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_ERROR("validateRids: At least 1 inValid Request id: {}",
- id);
- return false;
- }
- }
- return true;
-}
-
-inline bool Lock::isValidLockRequest(const LockRequest& refLockRecord)
-{
- // validate the locktype
-
- if (!((std::get<2>(refLockRecord) == "Read" ||
- (std::get<2>(refLockRecord) == "Write"))))
- {
- BMCWEB_LOG_DEBUG("Validation of LockType Failed");
- BMCWEB_LOG_DEBUG("Locktype : {}", std::get<2>(refLockRecord));
- return false;
- }
-
- BMCWEB_LOG_DEBUG("{}", static_cast<int>(std::get<4>(refLockRecord).size()));
-
- // validate the number of segments
- // Allowed No of segments are between 2 and 6
- if ((static_cast<int>(std::get<4>(refLockRecord).size()) > 6) ||
- (static_cast<int>(std::get<4>(refLockRecord).size()) < 2))
- {
- BMCWEB_LOG_DEBUG("Validation of Number of Segments Failed");
- BMCWEB_LOG_DEBUG("Number of Segments provided : {}",
- std::get<4>(refLockRecord).size());
- return false;
- }
-
- int lockFlag = 0;
- // validate the lockflags & segment length
-
- for (const auto& p : std::get<4>(refLockRecord))
- {
- // validate the lock flags
- // Allowed lockflags are locksame,lockall & dontlock
-
- if (!((p.first == "LockSame" || (p.first == "LockAll") ||
- (p.first == "DontLock"))))
- {
- BMCWEB_LOG_DEBUG("Validation of lock flags failed");
- BMCWEB_LOG_DEBUG("{}", p.first);
- return false;
- }
-
- // validate the segment length
- // Allowed values of segment length are between 1 and 4
-
- if (p.second < 1 || p.second > 4)
- {
- BMCWEB_LOG_DEBUG("Validation of Segment Length Failed");
- BMCWEB_LOG_DEBUG("{}", p.second);
- return false;
- }
-
- if ((p.first == "LockSame" || (p.first == "LockAll")))
- {
- ++lockFlag;
- if (lockFlag >= 2)
- {
- return false;
- }
- }
- }
-
- return true;
-}
-
-inline Rc Lock::isConflictWithTable(const LockRequests& refLockRequestStructure)
-{
- if (lockTable.empty())
- {
- uint32_t thisTransactionId = generateTransactionId();
- BMCWEB_LOG_DEBUG("{}", thisTransactionId);
- // Lock table is empty, so we are safe to add the lockrecords
- // as there will be no conflict
- BMCWEB_LOG_DEBUG("Lock table is empty, so adding the lockrecords");
- lockTable.emplace(thisTransactionId, refLockRequestStructure);
-
- return std::make_pair(false, thisTransactionId);
- }
- BMCWEB_LOG_DEBUG(
- "Lock table is not empty, check for conflict with lock table");
- // Lock table is not empty, compare the lockrequest entries with
- // the entries in the lock table
-
- for (const auto& lockRecord1 : refLockRequestStructure)
- {
- for (const auto& map : lockTable)
- {
- for (const auto& lockRecord2 : map.second)
- {
- bool status = isConflictRecord(lockRecord1, lockRecord2);
- if (status)
- {
- return std::make_pair(
- true, std::make_pair(map.first, lockRecord2));
- }
- }
- }
- }
-
- // Reached here, so no conflict with the locktable, so we are safe to
- // add the request records into the lock table
-
- // Lock table is empty, so we are safe to add the lockrecords
- // as there will be no conflict
- BMCWEB_LOG_DEBUG(" Adding elements into lock table");
- transactionId = generateTransactionId();
- lockTable.emplace(std::make_pair(transactionId, refLockRequestStructure));
-
- return std::make_pair(false, transactionId);
-}
-
-inline bool Lock::isConflictRequest(const LockRequests& refLockRequestStructure)
-{
- // check for all the locks coming in as a part of single request
- // return conflict if any two lock requests are conflicting
-
- if (refLockRequestStructure.size() == 1)
- {
- BMCWEB_LOG_DEBUG("Only single lock request, so there is no conflict");
- // This means , we have only one lock request in the current
- // request , so no conflict within the request
- return false;
- }
-
- BMCWEB_LOG_DEBUG(
- "There are multiple lock requests coming in a single request");
-
- // There are multiple requests a part of one request
-
- for (uint32_t i = 0; i < refLockRequestStructure.size(); i++)
- {
- for (uint32_t j = i + 1; j < refLockRequestStructure.size(); j++)
- {
- const LockRequest& p = refLockRequestStructure[i];
- const LockRequest& q = refLockRequestStructure[j];
- bool status = isConflictRecord(p, q);
-
- if (status)
- {
- return true;
- }
- }
- }
- return false;
-}
-
-// This function converts the provided uint64_t resource id's from the two
-// lock requests subjected for comparison, and this function also compares
-// the content by bytes mentioned by a uint32_t number.
-
-// If all the elements in the lock requests which are subjected for comparison
-// are same, then the last comparison would be to check for the respective
-// bytes in the resourceid based on the segment length.
-inline bool Lock::checkByte(uint64_t resourceId1, uint64_t resourceId2,
- uint32_t position)
-{
- if (position >= sizeof(resourceId1))
- {
- return false;
- }
-
- uint8_t pPosition = 0;
- uint8_t qPosition = 0;
- pPosition = 0xFF & (resourceId1 >> (8 * position));
- qPosition = 0xFF & (resourceId2 >> (8 * position));
-
- return pPosition == qPosition;
-}
-
-inline bool Lock::isConflictRecord(const LockRequest& refLockRecord1,
- const LockRequest& refLockRecord2)
-{
- // No conflict if both are read locks
-
- if (std::get<2>(refLockRecord1) == "Read" &&
- std::get<2>(refLockRecord2) == "Read")
- {
- BMCWEB_LOG_DEBUG("Both are read locks, no conflict");
- return false;
- }
-
- uint32_t i = 0;
- for (const auto& p : std::get<4>(refLockRecord1))
- {
- // return conflict when any of them is try to lock all resources
- // under the current resource level.
- if (p.first == "LockAll" ||
- std::get<4>(refLockRecord2)[i].first == "LockAll")
- {
- BMCWEB_LOG_DEBUG(
- "Either of the Comparing locks are trying to lock all "
- "resources under the current resource level");
- return true;
- }
-
- // determine if there is a lock-all-with-same-segment-size.
- // If the current segment sizes are the same,then we should fail.
-
- if ((p.first == "LockSame" ||
- std::get<4>(refLockRecord2)[i].first == "LockSame") &&
- (p.second == std::get<4>(refLockRecord2)[i].second))
- {
- return true;
- }
-
- // if segment lengths are not the same, it means two different locks
- // So no conflict
- if (p.second != std::get<4>(refLockRecord2)[i].second)
- {
- BMCWEB_LOG_DEBUG("Segment lengths are not same");
- BMCWEB_LOG_DEBUG("Segment 1 length : {}", p.second);
- BMCWEB_LOG_DEBUG("Segment 2 length : {}",
- std::get<4>(refLockRecord2)[i].second);
- return false;
- }
-
- // compare segment data
-
- for (uint32_t j = 0; j < p.second; j++)
- {
- // if the segment data is different, then the locks is on a
- // different resource so no conflict between the lock
- // records.
- // BMC is little endian, but the resourceID is formed by
- // the Management Console in such a way that, the first byte
- // from the MSB Position corresponds to the First Segment
- // data. Therefore we need to convert the incoming
- // resourceID into Big Endian before processing further.
- if (!(checkByte(
- boost::endian::endian_reverse(std::get<3>(refLockRecord1)),
- boost::endian::endian_reverse(std::get<3>(refLockRecord2)),
- j)))
- {
- return false;
- }
- }
-
- ++i;
- }
-
- return true;
-}
-
-inline uint32_t Lock::generateTransactionId()
-{
- ++transactionId;
- return transactionId;
-}
-
-} // namespace ibm_mc_lock
-} // namespace crow
diff --git a/include/ibm/management_console_rest.hpp b/include/ibm/management_console_rest.hpp
index ec8d4d653d..51437c9ac0 100644
--- a/include/ibm/management_console_rest.hpp
+++ b/include/ibm/management_console_rest.hpp
@@ -4,7 +4,7 @@
#include "async_resp.hpp"
#include "error_messages.hpp"
#include "event_service_manager.hpp"
-#include "ibm/locks.hpp"
+#include "ibm/utils.hpp"
#include "resource_messages.hpp"
#include "str_utility.hpp"
#include "utils/json_utils.hpp"
@@ -16,14 +16,6 @@
#include <filesystem>
#include <fstream>
-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::variant<std::string, std::vector<std::pair<uint32_t, LockRequests>>>;
-using ListOfSessionIds = std::vector<std::string>;
namespace crow
{
namespace ibm_mc
@@ -277,22 +269,6 @@ inline void
}
}
-inline void
- getLockServiceData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
-{
- asyncResp->res.jsonValue["@odata.type"] = "#LockService.v1_0_0.LockService";
- asyncResp->res.jsonValue["@odata.id"] = "/ibm/v1/HMC/LockService/";
- asyncResp->res.jsonValue["Id"] = "LockService";
- asyncResp->res.jsonValue["Name"] = "LockService";
-
- asyncResp->res.jsonValue["Actions"]["#LockService.AcquireLock"] = {
- {"target", "/ibm/v1/HMC/LockService/Actions/LockService.AcquireLock"}};
- asyncResp->res.jsonValue["Actions"]["#LockService.ReleaseLock"] = {
- {"target", "/ibm/v1/HMC/LockService/Actions/LockService.ReleaseLock"}};
- asyncResp->res.jsonValue["Actions"]["#LockService.GetLockList"] = {
- {"target", "/ibm/v1/HMC/LockService/Actions/LockService.GetLockList"}};
-}
-
inline void handleFileGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::string& fileID)
{
@@ -399,248 +375,6 @@ inline void handleFileUrl(const crow::Request& req,
}
}
-inline void
- handleAcquireLockAPI(const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- std::vector<nlohmann::json::object_t> body)
-{
- LockRequests lockRequestStructure;
- for (auto& element : body)
- {
- std::string lockType;
- uint64_t resourceId = 0;
-
- SegmentFlags segInfo;
- std::vector<nlohmann::json::object_t> segmentFlags;
-
- if (!redfish::json_util::readJsonObject(
- element, asyncResp->res, "LockType", lockType, "ResourceID",
- resourceId, "SegmentFlags", segmentFlags))
- {
- BMCWEB_LOG_DEBUG("Not a Valid JSON");
- asyncResp->res.result(boost::beast::http::status::bad_request);
- 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 = 0;
-
- if (!redfish::json_util::readJsonObject(
- e, asyncResp->res, "LockFlag", lockFlags, "SegmentLength",
- segmentLength))
- {
- asyncResp->res.result(boost::beast::http::status::bad_request);
- return;
- }
-
- BMCWEB_LOG_DEBUG("Lockflag : {}", lockFlags);
- BMCWEB_LOG_DEBUG("SegmentLength : {}", segmentLength);
-
- segInfo.emplace_back(std::make_pair(lockFlags, segmentLength));
- }
-
- lockRequestStructure.emplace_back(make_tuple(
- req.session->uniqueId, req.session->clientId.value_or(""), lockType,
- resourceId, segInfo));
- }
-
- // print lock request into journal
-
- for (auto& i : lockRequestStructure)
- {
- BMCWEB_LOG_DEBUG("{}", std::get<0>(i));
- BMCWEB_LOG_DEBUG("{}", std::get<1>(i));
- BMCWEB_LOG_DEBUG("{}", std::get<2>(i));
- BMCWEB_LOG_DEBUG("{}", std::get<3>(i));
-
- for (const auto& p : std::get<4>(i))
- {
- BMCWEB_LOG_DEBUG("{}, {}", p.first, p.second);
- }
- }
-
- const LockRequests& t = lockRequestStructure;
-
- auto varAcquireLock = crow::ibm_mc_lock::Lock::getInstance().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");
- asyncResp->res.result(boost::beast::http::status::bad_request);
- return;
- }
- if (validityStatus.first && (validityStatus.second == 1))
- {
- BMCWEB_LOG_ERROR("There is a conflict within itself");
- asyncResp->res.result(boost::beast::http::status::conflict);
- 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");
- asyncResp->res.result(boost::beast::http::status::ok);
-
- auto var = std::get<uint32_t>(conflictStatus.second);
- nlohmann::json returnJson;
- returnJson["id"] = var;
- asyncResp->res.jsonValue["TransactionID"] = var;
- return;
- }
- BMCWEB_LOG_DEBUG("There is a conflict with the lock table");
- asyncResp->res.result(boost::beast::http::status::conflict);
- auto var =
- std::get<std::pair<uint32_t, LockRequest>>(conflictStatus.second);
- nlohmann::json returnJson;
- nlohmann::json 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 (const auto& i : std::get<4>(var.second))
- {
- segments["LockFlag"] = i.first;
- segments["SegmentLength"] = i.second;
- myarray.push_back(segments);
- }
-
- returnJson["SegmentFlags"] = myarray;
- BMCWEB_LOG_ERROR("Conflicting lock record: {}", returnJson);
- asyncResp->res.jsonValue["Record"] = returnJson;
- return;
- }
-}
-inline void
- handleRelaseAllAPI(const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
-{
- crow::ibm_mc_lock::Lock::getInstance().releaseLock(req.session->uniqueId);
- asyncResp->res.result(boost::beast::http::status::ok);
-}
-
-inline void
- handleReleaseLockAPI(const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::vector<uint32_t>& listTransactionIds)
-{
- BMCWEB_LOG_DEBUG("{}", listTransactionIds.size());
- BMCWEB_LOG_DEBUG("Data is present");
- for (unsigned int listTransactionId : listTransactionIds)
- {
- BMCWEB_LOG_DEBUG("{}", listTransactionId);
- }
-
- // validate the request ids
-
- auto varReleaselock = crow::ibm_mc_lock::Lock::getInstance().releaseLock(
- listTransactionIds, std::make_pair(req.session->clientId.value_or(""),
- req.session->uniqueId));
-
- if (!varReleaselock.first)
- {
- // validation Failed
- BMCWEB_LOG_ERROR("handleReleaseLockAPI: validation failed");
- asyncResp->res.result(boost::beast::http::status::bad_request);
- return;
- }
- 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
- return;
- }
-
- // valid rid, but the current hmc does not own all the locks
- BMCWEB_LOG_DEBUG("Current HMC does not own all the locks");
- asyncResp->res.result(boost::beast::http::status::unauthorized);
-
- auto var = statusRelease.second;
- nlohmann::json returnJson;
- nlohmann::json 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 (const auto& i : std::get<4>(var.second))
- {
- segments["LockFlag"] = i.first;
- segments["SegmentLength"] = i.second;
- myArray.push_back(segments);
- }
-
- returnJson["SegmentFlags"] = myArray;
- BMCWEB_LOG_DEBUG("handleReleaseLockAPI: lockrecord: {}", returnJson);
- asyncResp->res.jsonValue["Record"] = returnJson;
-}
-
-inline void
- handleGetLockListAPI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const ListOfSessionIds& listSessionIds)
-{
- BMCWEB_LOG_DEBUG("{}", listSessionIds.size());
-
- auto status =
- crow::ibm_mc_lock::Lock::getInstance().getLockList(listSessionIds);
- auto var = std::get<std::vector<std::pair<uint32_t, LockRequests>>>(status);
-
- nlohmann::json lockRecords = nlohmann::json::array();
-
- for (const auto& transactionId : var)
- {
- for (const auto& lockRecord : transactionId.second)
- {
- nlohmann::json returnJson;
-
- returnJson["TransactionID"] = transactionId.first;
- returnJson["SessionID"] = std::get<0>(lockRecord);
- returnJson["HMCID"] = std::get<1>(lockRecord);
- returnJson["LockType"] = std::get<2>(lockRecord);
- returnJson["ResourceID"] = std::get<3>(lockRecord);
-
- nlohmann::json segments;
- nlohmann::json segmentInfoArray = nlohmann::json::array();
-
- for (const auto& segment : std::get<4>(lockRecord))
- {
- segments["LockFlag"] = segment.first;
- segments["SegmentLength"] = segment.second;
- segmentInfoArray.push_back(segments);
- }
-
- returnJson["SegmentFlags"] = segmentInfoArray;
- lockRecords.push_back(returnJson);
- }
- }
- asyncResp->res.result(boost::beast::http::status::ok);
- asyncResp->res.jsonValue["Records"] = lockRecords;
-}
-
inline bool isValidConfigFileName(const std::string& fileName,
crow::Response& res)
{
@@ -690,8 +424,6 @@ inline void requestRoutes(App& app)
asyncResp->res.jsonValue["Name"] = "IBM Service Root";
asyncResp->res.jsonValue["ConfigFiles"]["@odata.id"] =
"/ibm/v1/Host/ConfigFiles";
- asyncResp->res.jsonValue["LockService"]["@odata.id"] =
- "/ibm/v1/HMC/LockService";
asyncResp->res.jsonValue["BroadcastService"]["@odata.id"] =
"/ibm/v1/HMC/BroadcastService";
});
@@ -730,75 +462,6 @@ inline void requestRoutes(App& app)
handleFileUrl(req, asyncResp, fileName);
});
- BMCWEB_ROUTE(app, "/ibm/v1/HMC/LockService")
- .privileges({{"ConfigureComponents", "ConfigureManager"}})
- .methods(boost::beast::http::verb::get)(
- [](const crow::Request&,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
- getLockServiceData(asyncResp);
- });
-
- BMCWEB_ROUTE(app, "/ibm/v1/HMC/LockService/Actions/LockService.AcquireLock")
- .privileges({{"ConfigureComponents", "ConfigureManager"}})
- .methods(boost::beast::http::verb::post)(
- [](const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
- std::vector<nlohmann::json::object_t> body;
- if (!redfish::json_util::readJsonAction(req, asyncResp->res, "Request",
- body))
- {
- BMCWEB_LOG_DEBUG("Not a Valid JSON");
- asyncResp->res.result(boost::beast::http::status::bad_request);
- return;
- }
- handleAcquireLockAPI(req, asyncResp, body);
- });
- BMCWEB_ROUTE(app, "/ibm/v1/HMC/LockService/Actions/LockService.ReleaseLock")
- .privileges({{"ConfigureComponents", "ConfigureManager"}})
- .methods(boost::beast::http::verb::post)(
- [](const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
- std::string type;
- std::vector<uint32_t> listTransactionIds;
-
- if (!redfish::json_util::readJsonPatch(req, asyncResp->res, "Type",
- type, "TransactionIDs",
- listTransactionIds))
- {
- asyncResp->res.result(boost::beast::http::status::bad_request);
- return;
- }
- if (type == "Transaction")
- {
- handleReleaseLockAPI(req, asyncResp, listTransactionIds);
- }
- else if (type == "Session")
- {
- handleRelaseAllAPI(req, asyncResp);
- }
- else
- {
- BMCWEB_LOG_DEBUG(" Value of Type : {}is Not a Valid key", type);
- redfish::messages::propertyValueNotInList(asyncResp->res, type,
- "Type");
- }
- });
- BMCWEB_ROUTE(app, "/ibm/v1/HMC/LockService/Actions/LockService.GetLockList")
- .privileges({{"ConfigureComponents", "ConfigureManager"}})
- .methods(boost::beast::http::verb::post)(
- [](const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
- ListOfSessionIds listSessionIds;
-
- if (!redfish::json_util::readJsonPatch(req, asyncResp->res,
- "SessionIDs", listSessionIds))
- {
- asyncResp->res.result(boost::beast::http::status::bad_request);
- return;
- }
- handleGetLockListAPI(asyncResp, listSessionIds);
- });
-
BMCWEB_ROUTE(app, "/ibm/v1/HMC/BroadcastService")
.privileges({{"ConfigureComponents", "ConfigureManager"}})
.methods(boost::beast::http::verb::post)(
diff --git a/include/sessions.hpp b/include/sessions.hpp
index fb7276212c..1d0b620fb1 100644
--- a/include/sessions.hpp
+++ b/include/sessions.hpp
@@ -11,9 +11,6 @@
#include <csignal>
#include <optional>
#include <random>
-#ifdef BMCWEB_ENABLE_IBM_MANAGEMENT_CONSOLE
-#include "ibm/locks.hpp"
-#endif
namespace persistent_data
{
@@ -310,9 +307,6 @@ class SessionStore
void removeSession(const std::shared_ptr<UserSession>& session)
{
-#ifdef BMCWEB_ENABLE_IBM_MANAGEMENT_CONSOLE
- crow::ibm_mc_lock::Lock::getInstance().releaseLock(session->uniqueId);
-#endif
authTokens.erase(session->sessionToken);
needWrite = true;
}
@@ -396,10 +390,6 @@ class SessionStore
if (timeNow - authTokensIt->second->lastUpdated >=
timeoutInSeconds)
{
-#ifdef BMCWEB_ENABLE_IBM_MANAGEMENT_CONSOLE
- crow::ibm_mc_lock::Lock::getInstance().releaseLock(
- authTokensIt->second->uniqueId);
-#endif
authTokensIt = authTokens.erase(authTokensIt);
needWrite = true;
diff --git a/meson.build b/meson.build
index a965b7ff43..ee8a91f500 100644
--- a/meson.build
+++ b/meson.build
@@ -464,7 +464,6 @@ srcfiles_unittest = files(
'test/include/http_utility_test.cpp',
'test/include/human_sort_test.cpp',
'test/include/ibm/configfile_test.cpp',
- 'test/include/ibm/lock_test.cpp',
'test/include/json_html_serializer.cpp',
'test/include/multipart_test.cpp',
'test/include/openbmc_dbus_rest_test.cpp',
diff --git a/src/webserver_run.cpp b/src/webserver_run.cpp
index 2f28e16818..3c1c615539 100644
--- a/src/webserver_run.cpp
+++ b/src/webserver_run.cpp
@@ -76,7 +76,6 @@ int run()
#ifdef BMCWEB_ENABLE_IBM_MANAGEMENT_CONSOLE
crow::ibm_mc::requestRoutes(app);
- crow::ibm_mc_lock::Lock::getInstance();
#endif
#ifdef BMCWEB_ENABLE_GOOGLE_API
diff --git a/test/include/ibm/lock_test.cpp b/test/include/ibm/lock_test.cpp
deleted file mode 100644
index 9570ec6f90..0000000000
--- a/test/include/ibm/lock_test.cpp
+++ /dev/null
@@ -1,314 +0,0 @@
-#include "ibm/locks.hpp"
-
-#include <cstdint>
-#include <string>
-#include <tuple>
-#include <utility>
-#include <variant>
-#include <vector>
-
-#include <gmock/gmock.h> // IWYU pragma: keep
-#include <gtest/gtest.h> // IWYU pragma: keep
-
-// IWYU pragma: no_include <gtest/gtest-message.h>
-// IWYU pragma: no_include <gtest/gtest-test-part.h>
-// IWYU pragma: no_include "gtest/gtest_pred_impl.h"
-
-namespace crow::ibm_mc_lock
-{
-namespace
-{
-
-using SType = std::string;
-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, std::pair<uint32_t, LockRequest>>;
-using RcGetLockList =
- 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>;
-using ListOfSessionIds = std::vector<std::string>;
-using ::testing::IsEmpty;
-
-class LockTest : public ::testing::Test
-{
- protected:
- LockRequests request;
- LockRequests request1, request2;
- LockRequest record;
-
- public:
- LockTest() :
- // lockrequest with multiple lockrequests
- request{{"xxxxx",
- "hmc-id",
- "Read",
- 234,
- {{"DontLock", 2}, {"DontLock", 4}}},
- {"xxxxx",
- "hmc-id",
- "Read",
- 234,
- {{"DontLock", 2}, {"DontLock", 4}}}},
- request1{{"xxxxx",
- "hmc-id",
- "Read",
- 234,
- {{"DontLock", 2}, {"DontLock", 4}}}},
- request2{{"xxxxx",
- "hmc-id",
- "Write",
- 234,
- {{"LockAll", 2}, {"DontLock", 4}}}},
- record{
- "xxxxx", "hmc-id", "Read", 234, {{"DontLock", 2}, {"DontLock", 4}}}
- {}
-
- ~LockTest() override = default;
-
- LockTest(const LockTest&) = delete;
- LockTest(LockTest&&) = delete;
- LockTest& operator=(const LockTest&) = delete;
- LockTest& operator=(const LockTest&&) = delete;
-};
-
-class MockLock : public crow::ibm_mc_lock::Lock
-{
- public:
- bool isValidLockRequest(const LockRequest& record1) override
- {
- bool status = Lock::isValidLockRequest(record1);
- return status;
- }
- bool isConflictRequest(const LockRequests& request) override
- {
- bool status = Lock::isConflictRequest(request);
- return status;
- }
- Rc isConflictWithTable(const LockRequests& request) override
- {
- auto conflict = Lock::isConflictWithTable(request);
- return conflict;
- }
- uint32_t generateTransactionId() override
- {
- uint32_t tid = Lock::generateTransactionId();
- return tid;
- }
-
- bool validateRids(const ListOfTransactionIds& tids) override
- {
- bool status = Lock::validateRids(tids);
- return status;
- }
- RcRelaseLock isItMyLock(const ListOfTransactionIds& tids,
- const SessionFlags& ids) override
- {
- auto status = Lock::isItMyLock(tids, ids);
- return status;
- }
- friend class LockTest;
-};
-
-TEST_F(LockTest, ValidationGoodTestCase)
-{
- MockLock lockManager;
- const LockRequest& t = record;
- EXPECT_TRUE(lockManager.isValidLockRequest(t));
-}
-
-TEST_F(LockTest, ValidationBadTestWithLocktype)
-{
- MockLock lockManager;
- // Corrupt the lock type
- std::get<2>(record) = "rwrite";
- const LockRequest& t = record;
- EXPECT_FALSE(lockManager.isValidLockRequest(t));
-}
-
-TEST_F(LockTest, ValidationBadTestWithlockFlags)
-{
- MockLock lockManager;
- // Corrupt the lockflag
- std::get<4>(record)[0].first = "lock";
- const LockRequest& t = record;
- EXPECT_FALSE(lockManager.isValidLockRequest(t));
-}
-
-TEST_F(LockTest, ValidationBadTestWithSegmentlength)
-{
- MockLock lockManager;
- // Corrupt the Segment length
- std::get<4>(record)[0].second = 7;
- const LockRequest& t = record;
- EXPECT_FALSE(lockManager.isValidLockRequest(t));
-}
-
-TEST_F(LockTest, MultiRequestWithoutConflict)
-{
- MockLock lockManager;
- const LockRequests& t = request;
- EXPECT_FALSE(lockManager.isConflictRequest(t));
-}
-
-TEST_F(LockTest, MultiRequestWithConflictduetoSameSegmentLength)
-{
- MockLock lockManager;
- // Corrupt the locktype
- std::get<2>(request[0]) = "Write";
- // Match the segment lengths to points them to lock similar kind of
- // resource
- std::get<4>(request[0])[0].first = "LockAll";
- const LockRequests& t = request;
- EXPECT_TRUE(lockManager.isConflictRequest(t));
-}
-
-TEST_F(LockTest, MultiRequestWithoutConflictduetoDifferentSegmentLength)
-{
- MockLock lockManager;
- // Corrupt the locktype
- std::get<2>(request[0]) = "Write";
- // Match the segment lengths to points them to lock similar kind of
- // resource
- std::get<4>(request[0])[0].first = "LockSame";
- // Change the segment length , so that the requests are trying to lock
- // two different kind of resources
- std::get<4>(request[0])[0].second = 3;
- const LockRequests& t = request;
- // Return No Conflict
- EXPECT_FALSE(lockManager.isConflictRequest(t));
-}
-
-TEST_F(LockTest, MultiRequestWithoutConflictduetoReadLocktype)
-{
- MockLock lockManager;
- // Match the segment lengths to points them to lock similar kind of
- // resource
- std::get<4>(request[0])[0].first = "LockAll";
- const LockRequests& t = request;
- // Return No Conflict
- EXPECT_FALSE(lockManager.isConflictRequest(t));
-}
-
-TEST_F(LockTest, MultiRequestWithoutConflictduetoReadLocktypeAndLockall)
-{
- MockLock lockManager;
- // Match the segment lengths to points them to lock similar kind of
- // resource
- std::get<4>(request[0])[0].first = "LockAll";
- std::get<4>(request[0])[1].first = "LockAll";
- const LockRequests& t = request;
- // Return No Conflict
- EXPECT_FALSE(lockManager.isConflictRequest(t));
-}
-
-TEST_F(LockTest, RequestNotConflictedWithLockTableEntries)
-{
- MockLock lockManager;
- const LockRequests& t = request1;
- // Insert the request1 into the lock table
- auto rc1 = lockManager.isConflictWithTable(t);
- // Corrupt the lock type
- std::get<2>(request[0]) = "Read";
- // Corrupt the lockflag
- std::get<4>(request[0])[1].first = "LockAll";
- const LockRequests& p = request;
- auto rc2 = lockManager.isConflictWithTable(p);
- // Return No Conflict
- EXPECT_FALSE(rc2.first);
-}
-
-TEST_F(LockTest, TestGenerateTransactionIDFunction)
-{
- MockLock lockManager;
- uint32_t transactionId1 = lockManager.generateTransactionId();
- uint32_t transactionId2 = lockManager.generateTransactionId();
- EXPECT_EQ(transactionId2, ++transactionId1);
-}
-
-TEST_F(LockTest, ValidateTransactionIDsGoodTestCase)
-{
- MockLock lockManager;
- const LockRequests& t = request1;
- // Insert the request1 into the lock table
- auto rc1 = lockManager.isConflictWithTable(t);
- std::vector<uint32_t> tids = {1};
- const std::vector<uint32_t>& p = tids;
- EXPECT_TRUE(lockManager.validateRids(p));
-}
-
-TEST_F(LockTest, ValidateTransactionIDsBadTestCase)
-{
- MockLock lockManager;
- // Insert the request1 into the lock table
- const LockRequests& t = request1;
- auto rc1 = lockManager.isConflictWithTable(t);
- std::vector<uint32_t> tids = {10};
- const std::vector<uint32_t>& p = tids;
- EXPECT_FALSE(lockManager.validateRids(p));
-}
-
-TEST_F(LockTest, ValidateisItMyLockGoodTestCase)
-{
- MockLock lockManager;
- // Insert the request1 into the lock table
- const LockRequests& t = request1;
- auto rc1 = lockManager.isConflictWithTable(t);
- std::vector<uint32_t> tids = {1};
- const std::vector<uint32_t>& p = tids;
- std::string hmcid = "hmc-id";
- std::string sessionid = "xxxxx";
- std::pair<SType, SType> ids = std::make_pair(hmcid, sessionid);
- auto rc = lockManager.isItMyLock(p, ids);
- EXPECT_TRUE(rc.first);
-}
-
-TEST_F(LockTest, ValidateisItMyLockBadTestCase)
-{
- MockLock lockManager;
- // Corrupt the client identifier
- std::get<1>(request1[0]) = "randomid";
- // Insert the request1 into the lock table
- const LockRequests& t = request1;
- auto rc1 = lockManager.isConflictWithTable(t);
- std::vector<uint32_t> tids = {1};
- const std::vector<uint32_t>& p = tids;
- std::string hmcid = "hmc-id";
- std::string sessionid = "random";
- std::pair<SType, SType> ids = std::make_pair(hmcid, sessionid);
- auto rc = lockManager.isItMyLock(p, ids);
- EXPECT_FALSE(rc.first);
-}
-
-TEST_F(LockTest, ValidateSessionIDForGetlocklistBadTestCase)
-{
- MockLock lockManager;
- // Insert the request1 into the lock table
- const LockRequests& t = request1;
- auto rc1 = lockManager.isConflictWithTable(t);
- std::vector<std::string> sessionid = {"random"};
- auto status = lockManager.getLockList(sessionid);
- auto result =
- std::get<std::vector<std::pair<uint32_t, LockRequests>>>(status);
- EXPECT_THAT(result, IsEmpty());
-}
-
-TEST_F(LockTest, ValidateSessionIDForGetlocklistGoodTestCase)
-{
- MockLock lockManager;
- // Insert the request1 into the lock table
- const LockRequests& t = request1;
- auto rc1 = lockManager.isConflictWithTable(t);
- std::vector<std::string> sessionid = {"xxxxx"};
- auto status = lockManager.getLockList(sessionid);
- auto result =
- std::get<std::vector<std::pair<uint32_t, LockRequests>>>(status);
- EXPECT_EQ(result.size(), 1);
-}
-
-} // namespace
-} // namespace crow::ibm_mc_lock