From cf29e5f454deb9879b8907a879ceb2932e891ef6 Mon Sep 17 00:00:00 2001 From: Eric Cano <Eric.Cano@cern.ch> Date: Wed, 4 Mar 2015 16:41:20 +0100 Subject: [PATCH] Created AdminUsersList in the object store as a first step to implement an object store middle tier. Some namespace fixes for unit tests. --- CMakeLists.txt | 3 + objectstore/AdminUsersList.cpp | 31 ++ objectstore/AdminUsersList.hpp | 22 ++ objectstore/BackendTest.cpp | 6 +- objectstore/BackendTest.hpp | 5 + objectstore/CMakeLists.txt | 1 + objectstore/FIFOTest.cpp | 6 +- objectstore/GarbageCollectorTest.cpp | 6 +- objectstore/RootEntry.hpp | 6 + objectstore/RootEntryTest.cpp | 6 +- objectstore/cta.proto | 19 ++ objectstore/exception/Exception.hpp | 2 +- objectstore/tapeResourceManagerTest.cpp | 4 +- objectstore_middletier/CMakeLists.txt | 8 + .../ObjectStoreMiddleTier.cpp | 47 +++ .../ObjectStoreMiddleTier.hpp | 293 ++++++++++++++++++ 16 files changed, 459 insertions(+), 6 deletions(-) create mode 100644 objectstore/AdminUsersList.cpp create mode 100644 objectstore/AdminUsersList.hpp create mode 100644 objectstore_middletier/CMakeLists.txt create mode 100644 objectstore_middletier/ObjectStoreMiddleTier.cpp create mode 100644 objectstore_middletier/ObjectStoreMiddleTier.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 7d311e83f2..b5ac62eb0b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,8 +29,11 @@ set(CMAKE_DISABLE_SOURCE_CHANGES ON) set(CMAKE_DISABLE_IN_SOURCE_BUILD ON) list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) +include_directories(${CMAKE_SOURCE_DIR}) + add_subdirectory(libs) add_subdirectory(objectstore) +add_subdirectory(objectstore_middletier) add_subdirectory(tests) add_subdirectory(xroot_clients) add_subdirectory(xroot_plugins) diff --git a/objectstore/AdminUsersList.cpp b/objectstore/AdminUsersList.cpp new file mode 100644 index 0000000000..9b3676f348 --- /dev/null +++ b/objectstore/AdminUsersList.cpp @@ -0,0 +1,31 @@ +#include "AdminUsersList.hpp" + +namespace cta { namespace objectstore { + +AdminUsersList::AdminUsersList(Backend& os): + ObjectOps<serializers::AdminUsersList>(os) {} + +AdminUsersList::AdminUsersList(const std::string & name, Backend& os): + ObjectOps<serializers::AdminUsersList>(os, name) {} + +void AdminUsersList::add(const cta::AdminUser& adminUser) { + // Check that the admin user is not already present + ::google::protobuf::RepeatedPtrField<serializers::AdminUser>* list = + m_payload.mutable_element(); + for (size_t i=0; i<(size_t)list->size(); i++) { + if (adminUser.getUser().getUid() == list->Get(i).user().uid()) { + throw cta::exception::Exception("Attempt to duplicate entry in AdminUsersList"); + } + } + // Insert the new admin user + serializers::AdminUser * newEntry = list->Add(); + // Set the content of the new entry + newEntry->mutable_user()->set_uid(adminUser.getUser().getUid()); + newEntry->mutable_user()->set_gid(adminUser.getUser().getUid()); + newEntry->mutable_creator()->set_uid(adminUser.getCreator().getUid()); + newEntry->mutable_creator()->set_gid(adminUser.getCreator().getGid()); + newEntry->set_creationtime(adminUser.getCreationTime()); + newEntry->set_comment(adminUser.getComment()); +} + +}} \ No newline at end of file diff --git a/objectstore/AdminUsersList.hpp b/objectstore/AdminUsersList.hpp new file mode 100644 index 0000000000..cfbf0ac42b --- /dev/null +++ b/objectstore/AdminUsersList.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include "ObjectOps.hpp" +#include "objectstore/cta.pb.h" +#include "libs/middletier/AdminUser.hpp" + +namespace cta { namespace objectstore { + +/** + * Class containing the list of admin users + */ + +class AdminUsersList: public ObjectOps<serializers::AdminUsersList> { +public: + AdminUsersList(Backend & os); + + AdminUsersList(const std::string & name, Backend & os); + + void add(const cta::AdminUser & adminUser); +}; + +}} \ No newline at end of file diff --git a/objectstore/BackendTest.cpp b/objectstore/BackendTest.cpp index 7f8b1062fd..ccf819629e 100644 --- a/objectstore/BackendTest.cpp +++ b/objectstore/BackendTest.cpp @@ -3,6 +3,8 @@ #include "BackendRados.hpp" #include "exception/Exception.hpp" +namespace unitTests { + TEST_P(BackendAbstractTest, BasicReadWrite) { std::cout << "Type=" << m_os->typeName() << std::endl; const std::string testValue = "1234"; @@ -63,4 +65,6 @@ cta::objectstore::BackendRados osRados("tapetest", "tapetest"); INSTANTIATE_TEST_CASE_P(BackendTest, BackendAbstractTest, ::testing::Values(&osVFS, &osRados)); #else INSTANTIATE_TEST_CASE_P(BackendTest, BackendAbstractTest, ::testing::Values((cta::objectstore::Backend*)&osVFS)); -#endif \ No newline at end of file +#endif + +} diff --git a/objectstore/BackendTest.hpp b/objectstore/BackendTest.hpp index 94acd8eca9..7a97838705 100644 --- a/objectstore/BackendTest.hpp +++ b/objectstore/BackendTest.hpp @@ -3,6 +3,8 @@ #include <gtest/gtest.h> #include "Backend.hpp" +namespace unitTests { + class BackendAbstractTest: public ::testing::TestWithParam<cta::objectstore::Backend *> { protected: BackendAbstractTest() {} @@ -11,3 +13,6 @@ protected: } cta::objectstore::Backend * m_os; }; + +} + diff --git a/objectstore/CMakeLists.txt b/objectstore/CMakeLists.txt index 8cfc03e97d..f24a7b4a12 100644 --- a/objectstore/CMakeLists.txt +++ b/objectstore/CMakeLists.txt @@ -16,6 +16,7 @@ add_library (CTAObjectStore Agent.cpp AgentRegister.cpp AgentWatchdog.cpp + AdminUsersList.cpp BackendVFS.cpp BackendRados.cpp ObjectOps.cpp diff --git a/objectstore/FIFOTest.cpp b/objectstore/FIFOTest.cpp index d088cca03a..a8ceb281c7 100644 --- a/objectstore/FIFOTest.cpp +++ b/objectstore/FIFOTest.cpp @@ -4,6 +4,8 @@ #include "FIFO.hpp" #include "Agent.hpp" +namespace unitTests { + TEST(FIFO, BasicFuctionnality) { cta::objectstore::BackendVFS be; cta::objectstore::Agent agent(be); @@ -68,4 +70,6 @@ TEST(FIFO, BasicFuctionnality) { ASSERT_EQ(0, ff.size()); ff.remove(); ASSERT_EQ(false, ff.exists()); -} \ No newline at end of file +} + +} diff --git a/objectstore/GarbageCollectorTest.cpp b/objectstore/GarbageCollectorTest.cpp index d5bf4ef1c5..8f3d0900fc 100644 --- a/objectstore/GarbageCollectorTest.cpp +++ b/objectstore/GarbageCollectorTest.cpp @@ -7,6 +7,8 @@ #include "AgentRegister.hpp" #include "RootEntry.hpp" +namespace unitTests { + TEST(GarbageCollector, BasicFuctionnality) { cta::objectstore::BackendVFS be; cta::objectstore::Agent agent(be); @@ -80,4 +82,6 @@ TEST(GarbageCollector, BasicFuctionnality) { ffLock.lock(ff); ff.fetch(); ASSERT_EQ(100, ff.size()); -} \ No newline at end of file +} + +} diff --git a/objectstore/RootEntry.hpp b/objectstore/RootEntry.hpp index 1ac27450ab..00c2a13199 100644 --- a/objectstore/RootEntry.hpp +++ b/objectstore/RootEntry.hpp @@ -34,6 +34,12 @@ public: // Get the name of a (possibly freshly created) job pool std::string allocateOrGetJobPool(Agent & agent); + // Get the name of the AdminUsersList (or exception if not available) + std::string getAdminUsersList(); + + // Get the name of a (possibly freshly created) AdminUsersList + std::string allocateOrGetAdminUsersList(Agent & agent); + private: void addIntendedAgentRegistry(const std::string & name); diff --git a/objectstore/RootEntryTest.cpp b/objectstore/RootEntryTest.cpp index 7548a46899..6f70cf61fb 100644 --- a/objectstore/RootEntryTest.cpp +++ b/objectstore/RootEntryTest.cpp @@ -4,6 +4,8 @@ #include "RootEntry.hpp" #include "Agent.hpp" +namespace unitTests { + TEST(RootEntry, BasicAccess) { cta::objectstore::BackendVFS be; { @@ -39,4 +41,6 @@ TEST(RootEntry, BasicAccess) { cta::objectstore::ScopedExclusiveLock lock(re); re.remove(); ASSERT_EQ(false, re.exists()); -} \ No newline at end of file +} + +} diff --git a/objectstore/cta.proto b/objectstore/cta.proto index d2815b227e..790e4e3a82 100644 --- a/objectstore/cta.proto +++ b/objectstore/cta.proto @@ -12,6 +12,7 @@ enum ObjectType { RecallJob_t = 6; Counter_t = 7; FIFO_t = 8; + AdminUsersList_t = 9; GenericObject_t = 1000; } @@ -68,6 +69,8 @@ message RootEntry { repeated string agentregisterintentlog = 92; optional string jobpool = 93; repeated string jobpoolintentlog = 94; + optional string adminuserslist = 95; + repeated string adminuserslistintentlog = 96; } // The registers (simple name arrays) @@ -150,4 +153,20 @@ message RecallFIFO {} message MigrationFIFO {} +message UserIdentity { + required uint32 uid = 8001; + required uint32 gid = 8002; +} + +message AdminUser { + required UserIdentity user = 8010; + required UserIdentity creator = 8011; + required uint64 creationTime = 8012; + required string comment = 8013; +} + +message AdminUsersList { + repeated AdminUser element = 8020; +} + diff --git a/objectstore/exception/Exception.hpp b/objectstore/exception/Exception.hpp index b1ca73e7ad..55412a305a 100644 --- a/objectstore/exception/Exception.hpp +++ b/objectstore/exception/Exception.hpp @@ -24,7 +24,7 @@ #pragma once -#include "exception/Backtrace.hpp" +#include "objectstore/exception/Backtrace.hpp" #include <exception> #include <sstream> diff --git a/objectstore/tapeResourceManagerTest.cpp b/objectstore/tapeResourceManagerTest.cpp index 8ca607ec6a..df0e13f2aa 100644 --- a/objectstore/tapeResourceManagerTest.cpp +++ b/objectstore/tapeResourceManagerTest.cpp @@ -15,7 +15,7 @@ #include "Counter.hpp" #include <math.h> - +namespace systemTests { class jobExecutorThread: public cta::threading::Thread { public: @@ -239,3 +239,5 @@ int main(void){ return 0; } + +} diff --git a/objectstore_middletier/CMakeLists.txt b/objectstore_middletier/CMakeLists.txt new file mode 100644 index 0000000000..6df1a3271c --- /dev/null +++ b/objectstore_middletier/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required (VERSION 2.6) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +include_directories(${CMAKE_BINARY_DIR}) + +add_library (CTAObjectStoreMiddleTier + ObjectStoreMiddleTier.cpp +) \ No newline at end of file diff --git a/objectstore_middletier/ObjectStoreMiddleTier.cpp b/objectstore_middletier/ObjectStoreMiddleTier.cpp new file mode 100644 index 0000000000..5affbd7aac --- /dev/null +++ b/objectstore_middletier/ObjectStoreMiddleTier.cpp @@ -0,0 +1,47 @@ +#include "ObjectStoreMiddleTier.hpp" +#include "objectstore/Backend.hpp" +#include "objectstore/RootEntry.hpp" +#include "objectstore/AdminUsersList.hpp" +#include "../libs/middletier/Exception.hpp" + +namespace cta { + +//------------------------------------------------------------------------------ +// constructor +//------------------------------------------------------------------------------ +OStoreMiddleTierAdmin::OStoreMiddleTierAdmin(objectstore::Backend& backend): + m_backend(backend) { + // check that we can at least access the root entry + objectstore::RootEntry re(m_backend); + objectstore::ScopedSharedLock reLock(re); + re.fetch(); +} + +//------------------------------------------------------------------------------ +// destructor +//------------------------------------------------------------------------------ +OStoreMiddleTierAdmin::~OStoreMiddleTierAdmin() throw() { +} + +//------------------------------------------------------------------------------ +// createAdminUser +//------------------------------------------------------------------------------ +void OStoreMiddleTierAdmin::createAdminUser( + const SecurityIdentity &requester, + const UserIdentity &user, + const std::string &comment) { + // TODO: authz is needed here! + // Find the admin users list from the root entry. + objectstore::RootEntry re(m_backend); + objectstore::ScopedSharedLock reLock(re); + re.fetch(); + objectstore::AdminUsersList aul(re.getAdminUsersList(), m_backend); + reLock.release(); + objectstore::ScopedExclusiveLock auLock(aul); + aul.fetch(); + AdminUser au(user, requester.user, time(NULL), comment); + aul.add(au); + aul.commit(); +} + +} diff --git a/objectstore_middletier/ObjectStoreMiddleTier.hpp b/objectstore_middletier/ObjectStoreMiddleTier.hpp new file mode 100644 index 0000000000..1683594ecb --- /dev/null +++ b/objectstore_middletier/ObjectStoreMiddleTier.hpp @@ -0,0 +1,293 @@ +#pragma once + +#include "../libs/middletier/MiddleTierAdmin.hpp" + +namespace cta { + +namespace objectstore { + class Backend; +} + +/** + * The administration API of the the middle-tier. + * ObjectStore based implementation + */ +class OStoreMiddleTierAdmin: public MiddleTierAdmin { +public: + /** + * Contructor + */ + OStoreMiddleTierAdmin(objectstore::Backend & backend); + + /** + * Destructor + */ + virtual ~OStoreMiddleTierAdmin() throw(); + + /** + * Creates the specified administrator. + * + * @param requester The identity of the user requesting the creation of the + * administrator. + * @param user The identity of the administrator. + * @param comment The comment describing the sministrator. + */ + virtual void createAdminUser( + const SecurityIdentity &requester, + const UserIdentity &user, + const std::string &comment); + + /** + * Deletes the specified administrator. + * + * @param requester The identity of the user requesting the deletion of the + * administrator. + * @param user The identity of the administrator. + */ + virtual void deleteAdminUser( + const SecurityIdentity &requester, + const UserIdentity &user); + + /** + * Returns the current list of administrators in lexicographical order. + * + * @param requester The identity of the user requesting the list. + * @return The current list of administrators in lexicographical order. + */ + virtual std::list<AdminUser> getAdminUsers(const SecurityIdentity &requester) + const; + + /** + * Creates the specified administration host. + * + * @param requester The identity of the user requesting the creation of the + * administration host. + * @param hostName The network name of the administration host. + * @param comment The comment describing the administration host. + */ + virtual void createAdminHost( + const SecurityIdentity &requester, + const std::string &hostName, + const std::string &comment); + + /** + * Deletes the specified administration host. + * + * @param requester The identity of the user requesting the deletion of the + * administration host. + * @param hostName The network name of the administration host. + * @param comment The comment describing the administration host. + */ + virtual void deleteAdminHost( + const SecurityIdentity &requester, + const std::string &hostName); + + /** + * Returns the current list of administration hosts in lexicographical order. + * + * @param requester The identity of the user requesting the list. + * @return The current list of administration hosts in lexicographical order. + */ + virtual std::list<AdminHost> getAdminHosts(const SecurityIdentity &requester) + const; + + /** + * Creates the specified storage class. + * + * @param requester The identity of the user requesting the creation of the + * storage class. + * @param name The name of the storage class. + * @param nbCopies The number of copies a file associated with this storage + * class should have on tape. + * @param comment The comment describing the storage class. + */ + virtual void createStorageClass( + const SecurityIdentity &requester, + const std::string &name, + const uint8_t nbCopies, + const std::string &comment); + + /** + * Deletes the specified storage class. + * + * @param requester The identity of the user requesting the deletion of the + * storage class. + * @param name The name of the storage class. + */ + virtual void deleteStorageClass( + const SecurityIdentity &requester, + const std::string &name); + + /** + * Gets the current list of storage classes in lexicographical order. + * + * @param requester The identity of the user requesting the list. + * @return The current list of storage classes in lexicographical order. + */ + virtual std::list<StorageClass> getStorageClasses( + const SecurityIdentity &requester) const; + + /** + * Creates a tape pool with the specifed name. + * + * @param requester The identity of the user requesting the creation of the + * tape pool. + * @param name The name of the tape pool. + * @param nbDrives The maximum number of drives that can be concurrently + * assigned to this pool independent of whether they are archiving or + * retrieving files. + * @param nbPartialTapes The maximum number of tapes that can be partially + * full at any moment in time. + * @param comment The comment describing the tape pool. + */ + virtual void createTapePool( + const SecurityIdentity &requester, + const std::string &name, + const uint16_t nbDrives, + const uint32_t nbPartialTapes, + const std::string &comment); + + /** + * Delete the tape pool with the specifed name. + * + * @param requester The identity of the user requesting the deletion of the + * tape pool. + * @param name The name of the tape pool. + */ + virtual void deleteTapePool( + const SecurityIdentity &requester, + const std::string &name); + + /** + * Gets the current list of tape pools in lexicographical order. + * + * @param requester The identity of the user requesting the list. + * @return The current list of tape pools in lexicographical order. + */ + virtual std::list<TapePool> getTapePools( + const SecurityIdentity &requester) const; + + /** + * Creates the specified archive route. + * + * @param requester The identity of the user requesting the creation of the + * archive route. + * @param storageClassName The name of the storage class that identifies the + * source disk files. + * @param copyNb The tape copy number. + * @param tapePoolName The name of the destination tape pool. + * @param comment The comment describing the archive route. + */ + virtual void createArchiveRoute( + const SecurityIdentity &requester, + const std::string &storageClassName, + const uint8_t copyNb, + const std::string &tapePoolName, + const std::string &comment); + + /** + * Deletes the specified archive route. + * + * @param requester The identity of the user requesting the deletion of the + * archive route. + * @param storageClassName The name of the storage class that identifies the + * source disk files. + * @param copyNb The tape copy number. + */ + virtual void deleteArchiveRoute( + const SecurityIdentity &requester, + const std::string &storageClassName, + const uint8_t copyNb); + + /** + * Gets the current list of archive routes. + * + * @param requester The identity of the user requesting the list. + */ + virtual std::list<ArchiveRoute> getArchiveRoutes( + const SecurityIdentity &requester) const; + + /** + * Creates a logical library with the specified name. + * + * @param requester The identity of the user requesting the creation of the + * logical library. + * @param name The name of the logical library. + * @param comment The comment describing the logical library. + */ + virtual void createLogicalLibrary( + const SecurityIdentity &requester, + const std::string &name, + const std::string &comment); + + /** + * Deletes the logical library with the specified name. + * + * @param requester The identity of the user requesting the deletion of the + * logical library. + * @param name The name of the logical library. + */ + virtual void deleteLogicalLibrary( + const SecurityIdentity &requester, + const std::string &name); + + /** + * Returns the current list of libraries in lexicographical order. + * + * @param requester The identity of the user requesting the list. + * @return The current list of libraries in lexicographical order. + */ + virtual std::list<LogicalLibrary> getLogicalLibraries( + const SecurityIdentity &requester) const; + + /** + * Creates a tape. + * + * @param requester The identity of the user requesting the creation of the + * tape. + * @param vid The volume identifier of the tape. + * @param logicalLibrary The name of the logical library to which the tape + * belongs. + * @param tapePoolName The name of the tape pool to which the tape belongs. + * @param capacityInBytes The capacity of the tape. + * @param comment The comment describing the logical library. + */ + virtual void createTape( + const SecurityIdentity &requester, + const std::string &vid, + const std::string &logicalLibraryName, + const std::string &tapePoolName, + const uint64_t capacityInBytes, + const std::string &comment); + + /** + * Deletes the tape with the specified volume identifier. + * + * @param requester The identity of the user requesting the deletion of the + * tape. + * @param vid The volume identifier of the tape. + */ + virtual void deleteTape( + const SecurityIdentity &requester, + const std::string &vid); + + /** + * Returns the current list of tapes in the lexicographical order of their + * volume identifiers. + * + * @param requester The identity of the user requesting the list. + * @return The current list of tapes in the lexicographical order of their + * volume identifiers. + */ + virtual std::list<Tape> getTapes( + const SecurityIdentity &requester) const; + +private: + /** + * Reference to the backend used for storing objects + */ + objectstore::Backend & m_backend; +}; + +} + -- GitLab