From d3e5d9f1797befdcfbd8400d1961af96a7f82168 Mon Sep 17 00:00:00 2001
From: Cedric Caffy <cedric.caffy@cern.ch>
Date: Tue, 21 Jul 2020 13:49:51 +0200
Subject: [PATCH] [cta-frontend] Added cta-admin schedulinginfos ls command

---
 cmdline/CtaAdminCmd.cpp                   |   3 +
 cmdline/CtaAdminCmdParse.hpp              |   8 +-
 cmdline/CtaAdminTextFormatter.cpp         |   5 +
 cmdline/CtaAdminTextFormatter.hpp         |   1 +
 xroot_plugins/XrdCtaSchedulingInfosLs.hpp | 137 ++++++++++++++++++++++
 xroot_plugins/XrdSsiCtaRequestMessage.cpp |  14 +++
 xroot_plugins/XrdSsiCtaRequestMessage.hpp |   1 +
 7 files changed, 167 insertions(+), 2 deletions(-)
 create mode 100644 xroot_plugins/XrdCtaSchedulingInfosLs.hpp

diff --git a/cmdline/CtaAdminCmd.cpp b/cmdline/CtaAdminCmd.cpp
index e42d7b359e..9c1bc55e41 100644
--- a/cmdline/CtaAdminCmd.cpp
+++ b/cmdline/CtaAdminCmd.cpp
@@ -106,6 +106,7 @@ void IStreamBuffer<cta::xrd::Data>::DataCallback(cta::xrd::Data record) const
          case Data::kVolsItem:      std::cout << Log::DumpProtobuf(&record.vols_item());    break;
          case Data::kVersionItem:   std::cout << Log::DumpProtobuf(&record.version_item()); break;
          case Data::kMtlsItem:      std::cout << Log::DumpProtobuf(&record.mtls_item());    break;
+         case Data::kSilsItem:      std::cout << Log::DumpProtobuf(&record.sils_item());    break;
          default:
             throw std::runtime_error("Received invalid stream data from CTA Frontend.");
       }
@@ -137,6 +138,7 @@ void IStreamBuffer<cta::xrd::Data>::DataCallback(cta::xrd::Data record) const
          case Data::kVolsItem:      formattedText.print(record.vols_item());    break;
          case Data::kVersionItem:   formattedText.print(record.version_item()); break;
          case Data::kMtlsItem:      formattedText.print(record.mtls_item());    break;
+         case Data::kSilsItem:      break;
          default:
             throw std::runtime_error("Received invalid stream data from CTA Frontend.");
    }
@@ -298,6 +300,7 @@ void CtaAdminCmd::send() const
             case HeaderType::VIRTUALORGANIZATION_LS:       formattedText.printVirtualOrganizationLsHeader(); break;
             case HeaderType::VERSION_CMD:                  formattedText.printVersionHeader(); break;
             case HeaderType::MEDIATYPE_LS:                 formattedText.printMediaTypeLsHeader(); break;
+            case HeaderType::SCHEDULINGINFOS_LS:            formattedText.printSchedulingInfosLsHeader(); break;
             case HeaderType::NONE:
             default:                                       break;
          }
diff --git a/cmdline/CtaAdminCmdParse.hpp b/cmdline/CtaAdminCmdParse.hpp
index ed726bd5ed..414195d3d8 100644
--- a/cmdline/CtaAdminCmdParse.hpp
+++ b/cmdline/CtaAdminCmdParse.hpp
@@ -220,7 +220,9 @@ const cmdLookup_t cmdLookup = {
    { "virtualorganization",     AdminCmd::CMD_VIRTUALORGANIZATION },
    { "vo",                      AdminCmd::CMD_VIRTUALORGANIZATION },
    { "version",                 AdminCmd::CMD_VERSION},
-   { "v",                 AdminCmd::CMD_VERSION},
+   { "v",                       AdminCmd::CMD_VERSION},
+   { "schedulinginfos",         AdminCmd::CMD_SCHEDULINGINFOS},
+   { "si",                      AdminCmd::CMD_SCHEDULINGINFOS},
 };
 
 
@@ -409,7 +411,8 @@ const std::map<AdminCmd::Cmd, CmdHelp> cmdHelp = {
 			    "\n\n"
 					 }},
    { AdminCmd::CMD_VIRTUALORGANIZATION,  { "virtualorganization",   "vo",  { "add", "ch", "rm", "ls" } }},
-   { AdminCmd::CMD_VERSION,              { "version",           "v",  { } }},
+   { AdminCmd::CMD_VERSION,              { "version",               "v",  { } }},
+   { AdminCmd::CMD_SCHEDULINGINFOS,      { "schedulinginfos",       "si",  { "ls" } }},
 };
 
 
@@ -642,6 +645,7 @@ const std::map<cmd_key_t, cmd_val_t> cmdOptions = {
    {{ AdminCmd::CMD_VIRTUALORGANIZATION,           AdminCmd::SUBCMD_LS   },
       { }},
    {{ AdminCmd::CMD_VERSION,           AdminCmd::SUBCMD_NONE   }, { }},
+   {{ AdminCmd::CMD_SCHEDULINGINFOS,      AdminCmd::SUBCMD_LS   }, { }},
 };
 
 
diff --git a/cmdline/CtaAdminTextFormatter.cpp b/cmdline/CtaAdminTextFormatter.cpp
index c9c7eba7a6..05c89a57b1 100644
--- a/cmdline/CtaAdminTextFormatter.cpp
+++ b/cmdline/CtaAdminTextFormatter.cpp
@@ -1092,4 +1092,9 @@ void TextFormatter::print(const VersionItem & version_item){
   );
 }
 
+void TextFormatter::printSchedulingInfosLsHeader(){
+  push_back("HEADER");
+  push_back("No tabular output available for this command, please use the --json flag.");
+}
+
 }}
diff --git a/cmdline/CtaAdminTextFormatter.hpp b/cmdline/CtaAdminTextFormatter.hpp
index cf2e827eb4..5737cd7be8 100644
--- a/cmdline/CtaAdminTextFormatter.hpp
+++ b/cmdline/CtaAdminTextFormatter.hpp
@@ -69,6 +69,7 @@ public:
   void printVirtualOrganizationLsHeader();
   void printVersionHeader();
   void printMediaTypeLsHeader();
+  void printSchedulingInfosLsHeader();
    
   // Output records
   void print(const AdminLsItem &adls_item);
diff --git a/xroot_plugins/XrdCtaSchedulingInfosLs.hpp b/xroot_plugins/XrdCtaSchedulingInfosLs.hpp
new file mode 100644
index 0000000000..c45054d75d
--- /dev/null
+++ b/xroot_plugins/XrdCtaSchedulingInfosLs.hpp
@@ -0,0 +1,137 @@
+/*!
+ * @project        The CERN Tape Archive (CTA)
+ * @brief          CTA Show Queues stream implementation
+ * @copyright      Copyright 2019 CERN
+ * @license        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 <xroot_plugins/XrdCtaStream.hpp>
+#include <xroot_plugins/XrdSsiCtaRequestMessage.hpp>
+#include <common/dataStructures/MountTypeSerDeser.hpp>
+
+namespace cta { namespace xrd {
+
+/*!
+ * Stream object which implements "tapepool ls" command
+ */
+class SchedulingInfosLsStream: public XrdCtaStream{
+public:
+  /*!
+   * Constructor
+   *
+   * @param[in]    requestMsg    RequestMessage containing command-line arguments
+   * @param[in]    catalogue     CTA Catalogue
+   * @param[in]    scheduler     CTA Scheduler
+   */
+  SchedulingInfosLsStream(const RequestMessage &requestMsg, cta::catalogue::Catalogue &catalogue,
+    cta::Scheduler &scheduler, log::LogContext &lc);
+
+private:
+  /*!
+   * Can we close the stream?
+   */
+  virtual bool isDone() const {
+    return m_schedulingInfosList.empty();
+  }
+
+  /*!
+   * Fill the buffer
+   */
+  virtual int fillBuffer(XrdSsiPb::OStreamBuffer<Data> *streambuf);
+
+  std::list<cta::SchedulingInfos> m_schedulingInfosList;    //!< List of queues and mounts from the scheduler
+
+  static constexpr const char* const LOG_SUFFIX  = "SchedulingInfosStream";                   //!< Identifier for log messages
+};
+
+SchedulingInfosLsStream::SchedulingInfosLsStream(const RequestMessage &requestMsg, cta::catalogue::Catalogue &catalogue,
+  cta::Scheduler &scheduler, log::LogContext &lc) :
+  XrdCtaStream(catalogue, scheduler),
+  m_schedulingInfosList(scheduler.getSchedulingInformations(lc))
+{
+  using namespace cta::admin;
+
+  XrdSsiPb::Log::Msg(XrdSsiPb::Log::DEBUG, LOG_SUFFIX, "SchedulingInfosLsStream() constructor");
+}
+
+int SchedulingInfosLsStream::fillBuffer(XrdSsiPb::OStreamBuffer<Data> *streambuf) {
+  using namespace cta::admin;
+
+  for(bool is_buffer_full = false; !m_schedulingInfosList.empty() && !is_buffer_full; m_schedulingInfosList.pop_front()) {
+    Data record;
+
+    auto &schedulingInfo      = m_schedulingInfosList.front();
+    auto sils_item = record.mutable_sils_item();
+    sils_item->set_logical_library(schedulingInfo.getLogicalLibraryName());
+    auto potentialMounts = schedulingInfo.getPotentialMounts();
+    for(auto & potentialMount: potentialMounts){
+      auto potentialMountToAdd = sils_item->mutable_potential_mounts()->Add();
+      potentialMountToAdd->set_vid(potentialMount.vid);
+      potentialMountToAdd->set_tapepool(potentialMount.tapePool);
+      potentialMountToAdd->set_vo(potentialMount.vo);
+      potentialMountToAdd->set_media_type(potentialMount.mediaType);
+      potentialMountToAdd->set_vendor(potentialMount.vendor);
+      potentialMountToAdd->set_mount_type(MountTypeToProtobuf(potentialMount.type));
+      potentialMountToAdd->set_tape_capacity_in_bytes(potentialMount.capacityInBytes);
+      potentialMountToAdd->set_mount_policy_priority(potentialMount.priority);
+      potentialMountToAdd->set_mount_policy_min_request_age(potentialMount.minRequestAge);
+      potentialMountToAdd->set_mount_policy_max_drives_allowed(potentialMount.maxDrivesAllowed);
+      potentialMountToAdd->set_files_queued(potentialMount.filesQueued);
+      potentialMountToAdd->set_bytes_queued(potentialMount.bytesQueued);
+      potentialMountToAdd->set_oldest_job_start_time(potentialMount.oldestJobStartTime);
+      potentialMountToAdd->set_sleeping_mount(potentialMount.sleepingMount);
+      potentialMountToAdd->set_sleep_time(potentialMount.sleepTime);
+      potentialMountToAdd->set_disk_system_slept_for(potentialMount.diskSystemSleptFor);
+      potentialMountToAdd->set_mount_count(potentialMount.mountCount);
+      potentialMountToAdd->set_logical_library(potentialMount.logicalLibrary);
+    }
+    is_buffer_full = streambuf->Push(record);
+    /*
+
+    sq_item->set_mount_type(MountTypeToProtobuf(sq.mountType));
+    sq_item->set_tapepool(sq.tapePool);
+    sq_item->set_logical_library(sq.logicalLibrary);
+    sq_item->set_vid(sq.vid);
+    sq_item->set_queued_files(sq.filesQueued);
+    sq_item->set_queued_bytes(sq.bytesQueued);
+    sq_item->set_oldest_age(sq.oldestJobAge);
+    sq_item->set_cur_mounts(sq.currentMounts);
+    sq_item->set_cur_files(sq.currentFiles);
+    sq_item->set_cur_bytes(sq.currentBytes);
+    sq_item->set_bytes_per_second(sq.latestBandwidth);
+    sq_item->set_next_mounts(sq.nextMounts);
+    sq_item->set_tapes_capacity(sq.tapesCapacity);
+    sq_item->set_tapes_files(sq.filesOnTapes);
+    sq_item->set_tapes_bytes(sq.dataOnTapes);
+    sq_item->set_full_tapes(sq.fullTapes);
+    sq_item->set_empty_tapes(sq.emptyTapes);
+    sq_item->set_disabled_tapes(sq.disabledTapes);
+    sq_item->set_rdonly_tapes(sq.readOnlyTapes);
+    sq_item->set_writable_tapes(sq.writableTapes);
+    if (sq.sleepForSpaceInfo) {
+      sq_item->set_sleeping_for_space(true);
+      sq_item->set_sleep_start_time(sq.sleepForSpaceInfo.value().startTime);
+      sq_item->set_disk_system_slept_for(sq.sleepForSpaceInfo.value().diskSystemName);
+    } else {
+      sq_item->set_sleeping_for_space(false);
+    }
+
+    is_buffer_full = streambuf->Push(record);*/
+  }
+  return streambuf->Size();
+}
+
+}} // namespace cta::xrd
diff --git a/xroot_plugins/XrdSsiCtaRequestMessage.cpp b/xroot_plugins/XrdSsiCtaRequestMessage.cpp
index f164e0be66..a5e6c96fcf 100644
--- a/xroot_plugins/XrdSsiCtaRequestMessage.cpp
+++ b/xroot_plugins/XrdSsiCtaRequestMessage.cpp
@@ -42,6 +42,7 @@ using XrdSsiPb::PbException;
 #include "XrdCtaDiskSystemLs.hpp"
 #include "XrdCtaVirtualOrganizationLs.hpp"
 #include "XrdCtaVersion.hpp"
+#include "XrdCtaSchedulingInfosLs.hpp"
 
 #include <limits>
 #include <sstream>
@@ -288,6 +289,9 @@ void RequestMessage::process(const cta::xrd::Request &request, cta::xrd::Respons
            case cmd_pair(AdminCmd::CMD_VERSION, AdminCmd::SUBCMD_NONE):
              processVersion(response, stream);
              break;
+           case cmd_pair(AdminCmd::CMD_SCHEDULINGINFOS, AdminCmd::SUBCMD_LS):
+             processSchedulingInfos_Ls(response,stream);
+             break;
             default:
                throw PbException("Admin command pair <" +
                      AdminCmd_Cmd_Name(request.admincmd().cmd()) + ", " +
@@ -2110,4 +2114,14 @@ void RequestMessage::processVersion(cta::xrd::Response &response, XrdSsiStream *
   response.set_type(cta::xrd::Response::RSP_SUCCESS);
 }
 
+void RequestMessage::processSchedulingInfos_Ls(cta::xrd::Response &response, XrdSsiStream * & stream) {
+  using namespace cta::admin;
+  
+  stream = new SchedulingInfosLsStream(*this,m_catalogue,m_scheduler,m_lc);
+  
+  //TODO TO BE CHANGED
+  response.set_show_header(HeaderType::SCHEDULINGINFOS_LS);
+  response.set_type(cta::xrd::Response::RSP_SUCCESS);
+}
+
 }} // namespace cta::xrd
diff --git a/xroot_plugins/XrdSsiCtaRequestMessage.hpp b/xroot_plugins/XrdSsiCtaRequestMessage.hpp
index 91dceea9e4..4f7b664030 100644
--- a/xroot_plugins/XrdSsiCtaRequestMessage.hpp
+++ b/xroot_plugins/XrdSsiCtaRequestMessage.hpp
@@ -238,6 +238,7 @@ private:
   admincmdstream_t processDiskSystem_Ls;
   admincmdstream_t processVirtualOrganization_Ls;
   admincmdstream_t processVersion;
+  admincmdstream_t processSchedulingInfos_Ls;
 
   /*!
    * Log an admin command
-- 
GitLab