From df38b5be3e31006f09eabfb571a546ed0dc11986 Mon Sep 17 00:00:00 2001 From: Cedric CAFFY <cedric.caffy@cern.ch> Date: Wed, 4 Mar 2020 10:51:35 +0100 Subject: [PATCH] Implemented Catalogue::deleteVirtualOrganization + NOT ALL unit tests --- catalogue/CMakeLists.txt | 5 +- catalogue/Catalogue.hpp | 8 +- catalogue/CatalogueRetryWrapper.hpp | 4 + catalogue/CatalogueTest.cpp | 24 +++++ catalogue/DummyCatalogue.hpp | 1 + catalogue/RdbmsCatalogue.cpp | 95 +++++++++++++++++++ catalogue/RdbmsCatalogue.hpp | 24 +++++ ...irtualOrganizationUsedByStorageClasses.cpp | 39 ++++++++ ...irtualOrganizationUsedByStorageClasses.hpp | 49 ++++++++++ ...fiedVirtualOrganizationUsedByTapepools.cpp | 39 ++++++++ ...fiedVirtualOrganizationUsedByTapepools.hpp | 49 ++++++++++ 11 files changed, 335 insertions(+), 2 deletions(-) create mode 100644 catalogue/UserSpecifiedVirtualOrganizationUsedByStorageClasses.cpp create mode 100644 catalogue/UserSpecifiedVirtualOrganizationUsedByStorageClasses.hpp create mode 100644 catalogue/UserSpecifiedVirtualOrganizationUsedByTapepools.cpp create mode 100644 catalogue/UserSpecifiedVirtualOrganizationUsedByTapepools.hpp diff --git a/catalogue/CMakeLists.txt b/catalogue/CMakeLists.txt index 7b94693178..1b22008d88 100644 --- a/catalogue/CMakeLists.txt +++ b/catalogue/CMakeLists.txt @@ -83,7 +83,10 @@ set (CATALOGUE_LIB_SRC_FILES UserSpecifiedStorageClassUsedByArchiveFiles.cpp UserSpecifiedStorageClassUsedByArchiveRoutes.cpp UserSpecifiedAZeroCapacity.cpp - UserSpecifiedAZeroCopyNb.cpp) + UserSpecifiedAZeroCopyNb.cpp + UserSpecifiedVirtualOrganizationUsedByTapepools.cpp + UserSpecifiedVirtualOrganizationUsedByStorageClasses.cpp +) add_library (ctacatalogue SHARED ${CATALOGUE_LIB_SRC_FILES}) diff --git a/catalogue/Catalogue.hpp b/catalogue/Catalogue.hpp index 1e0b4613de..37fcc0e2f3 100644 --- a/catalogue/Catalogue.hpp +++ b/catalogue/Catalogue.hpp @@ -233,6 +233,12 @@ public: */ virtual void createVirtualOrganization(const common::dataStructures::SecurityIdentity &admin, const common::dataStructures::VirtualOrganization &vo) = 0; + /** + * Deletes the specified Virtual Organization + * @param voName the name of the VirtualOrganization to delete + */ + virtual void deleteVirtualOrganization(const std::string &voName) = 0; + /** * Creates the specified storage class. * @@ -247,7 +253,7 @@ public: * Deletes the specified storage class. * * @param storageClassName The name of the storage class which is only - * guaranteed to be unique within its disk isntance. + * guaranteed to be unique within its disk instance. */ virtual void deleteStorageClass(const std::string &storageClassName) = 0; diff --git a/catalogue/CatalogueRetryWrapper.hpp b/catalogue/CatalogueRetryWrapper.hpp index b82233e422..7919c7d1fe 100644 --- a/catalogue/CatalogueRetryWrapper.hpp +++ b/catalogue/CatalogueRetryWrapper.hpp @@ -119,6 +119,10 @@ public: void createVirtualOrganization(const common::dataStructures::SecurityIdentity &admin, const common::dataStructures::VirtualOrganization &vo) override { return retryOnLostConnection(m_log, [&]{return m_catalogue->createVirtualOrganization(admin, vo);}, m_maxTriesToConnect); } + + void deleteVirtualOrganization(const std::string &voName) override { + return retryOnLostConnection(m_log, [&]{return m_catalogue->deleteVirtualOrganization(voName);}, m_maxTriesToConnect); + } void createStorageClass(const common::dataStructures::SecurityIdentity &admin, const common::dataStructures::StorageClass &storageClass) override { return retryOnLostConnection(m_log, [&]{return m_catalogue->createStorageClass(admin, storageClass);}, m_maxTriesToConnect); diff --git a/catalogue/CatalogueTest.cpp b/catalogue/CatalogueTest.cpp index e5d5897e9f..9413b1ea60 100644 --- a/catalogue/CatalogueTest.cpp +++ b/catalogue/CatalogueTest.cpp @@ -15325,4 +15325,28 @@ TEST_P(cta_catalogue_CatalogueTest, createVirtualOrganizationEmptyName) { ASSERT_THROW(m_catalogue->createVirtualOrganization(m_admin,vo),cta::exception::UserError); } +TEST_P(cta_catalogue_CatalogueTest, deleteVirtualOrganization) { + using namespace cta; + + common::dataStructures::VirtualOrganization vo; + vo.name = "vo"; + vo.comment = "comment"; + + ASSERT_NO_THROW(m_catalogue->createVirtualOrganization(m_admin,vo)); + + ASSERT_NO_THROW(m_catalogue->deleteVirtualOrganization(vo.name)); +} + +TEST_P(cta_catalogue_CatalogueTest, deleteVirtualOrganizationNameDoesNotExist) { + using namespace cta; + + common::dataStructures::VirtualOrganization vo; + vo.name = "vo"; + vo.comment = "comment"; + + ASSERT_NO_THROW(m_catalogue->createVirtualOrganization(m_admin,vo)); + + ASSERT_THROW(m_catalogue->deleteVirtualOrganization("DOES_NOT_EXIST"),cta::exception::UserError); +} + } // namespace unitTests diff --git a/catalogue/DummyCatalogue.hpp b/catalogue/DummyCatalogue.hpp index c2cff5b265..204070ee42 100644 --- a/catalogue/DummyCatalogue.hpp +++ b/catalogue/DummyCatalogue.hpp @@ -89,6 +89,7 @@ public: void modifyAdminUserComment(const common::dataStructures::SecurityIdentity& admin, const std::string& username, const std::string& comment) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); } void createVirtualOrganization(const common::dataStructures::SecurityIdentity &admin, const common::dataStructures::VirtualOrganization &vo) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); } + void deleteVirtualOrganization(const std::string &voName) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); } void modifyArchiveRouteComment(const common::dataStructures::SecurityIdentity& admin, const std::string& storageClassName, const uint32_t copyNb, const std::string& comment) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); } void modifyArchiveRouteTapePoolName(const common::dataStructures::SecurityIdentity& admin, const std::string& storageClassName, const uint32_t copyNb, const std::string& tapePoolName) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); } void modifyLogicalLibraryName(const common::dataStructures::SecurityIdentity &admin, const std::string ¤tName, const std::string &newName) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); } diff --git a/catalogue/RdbmsCatalogue.cpp b/catalogue/RdbmsCatalogue.cpp index 37f4cf8bad..e19a1eb3f4 100644 --- a/catalogue/RdbmsCatalogue.cpp +++ b/catalogue/RdbmsCatalogue.cpp @@ -395,6 +395,45 @@ void RdbmsCatalogue::createVirtualOrganization(const common::dataStructures::Sec } } +//------------------------------------------------------------------------------ +// deleteVirtualOrganization +//------------------------------------------------------------------------------ +void RdbmsCatalogue::deleteVirtualOrganization(const std::string &voName){ + try { + auto conn = m_connPool.getConn(); + + if(virtualOrganizationIsUsedByStorageClasses(conn, voName)) { + throw UserSpecifiedStorageClassUsedByArchiveRoutes(std::string("The ") + voName + + " Virtual Organization is being used by one or more storage classes"); + } + + if(virtualOrganizationIsUsedByTapepools(conn, voName)) { + throw UserSpecifiedStorageClassUsedByArchiveFiles(std::string("The ") + voName + + " Virtual Organization is being used by one or more Tapepools"); + } + + const char *const sql = + "DELETE FROM " + "VIRTUAL_ORGANIZATION " + "WHERE " + "VIRTUAL_ORGANIZATION_NAME = :VIRTUAL_ORGANIZATION_NAME"; + auto stmt = conn.createStmt(sql); + + stmt.bindString(":VIRTUAL_ORGANIZATION_NAME", voName); + + stmt.executeNonQuery(); + if(0 == stmt.getNbAffectedRows()) { + throw exception::UserError(std::string("Cannot delete Virtual Organization : ") + + voName + " because it does not exist"); + } + } catch(exception::UserError &) { + throw; + } catch(exception::Exception &ex) { + ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str()); + throw; + } +} + //------------------------------------------------------------------------------ // createStorageClass //------------------------------------------------------------------------------ @@ -600,6 +639,62 @@ bool RdbmsCatalogue::storageClassIsUsedByArchiveFiles(rdbms::Conn &conn, const s } } +//------------------------------------------------------------------------------ +// virtualOrganizationIsUsedByStorageClasses +//------------------------------------------------------------------------------ +bool RdbmsCatalogue::virtualOrganizationIsUsedByStorageClasses(rdbms::Conn &conn, const std::string &voName) const { + try { + const char *const sql = + "SELECT " + "VIRTUAL_ORGANIZATION_NAME AS VIRTUAL_ORGANIZATION_NAME " + "FROM " + "VIRTUAL_ORGANIZATION " + "INNER JOIN " + "STORAGE_CLASS " + "ON " + "VIRTUAL_ORGANIZATION.VIRTUAL_ORGANIZATION_ID = STORAGE_CLASS.VIRTUAL_ORGANIZATION_ID " + "WHERE " + "VIRTUAL_ORGANIZATION_NAME = :VIRTUAL_ORGANIZATION_NAME"; + auto stmt = conn.createStmt(sql); + stmt.bindString(":VIRTUAL_ORGANIZATION_NAME", voName); + auto rset = stmt.executeQuery(); + return rset.next(); + } catch(exception::UserError &) { + throw; + } catch(exception::Exception &ex) { + ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str()); + throw; + } +} + +//------------------------------------------------------------------------------ +// virtualOrganizationIsUsedByTapepools +//------------------------------------------------------------------------------ +bool RdbmsCatalogue::virtualOrganizationIsUsedByTapepools(rdbms::Conn &conn, const std::string &voName) const { + try { + const char *const sql = + "SELECT " + "VIRTUAL_ORGANIZATION_NAME AS VIRTUAL_ORGANIZATION_NAME " + "FROM " + "VIRTUAL_ORGANIZATION " + "INNER JOIN " + "TAPE_POOL " + "ON " + "VIRTUAL_ORGANIZATION.VIRTUAL_ORGANIZATION_ID = TAPE_POOL.VIRTUAL_ORGANIZATION_ID " + "WHERE " + "VIRTUAL_ORGANIZATION_NAME = :VIRTUAL_ORGANIZATION_NAME"; + auto stmt = conn.createStmt(sql); + stmt.bindString(":VIRTUAL_ORGANIZATION_NAME", voName); + auto rset = stmt.executeQuery(); + return rset.next(); + } catch(exception::UserError &) { + throw; + } catch(exception::Exception &ex) { + ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str()); + throw; + } +} + //------------------------------------------------------------------------------ // getStorageClasses //------------------------------------------------------------------------------ diff --git a/catalogue/RdbmsCatalogue.hpp b/catalogue/RdbmsCatalogue.hpp index 7fbbf3d241..26f0bd358e 100644 --- a/catalogue/RdbmsCatalogue.hpp +++ b/catalogue/RdbmsCatalogue.hpp @@ -218,6 +218,12 @@ public: * @param vo the Virtual Organization */ void createVirtualOrganization(const common::dataStructures::SecurityIdentity &admin, const common::dataStructures::VirtualOrganization &vo) override; + + /** + * Deletes the specified Virtual Organization + * @param voName the name of the VirtualOrganization to delete + */ + void deleteVirtualOrganization(const std::string &voName) override; /** * Creates the specified storage class. @@ -1551,6 +1557,24 @@ protected: * @param storageClassName The name of the storage class. */ bool storageClassIsUsedByArchiveFiles(rdbms::Conn &conn, const std::string &storageClassName) const; + + /** + * Returns true if the specified Virtual Organization is currently being used by one + * or more StorageClasses + * + * @param conn The database connection. + * @param voName The name of the Virtual Organization. + */ + bool virtualOrganizationIsUsedByStorageClasses(rdbms::Conn &conn, const std::string &voName) const; + + /** + * Returns true if the specified Virtual Organization is currently being used by one + * or more Tapepools + * + * @param conn The database connection. + * @param voName The name of the Virtual Organization. + */ + bool virtualOrganizationIsUsedByTapepools(rdbms::Conn &conn, const std::string &voName) const; /** * Returns the ID of the specified logical library or nullopt if the logical diff --git a/catalogue/UserSpecifiedVirtualOrganizationUsedByStorageClasses.cpp b/catalogue/UserSpecifiedVirtualOrganizationUsedByStorageClasses.cpp new file mode 100644 index 0000000000..8437c1c059 --- /dev/null +++ b/catalogue/UserSpecifiedVirtualOrganizationUsedByStorageClasses.cpp @@ -0,0 +1,39 @@ +/* + * 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 "catalogue/UserSpecifiedVirtualOrganizationUsedByStorageClasses.hpp" + +namespace cta { +namespace catalogue { + + +//------------------------------------------------------------------------------ +// constructor +//------------------------------------------------------------------------------ +UserSpecifiedVirtualOrganizationUsedByStorageClasses::UserSpecifiedVirtualOrganizationUsedByStorageClasses(const std::string &context, + const bool embedBacktrace): cta::exception::UserError(context, embedBacktrace) { +} + +//------------------------------------------------------------------------------ +// destructor +//------------------------------------------------------------------------------ +UserSpecifiedVirtualOrganizationUsedByStorageClasses::~UserSpecifiedVirtualOrganizationUsedByStorageClasses() { +} + +} // namespace catalogue +} // namespace cta diff --git a/catalogue/UserSpecifiedVirtualOrganizationUsedByStorageClasses.hpp b/catalogue/UserSpecifiedVirtualOrganizationUsedByStorageClasses.hpp new file mode 100644 index 0000000000..fb21065afc --- /dev/null +++ b/catalogue/UserSpecifiedVirtualOrganizationUsedByStorageClasses.hpp @@ -0,0 +1,49 @@ +/* + * 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/UserError.hpp" + +namespace cta { +namespace catalogue { + +/** + * User specified a storage class which is currently being used by one or more + * archive files. + */ +class UserSpecifiedVirtualOrganizationUsedByStorageClasses: public exception::UserError { +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 + */ + UserSpecifiedVirtualOrganizationUsedByStorageClasses(const std::string &context = "", const bool embedBacktrace = true); + + /** + * Destructor. + */ + ~UserSpecifiedVirtualOrganizationUsedByStorageClasses() override; +}; // class UserSpecifiedVirtualOrganizationUsedByStorageClasses + +} // namespace catalogue +} // namespace cta diff --git a/catalogue/UserSpecifiedVirtualOrganizationUsedByTapepools.cpp b/catalogue/UserSpecifiedVirtualOrganizationUsedByTapepools.cpp new file mode 100644 index 0000000000..7c9d6264e6 --- /dev/null +++ b/catalogue/UserSpecifiedVirtualOrganizationUsedByTapepools.cpp @@ -0,0 +1,39 @@ +/* + * 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 "catalogue/UserSpecifiedVirtualOrganizationUsedByTapepools.hpp" + +namespace cta { +namespace catalogue { + + +//------------------------------------------------------------------------------ +// constructor +//------------------------------------------------------------------------------ +UserSpecifiedVirtualOrganizationUsedByTapepools::UserSpecifiedVirtualOrganizationUsedByTapepools(const std::string &context, + const bool embedBacktrace): cta::exception::UserError(context, embedBacktrace) { +} + +//------------------------------------------------------------------------------ +// destructor +//------------------------------------------------------------------------------ +UserSpecifiedVirtualOrganizationUsedByTapepools::~UserSpecifiedVirtualOrganizationUsedByTapepools() { +} + +} // namespace catalogue +} // namespace cta diff --git a/catalogue/UserSpecifiedVirtualOrganizationUsedByTapepools.hpp b/catalogue/UserSpecifiedVirtualOrganizationUsedByTapepools.hpp new file mode 100644 index 0000000000..47b5e69952 --- /dev/null +++ b/catalogue/UserSpecifiedVirtualOrganizationUsedByTapepools.hpp @@ -0,0 +1,49 @@ +/* + * 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/UserError.hpp" + +namespace cta { +namespace catalogue { + +/** + * User specified a storage class which is currently being used by one or more + * archive files. + */ +class UserSpecifiedVirtualOrganizationUsedByTapepools: public exception::UserError { +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 + */ + UserSpecifiedVirtualOrganizationUsedByTapepools(const std::string &context = "", const bool embedBacktrace = true); + + /** + * Destructor. + */ + ~UserSpecifiedVirtualOrganizationUsedByTapepools() override; +}; // class UserSpecifiedVirtualOrganizationUsedByTapepools + +} // namespace catalogue +} // namespace cta -- GitLab