diff --git a/catalogue/CMakeLists.txt b/catalogue/CMakeLists.txt index 1e3f20791e90d677d07028b7c736c8ded21786a7..4b077a5654d72b159dc0ec08c21b55be5a1480d0 100644 --- a/catalogue/CMakeLists.txt +++ b/catalogue/CMakeLists.txt @@ -25,8 +25,10 @@ set (CATALOGUE_LIB_SRC_FILES ArchiveFileItor.cpp ArchiveFileItorImpl.cpp Catalogue.cpp + CatalogueFactory.cpp CmdLineTool.cpp InMemoryCatalogue.cpp + OracleCatalogue.cpp SqliteCatalogueSchema.cpp TapeFileWritten.cpp RdbmsArchiveFileItorImpl.cpp @@ -35,11 +37,6 @@ set (CATALOGUE_LIB_SRC_FILES SqliteCatalogue.cpp TapeForWriting.cpp) -set (CATALOGUE_LIB_SRC_FILES - ${CATALOGUE_LIB_SRC_FILES} - CatalogueFactory.cpp - OracleCatalogue.cpp) - add_library (ctacatalogue SHARED ${CATALOGUE_LIB_SRC_FILES}) set_property(TARGET ctacatalogue PROPERTY SOVERSION "${CTA_SOVERSION}") diff --git a/catalogue/Catalogue.cpp b/catalogue/Catalogue.cpp index b958c14715ea9db3cfd5120fc646a7bd485a1536..a0866c30ba3a4f2894d03a13d37c25d1b4c554b3 100644 --- a/catalogue/Catalogue.cpp +++ b/catalogue/Catalogue.cpp @@ -21,12 +21,6 @@ namespace cta { namespace catalogue { -//------------------------------------------------------------------------------ -// constructor -//------------------------------------------------------------------------------ -Catalogue::Catalogue(log::Logger &log): m_log(log) { -} - //------------------------------------------------------------------------------ // destructor //------------------------------------------------------------------------------ diff --git a/catalogue/Catalogue.hpp b/catalogue/Catalogue.hpp index bdddd9746c18c8be659fda82ebe079d2f6f1cc5a..49502f95771f9f161f039e93bc88dc43ed83d98f 100644 --- a/catalogue/Catalogue.hpp +++ b/catalogue/Catalogue.hpp @@ -77,12 +77,6 @@ namespace catalogue { */ class Catalogue { public: - /** - * Constructor. - * - * @param log Object representing the API to the CTA logging system. - */ - Catalogue(log::Logger &log); /** * Destructor. @@ -128,6 +122,7 @@ public: * disabled, not full and are in the specified logical library. * * @param logicalLibraryName The name of the logical library. + * @return The list of tapes for writing. */ virtual std::list<TapeForWriting> getTapesForWriting(const std::string &logicalLibraryName) const = 0; @@ -585,13 +580,6 @@ public: */ virtual bool tapeExists(const std::string &vid) const = 0; -protected: - - /** - * Object representing the API to the CTA logging system. - */ - log::Logger &m_log; - }; // class Catalogue } // namespace catalogue diff --git a/catalogue/CatalogueFactory.cpp b/catalogue/CatalogueFactory.cpp index 7f16fb1228a589c0d126a1d51bb1cc190eb77fbd..5cceb8b39eb412ede3b2429784ecac86303b03f2 100644 --- a/catalogue/CatalogueFactory.cpp +++ b/catalogue/CatalogueFactory.cpp @@ -33,16 +33,18 @@ std::unique_ptr<Catalogue> CatalogueFactory::create( log::Logger &log, const rdbms::Login &login, const uint64_t nbConns, - const uint64_t nbArchiveFileListingConns) { + const uint64_t nbArchiveFileListingConns, + const uint32_t maxTriesToConnect) { try { switch(login.dbType) { case rdbms::Login::DBTYPE_IN_MEMORY: - return cta::make_unique<InMemoryCatalogue>(log, nbConns, nbArchiveFileListingConns); + return cta::make_unique<InMemoryCatalogue>(log, nbConns, nbArchiveFileListingConns, maxTriesToConnect); case rdbms::Login::DBTYPE_ORACLE: return cta::make_unique<OracleCatalogue>(log, login.username, login.password, login.database, nbConns, - nbArchiveFileListingConns); + nbArchiveFileListingConns, maxTriesToConnect); case rdbms::Login::DBTYPE_SQLITE: - return cta::make_unique<SqliteCatalogue>(log, login.database, nbConns, nbArchiveFileListingConns); + return cta::make_unique<SqliteCatalogue>(log, login.database, nbConns, nbArchiveFileListingConns, + maxTriesToConnect); case rdbms::Login::DBTYPE_NONE: throw exception::Exception("Cannot create a catalogue without a database type"); default: diff --git a/catalogue/CatalogueFactory.hpp b/catalogue/CatalogueFactory.hpp index d76d19461b68cc181f8ba81d70c9590cf9aa47e7..7c0cae56b3d15e3852be295900318deb5f8dc7de 100644 --- a/catalogue/CatalogueFactory.hpp +++ b/catalogue/CatalogueFactory.hpp @@ -51,12 +51,16 @@ public: * listing archive files. * @return The newly created CTA catalogue object. Please note that it is the * responsibility of the caller to delete the returned CTA catalogue object. + * @param maxTriesToConnext The maximum number of times a single method should + * try to connect to the database in the event of LostDatabaseConnection + * exceptions being thrown. */ static std::unique_ptr<Catalogue> create( log::Logger &log, const rdbms::Login &login, const uint64_t nbConns, - const uint64_t nbArchiveFileListingConns); + const uint64_t nbArchiveFileListingConns, + const uint32_t maxTriesToConnect = 3); }; // class CatalogueFactory diff --git a/catalogue/DummyCatalogue.hpp b/catalogue/DummyCatalogue.hpp index 1e84cf92ad86f38bf87a15faa58e339c9838da4f..008c80c32863c8c744eed87370a5c7b72bb501ec 100644 --- a/catalogue/DummyCatalogue.hpp +++ b/catalogue/DummyCatalogue.hpp @@ -31,7 +31,7 @@ namespace catalogue { */ class DummyCatalogue: public Catalogue { public: - DummyCatalogue(log::Logger &l): Catalogue(l) {} + DummyCatalogue() {} virtual ~DummyCatalogue() { } void createAdminHost(const common::dataStructures::SecurityIdentity& admin, const std::string& hostName, const std::string& comment) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); } diff --git a/catalogue/InMemoryCatalogue.cpp b/catalogue/InMemoryCatalogue.cpp index 69eeb195103a9fff734d880278768a63f91c97d6..03af6576982ec2b04ea022c2308ba3cb6340659d 100644 --- a/catalogue/InMemoryCatalogue.cpp +++ b/catalogue/InMemoryCatalogue.cpp @@ -27,8 +27,10 @@ namespace catalogue { InMemoryCatalogue::InMemoryCatalogue( log::Logger &log, const uint64_t nbConns, - const uint64_t nbArchiveFileListingConns): - SchemaCreatingSqliteCatalogue(log, "file::memory:?cache=shared", nbConns, nbArchiveFileListingConns) { + const uint64_t nbArchiveFileListingConns, + const uint32_t maxTriesToConnect): + SchemaCreatingSqliteCatalogue(log, "file::memory:?cache=shared", nbConns, nbArchiveFileListingConns, + maxTriesToConnect) { } //------------------------------------------------------------------------------ diff --git a/catalogue/InMemoryCatalogue.hpp b/catalogue/InMemoryCatalogue.hpp index 6605647dcbc0cde497d75e1ff22c2a29f4a04bdc..06376bd981f3843afb3cd46ca91eebbd4533017a 100644 --- a/catalogue/InMemoryCatalogue.hpp +++ b/catalogue/InMemoryCatalogue.hpp @@ -41,11 +41,15 @@ public: * @param nbArchiveFileListingConns The maximum number of concurrent * connections to the underlying relational database for the sole purpose of * listing archive files. + * @param maxTriesToConnext The maximum number of times a single method should + * try to connect to the database in the event of LostDatabaseConnection + * exceptions being thrown. */ InMemoryCatalogue( log::Logger &log, const uint64_t nbConns, - const uint64_t nbArchiveFileListingConns); + const uint64_t nbArchiveFileListingConns, + const uint32_t maxTriesToConnect); /** * Destructor. diff --git a/catalogue/InMemoryCatalogueTest.cpp b/catalogue/InMemoryCatalogueTest.cpp index 51372829814ce52e91bce7ec0f61af8a39b3dca5..24f58e9e0ab47df8a676c100a85c64ba7d2a4156 100644 --- a/catalogue/InMemoryCatalogueTest.cpp +++ b/catalogue/InMemoryCatalogueTest.cpp @@ -39,15 +39,16 @@ TEST_F(cta_catalogue_InMemoryCatalogue, createSameSchemaInTwoSeparateInMemoryDat log::DummyLogger dummyLog("dummy"); const uint64_t nbConns = 1; const uint64_t nbArchiveFileListingConns = 0; + const uint32_t maxTriesToConnect = 1; // First in-memory database { - catalogue::InMemoryCatalogue inMemoryCatalogue(dummyLog, nbConns, nbArchiveFileListingConns); + catalogue::InMemoryCatalogue inMemoryCatalogue(dummyLog, nbConns, nbArchiveFileListingConns, maxTriesToConnect); } // Second in-memory database { - catalogue::InMemoryCatalogue inMemoryCatalogue(dummyLog, nbConns, nbArchiveFileListingConns); + catalogue::InMemoryCatalogue inMemoryCatalogue(dummyLog, nbConns, nbArchiveFileListingConns, maxTriesToConnect); } } diff --git a/catalogue/OracleCatalogue.cpp b/catalogue/OracleCatalogue.cpp index 308baaea692a8ca488bdffec41bd9d66736218c1..d8b6d840bfebf4b61bec5d89eb3968a075a0c2b8 100644 --- a/catalogue/OracleCatalogue.cpp +++ b/catalogue/OracleCatalogue.cpp @@ -18,8 +18,10 @@ #include "catalogue/ArchiveFileRow.hpp" #include "catalogue/OracleCatalogue.hpp" -#include "common/exception/UserError.hpp" +#include "catalogue/retryOnLostConnection.hpp" #include "common/exception/Exception.hpp" +#include "common/exception/LostDatabaseConnection.hpp" +#include "common/exception/UserError.hpp" #include "common/make_unique.hpp" #include "common/threading/MutexLocker.hpp" #include "common/Timer.hpp" @@ -118,13 +120,14 @@ OracleCatalogue::OracleCatalogue( const std::string &password, const std::string &database, const uint64_t nbConns, - const uint64_t nbArchiveFileListingConns): + const uint64_t nbArchiveFileListingConns, + const uint32_t maxTriesToConnect): RdbmsCatalogue( log, rdbms::Login(rdbms::Login::DBTYPE_ORACLE, username, password, database), nbConns, - nbArchiveFileListingConns) { - + nbArchiveFileListingConns, + maxTriesToConnect) { } //------------------------------------------------------------------------------ @@ -137,6 +140,15 @@ OracleCatalogue::~OracleCatalogue() { // deleteArchiveFile //------------------------------------------------------------------------------ void OracleCatalogue::deleteArchiveFile(const std::string &diskInstanceName, const uint64_t archiveFileId, + log::LogContext &lc) { + return retryOnLostConnection(m_log, [&]{return deleteArchiveFileInternal(diskInstanceName, archiveFileId, lc);}, + m_maxTriesToConnect); +} + +//------------------------------------------------------------------------------ +// deleteArchiveFileInternal +//------------------------------------------------------------------------------ +void OracleCatalogue::deleteArchiveFileInternal(const std::string &diskInstanceName, const uint64_t archiveFileId, log::LogContext &lc) { try { const char *selectSql = @@ -169,6 +181,7 @@ void OracleCatalogue::deleteArchiveFile(const std::string &diskInstanceName, con "FOR UPDATE"; utils::Timer t; auto conn = m_connPool.getConn(); + rdbms::AutoRollback autoRollback(conn); const auto getConnTime = t.secs(utils::Timer::resetCounter); auto selectStmt = conn.createStmt(selectSql, rdbms::AutocommitMode::OFF); const auto createStmtTime = t.secs(); @@ -315,6 +328,8 @@ void OracleCatalogue::deleteArchiveFile(const std::string &diskInstanceName, con spc.add("TAPE FILE", tapeCopyLogStream.str()); } lc.log(log::INFO, "Archive file deleted from CTA catalogue"); + } catch(exception::LostDatabaseConnection &le) { + throw exception::LostDatabaseConnection(std::string(__FUNCTION__) + " failed: " + le.getMessage().str()); } catch(exception::UserError &) { throw; } catch(exception::Exception &ex) { @@ -327,8 +342,17 @@ void OracleCatalogue::deleteArchiveFile(const std::string &diskInstanceName, con //------------------------------------------------------------------------------ void OracleCatalogue::deleteArchiveFileByDiskFileId(const std::string &diskInstanceName, const std::string &diskFileId, log::LogContext &lc) { + return retryOnLostConnection(m_log, [&]{return deleteArchiveFileByDiskFileIdInternal(diskInstanceName, diskFileId, + lc);}, m_maxTriesToConnect); +} + +//------------------------------------------------------------------------------ +// deleteArchiveFileByDiskFileIdInternal +//------------------------------------------------------------------------------ +void OracleCatalogue::deleteArchiveFileByDiskFileIdInternal(const std::string &diskInstanceName, + const std::string &diskFileId, log::LogContext &lc) { try { - const char *selectSql = + const char *const selectSql = "SELECT " "ARCHIVE_FILE.ARCHIVE_FILE_ID AS ARCHIVE_FILE_ID," "ARCHIVE_FILE.DISK_INSTANCE_NAME AS DISK_INSTANCE_NAME," @@ -465,6 +489,8 @@ void OracleCatalogue::deleteArchiveFileByDiskFileId(const std::string &diskInsta spc.add("TAPE FILE", tapeCopyLogStream.str()); } lc.log(log::INFO, "Archive file deleted from CTA catalogue"); + } catch(exception::LostDatabaseConnection &le) { + throw exception::LostDatabaseConnection(std::string(__FUNCTION__) + " failed: " + le.getMessage().str()); } catch(exception::UserError &) { throw; } catch(exception::Exception &ex) { @@ -591,6 +617,13 @@ common::dataStructures::Tape OracleCatalogue::selectTapeForUpdate(rdbms::Conn &c // filesWrittenToTape //------------------------------------------------------------------------------ void OracleCatalogue::filesWrittenToTape(const std::set<TapeFileWritten> &events) { + return retryOnLostConnection(m_log, [&]{return filesWrittenToTapeInternal(events);}, m_maxTriesToConnect); +} + +//------------------------------------------------------------------------------ +// filesWrittenToTapeInternal +//------------------------------------------------------------------------------ +void OracleCatalogue::filesWrittenToTapeInternal(const std::set<TapeFileWritten> &events) { try { if (events.empty()) { return; @@ -692,6 +725,8 @@ void OracleCatalogue::filesWrittenToTape(const std::set<TapeFileWritten> &events conn.commit(); + } catch(exception::LostDatabaseConnection &le) { + throw exception::LostDatabaseConnection(std::string(__FUNCTION__) + " failed: " + le.getMessage().str()); } catch(exception::Exception &ex) { throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str()); } catch(std::exception &se) { diff --git a/catalogue/OracleCatalogue.hpp b/catalogue/OracleCatalogue.hpp index 99a404752a8cb398e46e9fb007840298676dc9ce..3823ce0b423bf999ee8bd6a6751545128f81b763 100644 --- a/catalogue/OracleCatalogue.hpp +++ b/catalogue/OracleCatalogue.hpp @@ -21,14 +21,9 @@ #include "catalogue/RdbmsCatalogue.hpp" #include "rdbms/Conn.hpp" -#include <occi.h> -#include <string.h> - namespace cta { namespace catalogue { -class CatalogueFactory; - /** * An Oracle based implementation of the CTA catalogue. */ @@ -48,6 +43,9 @@ public: * @param nbArchiveFileListingConns The maximum number of concurrent * connections to the underlying relational database for the sole purpose of * listing archive files. + * @param maxTriesToConnext The maximum number of times a single method should + * try to connect to the database in the event of LostDatabaseConnection + * exceptions being thrown. */ OracleCatalogue( log::Logger &log, @@ -55,7 +53,8 @@ public: const std::string &password, const std::string &database, const uint64_t nbConns, - const uint64_t nbArchiveFileListingConns); + const uint64_t nbArchiveFileListingConns, + const uint32_t maxTriesToConnect = 3); /** * Destructor. @@ -127,6 +126,64 @@ public: private: + /** + * Deletes the specified archive file and its associated tape copies from the + * catalogue. + * + * Please note that the name of the disk instance is specified in order to + * prevent a disk instance deleting an archive file that belongs to another + * disk instance. + * + * Please note that this method is idempotent. If the file to be deleted does + * not exist in the CTA catalogue then this method returns without error. + * + * This internal method can be re-tried if it throws a LostDatabaseConnection + * exception. + * + * @param instanceName The name of the instance from where the deletion request + * originated + * @param archiveFileId The unique identifier of the archive file. + * @param lc The log context. + * @return The metadata of the deleted archive file including the metadata of + * the associated and also deleted tape copies. + */ + void deleteArchiveFileInternal(const std::string &diskInstanceName, const uint64_t archiveFileId, + log::LogContext &lc); + + /** + * Deletes the specified archive file and its associated tape copies from the + * catalogue. + * + * Please note that this method is idempotent. If the file to be deleted does + * not exist in the CTA catalogue then this method returns without error. + * + * This internal method can be re-tried if it throws a LostDatabaseConnection + * exception. + * + * @param diskInstanceName The name of the instance from where the deletion + * request originated + * @param diskFileId The identifier of the source disk file which is unique + * within it's host disk system. Two files from different disk systems may + * have the same identifier. The combination of diskInstanceName and + * diskFileId must be globally unique, in other words unique within the CTA + * catalogue. + * @param lc The log context. + * @return The metadata of the deleted archive file including the metadata of + * the associated and also deleted tape copies. + */ + void deleteArchiveFileByDiskFileIdInternal(const std::string &diskInstanceName, const std::string &diskFileId, + log::LogContext &lc); + + /** + * Notifies the catalogue that the specified files have been written to tape. + * + * This internal method can be re-tried if it throws a LostDatabaseConnection + * exception. + * + * @param events The tape file written events. + */ + void filesWrittenToTapeInternal(const std::set<TapeFileWritten> &events); + /** * Selects the specified tape within the Tape table for update. * diff --git a/catalogue/RdbmsCatalogue.cpp b/catalogue/RdbmsCatalogue.cpp index 39415e5cc38048cadfcd2f4df3b861df856d6901..cdea6a3a304c45e5ad1722d23782b59c99166e58 100644 --- a/catalogue/RdbmsCatalogue.cpp +++ b/catalogue/RdbmsCatalogue.cpp @@ -19,6 +19,7 @@ #include "catalogue/ArchiveFileRow.hpp" #include "catalogue/RdbmsArchiveFileItorImpl.hpp" #include "catalogue/RdbmsCatalogue.hpp" +#include "catalogue/retryOnLostConnection.hpp" #include "catalogue/SqliteCatalogueSchema.hpp" #include "common/dataStructures/TapeFile.hpp" #include "common/exception/Exception.hpp" @@ -32,6 +33,7 @@ #include <ctype.h> #include <memory> #include <time.h> +#include <common/exception/LostDatabaseConnection.hpp> namespace cta { namespace catalogue { @@ -43,10 +45,12 @@ RdbmsCatalogue::RdbmsCatalogue( log::Logger &log, const rdbms::Login &login, const uint64_t nbConns, - const uint64_t nbArchiveFileListingConns): - Catalogue(log), + const uint64_t nbArchiveFileListingConns, + const uint32_t maxTriesToConnect): + m_log(log), m_connPool(login, nbConns), - m_archiveFileListingConnPool(login, nbArchiveFileListingConns) { + m_archiveFileListingConnPool(login, nbArchiveFileListingConns), + m_maxTriesToConnect(maxTriesToConnect) { } //------------------------------------------------------------------------------ @@ -2190,6 +2194,13 @@ void RdbmsCatalogue::modifyTapeEncryptionKey(const common::dataStructures::Secur // tapeMountedForArchive //------------------------------------------------------------------------------ void RdbmsCatalogue::tapeMountedForArchive(const std::string &vid, const std::string &drive) { + return retryOnLostConnection(m_log, [&]{return tapeMountedForArchiveInternal(vid, drive);}, m_maxTriesToConnect); +} + +//------------------------------------------------------------------------------ +// tapeMountedForArchiveInternal +//------------------------------------------------------------------------------ +void RdbmsCatalogue::tapeMountedForArchiveInternal(const std::string &vid, const std::string &drive) { try { const time_t now = time(nullptr); const char *const sql = @@ -2205,9 +2216,11 @@ void RdbmsCatalogue::tapeMountedForArchive(const std::string &vid, const std::st stmt.bindString(":VID", vid); stmt.executeNonQuery(); - if(0 == stmt.getNbAffectedRows()) { + if (0 == stmt.getNbAffectedRows()) { throw exception::UserError(std::string("Cannot modify tape ") + vid + " because it does not exist"); } + } catch(exception::LostDatabaseConnection &le) { + throw exception::LostDatabaseConnection(std::string(__FUNCTION__) + "failed: " + le.getMessage().str()); } catch(exception::UserError &) { throw; } catch (exception::Exception &ex) { @@ -2219,6 +2232,13 @@ void RdbmsCatalogue::tapeMountedForArchive(const std::string &vid, const std::st // tapeMountedForRetrieve //------------------------------------------------------------------------------ void RdbmsCatalogue::tapeMountedForRetrieve(const std::string &vid, const std::string &drive) { + return retryOnLostConnection(m_log, [&]{return tapeMountedForRetrieveInternal(vid, drive);}, m_maxTriesToConnect); +} + +//------------------------------------------------------------------------------ +// tapeMountedForRetrieveInternal +//------------------------------------------------------------------------------ +void RdbmsCatalogue::tapeMountedForRetrieveInternal(const std::string &vid, const std::string &drive) { try { const time_t now = time(nullptr); const char *const sql = @@ -2237,6 +2257,8 @@ void RdbmsCatalogue::tapeMountedForRetrieve(const std::string &vid, const std::s if(0 == stmt.getNbAffectedRows()) { throw exception::UserError(std::string("Cannot modify tape ") + vid + " because it does not exist"); } + } catch(exception::LostDatabaseConnection &le) { + throw exception::LostDatabaseConnection(std::string(__FUNCTION__) + "failed: " + le.getMessage().str()); } catch(exception::UserError &) { throw; } catch (exception::Exception &ex) { @@ -2282,6 +2304,13 @@ void RdbmsCatalogue::setTapeFull(const common::dataStructures::SecurityIdentity // noSpaceLeftOnTape //------------------------------------------------------------------------------ void RdbmsCatalogue::noSpaceLeftOnTape(const std::string &vid) { + return retryOnLostConnection(m_log, [&]{return noSpaceLeftOnTapeInternal(vid);}, m_maxTriesToConnect); +} + +//------------------------------------------------------------------------------ +// noSpaceLeftOnTapeInternal +//------------------------------------------------------------------------------ +void RdbmsCatalogue::noSpaceLeftOnTapeInternal(const std::string &vid) { try { const char *const sql = "UPDATE TAPE SET " @@ -2293,9 +2322,11 @@ void RdbmsCatalogue::noSpaceLeftOnTape(const std::string &vid) { stmt.bindString(":VID", vid); stmt.executeNonQuery(); - if(0 == stmt.getNbAffectedRows()) { + if (0 == stmt.getNbAffectedRows()) { throw exception::Exception(std::string("Tape ") + vid + " does not exist"); } + } catch (exception::LostDatabaseConnection &le) { + throw exception::LostDatabaseConnection(std::string(__FUNCTION__) + " failed: " + le.getMessage().str()); } catch (exception::Exception &ex) { throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str()); } @@ -3747,6 +3778,13 @@ common::dataStructures::ArchiveFile RdbmsCatalogue::getArchiveFileById(const uin // tapeLabelled //------------------------------------------------------------------------------ void RdbmsCatalogue::tapeLabelled(const std::string &vid, const std::string &drive, const bool lbpIsOn) { + return retryOnLostConnection(m_log, [&]{return tapeLabelledInternal(vid, drive, lbpIsOn);}, m_maxTriesToConnect); +} + +//------------------------------------------------------------------------------ +// tapeLabelledInternal +//------------------------------------------------------------------------------ +void RdbmsCatalogue::tapeLabelledInternal(const std::string &vid, const std::string &drive, const bool lbpIsOn) { try { const time_t now = time(nullptr); const char *const sql = @@ -3767,6 +3805,8 @@ void RdbmsCatalogue::tapeLabelled(const std::string &vid, const std::string &dri if(0 == stmt.getNbAffectedRows()) { throw exception::UserError(std::string("Cannot modify tape ") + vid + " because it does not exist"); } + } catch(exception::LostDatabaseConnection &le) { + throw exception::LostDatabaseConnection(std::string(__FUNCTION__) + " failed: " + le.getMessage().str()); } catch(exception::UserError &) { throw; } catch (exception::Exception &ex) { @@ -3779,6 +3819,16 @@ void RdbmsCatalogue::tapeLabelled(const std::string &vid, const std::string &dri //------------------------------------------------------------------------------ common::dataStructures::ArchiveFileQueueCriteria RdbmsCatalogue::prepareForNewFile(const std::string &diskInstanceName, const std::string &storageClassName, const common::dataStructures::UserIdentity &user) { + return retryOnLostConnection( m_log, [&]{return prepareForNewFileInternal(diskInstanceName, storageClassName, user);}, + m_maxTriesToConnect); +} + +//------------------------------------------------------------------------------ +// prepareForNewFileInternal +//------------------------------------------------------------------------------ +common::dataStructures::ArchiveFileQueueCriteria RdbmsCatalogue::prepareForNewFileInternal( + const std::string &diskInstanceName, const std::string &storageClassName, + const common::dataStructures::UserIdentity &user) { try { auto conn = m_connPool.getConn(); const common::dataStructures::TapeCopyToPoolMap copyToPoolMap = getTapeCopyToPoolMap(conn, diskInstanceName, @@ -3816,10 +3866,12 @@ common::dataStructures::ArchiveFileQueueCriteria RdbmsCatalogue::prepareForNewFi } // Now that we have both the archive routes and the mount policy it's safe to - // consume an archive file identifierarchiveFileId + // consume an archive file identifier const uint64_t archiveFileId = getNextArchiveFileId(conn); return common::dataStructures::ArchiveFileQueueCriteria(archiveFileId, copyToPoolMap, mountPolicy); + } catch(exception::LostDatabaseConnection &le) { + throw exception::LostDatabaseConnection(std::string(__FUNCTION__) + " failed: " + le.getMessage().str()); } catch(exception::UserError &) { throw; } catch(exception::Exception &ex) { @@ -3922,6 +3974,18 @@ void RdbmsCatalogue::updateTape( // prepareToRetrieveFile //------------------------------------------------------------------------------ common::dataStructures::RetrieveFileQueueCriteria RdbmsCatalogue::prepareToRetrieveFile( + const std::string &diskInstanceName, + const uint64_t archiveFileId, + const common::dataStructures::UserIdentity &user, + log::LogContext &lc) { + return retryOnLostConnection( m_log, [&]{return prepareToRetrieveFileInternal(diskInstanceName, archiveFileId, user, + lc);}, m_maxTriesToConnect); +} + +//------------------------------------------------------------------------------ +// prepareToRetrieveFileInternal +//------------------------------------------------------------------------------ +common::dataStructures::RetrieveFileQueueCriteria RdbmsCatalogue::prepareToRetrieveFileInternal( const std::string &diskInstanceName, const uint64_t archiveFileId, const common::dataStructures::UserIdentity &user, @@ -3975,6 +4039,8 @@ common::dataStructures::RetrieveFileQueueCriteria RdbmsCatalogue::prepareToRetri criteria.archiveFile = *archiveFile; criteria.mountPolicy = mountPolicy; return criteria; + } catch(exception::LostDatabaseConnection &le) { + throw exception::LostDatabaseConnection(std::string(__FUNCTION__) + " failed: " + le.getMessage().str()); } catch(exception::UserError &) { throw; } catch(exception::Exception &ex) { @@ -3986,6 +4052,18 @@ common::dataStructures::RetrieveFileQueueCriteria RdbmsCatalogue::prepareToRetri // prepareToRetrieveFileByDiskFileId //------------------------------------------------------------------------------ common::dataStructures::RetrieveFileQueueCriteria RdbmsCatalogue::prepareToRetrieveFileByDiskFileId( + const std::string &diskInstanceName, + const std::string &diskFileId, + const common::dataStructures::UserIdentity &user, + log::LogContext &lc) { + return retryOnLostConnection( m_log, [&]{return prepareToRetrieveFileByDiskFileIdInternal(diskInstanceName, + diskFileId, user, lc);}, m_maxTriesToConnect); +} + +//------------------------------------------------------------------------------ +// prepareToRetrieveFileByDiskFileIdInternal +//------------------------------------------------------------------------------ +common::dataStructures::RetrieveFileQueueCriteria RdbmsCatalogue::prepareToRetrieveFileByDiskFileIdInternal( const std::string &diskInstanceName, const std::string &diskFileId, const common::dataStructures::UserIdentity &user, @@ -4033,6 +4111,8 @@ common::dataStructures::RetrieveFileQueueCriteria RdbmsCatalogue::prepareToRetri criteria.archiveFile = *archiveFile; criteria.mountPolicy = mountPolicy; return criteria; + } catch(exception::LostDatabaseConnection &le) { + throw exception::LostDatabaseConnection(std::string(__FUNCTION__) + " failed: " + le.getMessage().str()); } catch(exception::UserError &) { throw; } catch(exception::Exception &ex) { @@ -4146,8 +4226,23 @@ RequesterAndGroupMountPolicies RdbmsCatalogue::getMountPolicies( // isAdmin //------------------------------------------------------------------------------ bool RdbmsCatalogue::isAdmin(const common::dataStructures::SecurityIdentity &admin) const { - auto conn = m_connPool.getConn(); - return userIsAdmin(conn, admin.username) && hostIsAdmin(conn, admin.host); + return retryOnLostConnection(m_log, [&]{return isAdminInternal(admin);}, m_maxTriesToConnect); +} + +//------------------------------------------------------------------------------ +// isAdminInternal +//------------------------------------------------------------------------------ +bool RdbmsCatalogue::isAdminInternal(const common::dataStructures::SecurityIdentity &admin) const { + try { + auto conn = m_connPool.getConn(); + return userIsAdmin(conn, admin.username) && hostIsAdmin(conn, admin.host); + } catch(exception::LostDatabaseConnection &le) { + throw exception::LostDatabaseConnection(std::string(__FUNCTION__) + " failed: " + le.getMessage().str()); + } catch(exception::UserError &) { + throw; + } catch(exception::Exception &ex) { + throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str()); + } } //------------------------------------------------------------------------------ @@ -4188,6 +4283,13 @@ bool RdbmsCatalogue::hostIsAdmin(rdbms::Conn &conn, const std::string &hostName) // getTapesForWriting //------------------------------------------------------------------------------ std::list<TapeForWriting> RdbmsCatalogue::getTapesForWriting(const std::string &logicalLibraryName) const { + return retryOnLostConnection(m_log, [&]{return getTapesForWritingInternal(logicalLibraryName);}, m_maxTriesToConnect); +} + +//------------------------------------------------------------------------------ +// getTapesForWritingInternal +//------------------------------------------------------------------------------ +std::list<TapeForWriting> RdbmsCatalogue::getTapesForWritingInternal(const std::string &logicalLibraryName) const { try { std::list<TapeForWriting> tapes; const char *const sql = @@ -4197,15 +4299,16 @@ std::list<TapeForWriting> RdbmsCatalogue::getTapesForWriting(const std::string & "CAPACITY_IN_BYTES AS CAPACITY_IN_BYTES," "DATA_IN_BYTES AS DATA_IN_BYTES," "LAST_FSEQ AS LAST_FSEQ " - "FROM " + "FROM " "TAPE " - "WHERE " + "WHERE " // "LBP_IS_ON IS NOT NULL AND " // Set when the tape has been labelled // "LABEL_DRIVE IS NOT NULL AND " // Set when the tape has been labelled // "LABEL_TIME IS NOT NULL AND " // Set when the tape has been labelled "IS_DISABLED = 0 AND " "IS_FULL = 0 AND " "LOGICAL_LIBRARY_NAME = :LOGICAL_LIBRARY_NAME"; + auto conn = m_connPool.getConn(); auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); stmt.bindString(":LOGICAL_LIBRARY_NAME", logicalLibraryName); @@ -4220,8 +4323,9 @@ std::list<TapeForWriting> RdbmsCatalogue::getTapesForWriting(const std::string & tapes.push_back(tape); } - return tapes; + } catch(exception::LostDatabaseConnection &le) { + throw exception::LostDatabaseConnection(std::string(__FUNCTION__) + " failed: " + le.getMessage().str()); } catch(exception::Exception &ex) { throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str()); } diff --git a/catalogue/RdbmsCatalogue.hpp b/catalogue/RdbmsCatalogue.hpp index 738b78b4b8cc7060ec8b37226dd2e5ca1f2835b1..d15b4dfefd207f53c3019edce2857362eca98364 100644 --- a/catalogue/RdbmsCatalogue.hpp +++ b/catalogue/RdbmsCatalogue.hpp @@ -70,12 +70,16 @@ protected: * @param nbArchiveFileListingConns The maximum number of concurrent * connections to the underlying relational database for the sole purpose of * listing archive files. + * @param maxTriesToConnext The maximum number of times a single method should + * try to connect to the database in the event of LostDatabaseConnection + * exceptions being thrown. */ RdbmsCatalogue( log::Logger &log, const rdbms::Login &login, const uint64_t nbConns, - const uint64_t nbArchiveFileListingConns); + const uint64_t nbArchiveFileListingConns, + const uint32_t maxTriesToConnect); public: @@ -123,6 +127,7 @@ public: * disabled, not full and are in the specified logical library. * * @param logicalLibraryName The name of the logical library. + * @return The list of tapes for writing. */ std::list<TapeForWriting> getTapesForWriting(const std::string &logicalLibraryName) const override; @@ -529,6 +534,11 @@ public: protected: + /** + * Object representing the API to the CTA logging system. + */ + log::Logger &m_log; + /** * Mutex to be used to a take a global lock on the database. */ @@ -547,6 +557,12 @@ protected: */ mutable rdbms::ConnPool m_archiveFileListingConnPool; + /** + * The maximum number of times a single method should try to connect to the + * database in the event of LostDatabaseConnection exceptions being thrown. + */ + uint32_t m_maxTriesToConnect; + /** * Returns true if the specified admin user exists. * @@ -969,6 +985,155 @@ protected: */ void checkTapeFileWrittenFieldsAreSet(const TapeFileWritten &event); + /** + * Returns true if the specified user running the CTA command-line tool on + * the specified host has administrator privileges. + * + * This internal method can be re-tried if it throws a LostDatabaseConnection + * exception. + * + * @param admin The administrator. + * @return True if the specified user running the CTA command-line tool on + * the specified host has administrator privileges. + */ + bool isAdminInternal(const common::dataStructures::SecurityIdentity &admin) const; + + /** + * Notifies the catalogue that the specified tape was labelled. + * + * @param vid The volume identifier of the tape. + * @param drive The name of tape drive that was used to label the tape. + * @param lbpIsOn Set to true if Logical Block Protection (LBP) was enabled. + */ + void tapeLabelledInternal(const std::string &vid, const std::string &drive, const bool lbpIsOn); + + /** + * Returns the list of tapes that can be written to by a tape drive in the + * specified logical library, in other words tapes that are labelled, not + * disabled, not full and are in the specified logical library. + * + * This internal method can be re-tried if it throws a LostDatabaseConnection + * exception. + * + * @param logicalLibraryName The name of the logical library. + * @return The list of tapes for writing. + */ + std::list<TapeForWriting> getTapesForWritingInternal(const std::string &logicalLibraryName) const; + + /** + * Notifies the CTA catalogue that the specified tape has been mounted in + * order to archive files. + * + * The purpose of this method is to keep track of which drive mounted a given + * tape for archiving files last. + * + * This internal method can be re-tried if it throws a LostDatabaseConnection + * exception. + * + * @param vid The volume identifier of the tape. + * @param drive The name of the drive where the tape was mounted. + */ + void tapeMountedForArchiveInternal(const std::string &vid, const std::string &drive); + + /** + * Prepares for a file retrieval by returning the information required to + * queue the associated retrieve request(s). + * + * This internal method can be re-tried if it throws a LostDatabaseConnection + * exception. + * + * @param diskInstanceName The name of the instance from where the retrieval + * request originated + * @param archiveFileId The unique identifier of the archived file that is + * to be retrieved. + * @param user The user for whom the file is to be retrieved. This will be + * used by the Catalogue to determine the mount policy to be used when + * retrieving the file. + * @param lc The log context. + * + * @return The information required to queue the associated retrieve request(s). + */ + common::dataStructures::RetrieveFileQueueCriteria prepareToRetrieveFileInternal( + const std::string &diskInstanceName, + const uint64_t archiveFileId, + const common::dataStructures::UserIdentity &user, + log::LogContext &lc); + + /** + * Prepares for a file retrieval by returning the information required to + * queue the associated retrieve request(s). + * + * This internal method can be re-tried if it throws a LostDatabaseConnection + * exception. + * + * @param diskInstanceName The name of the instance from where the retrieval + * request originated + * @param diskFileId The identifier of the source disk file which is unique + * within it's host disk system. Two files from different disk systems may + * have the same identifier. The combination of diskInstanceName and + * diskFileId must be globally unique, in other words unique within the CTA + * catalogue. + * @param archiveFileId The unique identifier of the archived file that is + * to be retrieved. + * @param user The user for whom the file is to be retrieved. This will be + * used by the Catalogue to determine the mount policy to be used when + * retrieving the file. + * @param lc The log context. + * + * @return The information required to queue the associated retrieve request(s). + */ + common::dataStructures::RetrieveFileQueueCriteria prepareToRetrieveFileByDiskFileIdInternal( + const std::string &diskInstanceName, + const std::string &diskFileId, + const common::dataStructures::UserIdentity &user, + log::LogContext &lc); + + /** + * Notifies the CTA catalogue that the specified tape has been mounted in + * order to retrieve files. + * + * The purpose of this method is to keep track of which drive mounted a given + * tape for retrieving files last. + * + * This internal method can be re-tried if it throws a LostDatabaseConnection + * exception. + * + * @param vid The volume identifier of the tape. + * @param drive The name of the drive where the tape was mounted. + */ + void tapeMountedForRetrieveInternal(const std::string &vid, const std::string &drive); + + /** + * This method notifies the CTA catalogue that there is no more free space on + * the specified tape. + * + * @param vid The volume identifier of the tape. + */ + void noSpaceLeftOnTapeInternal(const std::string &vid); + + /** + * Prepares the catalogue for a new archive file and returns the information + * required to queue the associated archive request. + * + * This internal method can be re-tried if it throws a LostDatabaseConnection + * exception. + * + * @param diskInstanceName The name of the disk instance to which the + * storage class belongs. + * @param storageClassName The name of the storage class of the file to be + * archived. The storage class name is only guaranteed to be unique within + * its disk instance. The storage class name will be used by the Catalogue + * to determine the destination tape pool for each tape copy. + * @param user The user for whom the file is to be archived. This will be + * used by the Catalogue to determine the mount policy to be used when + * archiving the file. + * @return The information required to queue the associated archive request. + */ + common::dataStructures::ArchiveFileQueueCriteria prepareForNewFileInternal( + const std::string &diskInstanceName, + const std::string &storageClassName, + const common::dataStructures::UserIdentity &user); + }; // class RdbmsCatalogue } // namespace catalogue diff --git a/catalogue/SchemaCreatingSqliteCatalogue.cpp b/catalogue/SchemaCreatingSqliteCatalogue.cpp index e492e78fb9e7146f972d76535482cdc3e4c7d8d0..dd236e42d373c2a62657a325dd3cbe84dc2a291d 100644 --- a/catalogue/SchemaCreatingSqliteCatalogue.cpp +++ b/catalogue/SchemaCreatingSqliteCatalogue.cpp @@ -29,8 +29,9 @@ SchemaCreatingSqliteCatalogue::SchemaCreatingSqliteCatalogue( log::Logger &log, const std::string &filename, const uint64_t nbConns, - const uint64_t nbArchiveFileListingConns): - SqliteCatalogue(log, filename, nbConns, nbArchiveFileListingConns) { + const uint64_t nbArchiveFileListingConns, + const uint32_t maxTriesToConnect): + SqliteCatalogue(log, filename, nbConns, nbArchiveFileListingConns, maxTriesToConnect) { try { createCatalogueSchema(); } catch(exception::Exception &ex) { diff --git a/catalogue/SchemaCreatingSqliteCatalogue.hpp b/catalogue/SchemaCreatingSqliteCatalogue.hpp index fe265c3932deb6fb38d00a91ba58f33e23c9b368..790f1bafd3ae0766c4b6319b84f2022af6927f8b 100644 --- a/catalogue/SchemaCreatingSqliteCatalogue.hpp +++ b/catalogue/SchemaCreatingSqliteCatalogue.hpp @@ -42,12 +42,16 @@ public: * @param nbArchiveFileListingConns The maximum number of concurrent * connections to the underlying relational database for the sole purpose of * listing archive files. + * @param maxTriesToConnext The maximum number of times a single method should + * try to connect to the database in the event of LostDatabaseConnection + * exceptions being thrown. */ SchemaCreatingSqliteCatalogue( log::Logger &log, const std::string &filename, const uint64_t nbConns, - const uint64_t nbArchiveFileListingConns); + const uint64_t nbArchiveFileListingConns, + const uint32_t maxTriesToConnect); /** * Destructor. diff --git a/catalogue/SqliteCatalogue.cpp b/catalogue/SqliteCatalogue.cpp index b923e49f71facba47e5d335dcf51427718d1487e..6ed110590118180bcbb7efbefccb6ff867891f3c 100644 --- a/catalogue/SqliteCatalogue.cpp +++ b/catalogue/SqliteCatalogue.cpp @@ -37,12 +37,14 @@ SqliteCatalogue::SqliteCatalogue( log::Logger &log, const std::string &filename, const uint64_t nbConns, - const uint64_t nbArchiveFileListingConns): + const uint64_t nbArchiveFileListingConns, + const uint32_t maxTriesToConnect): RdbmsCatalogue( log, rdbms::Login(rdbms::Login::DBTYPE_SQLITE, "", "", filename), nbConns, - nbArchiveFileListingConns) { + nbArchiveFileListingConns, + maxTriesToConnect) { } //------------------------------------------------------------------------------ diff --git a/catalogue/SqliteCatalogue.hpp b/catalogue/SqliteCatalogue.hpp index a1d8d966d7f856f39ab7fb123f1deb3026e976ee..db78c06be4dba1f88b040968caa942be48556548 100644 --- a/catalogue/SqliteCatalogue.hpp +++ b/catalogue/SqliteCatalogue.hpp @@ -42,12 +42,16 @@ public: * @param nbArchiveFileListingConns The maximum number of concurrent * connections to the underlying relational database for the sole purpose of * listing archive files. + * @param maxTriesToConnext The maximum number of times a single method should + * try to connect to the database in the event of LostDatabaseConnection + * exceptions being thrown. */ SqliteCatalogue( log::Logger &log, const std::string &filename, const uint64_t nbConns, - const uint64_t nbArchiveFileListingConns); + const uint64_t nbArchiveFileListingConns, + const uint32_t maxTriesToConnect); public: diff --git a/catalogue/retryOnLostConnection.hpp b/catalogue/retryOnLostConnection.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d3be72926099eed8bb98fd3319df33398691caa2 --- /dev/null +++ b/catalogue/retryOnLostConnection.hpp @@ -0,0 +1,74 @@ +/* + * The CERN Tape Archive(CTA) project + * Copyright(C) 2015 CERN + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + *(at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include "common/exception/Exception.hpp" +#include "common/exception/LostDatabaseConnection.hpp" +#include "common/log/Logger.hpp" + +#include <list> +#include <stdint.h> +#include <type_traits> + +namespace cta { +namespace catalogue { + +/** + * Retries calling the specified callable if it throws a LostDatabaseConnection + * exception. + * + * @tparam T The type of the callable. + * @param log Object representing the API to the CTA logging system. + * @param callable The callable. + * @param maxTriesToConnect The maximum number of times the callable should be called in the event of a + * LostDatbaseConnection exception. + * @return The result of calling the callable. + */ +template<typename T> +typename std::result_of<T()>::type retryOnLostConnection(log::Logger &log, const T &callable, + const uint32_t maxTriesToConnect) { + try { + for (uint32_t tryNb = 1; tryNb <= maxTriesToConnect; tryNb++) { + try { + return callable(); + } catch (exception::LostDatabaseConnection &le) { + // Log lost connection + std::list<log::Param> params = { + {"maxTriesToConnect", maxTriesToConnect}, + {"tryNb", tryNb}, + {"msg", le.getMessage()} + }; + log(cta::log::WARNING, "Lost database connection", params); + } + } + + exception::Exception ex; + ex.getMessage() << "Lost the database connection after trying " << maxTriesToConnect << " times"; + throw ex; + } catch (exception::UserError &) { + throw; + } catch (exception::Exception &) { + throw; + } catch (std::exception &se) { + throw exception::Exception(se.what()); + } +} + +} // namespace catalogue +} // namespace cta diff --git a/cmdline/CMakeLists.txt b/cmdline/CMakeLists.txt index ba6bdddc409bd3b0568e0f12943077c779367c1e..37a98021394d2ca7a44bbf0d917eca98ad42cf4e 100644 --- a/cmdline/CMakeLists.txt +++ b/cmdline/CMakeLists.txt @@ -19,34 +19,16 @@ cmake_minimum_required (VERSION 2.6) find_package(xrootdclient REQUIRED) find_package(xrootd REQUIRED) find_package(Protobuf3 REQUIRED) -# Cryptopp can be dropped when we get rid of eoscta_stub -find_package(cryptopp REQUIRED) -# # XRootD SSI -# include_directories(${XROOTD_INCLUDE_DIR} ${XROOTD_INCLUDE_DIR}/private) -# # XRootD SSI Protocol Buffer bindings -# include_directories(${XRD_SSI_PB_DIR}/include ${XRD_SSI_PB_DIR}/eos_cta/include) -# # Compiled protocol buffers -# include_directories(${CMAKE_BINARY_DIR}/eos_cta ${PROTOBUF3_INCLUDE_DIRS}) -# -# eoscta_stub is a drop-in replacement for "cta archive|retrieve|delete" -# -add_executable(eoscta_stub EosCtaStub.cpp Configuration.cpp) -target_link_libraries(eoscta_stub cryptopp ctacommon XrdSsiPbEosCta XrdSsi-4 XrdSsiLib) -set_property (TARGET eoscta_stub APPEND PROPERTY INSTALL_RPATH ${PROTOBUF3_RPATH}) -# Get some extra debug messages on stdout -#target_compile_definitions(eoscta_stub PUBLIC XRDSSI_DEBUG) -install(TARGETS eoscta_stub DESTINATION usr/bin) - # # cta-admin <admin_command> is the SSI version of "cta <admin_command>" # @@ -55,10 +37,21 @@ target_link_libraries(cta-admin XrdSsiPbEosCta XrdSsi-4 XrdSsiLib) set_property (TARGET cta-admin APPEND PROPERTY INSTALL_RPATH ${PROTOBUF3_RPATH}) # Get some extra debug messages on stdout #target_compile_definitions(cta-admin PUBLIC XRDSSI_DEBUG) -install(TARGETS cta-admin DESTINATION usr/bin) -add_executable(cta.deprecated CTACmdMain.cpp Configuration.cpp) -target_link_libraries(cta.deprecated ${XROOTD_XRDCL_LIB} cryptopp) -install(TARGETS cta.deprecated DESTINATION usr/bin) -INSTALL(FILES cta-cli.conf DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/cta) +# +# cta-wfe-test archive|retrieve|delete <options> allows testing of the SSI WorkFlow Engine hooks +# without invoking EOS. +# +# Previously this was the eoscta_stub which was called by a script invoked by the EOS WFE. +# +find_package(cryptopp REQUIRED) +add_executable(cta-wfe-test EosCtaStub.cpp Configuration.cpp) +target_link_libraries(cta-wfe-test cryptopp ctacommon XrdSsiPbEosCta XrdSsi-4 XrdSsiLib) +set_property (TARGET cta-wfe-test APPEND PROPERTY INSTALL_RPATH ${PROTOBUF3_RPATH}) +# Get some extra debug messages on stdout +#target_compile_definitions(eoscta_stub PUBLIC XRDSSI_DEBUG) + +install(TARGETS cta-admin DESTINATION usr/bin) +install(TARGETS cta-wfe-test DESTINATION usr/bin) +install(FILES cta-cli.conf DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/cta) diff --git a/cmdline/CTACmdMain.cpp b/cmdline/CTACmdMain.cpp deleted file mode 100644 index b7eb084c79e1f7139d8193b983b37f85fe0b1441..0000000000000000000000000000000000000000 --- a/cmdline/CTACmdMain.cpp +++ /dev/null @@ -1,209 +0,0 @@ -/* - * The CERN Tape Archive (CTA) project - * Copyright (C) 2015 CERN - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "cmdline/Configuration.hpp" -#include "common/Configuration.hpp" -#include "common/dataStructures/FrontendReturnCode.hpp" - -#include "XrdCl/XrdClCopyProcess.hh" -#include "XrdCl/XrdClEnv.hh" -#include "XrdCl/XrdClDefaultEnv.hh" - -#include <cryptopp/base64.h> -#include <cryptopp/osrng.h> - -#include <iostream> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <stdexcept> -#include <xrootd/XrdCl/XrdClFile.hh> - -/** - * Returns true if --stderr is on the command-line. - * - * @param argc The number of command-line arguments. - * @param argv The command-line arguments. - */ -static bool stderrIsOnTheCmdLine(const int argc, const char *const *const argv) { - for(int i = 1; i < argc; i++) { - const std::string arg = argv[i]; - - if(arg == "--stderr") { - return true; - } - } - - return false; -} - -/** - * Replaces all occurrences in a string "str" of a substring "from" with the string "to" - * - * @param str The original string - * @param from The substring to replace - * @param to The replacement string - */ -void replaceAll(std::string& str, const std::string& from, const std::string& to){ - if(from.empty() || str.empty()) - return; - size_t start_pos = 0; - while((start_pos = str.find(from, start_pos)) != std::string::npos) { - str.replace(start_pos, from.length(), to); - start_pos += to.length(); - } -} - -/** - * Encodes a string in base 64 and replaces slashes ('/') in the result - * with underscores ('_'). - * - * @param msg string to encode - * @return encoded string - */ -std::string encode(const std::string msg) { - std::string ret; - const bool noNewLineInBase64Output = false; - CryptoPP::StringSource ss1(msg, true, new CryptoPP::Base64Encoder(new CryptoPP::StringSink(ret), noNewLineInBase64Output)); - - // need to replace slashes ('/') with underscores ('_') because xroot removes - // consecutive slashes, and the cryptopp base64 algorithm may produce - // consecutive slashes. This is solved in cryptopp-5.6.3 (using - // Base64URLEncoder instead of Base64Encoder) but we currently have - // cryptopp-5.6.2. To be changed in the future... - replaceAll(ret, "/", "_"); - - return ret; -} - -/** - * Formats the command path string - * - * @param argc The number of command-line arguments. - * @param argv The command-line arguments. - * @return the command string - */ -std::string formatCommandPath(const int argc, const char **argv) { - cta::cmdline::Configuration cliConf("/etc/cta/cta-cli.conf"); - std::string cmdPath = "root://"+cliConf.getFrontendHostAndPort()+"//"; - - for(int i=0; i<argc; i++) { - if(i) cmdPath += "&"; - cmdPath += encode(std::string(argv[i])); - } - return cmdPath; -} - -/** - * Sends the command and waits for the reply - * - * @param argc The number of command-line arguments. - * @param argv The command-line arguments. - * @return the return code - */ -int sendCommand(const int argc, const char **argv) { - int rc = 0; - const bool writeToStderr = stderrIsOnTheCmdLine(argc, argv); - const std::string cmdPath = formatCommandPath(argc, argv); - XrdCl::File xrootFile; - - // Open the xroot file reprsenting the execution of the command - { - const XrdCl::Access::Mode openMode = XrdCl::Access::None; - const uint16_t openTimeout = 15; // Timeout in seconds that is rounded up to the nearest 15 seconds - const XrdCl::XRootDStatus openStatus = xrootFile.Open(cmdPath, XrdCl::OpenFlags::Read, openMode, openTimeout); - if(!openStatus.IsOK()) { - throw std::runtime_error(std::string("Failed to open ") + cmdPath + ": " + openStatus.ToStr()); - } - } - - // The cta frontend return code is the first char of the answer - { - uint64_t readOffset = 0; - uint32_t bytesRead = 0; - char rc_char = '0'; - const XrdCl::XRootDStatus readStatus = xrootFile.Read(readOffset, 1, &rc_char, bytesRead); - if(!readStatus.IsOK()) { - throw std::runtime_error(std::string("Failed to read first byte from ") + cmdPath + ": " + - readStatus.ToStr()); - } - if(bytesRead != 1) { - throw std::runtime_error(std::string("Failed to read first byte from ") + cmdPath + - ": Expected to read exactly 1 byte, actually read " + - std::to_string((long long unsigned int)bytesRead) + " bytes"); - } - rc = rc_char - '0'; - } - - // Read and print the command result - { - uint64_t readOffset = 1; // The first character at offset 0 has already been read - uint32_t bytesRead = 0; - const size_t bufSize = 20480; - std::unique_ptr<char []> buf(new char[bufSize]); - do { - bytesRead = 0; - memset(buf.get(), 0, bufSize); - const XrdCl::XRootDStatus readStatus = xrootFile.Read(readOffset, bufSize - 1, buf.get(), bytesRead); - if(!readStatus.IsOK()) { - throw std::runtime_error(std::string("Failed to read ") + cmdPath + ": " + readStatus.ToStr()); - } - - if(bytesRead > 0) { - std::cout << buf.get(); - - if(writeToStderr) { - std::cerr << buf.get(); - } - } - - readOffset += bytesRead; - } while(bytesRead > 0); - } - - // Close the xroot file reprsenting the execution of the command - { - const XrdCl::XRootDStatus closeStatus = xrootFile.Close(); - if(!closeStatus.IsOK()) { - throw std::runtime_error(std::string("Failed to close ") + cmdPath + ": " + closeStatus.ToStr()); - } - } - - return rc; -} - -/** - * The entry function of the command. - * - * @param argc The number of command-line arguments. - * @param argv The command-line arguments. - */ -int main(const int argc, const char **argv) { - try { - return sendCommand(argc, argv); - } catch (std::exception &ex) { - std::cerr << "Failed to execute the command. Reason: " << ex.what() << std::endl; - return cta::common::dataStructures::FrontendReturnCode::ctaErrorNoRetry; - } catch (...) { - std::cerr << "Failed to execute the command for an unknown reason" << std::endl; - return cta::common::dataStructures::FrontendReturnCode::ctaErrorNoRetry; - } -} diff --git a/cmdline/EosCtaStub.cpp b/cmdline/EosCtaStub.cpp index 73be6dc73e49b301d58fbd43e1658d1011c8c52e..3014a72eda20feb27cdecd07b62d1b2187a0af57 100644 --- a/cmdline/EosCtaStub.cpp +++ b/cmdline/EosCtaStub.cpp @@ -53,7 +53,7 @@ void RequestCallback<cta::xrd::Alert>::operator()(const cta::xrd::Alert &alert) //! Usage exception -const std::runtime_error Usage("Usage: eoscta_stub archive|retrieve|deletearchive [options] [--stderr]"); +const std::runtime_error Usage("Usage: cta-wfe-test archive|retrieve|deletearchive [options] [--stderr]"); diff --git a/cmdline/cta.1cta b/cmdline/cta.1cta deleted file mode 100644 index 9daef238e74ac7c89c523e8e54601712def61852..0000000000000000000000000000000000000000 --- a/cmdline/cta.1cta +++ /dev/null @@ -1,28 +0,0 @@ -.\" The CERN Tape Archive (CTA) project -.\" Copyright (C) 2015 CERN -.\" -.\" This program is free software: you can redistribute it and/or modify -.\" it under the terms of the GNU General Public License as published by -.\" the Free Software Foundation, either version 3 of the License, or -.\" (at your option) any later version. -.\" -.\" This program is distributed in the hope that it will be useful, -.\" but WITHOUT ANY WARRANTY; without even the implied warranty of -.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -.\" GNU General Public License for more details. -.\" -.\" You should have received a copy of the GNU General Public License -.\" along with this program. If not, see <http://www.gnu.org/licenses/>. -.TH CTA 1CTA "August 2016" CTA CTA -.SH NAME -cta \- main command line interface to the CERN Tape Archive -.SH SYNOPSIS -.BI "cta" - -.SH DESCRIPTION -Please refer to the help provided within the \fBcta\fP command. Just type \fBcta\fP for generic help or -\fBcta <command>\fP for help on a specific command. - -.SH AUTHOR -\fBCTA\fP Team - diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 73f7306c0342996a58fb068fb23baa8d74beaa46..3aa0c85c7c16e0ea7eb2925c0d80f8287ebe8a72 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -83,6 +83,7 @@ set (COMMON_LIB_SRC_FILES exception/Exception.cpp exception/InvalidArgument.cpp exception/InvalidConfigEntry.cpp + exception/LostDatabaseConnection.cpp exception/Mismatch.cpp exception/MissingOperand.cpp exception/MountFailed.cpp diff --git a/common/exception/LostDatabaseConnection.cpp b/common/exception/LostDatabaseConnection.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f464441cb708617605dffbf4d9057eaf8c6004cd --- /dev/null +++ b/common/exception/LostDatabaseConnection.cpp @@ -0,0 +1,33 @@ +/* + * The CERN Tape Archive (CTA) project + * Copyright (C) 2015 CERN + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "common/exception/LostDatabaseConnection.hpp" + + +//------------------------------------------------------------------------------ +// constructor +//------------------------------------------------------------------------------ +cta::exception::LostDatabaseConnection::LostDatabaseConnection(const std::string &context, const bool embedBacktrace): + Exception(context, embedBacktrace) { +} + +//------------------------------------------------------------------------------ +// destructor +//------------------------------------------------------------------------------ +cta::exception::LostDatabaseConnection::~LostDatabaseConnection() noexcept { +} diff --git a/common/exception/LostDatabaseConnection.hpp b/common/exception/LostDatabaseConnection.hpp new file mode 100644 index 0000000000000000000000000000000000000000..9acc170dd4b02609928eb21936b94378731d0e75 --- /dev/null +++ b/common/exception/LostDatabaseConnection.hpp @@ -0,0 +1,55 @@ +/* + * The CERN Tape Archive (CTA) project + * Copyright (C) 2015 CERN + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include "common/exception/Exception.hpp" + +#include <string> + + +namespace cta { +namespace exception { + +/** + * The database connection has been lost. + */ +class LostDatabaseConnection : public cta::exception::Exception { +public: + + /** + * Constructor. + * + * @param context optional context string added to the message + * at initialisation time. + * @param embedBacktrace whether to embed a backtrace of where the + * exception was throw in the message + */ + LostDatabaseConnection(const std::string &context = "", const bool embedBacktrace = true); + + /** + * Empty Destructor, explicitely non-throwing (needed for std::exception + * inheritance) + */ + ~LostDatabaseConnection() noexcept override; + +}; // class LostDatabaseConnection + +} // namespace exception +} // namespace cta + diff --git a/continuousintegration/README.md b/continuousintegration/README.md index 58066919d28fd39accdda710da9f05374f997bc8..01b4a6398d23356a11f67391ae3bf155ecacddcf 100644 --- a/continuousintegration/README.md +++ b/continuousintegration/README.md @@ -1,6 +1,20 @@ -Folder content: +# Folder content + * `ci_helpers`: helper scripts used by gilab_ci * `docker`: Docker files and content needed to build the needed docker images * `orchestration`: orchestration specific files: this contains all the pods definitions and *startup scripts* launched in the pod containers during instanciation. * `buildtree_runner`: setup scripts for running the ci tests from the build tree instead of RPMs * `buildtree_runner/vmBootstrap`: As set of scripts describing the preparation of a machine for fresh install to running CI scripts **MUST NOT BE RUN BLINDLY** + +# How to update the EOS version used in CI + +1. ssh to **aiadm**, then: +``` +$ cd /eos/user/c/ctareg/www/cta-ci-repo/ +$ cp <path_to_rpms>/eos-*.rpm eos/x86_64/ +$ ./update_repos.sh +``` +2. In the CTA repository, update the yum version lock list with the new EOS version: +``` +/CTA/continuousintegration/docker/ctafrontend/cc7/etc/yum/pluginconf.d/versionlock.list +``` diff --git a/continuousintegration/docker/ctafrontend/cc7/etc/yum/pluginconf.d/versionlock.list b/continuousintegration/docker/ctafrontend/cc7/etc/yum/pluginconf.d/versionlock.list index 7e45d5f801c76205d49193baf1b3fbceed82b3f1..854df8e319a7a9ce610e13cf0515fee032b38884 100644 --- a/continuousintegration/docker/ctafrontend/cc7/etc/yum/pluginconf.d/versionlock.list +++ b/continuousintegration/docker/ctafrontend/cc7/etc/yum/pluginconf.d/versionlock.list @@ -1,34 +1,34 @@ -0:eos-archive-4.2.4-20171206151625gitda6f67d.el7.cern.x86_64 -0:eos-cleanup-4.2.4-20171206151625gitda6f67d.el7.cern.x86_64 -0:eos-client-4.2.4-20171206151625gitda6f67d.el7.cern.x86_64 -0:eos-debuginfo-4.2.4-20171206151625gitda6f67d.el7.cern.x86_64 -0:eos-fuse-4.2.4-20171206151625gitda6f67d.el7.cern.x86_64 -0:eos-fuse-core-4.2.4-20171206151625gitda6f67d.el7.cern.x86_64 -0:eos-fuse-sysv-4.2.4-20171206151625gitda6f67d.el7.cern.x86_64 -0:eos-fusex-4.2.4-20171206151625gitda6f67d.el7.cern.x86_64 -0:eos-fusex-core-4.2.4-20171206151625gitda6f67d.el7.cern.x86_64 -0:eos-fusex-selinux-4.2.4-20171206151625gitda6f67d.el7.cern.x86_64 -0:eos-server-4.2.4-20171206151625gitda6f67d.el7.cern.x86_64 -0:eos-srm-4.2.4-20171206151625gitda6f67d.el7.cern.x86_64 -0:eos-test-4.2.4-20171206151625gitda6f67d.el7.cern.x86_64 -0:eos-testkeytab-4.2.4-20171206151625gitda6f67d.el7.cern.x86_64 -1:python2-xrootd-4.8.0-0.rc1.el7.x86_64 -1:python3-xrootd-4.8.0-0.rc1.el7.x86_64 -1:xrootd-4.8.0-0.rc1.el7.x86_64 -1:xrootd-client-4.8.0-0.rc1.el7.x86_64 -1:xrootd-client-devel-4.8.0-0.rc1.el7.x86_64 -1:xrootd-client-libs-4.8.0-0.rc1.el7.x86_64 -1:xrootd-debuginfo-4.8.0-0.rc1.el7.x86_64 -1:xrootd-devel-4.8.0-0.rc1.el7.x86_64 -1:xrootd-doc-4.8.0-0.rc1.el7.noarch -1:xrootd-fuse-4.8.0-0.rc1.el7.x86_64 -1:xrootd-libs-4.8.0-0.rc1.el7.x86_64 -1:xrootd-private-devel-4.8.0-0.rc1.el7.x86_64 -1:xrootd-selinux-4.8.0-0.rc1.el7.noarch -1:xrootd-server-4.8.0-0.rc1.el7.x86_64 -1:xrootd-server-devel-4.8.0-0.rc1.el7.x86_64 -1:xrootd-server-libs-4.8.0-0.rc1.el7.x86_64 -1:xrootd-tests-4.8.0-0.rc1.el7.x86_64 +0:eos-archive-4.2.12-20180202120141git3855655.el7.cern.x86_64 +0:eos-cleanup-4.2.12-20180202120141git3855655.el7.cern.x86_64 +0:eos-client-4.2.12-20180202120141git3855655.el7.cern.x86_64 +0:eos-debuginfo-4.2.12-20180202120141git3855655.el7.cern.x86_64 +0:eos-fuse-4.2.12-20180202120141git3855655.el7.cern.x86_64 +0:eos-fuse-core-4.2.12-20180202120141git3855655.el7.cern.x86_64 +0:eos-fuse-sysv-4.2.12-20180202120141git3855655.el7.cern.x86_64 +0:eos-fusex-4.2.12-20180202120141git3855655.el7.cern.x86_64 +0:eos-fusex-core-4.2.12-20180202120141git3855655.el7.cern.x86_64 +0:eos-fusex-selinux-4.2.12-20180202120141git3855655.el7.cern.x86_64 +0:eos-server-4.2.12-20180202120141git3855655.el7.cern.x86_64 +0:eos-srm-4.2.12-20180202120141git3855655.el7.cern.x86_64 +0:eos-test-4.2.12-20180202120141git3855655.el7.cern.x86_64 +0:eos-testkeytab-4.2.12-20180202120141git3855655.el7.cern.x86_64 +1:python2-xrootd-4.8.1-1.el7.cern.x86_64 +1:python3-xrootd-4.8.1-1.el7.cern.x86_64 +1:xrootd-4.8.1-1.el7.cern.x86_64 +1:xrootd-client-4.8.1-1.el7.cern.x86_64 +1:xrootd-client-devel-4.8.1-1.el7.cern.x86_64 +1:xrootd-client-libs-4.8.1-1.el7.cern.x86_64 +1:xrootd-debuginfo-4.8.1-1.el7.cern.x86_64 +1:xrootd-devel-4.8.1-1.el7.cern.x86_64 +1:xrootd-doc-4.8.1-1.el7.cern.noarch +1:xrootd-fuse-4.8.1-1.el7.cern.x86_64 +1:xrootd-libs-4.8.1-1.el7.cern.x86_64 +1:xrootd-private-devel-4.8.1-1.el7.cern.x86_64 +1:xrootd-selinux-4.8.1-1.el7.cern.noarch +1:xrootd-server-4.8.1-1.el7.cern.x86_64 +1:xrootd-server-devel-4.8.1-1.el7.cern.x86_64 +1:xrootd-server-libs-4.8.1-1.el7.cern.x86_64 +1:xrootd-tests-4.8.1-1.el7.cern.x86_64 2:ceph-12.2.2-0.el7.x86_64 2:ceph-base-12.2.2-0.el7.x86_64 2:ceph-common-12.2.2-0.el7.x86_64 diff --git a/continuousintegration/docker/ctafrontend/cc7/opt/run/bin/ctaeos-mgm.sh b/continuousintegration/docker/ctafrontend/cc7/opt/run/bin/ctaeos-mgm.sh index 350f39ff4afd15f4fd9ec9865591d078ad502bfa..db305fa7aa33a031026a90389be89dba5c3a5b86 100755 --- a/continuousintegration/docker/ctafrontend/cc7/opt/run/bin/ctaeos-mgm.sh +++ b/continuousintegration/docker/ctafrontend/cc7/opt/run/bin/ctaeos-mgm.sh @@ -34,7 +34,6 @@ eoshost=`hostname -f` EOS_INSTANCE=`hostname -s` TAPE_FS_ID=65535 CTA_BIN=/usr/bin/eoscta_stub -CTA_KT=/etc/cta/cta-cli.sss.keytab CTA_XrdSecPROTOCOL=sss CTA_PROC_DIR=/eos/${EOS_INSTANCE}/proc/cta CTA_WF_DIR=${CTA_PROC_DIR}/workflow @@ -43,14 +42,6 @@ CTA_TEST_DIR=/eos/${EOS_INSTANCE}/cta # dir for eos instance basic tests writable and readable by anyone EOS_TMP_DIR=/eos/${EOS_INSTANCE}/tmp -# prepare CTA cli commands environment -cat <<EOF > /etc/cta/cta-cli.conf -# The CTA frontend address in the form <FQDN>:<TCPPort> -# solved by kubernetes DNS server so KIS... -ctafrontend:10955 -EOF - - # setup eos host and instance name sed -i -e "s/DUMMY_HOST_TO_REPLACE/${eoshost}/" /etc/sysconfig/eos sed -i -e "s/DUMMY_INSTANCE_TO_REPLACE/${EOS_INSTANCE}/" /etc/sysconfig/eos @@ -188,30 +179,10 @@ test -e /usr/lib64/libjemalloc.so.1 && export LD_PRELOAD=/usr/lib64/libjemalloc. # set interval in which the WFE engine is running #eos space config default space.wfe.interval=1 -# ATTENTION -# for sss authorisation unix has to be replaced by sss - -# Set the worfklow rule for archiving files to tape -eos attr set sys.workflow.closew.default="bash:shell:cta XRD_LOGLEVEL=Error XrdSecDEBUG=1 XrdSecPROTOCOL=${CTA_XrdSecPROTOCOL} XrdSecSSSKT=${CTA_KT} ${CTA_BIN} archive --user <eos::wfe::rusername> --group <eos::wfe::rgroupname> --diskid <eos::wfe::fid> --instance ignored_instance_name --srcurl <eos::wfe::turl> --size <eos::wfe::size> --checksumtype <eos::wfe::checksumtype> --checksumvalue <eos::wfe::checksum> --storageclass <eos::wfe::cxattr:CTA_StorageClass> --diskfilepath <eos::wfe::path> --diskfileowner <eos::wfe::username> --diskfilegroup <eos::wfe::groupname> --recoveryblob:base64 <eos::wfe::base64:metadata> --reportURL 'eosQuery://${EOS_INSTANCE}//eos/wfe/passwd?mgm.pcmd=event\&mgm.fid=<eos::wfe::fxid>\&mgm.logid=cta\&mgm.event=archived\&mgm.workflow=default\&mgm.path=/eos/wfe/passwd\&mgm.ruid=0\&mgm.rgid=0' --stderr" ${CTA_WF_DIR} - -# Set the worflow rule for creating tape file replicas in the EOS namespace. -eos attr set sys.workflow.archived.default="bash:shell:cta eos file tag <eos::wfe::path> +<eos::wfe::cxattr:CTA_TapeFsId>" ${CTA_WF_DIR} - -# Set the worfklow rule for retrieving file from tape. -eos attr set sys.workflow.sync::prepare.default="bash:shell:cta XrdSecPROTOCOL=${CTA_XrdSecPROTOCOL} XrdSecSSSKT=${CTA_KT} ${CTA_BIN} retrieve --user <eos::wfe::rusername> --group <eos::wfe::rgroupname> --id <eos::wfe::fxattr:sys.archiveFileId> --dsturl '<eos::wfe::turl>\&eos.ruid=0\&eos.rgid=0\&eos.injection=1\&eos.workflow=CTA_retrieve' --diskfilepath <eos::wfe::path> --diskfileowner <eos::wfe::username> --diskfilegroup <eos::wfe::groupname> --recoveryblob:base64 <eos::wfe::base64:metadata> --stderr" ${CTA_WF_DIR} - -# Set the workflow rule for the closew event of the CTA_retrieve workflow. -# Using the CTA_retrieve workflow will prevent the default workflow from -# receiving the closew event. Triggering the default workflow in this way would -# haved causes the unwanted action of copying the disk file to tape again. -# The action of the CTA_retrieve workflow when triggered by the closew event is -# to set the CTA_retrieved_timestamp attribute. -eos attr set sys.workflow.closew.CTA_retrieve="bash:shell:cta eos attr set 'CTA_retrieved_timestamp=\"\`date\`\"' <eos::wfe::path>" ${CTA_WF_DIR} - - # configure preprod directory separately /opt/run/bin/eos_configure_preprod.sh echo "### ctaeos mgm ready ###" /bin/bash + diff --git a/continuousintegration/docker/ctafrontend/cc7/opt/run/bin/ctafrontend.sh b/continuousintegration/docker/ctafrontend/cc7/opt/run/bin/ctafrontend.sh index a8e7e59f059792e243f98d61cbeffcffca51b982..90ece0a057eca04fb05ee60430ac18013d9f077a 100755 --- a/continuousintegration/docker/ctafrontend/cc7/opt/run/bin/ctafrontend.sh +++ b/continuousintegration/docker/ctafrontend/cc7/opt/run/bin/ctafrontend.sh @@ -11,8 +11,7 @@ yum-config-manager --enable ceph yum -y install cta-frontend cta-debuginfo cta-catalogueutils ceph-common fi -# /etc/cta/cta-frontend-xrootd.conf is now provided by ctafrontend rpm and comes with -# CI ready content +# /etc/cta/cta-frontend-xrootd.conf is now provided by ctafrontend rpm and comes with CI-ready content /opt/run/bin/init_objectstore.sh . /tmp/objectstore-rc.sh @@ -21,7 +20,6 @@ echo "ObjectStore BackendPath $OBJECTSTOREURL" > /etc/cta/cta-frontend.conf echo "Catalogue NumberOfConnections 10" >>/etc/cta/cta-frontend.conf echo "Log URL file:/var/log/cta/cta-frontend.log" >>/etc/cta/cta-frontend.conf - /opt/run/bin/init_database.sh . /tmp/database-rc.sh @@ -30,15 +28,11 @@ echo ${DATABASEURL} >/etc/cta/cta-catalogue.conf # EOS INSTANCE NAME used as username for SSS key EOSINSTANCE=ctaeos -# Create SSS key for cta-cli, must be forwardable in kubernetes realm (this is what the + is for) -# USER IN THE SSS FILE IS THE EOS INSTANCE NAME THE REST IS BS -echo y | xrdsssadmin -k cta-cli+ -u ${EOSINSTANCE} -g cta add /etc/cta/cta-cli.sss.keytab -chmod 600 /etc/cta/cta-cli.sss.keytab -chown cta /etc/cta/cta-cli.sss.keytab -# DO NOT FORGET THAT YOU CAN DEFINE SEPARATE CLIENT AND SERVER KEYTABS - -# Wait for the keytab file to be pushed in by the creation script. -echo -n "Waiting for /etc/cta/cta-frontend.krb5.keytab" +# Wait for the keytab files to be pushed in by the creation script +echo -n "Waiting for /etc/cta/eos.sss.keytab." +for ((;;)); do test -e /etc/cta/eos.sss.keytab && break; sleep 1; echo -n .; done +echo OK +echo -n "Waiting for /etc/cta/cta-frontend.krb5.keytab." for ((;;)); do test -e /etc/cta/cta-frontend.krb5.keytab && break; sleep 1; echo -n .; done echo OK diff --git a/continuousintegration/docker/ctafrontend/cc7/opt/run/bin/eos_configure_preprod.sh b/continuousintegration/docker/ctafrontend/cc7/opt/run/bin/eos_configure_preprod.sh index 95e9147558350d5765ae5a1cb6527c0060b170b4..a91be345ba28732eee9ed3ccbed1d84b0c49b3b1 100755 --- a/continuousintegration/docker/ctafrontend/cc7/opt/run/bin/eos_configure_preprod.sh +++ b/continuousintegration/docker/ctafrontend/cc7/opt/run/bin/eos_configure_preprod.sh @@ -1,26 +1,15 @@ #!/bin/bash PREPROD_DIR=/eos/ctaeos/preprod -CTA_BIN=/usr/bin/eoscta_stub - -mkdir -p /var/eos/wfe/bash -cp /opt/ci/ctaeos/var/eos/wfe/bash/* /var/eos/wfe/bash/ -chmod 755 /var/eos/wfe/bash/* eos mkdir ${PREPROD_DIR} eos chmod 555 ${PREPROD_DIR} eos attr set sys.acl=g:eosusers:rwx!d,u:poweruser1:rwx+dp,u:poweruser2:rwx+dp ${PREPROD_DIR} eos attr set CTA_StorageClass=ctaStorageClass ${PREPROD_DIR} - eos attr set CTA_TapeFsId=65535 ${PREPROD_DIR} -eos attr set sys.workflow.closew.default="bash:shell:cta XRD_LOGLEVEL=Error XrdSecDEBUG=1 XrdSecPROTOCOL=sss XrdSecSSSKT=/etc/cta/cta-cli.sss.keytab ${CTA_BIN} archive --user <eos::wfe::rusername> --group <eos::wfe::rgroupname> --diskid <eos::wfe::fid> --instance ignored_instance_name --srcurl <eos::wfe::turl> --size <eos::wfe::size> --checksumtype <eos::wfe::checksumtype> --checksumvalue <eos::wfe::checksum> --storageclass <eos::wfe::cxattr:CTA_StorageClass> --diskfilepath <eos::wfe::path> --diskfileowner <eos::wfe::username> --diskfilegroup <eos::wfe::groupname> --recoveryblob:base64 cmVjb3ZlcnkK --reportURL 'eosQuery://ctaeos//eos/wfe/passwd?mgm.pcmd=event\&mgm.fid=<eos::wfe::fxid>\&mgm.logid=cta\&mgm.event=archived\&mgm.workflow=default\&mgm.path=/eos/wfe/passwd\&mgm.ruid=0\&mgm.rgid=0' --stderr" ${PREPROD_DIR} - -#eos attr set sys.workflow.archived.default="bash:shell:cta eos file tag <eos::wfe::path> +<eos::wfe::cxattr:CTA_TapeFsId>" ${PREPROD_DIR} -eos attr set sys.workflow.archived.default="bash:create_tape_drop_disk_replicas:cta <eos::wfe::path> <eos::wfe::cxattr:CTA_TapeFsId>" ${PREPROD_DIR} - -eos attr set sys.workflow.sync::prepare.default="bash:retrieve_archive_file:cta <eos::wfe::rusername> <eos::wfe::rgroupname> <eos::wfe::fxattr:sys.archiveFileId> <eos::wfe::turl> <eos::wfe::username> <eos::wfe::groupname> cmVjb3ZlcnkK <eos::wfe::path>" ${PREPROD_DIR} - -eos attr set sys.workflow.closew.CTA_retrieve="bash:shell:cta eos attr set 'CTA_retrieved_timestamp=\"\`date\`\"' <eos::wfe::path>" ${PREPROD_DIR} - -eos attr set sys.workflow.sync::delete.default="bash:delete_archive_file:cta <eos::wfe::rusername> <eos::wfe::rgroupname> <eos::wfe::fxattr:sys.archiveFileId> <eos::wfe::path>" ${PREPROD_DIR} +eos attr set sys.workflow.closew.default="proto/cta:ctafrontend:10955 <parent/file>" ${PREPROD_DIR} +eos attr set sys.workflow.closew.CTA_retrieve="proto/cta:ctafrontend:10955 <parent/file>" ${PREPROD_DIR} +eos attr set sys.workflow.archived.default="proto/cta:ctafrontend:10955 <parent/file>" ${PREPROD_DIR} +eos attr set sys.workflow.sync::prepare.default="proto/cta:ctafrontend:10955 <parent/file>" ${PREPROD_DIR} +eos attr set sys.workflow.sync::delete.default="proto/cta:ctafrontend:10955 <parent/file>" ${PREPROD_DIR} diff --git a/continuousintegration/orchestration/create_instance.sh b/continuousintegration/orchestration/create_instance.sh index 87c76607d8fa0807e7b9a3b5b985b9d8ca82674b..709a53d134e9a7f552582c25367bbf994798b662 100755 --- a/continuousintegration/orchestration/create_instance.sh +++ b/continuousintegration/orchestration/create_instance.sh @@ -10,6 +10,9 @@ config_database="./database-sqlite.yaml" # default library model model="mhvtl" +# EOS short instance name +EOSINSTANCE=ctaeos + # By default keep Database and keep Objectstore # default should not make user loose data if he forgot the option keepdatabase=1 @@ -275,16 +278,15 @@ kubectl --namespace=${instance} exec ctacli klist echo -n "Configuring cta SSS for ctafrontend access from ctaeos" for ((i=0; i<300; i++)); do echo -n "." - [ "`kubectl --namespace=${instance} exec ctafrontend -- bash -c "[ -f /etc/cta/cta-cli.sss.keytab ] && echo -n Ready || echo -n Not ready"`" = "Ready" ] && break + [ "`kubectl --namespace=${instance} exec ctaeos -- bash -c "[ -f /etc/eos.keytab ] && echo -n Ready || echo -n Not ready"`" = "Ready" ] && break sleep 1 done -[ "`kubectl --namespace=${instance} exec ctafrontend -- bash -c "[ -f /etc/cta/cta-cli.sss.keytab ] && echo -n Ready || echo -n Not ready"`" = "Ready" ] || die "TIMED OUT" -# just in case /etc/cta directory does not exist yet -kubectl --namespace=${instance} exec -i ctaeos -- bash -c "mkdir -p /etc/cta" -kubectl --namespace=${instance} exec ctafrontend -- cat /etc/cta/cta-cli.sss.keytab | kubectl --namespace=${instance} exec -i ctaeos -- bash -c "cat > /etc/cta/cta-cli.sss.keytab; chmod 600 /etc/cta/cta-cli.sss.keytab; chown daemon /etc/cta/cta-cli.sss.keytab" +[ "`kubectl --namespace=${instance} exec ctaeos -- bash -c "[ -f /etc/eos.keytab ] && echo -n Ready || echo -n Not ready"`" = "Ready" ] || die "TIMED OUT" +kubectl --namespace=${instance} exec ctaeos -- grep ${EOSINSTANCE} /etc/eos.keytab | sed "s/daemon/${EOSINSTANCE}/g" |\ +kubectl --namespace=${instance} exec -i ctafrontend -- \ +bash -c "cat > /etc/cta/eos.sss.keytab.tmp; chmod 400 /etc/cta/eos.sss.keytab.tmp; chown cta:cta /etc/cta/eos.sss.keytab.tmp; mv /etc/cta/eos.sss.keytab.tmp /etc/cta/eos.sss.keytab" echo OK - echo -n "Waiting for EOS to be configured" for ((i=0; i<300; i++)); do echo -n "." @@ -295,6 +297,28 @@ kubectl --namespace=${instance} logs ctaeos | grep -q "### ctaeos mgm ready ### echo OK +# Set the workflow rules for archiving, creating tape file replicas in the EOS namespace, retrieving +# files from tape and deleting files. +# +# The closew.CTA_retrieve workflow prevents the default workflow from receiving the closew event, as +# we don't want to trigger the action of copying the retrived disk file to tape again. The +# closew.CTA_retrieve workflow sets the CTA_retrieved_timestamp attribute. +# +# The FQDN can be set as follows: +# CTA_ENDPOINT=ctafrontend.${instance}.svc.cluster.local:10955 +# +# however the simple hostname should be sufficient: +CTA_ENDPOINT=ctafrontend:10955 + +echo "Setting workflows in namespace ${instance} pod ctaeos:" +CTA_WF_DIR=/eos/${EOSINSTANCE}/proc/cta/workflow +for WORKFLOW in closew.default archived.default sync::prepare.default closew.CTA_retrieve sync::delete.default +do + echo "eos attr set sys.workflow.${WORKFLOW}=\"proto/cta:${CTA_ENDPOINT} <parent/file>\" ${CTA_WF_DIR}" + kubectl --namespace=${instance} exec ctaeos -- bash -c "eos attr set sys.workflow.${WORKFLOW}=\"proto/cta:${CTA_ENDPOINT} <parent/file>\" ${CTA_WF_DIR}" +done + + echo -n "Copying eos SSS on ctacli and client pods to allow recalls" kubectl --namespace=${instance} exec ctaeos cat /etc/eos.keytab | kubectl --namespace=${instance} exec -i ctacli -- bash -c "cat > /etc/eos.keytab; chmod 600 /etc/eos.keytab" kubectl --namespace=${instance} exec ctaeos cat /etc/eos.keytab | kubectl --namespace=${instance} exec -i client -- bash -c "cat > /etc/eos.keytab; chmod 600 /etc/eos.keytab" diff --git a/continuousintegration/orchestration/tests/client_ar.sh b/continuousintegration/orchestration/tests/client_ar.sh index 87ec5166592d72680c59b0958e8e1be87025a954..96aa0f93c0821288d94d3cea97dd076cf7d9914d 100644 --- a/continuousintegration/orchestration/tests/client_ar.sh +++ b/continuousintegration/orchestration/tests/client_ar.sh @@ -202,7 +202,7 @@ if [[ $REMOVE == 1 ]]; then else # displays what failed and fail admin_cta admin ls - die "Could not launch cta command." + die "Could not launch cta-admin command." fi # recount the files on tape as the workflows may have gone further... INITIALFILESONTAPE=$(admin_cta archivefile ls --all | grep ${EOS_DIR} | wc -l) @@ -233,7 +233,7 @@ if [[ $REMOVE == 1 ]]; then fi FILESONTAPE=$(admin_cta archivefile ls --all > >(grep ${EOS_DIR} | wc -l) 2> >(cat > /tmp/ctaerr)) if [[ $(cat /tmp/ctaerr | wc -l) -gt 0 ]]; then - echo "cta COMMAND FAILED!!" + echo "cta-admin COMMAND FAILED!!" echo "ERROR CTA ERROR MESSAGE:" cat /tmp/ctaerr break diff --git a/cta.spec.in b/cta.spec.in index ad1893c7d993461cd0f085ba641ee911ea33ae57..51539efc06422a4a1cd11f05bbc2d654c41970fc 100644 --- a/cta.spec.in +++ b/cta.spec.in @@ -38,10 +38,10 @@ BuildRequires: xrootd-client-devel = 1:4.2.3 BuildRequires: xrootd-devel = 1:4.2.3 BuildRequires: cryptopp-devel >= 5.6.2 %else -BuildRequires: xrootd-client-devel >= 1:4.8.0 -BuildRequires: xrootd-devel >= 1:4.8.0 -BuildRequires: xrootd-server-devel >= 1:4.8.0 -BuildRequires: xrootd-private-devel >= 1:4.8.0 +BuildRequires: xrootd-client-devel >= 1:4.8.1 +BuildRequires: xrootd-devel >= 1:4.8.1 +BuildRequires: xrootd-server-devel >= 1:4.8.1 +BuildRequires: xrootd-private-devel >= 1:4.8.1 BuildRequires: librados-devel = %{radosVersion}, libradosstriper-devel = %{radosVersion}, BuildRequires: protobuf3-compiler >= 3.3.1 protobuf3-devel >= 3.3.1 BuildRequires: gmock-devel >= 1.5.0 gtest-devel >= 1.5.0 @@ -113,9 +113,8 @@ CERN Tape Archive: The xroot plugin %files -n cta-cli %defattr(-,root,root) -%attr(0755,root,root) %{_bindir}/cta.deprecated %attr(0755,root,root) %{_bindir}/cta-admin -%attr(0755,root,root) %{_bindir}/eoscta_stub +%attr(0755,root,root) %{_bindir}/cta-wfe-test %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/cta/cta-cli.conf %else @@ -158,7 +157,6 @@ The xroot plugin /usr/bin/getent passwd cta || /usr/sbin/useradd -s /bin/nologin -c "CTA system account" -g cta cta %files -n cta-frontend %defattr(0755,root,root) -%{_libdir}/libXrdCtaOfs.so* %{_libdir}/libXrdSsiCta.so* %attr(0755,cta,cta) %dir /var/log/cta %attr(0644,root,root) %config(noreplace) /etc/logrotate.d/cta-frontend @@ -178,9 +176,8 @@ CERN Tape Archive: The xroot plugin %files -n cta-cli %defattr(-,root,root) -%attr(0755,root,root) %{_bindir}/cta.deprecated %attr(0755,root,root) %{_bindir}/cta-admin -%attr(0755,root,root) %{_bindir}/eoscta_stub +%attr(0755,root,root) %{_bindir}/cta-wfe-test %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/cta/cta-cli.conf %package -n cta-lib diff --git a/objectstore/GarbageCollectorTest.cpp b/objectstore/GarbageCollectorTest.cpp index 2a0a6ea6793cdca40a30114bfe5d78a603229573..7ef84ef2997faa16157b00455aaa7cd4d1d746b6 100644 --- a/objectstore/GarbageCollectorTest.cpp +++ b/objectstore/GarbageCollectorTest.cpp @@ -44,7 +44,7 @@ namespace unitTests { TEST(ObjectStore, GarbageCollectorBasicFuctionnality) { // We will need a log object cta::log::DummyLogger dl("unitTest"); - cta::catalogue::DummyCatalogue catalogue(dl); + cta::catalogue::DummyCatalogue catalogue; cta::log::LogContext lc(dl); // Here we check for the ability to detect dead (but empty agents) // and clean them up. @@ -98,7 +98,7 @@ TEST(ObjectStore, GarbageCollectorRegister) { // We will need a log object cta::log::DummyLogger dl("unitTest"); cta::log::LogContext lc(dl); - cta::catalogue::DummyCatalogue catalogue(dl); + cta::catalogue::DummyCatalogue catalogue; // Here we check that can successfully call agentRegister's garbage collector cta::objectstore::BackendVFS be; cta::objectstore::AgentReference agentRef("unitTestGarbageCollector", dl); @@ -158,7 +158,7 @@ TEST(ObjectStore, GarbageCollectorArchiveQueue) { cta::log::DummyLogger dl("unitTest"); cta::log::LogContext lc(dl); // We need a dummy catalogue - cta::catalogue::DummyCatalogue catalogue(dl); + cta::catalogue::DummyCatalogue catalogue; // Here we check that can successfully call agentRegister's garbage collector cta::objectstore::BackendVFS be; cta::objectstore::AgentReference agentRef("unitTestGarbageCollector", dl); @@ -218,7 +218,7 @@ TEST(ObjectStore, GarbageCollectorDriveRegister) { cta::log::DummyLogger dl("unitTest"); cta::log::LogContext lc(dl); // We need a dummy catalogue - cta::catalogue::DummyCatalogue catalogue(dl); + cta::catalogue::DummyCatalogue catalogue; // Here we check that can successfully call agentRegister's garbage collector cta::objectstore::BackendVFS be; cta::objectstore::AgentReference agentRef("unitTestGarbageCollector", dl); @@ -282,7 +282,7 @@ TEST(ObjectStore, GarbageCollectorArchiveRequest) { #endif cta::log::LogContext lc(dl); // We need a dummy catalogue - cta::catalogue::DummyCatalogue catalogue(dl); + cta::catalogue::DummyCatalogue catalogue; // Here we check that can successfully call ArchiveRequests's garbage collector cta::objectstore::BackendVFS be; // Create the root entry @@ -480,7 +480,7 @@ TEST(ObjectStore, GarbageCollectorRetrieveRequest) { #endif cta::log::LogContext lc(dl); // We need a dummy catalogue - cta::catalogue::DummyCatalogue catalogue(dl); + cta::catalogue::DummyCatalogue catalogue; // Here we check that can successfully call RetrieveRequests's garbage collector cta::objectstore::BackendVFS be; // Create the root entry diff --git a/rdbms/wrapper/OcciStmt.cpp b/rdbms/wrapper/OcciStmt.cpp index 3337affdf298bc5ee02a4acfa01caf4d740bf939..62f839926dd78dd34e923b7b602478a5b19b7c2d 100644 --- a/rdbms/wrapper/OcciStmt.cpp +++ b/rdbms/wrapper/OcciStmt.cpp @@ -17,6 +17,7 @@ */ #include "common/exception/Exception.hpp" +#include "common/exception/LostDatabaseConnection.hpp" #include "common/make_unique.hpp" #include "common/threading/MutexLocker.hpp" #include "rdbms/wrapper/OcciColumn.hpp" @@ -183,6 +184,9 @@ std::unique_ptr<Rset> OcciStmt::executeQuery() { try { return cta::make_unique<OcciRset>(*this, m_stmt->executeQuery()); } catch(occi::SQLException &ex) { + std::ostringstream msg; + msg << std::string(__FUNCTION__) << " failed for SQL statement " << getSqlForException() << ": " << ex.what(); + if(connShouldBeClosed(ex)) { // Close the statement first and then the connection try { @@ -194,9 +198,9 @@ std::unique_ptr<Rset> OcciStmt::executeQuery() { m_conn.close(); } catch(...) { } + throw exception::LostDatabaseConnection(msg.str()); } - throw exception::Exception(std::string(__FUNCTION__) + " failed for SQL statement " + - getSqlForException() + ": " + ex.what()); + throw exception::Exception(msg.str()); } } diff --git a/scheduler/OStoreDB/OStoreDBFactory.hpp b/scheduler/OStoreDB/OStoreDBFactory.hpp index 6aeb7f25e3f5ea8370d85637e81a7cb27ab3af52..6080c3be9e93eb2e6a8ec158a147c29e7f447dd9 100644 --- a/scheduler/OStoreDB/OStoreDBFactory.hpp +++ b/scheduler/OStoreDB/OStoreDBFactory.hpp @@ -171,7 +171,7 @@ template <> OStoreDBWrapper<cta::objectstore::BackendVFS>::OStoreDBWrapper( const std::string &context, const std::string &URL) : m_logger(new cta::log::DummyLogger("")), m_backend(new cta::objectstore::BackendVFS()), -m_catalogue(new cta::catalogue::DummyCatalogue(*m_logger)), +m_catalogue(new cta::catalogue::DummyCatalogue), m_OStoreDB(*m_backend, *m_catalogue, *m_logger), m_agentReference("OStoreDBFactory", *m_logger) { // We need to populate the root entry before using. objectstore::RootEntry re(*m_backend); @@ -198,7 +198,7 @@ template <> OStoreDBWrapper<cta::objectstore::BackendRados>::OStoreDBWrapper( const std::string &context, const std::string &URL) : m_logger(new cta::log::DummyLogger("")), m_backend(cta::objectstore::BackendFactory::createBackend(URL, *m_logger).release()), -m_catalogue(new cta::catalogue::DummyCatalogue(*m_logger)), +m_catalogue(new cta::catalogue::DummyCatalogue), m_OStoreDB(*m_backend, *m_catalogue, *m_logger), m_agentReference("OStoreDBFactory", *m_logger) { // We need to first clean up possible left overs in the pool auto l = m_backend->list(); diff --git a/scheduler/Scheduler.cpp b/scheduler/Scheduler.cpp index 93df03ffa7fa9a0d9665ae06c2bf553f6208138d..0c3b6a1eb1077a1d7325ca10379336cdf7a439d7 100644 --- a/scheduler/Scheduler.cpp +++ b/scheduler/Scheduler.cpp @@ -418,7 +418,7 @@ std::map<std::string, std::list<common::dataStructures::ArchiveJob> > Scheduler: std::list<common::dataStructures::ArchiveJob> Scheduler::getPendingArchiveJobs(const std::string &tapePoolName, log::LogContext & lc) const { utils::Timer t; if(!m_catalogue.tapePoolExists(tapePoolName)) { - throw exception::Exception(std::string("Tape pool ") + tapePoolName + " does not exist"); + throw exception::UserError(std::string("Tape pool ") + tapePoolName + " does not exist"); } auto catalogueTime = t.secs(utils::Timer::resetCounter); auto ret = m_db.getArchiveJobs(tapePoolName); diff --git a/scheduler/SchedulerTest.cpp b/scheduler/SchedulerTest.cpp index fe45504f62be2440f6242c14cf7811fb813c5ad5..743b51e6f5a547e1ab0a6552c0ffaa9712b3e29c 100644 --- a/scheduler/SchedulerTest.cpp +++ b/scheduler/SchedulerTest.cpp @@ -101,8 +101,10 @@ public: m_db = param.dbFactory.create(); const uint64_t nbConns = 1; const uint64_t nbArchiveFileListingConns = 1; + const uint32_t maxTriesToConnect = 1; //m_catalogue = cta::make_unique<catalogue::SchemaCreatingSqliteCatalogue>(m_tempSqliteFile.path(), nbConns); - m_catalogue = cta::make_unique<catalogue::InMemoryCatalogue>(m_dummyLog, nbConns, nbArchiveFileListingConns); + m_catalogue = cta::make_unique<catalogue::InMemoryCatalogue>(m_dummyLog, nbConns, nbArchiveFileListingConns, + maxTriesToConnect); m_scheduler = cta::make_unique<Scheduler>(*m_catalogue, *m_db, 5, 2*1000*1000); } diff --git a/tapeserver/castor/tape/tapeserver/daemon/DataTransferSessionTest.cpp b/tapeserver/castor/tape/tapeserver/daemon/DataTransferSessionTest.cpp index ecfe79f902d1a9ae163009af58110aecc9183e5a..e02b2431debb129517ca06f331f48d8cbd95dace 100644 --- a/tapeserver/castor/tape/tapeserver/daemon/DataTransferSessionTest.cpp +++ b/tapeserver/castor/tape/tapeserver/daemon/DataTransferSessionTest.cpp @@ -118,8 +118,10 @@ public: m_db = param.dbFactory.create(); const uint64_t nbConns = 1; const uint64_t nbArchiveFileListingConns = 1; + const uint32_t maxTriesToConnect = 1; //m_catalogue = cta::make_unique<catalogue::SchemaCreatingSqliteCatalogue>(m_tempSqliteFile.path(), nbConns); - m_catalogue = cta::make_unique<catalogue::InMemoryCatalogue>(m_dummyLog, nbConns, nbArchiveFileListingConns); + m_catalogue = cta::make_unique<catalogue::InMemoryCatalogue>(m_dummyLog, nbConns, nbArchiveFileListingConns, + maxTriesToConnect); m_scheduler = cta::make_unique<Scheduler>(*m_catalogue, *m_db, 5, 2*1000*1000); strncpy(m_tmpDir, "/tmp/DataTransferSessionTestXXXXXX", sizeof(m_tmpDir)); diff --git a/xroot_plugins/CMakeLists.txt b/xroot_plugins/CMakeLists.txt index 00f3d03843ae9b2baa2c6c5ef9fc78b63e0a44a8..671223ef854917c9166bf1e679b41cedd908310f 100644 --- a/xroot_plugins/CMakeLists.txt +++ b/xroot_plugins/CMakeLists.txt @@ -48,27 +48,27 @@ endif (OCCI_SUPPORT) # # XRootD OFS plugin for CTA Frontend (DEPRECATED) # -add_library (XrdCtaOfs MODULE - ListArchiveFilesCmd.cpp - XrdCtaFilesystem.cpp - XrdCtaFile.cpp - XrdCtaDir.cpp) -if(CMAKE_COMPILER_IS_GNUCC) - # Add -Wno-implicit-fallthrough compiler flag if using gcc version 7 or greater - if (GCC_VERSION VERSION_EQUAL 7 OR GCC_VERSION VERSION_GREATER 7) - set_property(SOURCE XrdCtaFile.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-implicit-fallthrough") - endif (GCC_VERSION VERSION_EQUAL 7 OR GCC_VERSION VERSION_GREATER 7) -endif(CMAKE_COMPILER_IS_GNUCC) - -set_property(TARGET XrdCtaOfs PROPERTY SOVERSION "${CTA_SOVERSION}") -set_property(TARGET XrdCtaOfs PROPERTY VERSION "${CTA_LIBVERSION}") -target_link_libraries (XrdCtaOfs ctacatalogue ctascheduler ctacommon ctaobjectstore cryptopp) -set_property (TARGET XrdCtaOfs APPEND PROPERTY INSTALL_RPATH ${PROTOBUF3_RPATH}) -if (OCCI_SUPPORT) - set_property (TARGET XrdCtaOfs APPEND PROPERTY INSTALL_RPATH ${ORACLE-INSTANTCLIENT_RPATH}) -endif (OCCI_SUPPORT) - -install (TARGETS XrdCtaOfs DESTINATION usr/${CMAKE_INSTALL_LIBDIR}) +#add_library (XrdCtaOfs MODULE +# ListArchiveFilesCmd.cpp +# XrdCtaFilesystem.cpp +# XrdCtaFile.cpp +# XrdCtaDir.cpp) +#if(CMAKE_COMPILER_IS_GNUCC) +# # Add -Wno-implicit-fallthrough compiler flag if using gcc version 7 or greater +# if (GCC_VERSION VERSION_EQUAL 7 OR GCC_VERSION VERSION_GREATER 7) +# set_property(SOURCE XrdCtaFile.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-implicit-fallthrough") +# endif (GCC_VERSION VERSION_EQUAL 7 OR GCC_VERSION VERSION_GREATER 7) +#endif(CMAKE_COMPILER_IS_GNUCC) +# +#set_property(TARGET XrdCtaOfs PROPERTY SOVERSION "${CTA_SOVERSION}") +#set_property(TARGET XrdCtaOfs PROPERTY VERSION "${CTA_LIBVERSION}") +#target_link_libraries (XrdCtaOfs ctacatalogue ctascheduler ctacommon ctaobjectstore cryptopp) +#set_property (TARGET XrdCtaOfs APPEND PROPERTY INSTALL_RPATH ${PROTOBUF3_RPATH}) +#if (OCCI_SUPPORT) +# set_property (TARGET XrdCtaOfs APPEND PROPERTY INSTALL_RPATH ${ORACLE-INSTANTCLIENT_RPATH}) +#endif (OCCI_SUPPORT) +# +#install (TARGETS XrdCtaOfs DESTINATION usr/${CMAKE_INSTALL_LIBDIR}) # #################################################################################################### diff --git a/xroot_plugins/XrdSsiCtaServiceProvider.cpp b/xroot_plugins/XrdSsiCtaServiceProvider.cpp index aeed04b59dde0179ca471c345f6944a2ded06ffb..f31cd337dc3218c324522bdff343ea3a72511b15 100644 --- a/xroot_plugins/XrdSsiCtaServiceProvider.cpp +++ b/xroot_plugins/XrdSsiCtaServiceProvider.cpp @@ -50,57 +50,6 @@ XrdSsiProvider *XrdSsiProviderServer = new XrdSsiCtaServiceProvider; -namespace XrdSsiPb { - -/*! - * Override the Service::Prepare method - * - * Ensures that resource.client->name is valid. This is obtained from the KRB5 or SSS key, so - * connections via unix sockets are not possible in this scheme. - */ -template<> -bool Service<cta::xrd::Request, cta::xrd::Response, cta::xrd::Alert>::Prepare(XrdSsiErrInfo &eInfo, const XrdSsiResource &resource) -{ - if(resource.client == nullptr || resource.client->name == nullptr) - { - eInfo.Set("Service::Prepare(): XRootD client name is not set. " - "Possible misconfiguration of the KRB5 or SSS keyfile.", EACCES); - return false; - } - -#ifdef XRDSSI_DEBUG - std::cerr << "[DEBUG] Service::Prepare():" << std::endl; - std::cerr << "[DEBUG] Resource name: " << resource.rName << std::endl - << "[DEBUG] Resource user: " << resource.rUser << std::endl - << "[DEBUG] Resource info: " << resource.rInfo << std::endl - << "[DEBUG] Hosts to avoid: " << resource.hAvoid << std::endl - << "[DEBUG] Affinity: "; - - switch(resource.affinity) - { - case XrdSsiResource::None: std::cerr << "None" << std::endl; break; - case XrdSsiResource::Default: std::cerr << "Default" << std::endl; break; - case XrdSsiResource::Weak: std::cerr << "Weak" << std::endl; break; - case XrdSsiResource::Strong: std::cerr << "Strong" << std::endl; break; - case XrdSsiResource::Strict: std::cerr << "Strict" << std::endl; break; - } - - std::cerr << "[DEBUG] Resource options: " - << (resource.rOpts & XrdSsiResource::Reusable ? "Resuable " : "") - << (resource.rOpts & XrdSsiResource::Discard ? "Discard" : "") - << std::endl; - - std::cerr << "[DEBUG] Resource client protocol: " << resource.client->prot << std::endl; - std::cerr << "[DEBUG] Resource client name: " << resource.client->name << std::endl; -#endif - - return true; -} - -} // namespace XrdSsiPb - - - /*! * Initialise the Service Provider */ diff --git a/xroot_plugins/cta-frontend-xrootd.conf b/xroot_plugins/cta-frontend-xrootd.conf index 062bbd45e3f42f4bd5be62fa2602557647dd7850..3bcbffe0e058bb16113df4a60f719a012273edb6 100644 --- a/xroot_plugins/cta-frontend-xrootd.conf +++ b/xroot_plugins/cta-frontend-xrootd.conf @@ -1,5 +1,6 @@ # Load the CTA SSI and OFS plugins -xrootd.fslib libXrdSsi.so libXrdCtaOfs.so +#xrootd.fslib libXrdSsi.so libXrdCtaOfs.so +xrootd.fslib libXrdSsi.so # Specify which paths are handled by the OFS plugin # @@ -8,10 +9,10 @@ xrootd.fslib libXrdSsi.so libXrdCtaOfs.so # # Y3Rh is the Base64 encoding of cta, so this string appears at the beginning # of all cta admin commands -ssi.fspath /Y3Rh +#ssi.fspath /Y3Rh # L3Vzci9iaW4vY3Rh is Base64 encoding of /usr/bin/cta which appears at # the beginning of commands called from the EOS WFE bash script -ssi.fspath /L3Vzci9iaW4vY3Rh +#ssi.fspath /L3Vzci9iaW4vY3Rh # Load the SSI module ssi.svclib libXrdSsiCta.so @@ -22,7 +23,7 @@ xrootd.seclib libXrdSec.so # Protocol specification # The xroot server process needs to be able to read the keytab file sec.protocol krb5 /etc/cta/cta-frontend.krb5.keytab cta/cta-frontend@TEST.CTA -sec.protocol sss -s /etc/cta/cta-cli.sss.keytab +sec.protocol sss -s /etc/cta/eos.sss.keytab # Only Kerberos 5 and sss are allowed sec.protbind * only sss krb5 @@ -41,5 +42,5 @@ all.export /ctafrontend nolock r/w # There can be more than one of these; anything that starts with the prefix # will go to the the underlying file system. Note that this prefix cannot be # a substring of '/ctafrontend', so it is not possible to simply export '/'. -all.export /Y3Rh -all.export /L3Vzci9iaW4vY3Rh +#all.export /Y3Rh +#all.export /L3Vzci9iaW4vY3Rh diff --git a/xrootd-ssi-protobuf-interface b/xrootd-ssi-protobuf-interface index d36f5a1848a4164b9a1182f21614e36e854f3785..1e0d5df3725dade40f968ca55de993a6efc93908 160000 --- a/xrootd-ssi-protobuf-interface +++ b/xrootd-ssi-protobuf-interface @@ -1 +1 @@ -Subproject commit d36f5a1848a4164b9a1182f21614e36e854f3785 +Subproject commit 1e0d5df3725dade40f968ca55de993a6efc93908