diff --git a/catalogue/CMakeLists.txt b/catalogue/CMakeLists.txt
index 20ac4a92ca9e49c8abda1887d3e3bd8ba7d296f2..296ef14bb6126b201bd5b8f92e4b388ad614fd75 100644
--- a/catalogue/CMakeLists.txt
+++ b/catalogue/CMakeLists.txt
@@ -54,8 +54,15 @@ set (CATALOGUE_LIB_SRC_FILES
   TapeForWriting.cpp
   UserSpecifiedANonEmptyTape.cpp
   UserSpecifiedANonExistentTape.cpp
+  UserSpecifiedANonExistentDiskSystem.cpp
+  UserSpecifiedANonEmptyDiskSystemAfterDelete.cpp
   UserSpecifiedAnEmptyStringComment.cpp
   UserSpecifiedAnEmptyStringDiskInstanceName.cpp
+  UserSpecifiedAnEmptyStringDiskSystemName.cpp
+  UserSpecifiedAnEmptyStringFileRegexp.cpp
+  UserSpecifiedAnEmptyStringFreeSpaceQueryURL.cpp
+  UserSpecifiedAZeroRefreshInterval.cpp
+  UserSpecifiedAZeroTargetedFreeSpace.cpp
   UserSpecifiedAnEmptyStringLogicalLibraryName.cpp
   UserSpecifiedAnEmptyStringMediaType.cpp
   UserSpecifiedAnEmptyStringStorageClassName.cpp
diff --git a/catalogue/Catalogue.hpp b/catalogue/Catalogue.hpp
index 9ccf2323da4958d1b9a1d347fdad36f9fb396ba6..fbc85e4542928eb40d7a6125e315873ef1a6cd7c 100644
--- a/catalogue/Catalogue.hpp
+++ b/catalogue/Catalogue.hpp
@@ -55,11 +55,11 @@
 #include "common/dataStructures/UserIdentity.hpp"
 #include "common/dataStructures/VidToTapeMap.hpp"
 #include "common/dataStructures/WriteTestResult.hpp"
+#include "common/dataStructures/DiskSystem.hpp"
 #include "common/exception/UserError.hpp"
 #include "common/log/LogContext.hpp"
 #include "common/log/Logger.hpp"
 #include "common/optional.hpp"
-#include "disk/DiskSystem.hpp"
 
 #include <list>
 #include <map>
@@ -492,8 +492,46 @@ public:
   virtual void deleteActivitiesFairShareWeight(const common::dataStructures::SecurityIdentity &admin, const std::string & diskInstanceName, const std::string & acttivity) = 0;
   virtual std::list<common::dataStructures::ActivitiesFairShareWeights> getActivitiesFairShareWeights() const = 0;
   
+  /**
+   * Returns all the disk systems within the CTA catalogue.
+   *
+   * @return The disk systems.
+   * requester group.
+   */
+  virtual common::dataStructures::DiskSystemList getAllDiskSystems() const = 0;
+  
+  /**
+   * Creates a disk system.
+   * 
+   * @param admin The administrator.
+   * @param name The name of the disk system.
+   * @param fileRegexp The regular expression allowing matching destination URLs
+   * for this disk system.
+   * @param freeSpaceQueryURL The query URL that describes a method to query the
+   * free space from the disk system.
+   * @param refreshInterval The refresh interval (seconds) defining how long do 
+   * we use a free space value.
+   * @param targetedFreeSpace The targeted free space (margin) based on the free
+   * space update latency (inherent to the file system and induced by the refresh 
+   * interval), and the expected external bandwidth from sources external to CTA.
+   * @param comment Comment.
+   */
+  virtual void createDiskSystem(
+    const common::dataStructures::SecurityIdentity &admin,
+    const std::string &name,
+    const std::string &fileRegexp,
+    const std::string &freeSpaceQueryURL,
+    const uint64_t refreshInterval,
+    const uint64_t targetedFreeSpace,
+    const std::string &comment) = 0;
+  
+  /**
+   * Deletes a disk system.
+   * 
+   * @param name The name of the disk system.
+   */
+   virtual void deleteDiskSystem(const std::string &name) = 0;
   
-  virtual cta::disk::DiskSystemList getDiskSystems() const = 0;
   /**
    * Returns the specified archive files.  Please note that the list of files
    * is ordered by archive file ID.
@@ -612,6 +650,14 @@ public:
    * @return True if the tape exists.
    */
   virtual bool tapeExists(const std::string &vid) const = 0;
+  
+  /**
+   * Returns true if the specified disk system exists.
+   *
+   * @param name The name identifier of the disk system.
+   * @return True if the tape exists.
+   */
+  virtual bool diskSystemExists(const std::string &name) const = 0;  
 
 }; // class Catalogue
 
diff --git a/catalogue/CatalogueRetryWrapper.hpp b/catalogue/CatalogueRetryWrapper.hpp
index ec70da97e5649883467dc68538d14bf23e95734c..12802504e5ece09dfb9c6f51787a9ca2b7782eab 100644
--- a/catalogue/CatalogueRetryWrapper.hpp
+++ b/catalogue/CatalogueRetryWrapper.hpp
@@ -361,10 +361,16 @@ public:
     return retryOnLostConnection(m_log, [&]{return m_catalogue->getActivitiesFairShareWeights();}, m_maxTriesToConnect);
   }
 
-  cta::disk::DiskSystemList getDiskSystems() const override {
-    return retryOnLostConnection(m_log, [&]{return m_catalogue->getDiskSystems();}, m_maxTriesToConnect);
+  common::dataStructures::DiskSystemList getAllDiskSystems() const override {
+    return retryOnLostConnection(m_log, [&]{return m_catalogue->getAllDiskSystems();}, m_maxTriesToConnect);
+  }
+  
+  void createDiskSystem(const common::dataStructures::SecurityIdentity &admin, const std::string &name, const std::string &fileRegexp, const std::string &freeSpaceQueryURL, const uint64_t refreshInterval, const uint64_t targetedFreeSpace, const std::string &comment)  override {
+    return retryOnLostConnection(m_log, [&]{return m_catalogue->createDiskSystem(admin, name, fileRegexp, freeSpaceQueryURL, refreshInterval, targetedFreeSpace, comment);}, m_maxTriesToConnect);
+  }
+  void deleteDiskSystem(const std::string &name) override {
+    return retryOnLostConnection(m_log, [&]{return m_catalogue->deleteDiskSystem(name);}, m_maxTriesToConnect);
   }
-
 
   ArchiveFileItor getArchiveFilesItor(const TapeFileSearchCriteria &searchCriteria = TapeFileSearchCriteria()) const override {
     return retryOnLostConnection(m_log, [&]{return m_catalogue->getArchiveFilesItor(searchCriteria);}, m_maxTriesToConnect);
@@ -410,6 +416,10 @@ public:
     return retryOnLostConnection(m_log, [&]{return m_catalogue->tapeExists(vid);}, m_maxTriesToConnect);
   }
 
+  bool diskSystemExists(const std::string &name) const override {
+    return retryOnLostConnection(m_log, [&]{return m_catalogue->diskSystemExists(name);}, m_maxTriesToConnect);
+  }; 
+
 protected:
 
   /**
diff --git a/catalogue/CatalogueTest.cpp b/catalogue/CatalogueTest.cpp
index 0e31d03ee7785a4a1f720994d2f45499e312e4ad..ebb5de86002e4a861890fb0ed9124d7bc9db8dfa 100644
--- a/catalogue/CatalogueTest.cpp
+++ b/catalogue/CatalogueTest.cpp
@@ -23,6 +23,12 @@
 #include "catalogue/FileSizeMismatch.hpp"
 #include "catalogue/UserSpecifiedANonEmptyTape.hpp"
 #include "catalogue/UserSpecifiedANonExistentTape.hpp"
+#include "catalogue/UserSpecifiedANonExistentDiskSystem.hpp"
+#include "catalogue/UserSpecifiedAnEmptyStringDiskSystemName.hpp"
+#include "catalogue/UserSpecifiedAnEmptyStringFileRegexp.hpp"
+#include "catalogue/UserSpecifiedAnEmptyStringFreeSpaceQueryURL.hpp"
+#include "catalogue/UserSpecifiedAZeroRefreshInterval.hpp"
+#include "catalogue/UserSpecifiedAZeroTargetedFreeSpace.hpp"
 #include "catalogue/UserSpecifiedAnEmptyStringComment.hpp"
 #include "catalogue/UserSpecifiedAnEmptyStringDiskInstanceName.hpp"
 #include "catalogue/UserSpecifiedAnEmptyStringLogicalLibraryName.hpp"
@@ -11432,6 +11438,270 @@ TEST_P(cta_catalogue_CatalogueTest, getAllTapes_many_tapes) {
   }
 }
 
+TEST_P(cta_catalogue_CatalogueTest, getAllDiskSystems_no_systems) {
+  using namespace cta;
+
+  ASSERT_TRUE(m_catalogue->getAllDiskSystems().empty());
+}
+
+TEST_P(cta_catalogue_CatalogueTest, getAllDiskSystems_many_diskSystems) {
+  using namespace cta;
+
+  ASSERT_TRUE(m_catalogue->getAllDiskSystems().empty());
+
+  const std::string fileRegexp = "file_regexp";
+  const std::string freeSpaceQueryURL = "free_space_query_URL";
+  const uint64_t refreshInterval = 32;
+  const uint64_t targetedFreeSpace = 64;
+  
+  const uint32_t nbDiskSystems = 16;
+  
+  for(uint32_t i = 0; i < nbDiskSystems; i++) {
+    std::ostringstream name;
+    name << "DiskSystem" << std::setfill('0') << std::setw(5) << i;
+    const std::string diskSystemComment = "Create disk system " + name.str();
+    m_catalogue->createDiskSystem(m_admin, name.str(), fileRegexp, 
+      freeSpaceQueryURL, refreshInterval + i, targetedFreeSpace + i, diskSystemComment);
+  }
+
+  auto diskSystemsList = m_catalogue->getAllDiskSystems();
+  ASSERT_EQ(nbDiskSystems, diskSystemsList.size());
+
+  for(uint32_t i = 0; i < nbDiskSystems; i++) {
+    std::ostringstream name;
+    name << "DiskSystem" << std::setfill('0') << std::setw(5) << i;
+    const std::string diskSystemComment = "Create disk system " + name.str();
+    ASSERT_NO_THROW(diskSystemsList.at(name.str()));
+    const auto diskSystem = diskSystemsList.at(name.str());
+    
+    ASSERT_EQ(name.str(), diskSystem.name);
+    ASSERT_EQ(fileRegexp, diskSystem.fileRegexp);
+    ASSERT_EQ(freeSpaceQueryURL, diskSystem.freeSpaceQueryURL);
+    ASSERT_EQ(refreshInterval + i, diskSystem.refreshInterval );
+    ASSERT_EQ(targetedFreeSpace + i, diskSystem.targetedFreeSpace);
+    ASSERT_EQ(diskSystemComment, diskSystem.comment);
+  }
+}
+
+TEST_P(cta_catalogue_CatalogueTest, diskSystemExists_emptyString) {
+  using namespace cta;
+
+  ASSERT_TRUE(m_catalogue->getAllDiskSystems().empty());
+
+  const std::string name = "";
+
+  ASSERT_THROW(m_catalogue->diskSystemExists(name), exception::Exception);
+}
+
+TEST_P(cta_catalogue_CatalogueTest, createDiskSystem_emptyStringDiskSystemName) {
+  using namespace cta;
+
+  ASSERT_TRUE(m_catalogue->getAllDiskSystems().empty());
+
+  const std::string name = "";
+  const std::string fileRegexp = "file_regexp";
+  const std::string freeSpaceQueryURL = "free_space_query_URL";
+  const uint64_t refreshInterval = 32;
+  const uint64_t targetedFreeSpace = 64;
+  const std::string comment = "Create disk system";
+
+  ASSERT_THROW(m_catalogue->createDiskSystem(m_admin, name, fileRegexp, 
+    freeSpaceQueryURL, refreshInterval, targetedFreeSpace, comment),
+    catalogue::UserSpecifiedAnEmptyStringDiskSystemName);
+}
+
+TEST_P(cta_catalogue_CatalogueTest, createDiskSystem_emptyStringFileRegexp) {
+  using namespace cta;
+
+  ASSERT_TRUE(m_catalogue->getAllDiskSystems().empty());
+
+  const std::string name = "disk_system_name";
+  const std::string fileRegexp = "";
+  const std::string freeSpaceQueryURL = "free_space_query_URL";
+  const uint64_t refreshInterval = 32;
+  const uint64_t targetedFreeSpace = 64;
+  const std::string comment = "Create disk system";
+
+  ASSERT_THROW(m_catalogue->createDiskSystem(m_admin, name, fileRegexp, 
+    freeSpaceQueryURL, refreshInterval, targetedFreeSpace, comment),
+    catalogue::UserSpecifiedAnEmptyStringFileRegexp);
+}
+
+TEST_P(cta_catalogue_CatalogueTest, createDiskSystem_emptyStringFresSpaceQueryURL) {
+  using namespace cta;
+
+  ASSERT_TRUE(m_catalogue->getAllDiskSystems().empty());
+
+  const std::string name = "disk_system_name";
+  const std::string fileRegexp = "file_regexp";
+  const std::string freeSpaceQueryURL = "";
+  const uint64_t refreshInterval = 32;
+  const uint64_t targetedFreeSpace = 64;
+  const std::string comment = "Create disk system";
+
+  ASSERT_THROW(m_catalogue->createDiskSystem(m_admin, name, fileRegexp, 
+    freeSpaceQueryURL, refreshInterval, targetedFreeSpace, comment),
+    catalogue::UserSpecifiedAnEmptyStringFreeSpaceQueryURL);
+}
+
+
+TEST_P(cta_catalogue_CatalogueTest, createDiskSystem_zeroRefreshInterval) {
+  using namespace cta;
+
+  ASSERT_TRUE(m_catalogue->getAllDiskSystems().empty());
+
+  const std::string name = "disk_system_name";
+  const std::string fileRegexp = "file_regexp";
+  const std::string freeSpaceQueryURL = "free_space_query_url";
+  const uint64_t refreshInterval = 0;
+  const uint64_t targetedFreeSpace = 64;
+  const std::string comment = "Create disk system";
+
+  ASSERT_THROW(m_catalogue->createDiskSystem(m_admin, name, fileRegexp, 
+    freeSpaceQueryURL, refreshInterval, targetedFreeSpace, comment),
+    catalogue::UserSpecifiedAZeroRefreshInterval);
+}
+
+TEST_P(cta_catalogue_CatalogueTest, createDiskSystem_zeroTargetedFreeSpace) {
+  using namespace cta;
+
+  ASSERT_TRUE(m_catalogue->getAllDiskSystems().empty());
+
+  const std::string name = "disk_system_name";
+  const std::string fileRegexp = "file_regexp";
+  const std::string freeSpaceQueryURL = "free_space_query_url";
+  const uint64_t refreshInterval = 32;
+  const uint64_t targetedFreeSpace = 0;
+  const std::string comment = "Create disk system";
+
+  ASSERT_THROW(m_catalogue->createDiskSystem(m_admin, name, fileRegexp, 
+    freeSpaceQueryURL, refreshInterval, targetedFreeSpace, comment),
+    catalogue::UserSpecifiedAZeroTargetedFreeSpace);
+}
+
+TEST_P(cta_catalogue_CatalogueTest, createDiskSystem_emptyStringComment) {
+  using namespace cta;
+
+  ASSERT_TRUE(m_catalogue->getAllDiskSystems().empty());
+
+  const std::string name = "disk_system_name";
+  const std::string fileRegexp = "file_regexp";
+  const std::string freeSpaceQueryURL = "free_space_query_url";
+  const uint64_t refreshInterval = 32;
+  const uint64_t targetedFreeSpace = 64;
+  const std::string comment = "";
+
+  ASSERT_THROW(m_catalogue->createDiskSystem(m_admin, name, fileRegexp, 
+    freeSpaceQueryURL, refreshInterval, targetedFreeSpace, comment),
+    catalogue::UserSpecifiedAnEmptyStringComment);
+}
+
+TEST_P(cta_catalogue_CatalogueTest, createDiskSystem_9_exabytes_targetedFreeSpace) {
+  using namespace cta;
+
+  ASSERT_TRUE(m_catalogue->getAllDiskSystems().empty());
+
+  const std::string name = "disk_system_name";
+  const std::string fileRegexp = "file_regexp";
+  const std::string freeSpaceQueryURL = "free_space_query_url";
+  const uint64_t refreshInterval = 32;
+  // The maximum size of an SQLite integer is a signed 64-bit integer
+  const uint64_t targetedFreeSpace = 9L * 1000 * 1000 * 1000 * 1000 * 1000 * 1000;
+  const std::string comment = "disk system comment";
+
+  m_catalogue->createDiskSystem(m_admin, name, fileRegexp, 
+    freeSpaceQueryURL, refreshInterval, targetedFreeSpace, comment);
+  
+  const auto diskSystemList = m_catalogue->getAllDiskSystems();
+
+  ASSERT_EQ(1, diskSystemList.size());
+
+  {
+    const auto &diskSystem = diskSystemList.front();
+    ASSERT_EQ(name, diskSystem.name);
+    ASSERT_EQ(fileRegexp, diskSystem.fileRegexp);
+    ASSERT_EQ(freeSpaceQueryURL, diskSystem.freeSpaceQueryURL);
+    ASSERT_EQ(refreshInterval, diskSystem.refreshInterval);
+    ASSERT_EQ(targetedFreeSpace, diskSystem.targetedFreeSpace);
+    ASSERT_EQ(comment, diskSystem.comment);
+
+    const auto creationLog = diskSystem.creationLog;
+    ASSERT_EQ(m_admin.username, creationLog.username);
+    ASSERT_EQ(m_admin.host, creationLog.host);
+
+    const auto lastModificationLog = diskSystem.lastModificationLog;
+    ASSERT_EQ(creationLog, lastModificationLog);
+  }
+}
+
+TEST_P(cta_catalogue_CatalogueTest, createDiskSystem_same_twice) {
+  using namespace cta;
+
+  ASSERT_TRUE(m_catalogue->getAllDiskSystems().empty());
+
+  const std::string name = "disk_system_name";
+  const std::string fileRegexp = "file_regexp";
+  const std::string freeSpaceQueryURL = "free_space_query_url";
+  const uint64_t refreshInterval = 32;
+  const uint64_t targetedFreeSpace = 64;
+  const std::string comment = "disk system comment";
+
+  m_catalogue->createDiskSystem(m_admin, name, fileRegexp, 
+    freeSpaceQueryURL, refreshInterval, targetedFreeSpace, comment);
+  
+  const auto diskSystemList = m_catalogue->getAllDiskSystems();
+
+  ASSERT_EQ(1, diskSystemList.size());
+  ASSERT_THROW(m_catalogue->createDiskSystem(m_admin, name, fileRegexp, 
+    freeSpaceQueryURL, refreshInterval, targetedFreeSpace, comment), exception::UserError);
+
+}
+
+TEST_P(cta_catalogue_CatalogueTest, deleteDiskSystem) {
+  using namespace cta;
+
+  ASSERT_TRUE(m_catalogue->getAllDiskSystems().empty());
+
+  const std::string name = "disk_system_name";
+  const std::string fileRegexp = "file_regexp";
+  const std::string freeSpaceQueryURL = "free_space_query_url";
+  const uint64_t refreshInterval = 32;
+  const uint64_t targetedFreeSpace = 64;
+  const std::string comment = "disk system comment";
+
+  m_catalogue->createDiskSystem(m_admin, name, fileRegexp, 
+    freeSpaceQueryURL, refreshInterval, targetedFreeSpace, comment);
+  
+  const auto diskSystemList = m_catalogue->getAllDiskSystems();
+
+  ASSERT_EQ(1, diskSystemList.size());
+  
+  const auto &diskSystem = diskSystemList.front();
+  ASSERT_EQ(name, diskSystem.name);
+  ASSERT_EQ(fileRegexp, diskSystem.fileRegexp);
+  ASSERT_EQ(freeSpaceQueryURL, diskSystem.freeSpaceQueryURL);
+  ASSERT_EQ(refreshInterval, diskSystem.refreshInterval);
+  ASSERT_EQ(targetedFreeSpace, diskSystem.targetedFreeSpace);
+  ASSERT_EQ(comment, diskSystem.comment);
+
+  const auto creationLog = diskSystem.creationLog;
+  ASSERT_EQ(m_admin.username, creationLog.username);
+  ASSERT_EQ(m_admin.host, creationLog.host);
+
+  const auto lastModificationLog = diskSystem.lastModificationLog;
+  ASSERT_EQ(creationLog, lastModificationLog);
+  
+  m_catalogue->deleteDiskSystem(diskSystem.name);
+  ASSERT_TRUE(m_catalogue->getAllDiskSystems().empty());
+}
+
+TEST_P(cta_catalogue_CatalogueTest, deleteDiskSystem_non_existant) {
+  using namespace cta;
+
+  ASSERT_TRUE(m_catalogue->getAllDiskSystems().empty());
+  ASSERT_THROW(m_catalogue->deleteDiskSystem("non_exsitant_disk_system"), catalogue::UserSpecifiedANonExistentDiskSystem);
+}
+
 TEST_P(cta_catalogue_CatalogueTest, reclaimTape_full_lastFSeq_0_no_tape_files) {
   using namespace cta;
 
diff --git a/catalogue/DropSchemaCmd.cpp b/catalogue/DropSchemaCmd.cpp
index b154bbd33f08db29941082feb147872bbcb58304..40bf7fa116cf9703908ad7718043f1d99623cb11 100644
--- a/catalogue/DropSchemaCmd.cpp
+++ b/catalogue/DropSchemaCmd.cpp
@@ -149,7 +149,8 @@ void DropSchemaCmd::dropSqliteCatalogueSchema(rdbms::Conn &conn) {
       "MOUNT_POLICY",
       "ACTIVITIES_WEIGHTS",
       "USAGESTATS",
-      "EXPERIMENTS"
+      "EXPERIMENTS",
+      "DISK_SYSTEM"
     };
     dropDatabaseTables(conn, tablesToDrop);
   } catch(exception::Exception &ex) {
@@ -180,7 +181,8 @@ void DropSchemaCmd::dropMysqlCatalogueSchema(rdbms::Conn &conn) {
       "MOUNT_POLICY",
       "ACTIVITIES_WEIGHTS",
       "USAGESTATS",
-      "EXPERIMENTS"
+      "EXPERIMENTS",
+      "DISK_SYSTEM"
     };
     dropDatabaseTables(conn, tablesToDrop);
 
@@ -248,7 +250,8 @@ void DropSchemaCmd::dropOracleCatalogueSchema(rdbms::Conn &conn) {
       "MOUNT_POLICY",
       "ACTIVITIES_WEIGHTS",
       "USAGESTATS",
-      "EXPERIMENTS"
+      "EXPERIMENTS",
+      "DISK_SYSTEM"
     };
 
     dropDatabaseTables(conn, tablesToDrop);
@@ -282,7 +285,8 @@ void DropSchemaCmd::dropPostgresCatalogueSchema(rdbms::Conn &conn) {
       "MOUNT_POLICY",
       "ACTIVITIES_WEIGHTS",
       "USAGESTATS",
-      "EXPERIMENTS"
+      "EXPERIMENTS",
+      "DISK_SYSTEM"
     };
 
     dropDatabaseTables(conn, tablesToDrop);
diff --git a/catalogue/DummyCatalogue.hpp b/catalogue/DummyCatalogue.hpp
index 4de9cadb1a7c7ad549e0ccd31b20e40b5c274f9b..5c09a0ca922413d358e5874d74604b9932b2cff5 100644
--- a/catalogue/DummyCatalogue.hpp
+++ b/catalogue/DummyCatalogue.hpp
@@ -57,7 +57,9 @@ public:
   void deleteTapePool(const std::string& name) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
   void filesWrittenToTape(const std::set<TapeItemWrittenPointer>& event) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
   std::list<common::dataStructures::ActivitiesFairShareWeights> getActivitiesFairShareWeights() const { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
-  cta::disk::DiskSystemList getDiskSystems() const override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
+  common::dataStructures::DiskSystemList getAllDiskSystems() const override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
+  void createDiskSystem(const common::dataStructures::SecurityIdentity &admin, const std::string &name, const std::string &fileRegexp, const std::string &freeSpaceQueryURL, const uint64_t refreshInterval, const uint64_t targetedFreeSpace, const std::string &comment)  override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
+  void deleteDiskSystem(const std::string &name) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
   std::list<common::dataStructures::AdminUser> getAdminUsers() const override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
   common::dataStructures::ArchiveFile getArchiveFileById(const uint64_t id) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
   ArchiveFileItor getArchiveFilesItor(const TapeFileSearchCriteria& searchCriteria) const { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
@@ -117,6 +119,7 @@ public:
   void setTapeFull(const common::dataStructures::SecurityIdentity& admin, const std::string& vid, const bool fullValue) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
   void setTapePoolEncryption(const common::dataStructures::SecurityIdentity& admin, const std::string& name, const bool encryptionValue) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
   bool tapeExists(const std::string& vid) const { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
+  bool diskSystemExists(const std::string& name) const { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
   void tapeLabelled(const std::string& vid, const std::string& drive) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
   void tapeMountedForArchive(const std::string& vid, const std::string& drive) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
   void tapeMountedForRetrieve(const std::string& vid, const std::string& drive) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
diff --git a/catalogue/RdbmsCatalogue.cpp b/catalogue/RdbmsCatalogue.cpp
index 48094211bc1b5b543e4f5ef7d5ab172e567f86d5..a0856c4aa9186e8d8201cdfcfb62967bd11e2fc5 100644
--- a/catalogue/RdbmsCatalogue.cpp
+++ b/catalogue/RdbmsCatalogue.cpp
@@ -22,9 +22,16 @@
 #include "catalogue/RdbmsCatalogueGetArchiveFilesForRepackItor.hpp"
 #include "catalogue/retryOnLostConnection.hpp"
 #include "catalogue/SqliteCatalogueSchema.hpp"
+#include "catalogue/UserSpecifiedANonExistentDiskSystem.hpp"
+#include "catalogue/UserSpecifiedANonEmptyDiskSystemAfterDelete.hpp"
 #include "catalogue/UserSpecifiedANonEmptyTape.hpp"
 #include "catalogue/UserSpecifiedANonExistentTape.hpp"
 #include "catalogue/UserSpecifiedAnEmptyStringComment.hpp"
+#include "catalogue/UserSpecifiedAnEmptyStringDiskSystemName.hpp"
+#include "catalogue/UserSpecifiedAnEmptyStringFileRegexp.hpp"
+#include "catalogue/UserSpecifiedAnEmptyStringFreeSpaceQueryURL.hpp"
+#include "catalogue/UserSpecifiedAZeroRefreshInterval.hpp"
+#include "catalogue/UserSpecifiedAZeroTargetedFreeSpace.hpp"
 #include "catalogue/UserSpecifiedAnEmptyStringDiskInstanceName.hpp"
 #include "catalogue/UserSpecifiedAnEmptyStringLogicalLibraryName.hpp"
 #include "catalogue/UserSpecifiedAnEmptyStringMediaType.hpp"
@@ -1891,6 +1898,45 @@ bool RdbmsCatalogue::tapeExists(rdbms::Conn &conn, const std::string &vid) const
   }
 }
 
+//------------------------------------------------------------------------------
+// diskSystemExists
+//------------------------------------------------------------------------------
+bool RdbmsCatalogue::diskSystemExists(const std::string &name) const {
+  try {
+    auto conn = m_connPool.getConn();
+    return diskSystemExists(conn, name);
+  } catch(exception::UserError &) {
+    throw;
+  } catch(exception::Exception &ex) {
+    ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
+    throw;
+  }
+}
+
+//------------------------------------------------------------------------------
+// diskSystemExists
+//------------------------------------------------------------------------------
+bool RdbmsCatalogue::diskSystemExists(rdbms::Conn &conn, const std::string &name) const {
+  try {
+    const char *const sql =
+      "SELECT "
+        "DISK_SYSTEM_NAME AS DISK_SYSTEM_NAME "
+      "FROM "
+        "DISK_SYSTEM "
+      "WHERE "
+        "DISK_SYSTEM_NAME = :DISK_SYSTEM_NAME";
+    auto stmt = conn.createStmt(sql);
+    stmt.bindString(":DISK_SYSTEM_NAME", name);
+    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;
+  }
+}
+
 //------------------------------------------------------------------------------
 // deleteTape
 //------------------------------------------------------------------------------
@@ -4199,10 +4245,189 @@ std::list<common::dataStructures::ActivitiesFairShareWeights> RdbmsCatalogue::ge
 }
 
 //------------------------------------------------------------------------------
-// getDiskSystems
+// getAllDiskSystems
 //------------------------------------------------------------------------------
-cta::disk::DiskSystemList RdbmsCatalogue::getDiskSystems() const {
-  return cta::disk::DiskSystemList();
+common::dataStructures::DiskSystemList RdbmsCatalogue::getAllDiskSystems() const {
+  try {
+    common::dataStructures::DiskSystemList diskSystemList;
+    std::string sql =
+      "SELECT "
+        "DISK_SYSTEM.DISK_SYSTEM_NAME AS DISK_SYSTEM_NAME,"
+        "DISK_SYSTEM.FILE_REGEXP AS FILE_REGEXP,"
+        "DISK_SYSTEM.FREE_SPACE_QUERY_URL AS FREE_SPACE_QUERY_URL,"
+        "DISK_SYSTEM.REFRESH_INTERVAL AS REFRESH_INTERVAL,"
+        "DISK_SYSTEM.TARGETED_FREE_SPACE AS TARGETED_FREE_SPACE,"
+        
+        "DISK_SYSTEM.USER_COMMENT AS USER_COMMENT,"
+
+        "DISK_SYSTEM.CREATION_LOG_USER_NAME AS CREATION_LOG_USER_NAME,"
+        "DISK_SYSTEM.CREATION_LOG_HOST_NAME AS CREATION_LOG_HOST_NAME,"
+        "DISK_SYSTEM.CREATION_LOG_TIME AS CREATION_LOG_TIME,"
+
+        "DISK_SYSTEM.LAST_UPDATE_USER_NAME AS LAST_UPDATE_USER_NAME,"
+        "DISK_SYSTEM.LAST_UPDATE_HOST_NAME AS LAST_UPDATE_HOST_NAME,"
+        "DISK_SYSTEM.LAST_UPDATE_TIME AS LAST_UPDATE_TIME "
+      "FROM "
+        "DISK_SYSTEM";
+
+    auto conn = m_connPool.getConn();
+    auto stmt = conn.createStmt(sql);
+
+    auto rset = stmt.executeQuery();
+    while (rset.next()) {
+      common::dataStructures::DiskSystem diskSystem;
+      diskSystem.name = rset.columnString("DISK_SYSTEM_NAME");
+      diskSystem.fileRegexp = rset.columnString("FILE_REGEXP");
+      diskSystem.freeSpaceQueryURL = rset.columnString("FREE_SPACE_QUERY_URL");
+      diskSystem.refreshInterval =  rset.columnUint64("REFRESH_INTERVAL");
+      diskSystem.targetedFreeSpace =  rset.columnUint64("TARGETED_FREE_SPACE");
+      diskSystem.comment = rset.columnString("USER_COMMENT");
+      diskSystem.creationLog.username = rset.columnString("CREATION_LOG_USER_NAME");
+      diskSystem.creationLog.host = rset.columnString("CREATION_LOG_HOST_NAME");
+      diskSystem.creationLog.time = rset.columnUint64("CREATION_LOG_TIME");
+      diskSystem.lastModificationLog.username = rset.columnString("LAST_UPDATE_USER_NAME");
+      diskSystem.lastModificationLog.host = rset.columnString("LAST_UPDATE_HOST_NAME");
+      diskSystem.lastModificationLog.time = rset.columnUint64("LAST_UPDATE_TIME");
+      diskSystemList.push_back(diskSystem);     
+    }
+    return diskSystemList;
+  } catch(exception::UserError &) {
+    throw;
+  } catch(exception::Exception &ex) {
+    ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
+    throw;
+  }
+}
+
+//------------------------------------------------------------------------------
+// createDiskSystem
+//------------------------------------------------------------------------------
+void RdbmsCatalogue::createDiskSystem(
+  const common::dataStructures::SecurityIdentity &admin,
+  const std::string &name,
+  const std::string &fileRegexp,
+  const std::string &freeSpaceQueryURL,
+  const uint64_t refreshInterval,
+  const uint64_t targetedFreeSpace,
+  const std::string &comment) {
+ try {
+    if(name.empty()) {
+      throw UserSpecifiedAnEmptyStringDiskSystemName("Cannot create disk system because the name is an empty string");
+    }
+    if(fileRegexp.empty()) {
+      throw UserSpecifiedAnEmptyStringFileRegexp("Cannot create disk system because the file regexp is an empty string");
+    }
+    if(freeSpaceQueryURL.empty()) {
+      throw UserSpecifiedAnEmptyStringFreeSpaceQueryURL("Cannot create disk system because the free space query URL is an empty string");
+    }
+    if(0 == refreshInterval) {
+      throw UserSpecifiedAZeroRefreshInterval("Cannot create disk system because the refresh interval is zero");
+    }
+    if(0 == targetedFreeSpace) {
+      throw UserSpecifiedAZeroTargetedFreeSpace("Cannot create disk system because the targeted free space is zero");
+    }
+    if(comment.empty()) {
+      throw UserSpecifiedAnEmptyStringComment("Cannot create disk system because the comment is an empty string");
+    }
+
+    auto conn = m_connPool.getConn();
+    if(diskSystemExists(conn, name)) {
+      throw exception::UserError(std::string("Cannot create disk system ") + name +
+        " because a disk system with the same name identifier already exists");
+    }
+    
+    const time_t now = time(nullptr);
+    const char *const sql =
+      "INSERT INTO DISK_SYSTEM("
+        "DISK_SYSTEM_NAME,"
+        "FILE_REGEXP,"
+        "FREE_SPACE_QUERY_URL,"
+        "REFRESH_INTERVAL,"
+        "TARGETED_FREE_SPACE,"
+
+        "USER_COMMENT,"
+
+        "CREATION_LOG_USER_NAME,"
+        "CREATION_LOG_HOST_NAME,"
+        "CREATION_LOG_TIME,"
+
+        "LAST_UPDATE_USER_NAME,"
+        "LAST_UPDATE_HOST_NAME,"
+        "LAST_UPDATE_TIME)"
+      "VALUES("
+        ":DISK_SYSTEM_NAME,"
+        ":FILE_REGEXP,"
+        ":FREE_SPACE_QUERY_URL,"
+        ":REFRESH_INTERVAL,"
+        ":TARGETED_FREE_SPACE,"
+  
+        ":USER_COMMENT,"
+
+        ":CREATION_LOG_USER_NAME,"
+        ":CREATION_LOG_HOST_NAME,"
+        ":CREATION_LOG_TIME,"
+
+        ":LAST_UPDATE_USER_NAME,"
+        ":LAST_UPDATE_HOST_NAME,"
+        ":LAST_UPDATE_TIME)";
+    auto stmt = conn.createStmt(sql);
+
+    stmt.bindString(":DISK_SYSTEM_NAME", name);
+    stmt.bindString(":FILE_REGEXP", fileRegexp);
+    stmt.bindString(":FREE_SPACE_QUERY_URL", freeSpaceQueryURL);
+    stmt.bindUint64(":REFRESH_INTERVAL", refreshInterval);
+    stmt.bindUint64(":TARGETED_FREE_SPACE", targetedFreeSpace);
+
+    stmt.bindString(":USER_COMMENT", comment);
+
+    stmt.bindString(":CREATION_LOG_USER_NAME", admin.username);
+    stmt.bindString(":CREATION_LOG_HOST_NAME", admin.host);
+    stmt.bindUint64(":CREATION_LOG_TIME", now);
+
+    stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username);
+    stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host);
+    stmt.bindUint64(":LAST_UPDATE_TIME", now);
+
+    stmt.executeNonQuery();
+  } catch(exception::UserError &) {
+    throw;
+  } catch(exception::Exception &ex) {
+    ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
+    throw;
+  }  
+}
+
+//------------------------------------------------------------------------------
+// deleteDiskSystem
+//------------------------------------------------------------------------------
+void RdbmsCatalogue::deleteDiskSystem(const std::string &name) {
+    try {
+    const char *const delete_sql =
+      "DELETE "
+      "FROM "
+        "DISK_SYSTEM "
+      "WHERE "
+        "DISK_SYSTEM_NAME = :DISK_SYSTEM_NAME";
+    auto conn = m_connPool.getConn();
+    auto stmt = conn.createStmt(delete_sql);
+    stmt.bindString(":DISK_SYSTEM_NAME", name);
+    stmt.executeNonQuery();
+
+    // The delete statement will effect no rows and will not raise an error if
+    // either the tape does not exist or if it still has tape files
+    if(0 == stmt.getNbAffectedRows()) {
+      if(diskSystemExists(conn, name)) {
+        throw UserSpecifiedANonEmptyDiskSystemAfterDelete(std::string("Cannot delete disk system ") + name + " for unknown reason");
+      } else {
+        throw UserSpecifiedANonExistentDiskSystem(std::string("Cannot delete disk system ") + name + " because it does not exist");
+      }
+    }
+  } catch(exception::UserError &) {
+    throw;
+  } catch(exception::Exception &ex) {
+    ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
+    throw;
+  }
 }
 
 //------------------------------------------------------------------------------
diff --git a/catalogue/RdbmsCatalogue.hpp b/catalogue/RdbmsCatalogue.hpp
index 90d7b12ef8a093168a7791cca008270f6fb6d494..a6188c64e2101074f2bb1b5fb2d029e75fefeecb 100644
--- a/catalogue/RdbmsCatalogue.hpp
+++ b/catalogue/RdbmsCatalogue.hpp
@@ -505,8 +505,45 @@ public:
   void deleteActivitiesFairShareWeight(const common::dataStructures::SecurityIdentity &admin, const std::string & diskInstanceName, const std::string & activity) override;
   std::list<common::dataStructures::ActivitiesFairShareWeights> getActivitiesFairShareWeights() const override;
 
-  cta::disk::DiskSystemList getDiskSystems() const override;
-
+  /**
+   * Returns all the disk systems within the CTA catalogue.
+   *
+   * @return The disk systems.
+   * requester group.
+   */
+  common::dataStructures::DiskSystemList getAllDiskSystems() const override;
+  
+  /**
+   * Creates a disk system.
+   * 
+   * @param admin The administrator.
+   * @param name The name of the disk system.
+   * @param fileRegexp The regular expression allowing matching destination URLs
+   * for this disk system.
+   * @param freeSpaceQueryURL The query URL that describes a method to query the
+   * free space from the disk system.
+   * @param refreshInterval The refresh interval (seconds) defining how long do 
+   * we use a free space value.
+   * @param targetedFreeSpace The targeted free space (margin) based on the free
+   * space update latency (inherent to the file system and induced by the refresh 
+   * interval), and the expected external bandwidth from sources external to CTA.
+   * @param comment Comment.
+   */
+  void createDiskSystem(
+    const common::dataStructures::SecurityIdentity &admin,
+    const std::string &name,
+    const std::string &fileRegexp,
+    const std::string &freeSpaceQueryURL,
+    const uint64_t refreshInterval,
+    const uint64_t targetedFreeSpace,
+    const std::string &comment) override;
+  
+  /**
+   * Deletes a disk system.
+   * 
+   * @param name The name of the disk system.
+   */
+   void deleteDiskSystem(const std::string &name) override;
   
   /**
    * Throws a UserError exception if the specified searchCriteria is not valid
@@ -756,6 +793,23 @@ protected:
    * @return True if the tape exists.
    */
   bool tapeExists(rdbms::Conn &conn, const std::string &vid) const;
+  
+  /**
+   * Returns true if the specified disk system exists.
+   *
+   * @param name The name identifier of the disk system.
+   * @return True if the tape exists.
+   */
+  bool diskSystemExists(const std::string &name) const override;  
+  
+  /**
+   * Returns true if the specified disk system exists.
+   *
+   * @param conn The database connection.
+   * @param name The name identifier of the disk system.
+   * @return True if the disk system exists.
+   */
+  bool diskSystemExists(rdbms::Conn &conn, const std::string &name) const;
 
   /**
    * Returns the list of tapes that meet the specified search criteria.
diff --git a/catalogue/UserSpecifiedANonEmptyDiskSystemAfterDelete.cpp b/catalogue/UserSpecifiedANonEmptyDiskSystemAfterDelete.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8e0ce64760eee2cf19aaa98a0d038208a4a796cc
--- /dev/null
+++ b/catalogue/UserSpecifiedANonEmptyDiskSystemAfterDelete.cpp
@@ -0,0 +1,32 @@
+/*
+ * 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 "UserSpecifiedANonEmptyDiskSystemAfterDelete.hpp"
+
+namespace cta {
+namespace catalogue {
+
+//------------------------------------------------------------------------------
+// constructor
+//------------------------------------------------------------------------------
+UserSpecifiedANonEmptyDiskSystemAfterDelete::UserSpecifiedANonEmptyDiskSystemAfterDelete(const std::string &context, const bool embedBacktrace):
+  UserError(context, embedBacktrace) {
+}
+
+} // namespace catalogue
+} // namespace cta
diff --git a/catalogue/UserSpecifiedANonEmptyDiskSystemAfterDelete.hpp b/catalogue/UserSpecifiedANonEmptyDiskSystemAfterDelete.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..fd679e7fb25d6d0e857e76cce59ba4e18ecabc35
--- /dev/null
+++ b/catalogue/UserSpecifiedANonEmptyDiskSystemAfterDelete.hpp
@@ -0,0 +1,45 @@
+/*
+ * 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 error thrown when a disk system was not deleted for unknown reason.
+ */
+class UserSpecifiedANonEmptyDiskSystemAfterDelete: 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
+   */
+  UserSpecifiedANonEmptyDiskSystemAfterDelete(const std::string &context = "", const bool embedBacktrace = true);
+
+}; // class UserSpecifiedANonEmptyDiskSystemAfterDelete
+
+} // namespace catalogue
+} // namespace cta
diff --git a/catalogue/UserSpecifiedANonExistentDiskSystem.cpp b/catalogue/UserSpecifiedANonExistentDiskSystem.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f5ad9a9348673ab53a76adebe062dfb80deb56c7
--- /dev/null
+++ b/catalogue/UserSpecifiedANonExistentDiskSystem.cpp
@@ -0,0 +1,32 @@
+/*
+ * 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 "UserSpecifiedANonExistentDiskSystem.hpp"
+
+namespace cta {
+namespace catalogue {
+
+//------------------------------------------------------------------------------
+// constructor
+//------------------------------------------------------------------------------
+UserSpecifiedANonExistentDiskSystem::UserSpecifiedANonExistentDiskSystem(const std::string &context, const bool embedBacktrace):
+  UserError(context, embedBacktrace) {
+}
+
+} // namespace catalogue
+} // namespace cta
diff --git a/catalogue/UserSpecifiedANonExistentDiskSystem.hpp b/catalogue/UserSpecifiedANonExistentDiskSystem.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..05dd1da503d837c0431cc8175c1c057fd599af61
--- /dev/null
+++ b/catalogue/UserSpecifiedANonExistentDiskSystem.hpp
@@ -0,0 +1,45 @@
+/*
+ * 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 error thrown when a disk system specified does not exists.
+ */
+class UserSpecifiedANonExistentDiskSystem: 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
+   */
+  UserSpecifiedANonExistentDiskSystem(const std::string &context = "", const bool embedBacktrace = true);
+
+}; // class UserSpecifiedANonExistentDiskSystem
+
+} // namespace catalogue
+} // namespace cta
diff --git a/catalogue/UserSpecifiedAZeroRefreshInterval.cpp b/catalogue/UserSpecifiedAZeroRefreshInterval.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..689ee12e2825755f55f32d9e84ff2bd3f0c53a9a
--- /dev/null
+++ b/catalogue/UserSpecifiedAZeroRefreshInterval.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/UserSpecifiedAZeroRefreshInterval.hpp"
+
+namespace cta {
+namespace catalogue {
+
+
+//------------------------------------------------------------------------------
+// constructor
+//------------------------------------------------------------------------------
+UserSpecifiedAZeroRefreshInterval::UserSpecifiedAZeroRefreshInterval(const std::string &context, const bool embedBacktrace):
+  cta::exception::UserError(context, embedBacktrace) {
+}
+
+//------------------------------------------------------------------------------
+// destructor
+//------------------------------------------------------------------------------
+UserSpecifiedAZeroRefreshInterval::~UserSpecifiedAZeroRefreshInterval() {
+}
+
+} // namespace catalogue
+} // namespace cta
diff --git a/catalogue/UserSpecifiedAZeroRefreshInterval.hpp b/catalogue/UserSpecifiedAZeroRefreshInterval.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..08680ce1602466c68001d30897b0c55f4175299e
--- /dev/null
+++ b/catalogue/UserSpecifiedAZeroRefreshInterval.hpp
@@ -0,0 +1,48 @@
+/*
+ * 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 zero refresh interval when this is not permitted.
+ */
+class UserSpecifiedAZeroRefreshInterval: 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
+   */
+  UserSpecifiedAZeroRefreshInterval(const std::string &context = "", const bool embedBacktrace = true);
+
+  /**
+   * Destructor.
+   */
+  ~UserSpecifiedAZeroRefreshInterval() override;
+}; // class UserSpecifiedAZeroRefreshInterval
+
+} // namespace catalogue
+} // namespace cta
diff --git a/catalogue/UserSpecifiedAZeroTargetedFreeSpace.cpp b/catalogue/UserSpecifiedAZeroTargetedFreeSpace.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..550de7ef660e1e797642c98d66904097f281e2e2
--- /dev/null
+++ b/catalogue/UserSpecifiedAZeroTargetedFreeSpace.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/UserSpecifiedAZeroTargetedFreeSpace.hpp"
+
+namespace cta {
+namespace catalogue {
+
+
+//------------------------------------------------------------------------------
+// constructor
+//------------------------------------------------------------------------------
+UserSpecifiedAZeroTargetedFreeSpace::UserSpecifiedAZeroTargetedFreeSpace(const std::string &context, const bool embedBacktrace):
+  cta::exception::UserError(context, embedBacktrace) {
+}
+
+//------------------------------------------------------------------------------
+// destructor
+//------------------------------------------------------------------------------
+UserSpecifiedAZeroTargetedFreeSpace::~UserSpecifiedAZeroTargetedFreeSpace() {
+}
+
+} // namespace catalogue
+} // namespace cta
diff --git a/catalogue/UserSpecifiedAZeroTargetedFreeSpace.hpp b/catalogue/UserSpecifiedAZeroTargetedFreeSpace.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..f5d8cc3444973852912d51ced9a67a0ca6cc0db1
--- /dev/null
+++ b/catalogue/UserSpecifiedAZeroTargetedFreeSpace.hpp
@@ -0,0 +1,48 @@
+/*
+ * 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 zero value for a targeted free space  when this is not permitted.
+ */
+class UserSpecifiedAZeroTargetedFreeSpace: 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
+   */
+  UserSpecifiedAZeroTargetedFreeSpace(const std::string &context = "", const bool embedBacktrace = true);
+
+  /**
+   * Destructor.
+   */
+  ~UserSpecifiedAZeroTargetedFreeSpace() override;
+}; // class UserSpecifiedAZeroTargetedFreeSpace
+
+} // namespace catalogue
+} // namespace cta
diff --git a/catalogue/UserSpecifiedAnEmptyStringDiskSystemName.cpp b/catalogue/UserSpecifiedAnEmptyStringDiskSystemName.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c814f346755b1f9bab77737249055e376b4dc4a2
--- /dev/null
+++ b/catalogue/UserSpecifiedAnEmptyStringDiskSystemName.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/UserSpecifiedAnEmptyStringDiskSystemName.hpp"
+
+namespace cta {
+namespace catalogue {
+
+
+//------------------------------------------------------------------------------
+// constructor
+//------------------------------------------------------------------------------
+UserSpecifiedAnEmptyStringDiskSystemName::UserSpecifiedAnEmptyStringDiskSystemName(const std::string &context, const bool embedBacktrace):
+  cta::exception::UserError(context, embedBacktrace) {
+}
+
+//------------------------------------------------------------------------------
+// destructor
+//------------------------------------------------------------------------------
+UserSpecifiedAnEmptyStringDiskSystemName::~UserSpecifiedAnEmptyStringDiskSystemName() {
+}
+
+} // namespace catalogue
+} // namespace cta
diff --git a/catalogue/UserSpecifiedAnEmptyStringDiskSystemName.hpp b/catalogue/UserSpecifiedAnEmptyStringDiskSystemName.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..efbc2d811c8983f01cc8e853351243e225c93c7e
--- /dev/null
+++ b/catalogue/UserSpecifiedAnEmptyStringDiskSystemName.hpp
@@ -0,0 +1,48 @@
+/*
+ * 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 an empty string for a disk system name when this is not permitted.
+ */
+class UserSpecifiedAnEmptyStringDiskSystemName: 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
+   */
+  UserSpecifiedAnEmptyStringDiskSystemName(const std::string &context = "", const bool embedBacktrace = true);
+
+  /**
+   * Destructor.
+   */
+  ~UserSpecifiedAnEmptyStringDiskSystemName() override;
+}; // class UserSpecifiedAnEmptyStringDiskSystemName
+
+} // namespace catalogue
+} // namespace cta
diff --git a/catalogue/UserSpecifiedAnEmptyStringFileRegexp.cpp b/catalogue/UserSpecifiedAnEmptyStringFileRegexp.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..331d34c8c7d01971e8ce518cbb93e2600a414079
--- /dev/null
+++ b/catalogue/UserSpecifiedAnEmptyStringFileRegexp.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/UserSpecifiedAnEmptyStringFileRegexp.hpp"
+
+namespace cta {
+namespace catalogue {
+
+
+//------------------------------------------------------------------------------
+// constructor
+//------------------------------------------------------------------------------
+UserSpecifiedAnEmptyStringFileRegexp::UserSpecifiedAnEmptyStringFileRegexp(const std::string &context, const bool embedBacktrace):
+  cta::exception::UserError(context, embedBacktrace) {
+}
+
+//------------------------------------------------------------------------------
+// destructor
+//------------------------------------------------------------------------------
+UserSpecifiedAnEmptyStringFileRegexp::~UserSpecifiedAnEmptyStringFileRegexp() {
+}
+
+} // namespace catalogue
+} // namespace cta
diff --git a/catalogue/UserSpecifiedAnEmptyStringFileRegexp.hpp b/catalogue/UserSpecifiedAnEmptyStringFileRegexp.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..c1899e48cc2c5475644d112621adb25eef6e986d
--- /dev/null
+++ b/catalogue/UserSpecifiedAnEmptyStringFileRegexp.hpp
@@ -0,0 +1,48 @@
+/*
+ * 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 an empty string for a file regexp when this is not permitted.
+ */
+class UserSpecifiedAnEmptyStringFileRegexp: 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
+   */
+  UserSpecifiedAnEmptyStringFileRegexp(const std::string &context = "", const bool embedBacktrace = true);
+
+  /**
+   * Destructor.
+   */
+  ~UserSpecifiedAnEmptyStringFileRegexp() override;
+}; // class UserSpecifiedAnEmptyStringFileRegexp
+
+} // namespace catalogue
+} // namespace cta
diff --git a/catalogue/UserSpecifiedAnEmptyStringFreeSpaceQueryURL.cpp b/catalogue/UserSpecifiedAnEmptyStringFreeSpaceQueryURL.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9d1eb07ae92e2265a5acec1adb7287437101afa0
--- /dev/null
+++ b/catalogue/UserSpecifiedAnEmptyStringFreeSpaceQueryURL.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/UserSpecifiedAnEmptyStringFreeSpaceQueryURL.hpp"
+
+namespace cta {
+namespace catalogue {
+
+
+//------------------------------------------------------------------------------
+// constructor
+//------------------------------------------------------------------------------
+UserSpecifiedAnEmptyStringFreeSpaceQueryURL::UserSpecifiedAnEmptyStringFreeSpaceQueryURL(const std::string &context, const bool embedBacktrace):
+  cta::exception::UserError(context, embedBacktrace) {
+}
+
+//------------------------------------------------------------------------------
+// destructor
+//------------------------------------------------------------------------------
+UserSpecifiedAnEmptyStringFreeSpaceQueryURL::~UserSpecifiedAnEmptyStringFreeSpaceQueryURL() {
+}
+
+} // namespace catalogue
+} // namespace cta
diff --git a/catalogue/UserSpecifiedAnEmptyStringFreeSpaceQueryURL.hpp b/catalogue/UserSpecifiedAnEmptyStringFreeSpaceQueryURL.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..3fb8d674ac6c0266b103e36548789f43ba33c15c
--- /dev/null
+++ b/catalogue/UserSpecifiedAnEmptyStringFreeSpaceQueryURL.hpp
@@ -0,0 +1,48 @@
+/*
+ * 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 an empty string for a free space query URL when this is not permitted.
+ */
+class UserSpecifiedAnEmptyStringFreeSpaceQueryURL: 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
+   */
+  UserSpecifiedAnEmptyStringFreeSpaceQueryURL(const std::string &context = "", const bool embedBacktrace = true);
+
+  /**
+   * Destructor.
+   */
+  ~UserSpecifiedAnEmptyStringFreeSpaceQueryURL() override;
+}; // class UserSpecifiedAnEmptyStringFreeSpaceQueryURL
+
+} // namespace catalogue
+} // namespace cta
diff --git a/catalogue/common_catalogue_schema.sql b/catalogue/common_catalogue_schema.sql
index c0228b3956947ef419863a2585cfe2b728c42011..1a0683e3b1ebe4e594a8443c2289d4ca4a76f6bf 100644
--- a/catalogue/common_catalogue_schema.sql
+++ b/catalogue/common_catalogue_schema.sql
@@ -13,6 +13,21 @@ CREATE TABLE ADMIN_USER(
   LAST_UPDATE_TIME        NUMERIC(20, 0)  CONSTRAINT ADMIN_USER_LUT_NN  NOT NULL,
   CONSTRAINT ADMIN_USER_PK PRIMARY KEY(ADMIN_USER_NAME)
 );
+CREATE TABLE DISK_SYSTEM(
+  DISK_SYSTEM_NAME        VARCHAR(100)    CONSTRAINT DISK_SYSTEM_DSNM_NN NOT NULL,
+  FILE_REGEXP             VARCHAR(100)    CONSTRAINT DISK_SYSTEM_FR_NN   NOT NULL,
+  FREE_SPACE_QUERY_URL    VARCHAR(1000)   CONSTRAINT DISK_SYSTEM_FSQU_NN NOT NULL,
+  REFRESH_INTERVAL        NUMERIC(20, 0)  CONSTRAINT DISK_SYSTEM_RI_NN   NOT NULL,
+  TARGETED_FREE_SPACE     NUMERIC(20, 0)  CONSTRAINT DISK_SYSTEM_TFS_NN  NOT NULL,
+  USER_COMMENT            VARCHAR(1000)   CONSTRAINT DISK_SYSTEM_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT DISK_SYSTEM_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT DISK_SYSTEM_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME       NUMERIC(20, 0)  CONSTRAINT DISK_SYSTEM_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT DISK_SYSTEM_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT DISK_SYSTEM_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME        NUMERIC(20, 0)  CONSTRAINT DISK_SYSTEM_LUT_NN  NOT NULL,
+  CONSTRAINT NAME_PK PRIMARY KEY(DISK_SYSTEM_NAME)
+);
 CREATE TABLE STORAGE_CLASS(
   STORAGE_CLASS_ID        NUMERIC(20, 0)  CONSTRAINT STORAGE_CLASS_SCI_NN  NOT NULL,
   DISK_INSTANCE_NAME      VARCHAR(100)    CONSTRAINT STORAGE_CLASS_DIN_NN  NOT NULL,
diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt
index 5c0965ce33438e166a913155209838590cc863b8..3cbe25cfaf36b96eb436bebca7aabac7570d49a0 100644
--- a/common/CMakeLists.txt
+++ b/common/CMakeLists.txt
@@ -41,6 +41,7 @@ set (COMMON_LIB_SRC_FILES
   dataStructures/DeleteArchiveRequest.cpp
   dataStructures/DesiredDriveState.cpp
   dataStructures/DiskFileInfo.cpp
+  dataStructures/DiskSystem.cpp
   dataStructures/DriveState.cpp
   dataStructures/DriveStatus.cpp
   dataStructures/EntryLog.cpp
diff --git a/disk/DiskSystem.cpp b/common/dataStructures/DiskSystem.cpp
similarity index 93%
rename from disk/DiskSystem.cpp
rename to common/dataStructures/DiskSystem.cpp
index b9bc00634324881a644b0422486fbc4c3458bdc0..4a768008404818ce78715d30f5d1ef08b1928b36 100644
--- a/disk/DiskSystem.cpp
+++ b/common/dataStructures/DiskSystem.cpp
@@ -20,7 +20,9 @@
 
 #include <algorithm>
 
-namespace cta { namespace disk {
+namespace cta {
+namespace common {
+namespace dataStructures {
 
 const DiskSystem& DiskSystemList::at(const std::string& name) {
   auto dsi = std::find_if(begin(), end(), [&](const DiskSystem& ds){ return ds.name == name;});
@@ -48,6 +50,6 @@ std::string DiskSystemList::getFSNAme(const std::string& fileURL) {
   
 }
 
-
-
-}} // namespace cta::disk
\ No newline at end of file
+} // namespace dataStructures
+} // namespace common
+} // namespace cta
\ No newline at end of file
diff --git a/disk/DiskSystem.hpp b/common/dataStructures/DiskSystem.hpp
similarity index 85%
rename from disk/DiskSystem.hpp
rename to common/dataStructures/DiskSystem.hpp
index e03bcbc9f04afd39858dbe8b62a5e33805c2a94d..90ec57ec5165d958337b89f5c3452a9f5cb50c0a 100644
--- a/disk/DiskSystem.hpp
+++ b/common/dataStructures/DiskSystem.hpp
@@ -21,13 +21,16 @@
 #include <string>
 #include <list>
 #include "common/utils/Regex.hpp"
+#include "common/dataStructures/EntryLog.hpp"
 
-namespace cta { namespace disk {
+namespace cta {
+namespace common {
+namespace dataStructures {
 
 /**
  * Description of a disk system as defined by operators.
  * Defines:
- *  -  a name used an index
+ *  - a name used an index
  *  - a regular expression allowing matching destination URLs for this disk system
  *  - a query URL that describes a method to query the free space from the filesystem
  *  - a refresh interval (seconds) defining how long do we use a 
@@ -40,6 +43,10 @@ struct DiskSystem {
   std::string freeSpaceQueryURL;
   uint64_t refreshInterval;
   uint64_t targetedFreeSpace;
+  
+  cta::common::dataStructures::EntryLog creationLog;
+  cta::common::dataStructures::EntryLog lastModificationLog;
+  std::string comment;
 };
 
 class DiskSystemList: public std::list<DiskSystem> {
@@ -62,5 +69,6 @@ private:
   
 };
 
-
-}} // namespace cta::disk
+} // namespace dataStructures
+} // namespace common
+} // namespace cta
diff --git a/disk/CMakeLists.txt b/disk/CMakeLists.txt
index 06618ef6f1889ccdd2432dc619a8174bd6c29ce2..8408fad249e7d8bf1fcae5d3f5a538e61b766223 100644
--- a/disk/CMakeLists.txt
+++ b/disk/CMakeLists.txt
@@ -27,7 +27,6 @@ add_library(ctadisk SHARED
   EOSReporter.cpp
   DiskFile.cpp
   RadosStriperPool.cpp
-  DiskSystem.cpp
 )
 
 target_link_libraries (ctadisk XrdCl cryptopp radosstriper)
@@ -43,4 +42,4 @@ set_property(TARGET ctadiskunittests PROPERTY SOVERSION "${CTA_SOVERSION}")
 set_property(TARGET ctadiskunittests PROPERTY   VERSION "${CTA_LIBVERSION}")
 
 install(TARGETS ctadisk DESTINATION usr/${CMAKE_INSTALL_LIBDIR})
-install(TARGETS ctadiskunittests DESTINATION usr/${CMAKE_INSTALL_LIBDIR})
\ No newline at end of file
+install(TARGETS ctadiskunittests DESTINATION usr/${CMAKE_INSTALL_LIBDIR})
diff --git a/scheduler/OStoreDB/OStoreDB.cpp b/scheduler/OStoreDB/OStoreDB.cpp
index f843c7bd34840097b90ddcdcb557d571d6794ce6..706335fef2d412d6e391c00e67ef1598b8cfcf34 100644
--- a/scheduler/OStoreDB/OStoreDB.cpp
+++ b/scheduler/OStoreDB/OStoreDB.cpp
@@ -3443,7 +3443,7 @@ const OStoreDB::RetrieveMount::MountInfo& OStoreDB::RetrieveMount::getMountInfo(
 // OStoreDB::RetrieveMount::getNextJobBatch()
 //------------------------------------------------------------------------------
 std::list<std::unique_ptr<SchedulerDatabase::RetrieveJob>> OStoreDB::RetrieveMount::getNextJobBatch(uint64_t filesRequested, 
-    uint64_t bytesRequested, disk::DiskSystemList& diskSystemList, log::LogContext& logContext) {
+    uint64_t bytesRequested, common::dataStructures::DiskSystemList& diskSystemList, log::LogContext& logContext) {
   typedef objectstore::ContainerAlgorithms<RetrieveQueue,RetrieveQueueToTransferForUser> RQAlgos;
   RQAlgos rqAlgos(m_oStoreDB.m_objectStore, *m_oStoreDB.m_agentReference);
   RQAlgos::PopCriteria popCriteria(filesRequested, bytesRequested);
diff --git a/scheduler/OStoreDB/OStoreDB.hpp b/scheduler/OStoreDB/OStoreDB.hpp
index e7a9889c7f0566a2066a7b333d0f649a8bb676b0..a531797e21ff86eb41d631baa1e5a86a9e059d6b 100644
--- a/scheduler/OStoreDB/OStoreDB.hpp
+++ b/scheduler/OStoreDB/OStoreDB.hpp
@@ -218,7 +218,7 @@ public:
   public:
     const MountInfo & getMountInfo() override;
     std::list<std::unique_ptr<cta::SchedulerDatabase::RetrieveJob> > getNextJobBatch(uint64_t filesRequested, uint64_t bytesRequested, 
-      disk::DiskSystemList& diskSystemList, log::LogContext& logContext) override;
+      common::dataStructures::DiskSystemList& diskSystemList, log::LogContext& logContext) override;
     void complete(time_t completionTime) override;
     void setDriveStatus(cta::common::dataStructures::DriveStatus status, time_t completionTime) override;
     void setTapeSessionStats(const castor::tape::tapeserver::daemon::TapeSessionStats &stats) override;
diff --git a/scheduler/RetrieveMount.cpp b/scheduler/RetrieveMount.cpp
index 4cff8c76c8eaaf9cb7b717f890af1ed094cb4b50..1d84a274e6932ffaabb62ca202ecddabef2132bd 100644
--- a/scheduler/RetrieveMount.cpp
+++ b/scheduler/RetrieveMount.cpp
@@ -138,8 +138,8 @@ std::list<std::unique_ptr<cta::RetrieveJob> > cta::RetrieveMount::getNextJobBatc
   if (!m_sessionRunning)
     throw SessionNotRunning("In RetrieveMount::getNextJobBatch(): trying to get job from complete/not started session");
   // Get the current file systems list from the catalogue
-  disk::DiskSystemList diskSystemList;
-  if (m_catalogue) diskSystemList = m_catalogue->getDiskSystems();
+  common::dataStructures::DiskSystemList diskSystemList;
+  if (m_catalogue) diskSystemList = m_catalogue->getAllDiskSystems();
   // Try and get a new job from the DB
   std::list<std::unique_ptr<cta::SchedulerDatabase::RetrieveJob>> dbJobBatch(m_dbMount->getNextJobBatch(filesRequested,
       bytesRequested, diskSystemList, logContext));
diff --git a/scheduler/Scheduler.cpp b/scheduler/Scheduler.cpp
index 60d61aeb137922d0792ceaf68916c56e9985b6b4..89d49688c73c5d0a22e5d43b6334aa366e24b195 100644
--- a/scheduler/Scheduler.cpp
+++ b/scheduler/Scheduler.cpp
@@ -212,7 +212,7 @@ void Scheduler::queueRetrieve(
   common::dataStructures::RetrieveFileQueueCriteria queueCriteria;
   queueCriteria = m_catalogue.prepareToRetrieveFile(instanceName, request.archiveFileID, request.requester, request.activity, lc);
   // Get DiskSystem list.
-  auto diskSystemList = m_catalogue.getDiskSystems();
+  auto diskSystemList = m_catalogue.getAllDiskSystems();
   auto catalogueTime = t.secs(cta::utils::Timer::resetCounter);
   // Determine disk system for this request, if any.
   optional<std::string> diskSystemName;
diff --git a/scheduler/SchedulerDatabase.hpp b/scheduler/SchedulerDatabase.hpp
index 4e08c982726abaf54637196ea7f6c60d872ce4a9..a672a57a9ea1dfd0ef5da4008ea9c657b087fb16 100644
--- a/scheduler/SchedulerDatabase.hpp
+++ b/scheduler/SchedulerDatabase.hpp
@@ -33,12 +33,12 @@
 #include "common/dataStructures/RetrieveRequest.hpp"
 #include "common/dataStructures/RepackInfo.hpp"
 #include "common/dataStructures/SecurityIdentity.hpp"
+#include "common/dataStructures/DiskSystem.hpp"
 #include "common/remoteFS/RemotePathAndStatus.hpp"
 #include "common/exception/Exception.hpp"
 #include "common/log/LogContext.hpp"
 #include "catalogue/TapeForWriting.hpp"
 #include "scheduler/TapeMount.hpp"
-#include "disk/DiskSystem.hpp"
 
 #include <list>
 #include <limits>
@@ -358,7 +358,7 @@ public:
     } mountInfo;
     virtual const MountInfo & getMountInfo() = 0;
     virtual std::list<std::unique_ptr<cta::SchedulerDatabase::RetrieveJob>> getNextJobBatch(uint64_t filesRequested,
-      uint64_t bytesRequested, disk::DiskSystemList & diskSystemList, log::LogContext& logContext) = 0;
+      uint64_t bytesRequested, common::dataStructures::DiskSystemList & diskSystemList, log::LogContext& logContext) = 0;
     virtual void complete(time_t completionTime) = 0;
     virtual void setDriveStatus(common::dataStructures::DriveStatus status, time_t completionTime) = 0;
     virtual void setTapeSessionStats(const castor::tape::tapeserver::daemon::TapeSessionStats &stats) = 0;
diff --git a/tapeserver/castor/tape/tapeserver/daemon/DiskWriteTaskTest.cpp b/tapeserver/castor/tape/tapeserver/daemon/DiskWriteTaskTest.cpp
index a6b34e00e6b3c2ed8fe913680b65ff1182788e90..6d73d320e390614bea98b7b8cd2d24e4d93ef49a 100644
--- a/tapeserver/castor/tape/tapeserver/daemon/DiskWriteTaskTest.cpp
+++ b/tapeserver/castor/tape/tapeserver/daemon/DiskWriteTaskTest.cpp
@@ -43,7 +43,7 @@ namespace unitTests{
   class TestingDatabaseRetrieveMount: public cta::SchedulerDatabase::RetrieveMount {
     const MountInfo & getMountInfo() override { throw std::runtime_error("Not implemented"); }
     std::list<std::unique_ptr<cta::SchedulerDatabase::RetrieveJob> > getNextJobBatch(uint64_t filesRequested, uint64_t bytesRequested,
-      cta::disk::DiskSystemList& diskSystemList, cta::log::LogContext& logContext) override { throw std::runtime_error("Not implemented");}
+      cta::common::dataStructures::DiskSystemList& diskSystemList, cta::log::LogContext& logContext) override { throw std::runtime_error("Not implemented");}
     void complete(time_t completionTime) override { throw std::runtime_error("Not implemented"); }
     void setDriveStatus(cta::common::dataStructures::DriveStatus status, time_t completionTime) override { throw std::runtime_error("Not implemented"); }
     void setTapeSessionStats(const castor::tape::tapeserver::daemon::TapeSessionStats &stats) override { throw std::runtime_error("Not implemented"); }
diff --git a/tapeserver/castor/tape/tapeserver/daemon/DiskWriteThreadPoolTest.cpp b/tapeserver/castor/tape/tapeserver/daemon/DiskWriteThreadPoolTest.cpp
index cdbbbdabce68fba288568a06ea336302730f0679..ef42751d3ee30d980d2d004bbe2061cc5e222926 100644
--- a/tapeserver/castor/tape/tapeserver/daemon/DiskWriteThreadPoolTest.cpp
+++ b/tapeserver/castor/tape/tapeserver/daemon/DiskWriteThreadPoolTest.cpp
@@ -36,7 +36,7 @@ namespace unitTests{
   
   class TestingDatabaseRetrieveMount: public cta::SchedulerDatabase::RetrieveMount {
     const MountInfo & getMountInfo() override { throw std::runtime_error("Not implemented"); }
-    std::list<std::unique_ptr<cta::SchedulerDatabase::RetrieveJob> > getNextJobBatch(uint64_t filesRequested, uint64_t bytesRequested, cta::disk::DiskSystemList& diskSystemList, cta::log::LogContext& logContext) override { throw std::runtime_error("Not implemented");}
+    std::list<std::unique_ptr<cta::SchedulerDatabase::RetrieveJob> > getNextJobBatch(uint64_t filesRequested, uint64_t bytesRequested, cta::common::dataStructures::DiskSystemList& diskSystemList, cta::log::LogContext& logContext) override { throw std::runtime_error("Not implemented");}
     void complete(time_t completionTime) override { throw std::runtime_error("Not implemented"); }
     void setDriveStatus(cta::common::dataStructures::DriveStatus status, time_t completionTime) override { throw std::runtime_error("Not implemented"); }
     void setTapeSessionStats(const castor::tape::tapeserver::daemon::TapeSessionStats &stats) override { throw std::runtime_error("Not implemented"); }
diff --git a/tapeserver/castor/tape/tapeserver/daemon/RecallTaskInjectorTest.cpp b/tapeserver/castor/tape/tapeserver/daemon/RecallTaskInjectorTest.cpp
index 912ab584c30af45c6747203059924fffa8a768a0..76769129192c44121452a1652c5f08de0b78fc59 100644
--- a/tapeserver/castor/tape/tapeserver/daemon/RecallTaskInjectorTest.cpp
+++ b/tapeserver/castor/tape/tapeserver/daemon/RecallTaskInjectorTest.cpp
@@ -132,7 +132,7 @@ namespace unitTests
   class TestingDatabaseRetrieveMount: public cta::SchedulerDatabase::RetrieveMount {
     const MountInfo & getMountInfo() override { throw std::runtime_error("Not implemented"); }
     std::list<std::unique_ptr<cta::SchedulerDatabase::RetrieveJob> > getNextJobBatch(uint64_t filesRequested, uint64_t bytesRequested,
-      cta::disk::DiskSystemList& diskSystemList, cta::log::LogContext& logContext) override { throw std::runtime_error("Not implemented");}
+      cta::common::dataStructures::DiskSystemList& diskSystemList, cta::log::LogContext& logContext) override { throw std::runtime_error("Not implemented");}
     void complete(time_t completionTime) override { throw std::runtime_error("Not implemented"); }
     void setDriveStatus(cta::common::dataStructures::DriveStatus status, time_t completionTime) override { throw std::runtime_error("Not implemented"); }
     void setTapeSessionStats(const castor::tape::tapeserver::daemon::TapeSessionStats &stats) override { throw std::runtime_error("Not implemented"); }
diff --git a/xrootd-ssi-protobuf-interface b/xrootd-ssi-protobuf-interface
index 602063b47e056ae84b45726fad63162ad6d6975b..703aa091b704c14e2a983f92b685e1d82e063bfa 160000
--- a/xrootd-ssi-protobuf-interface
+++ b/xrootd-ssi-protobuf-interface
@@ -1 +1 @@
-Subproject commit 602063b47e056ae84b45726fad63162ad6d6975b
+Subproject commit 703aa091b704c14e2a983f92b685e1d82e063bfa