From d4728d0754e1b81361a4a242ce5b8c9d77fd84be Mon Sep 17 00:00:00 2001 From: Lasse Tjernaes Wardenaer <lasse.tjernaes.wardenaer@cern.ch> Date: Thu, 6 Oct 2022 08:35:41 +0200 Subject: [PATCH] Resolve "Refactor operations cmd line tools to use common parsing logic" --- ReleaseNotes.md | 6 + cmdline/CMakeLists.txt | 20 +- cmdline/CtaCmdOptions.hpp | 94 --------- cmdline/standalone_cli_tools/CMakeLists.txt | 49 +++++ .../CtaSendEvent.cpp | 62 +----- .../CtaVerifyFile.cpp | 90 +++------ .../common/CmdLineArgs.cpp} | 150 +++++++++++---- .../common/CmdLineArgs.hpp} | 46 ++++- .../common}/CmdLineTool.cpp | 19 +- .../common}/CmdLineTool.hpp | 9 +- .../restore_files/CMakeLists.txt | 2 +- .../restore_files/RestoreFilesCmd.cpp | 70 ++++--- .../restore_files/RestoreFilesCmd.hpp | 23 +-- .../restore_files/RestoreFilesCmdMain.cpp | 2 +- .../cta-restore-deleted-files.1cta | 0 .../cc7/etc/cta/cta-frontend-xrootd.conf | 2 +- .../tests/README_restore_files.md | 27 +++ .../tests/common/archive_file.sh | 87 +++++++++ .../orchestration/tests/common/delete_file.sh | 58 ++++++ .../orchestration/tests/restore_files.sh | 180 ++++++++++++++++++ .../tests/restore_files_ctafrontend.sh | 57 ++++++ 21 files changed, 703 insertions(+), 350 deletions(-) delete mode 100644 cmdline/CtaCmdOptions.hpp create mode 100644 cmdline/standalone_cli_tools/CMakeLists.txt rename cmdline/{ => standalone_cli_tools}/CtaSendEvent.cpp (83%) rename cmdline/{ => standalone_cli_tools}/CtaVerifyFile.cpp (67%) rename cmdline/{restore_files/RestoreFilesCmdLineArgs.cpp => standalone_cli_tools/common/CmdLineArgs.cpp} (51%) rename cmdline/{restore_files/RestoreFilesCmdLineArgs.hpp => standalone_cli_tools/common/CmdLineArgs.hpp} (75%) rename cmdline/{restore_files => standalone_cli_tools/common}/CmdLineTool.cpp (88%) rename cmdline/{restore_files => standalone_cli_tools/common}/CmdLineTool.hpp (92%) rename cmdline/{ => standalone_cli_tools}/restore_files/CMakeLists.txt (91%) rename cmdline/{ => standalone_cli_tools}/restore_files/RestoreFilesCmd.cpp (94%) rename cmdline/{ => standalone_cli_tools}/restore_files/RestoreFilesCmd.hpp (92%) rename cmdline/{ => standalone_cli_tools}/restore_files/RestoreFilesCmdMain.cpp (96%) rename cmdline/{ => standalone_cli_tools}/restore_files/cta-restore-deleted-files.1cta (100%) create mode 100644 continuousintegration/orchestration/tests/README_restore_files.md create mode 100644 continuousintegration/orchestration/tests/common/archive_file.sh create mode 100644 continuousintegration/orchestration/tests/common/delete_file.sh create mode 100755 continuousintegration/orchestration/tests/restore_files.sh create mode 100644 continuousintegration/orchestration/tests/restore_files_ctafrontend.sh diff --git a/ReleaseNotes.md b/ReleaseNotes.md index fc57ca07ba..5dbbb707f4 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -1,3 +1,9 @@ +# v4.NEXT + +## Summary +### Features +- cta/CTA#146 - Refactoring of operation tools cmd line parsing + # v4.7.12-1 ## Summary diff --git a/cmdline/CMakeLists.txt b/cmdline/CMakeLists.txt index 91d0a453fe..66d988f3b6 100644 --- a/cmdline/CMakeLists.txt +++ b/cmdline/CMakeLists.txt @@ -15,7 +15,7 @@ cmake_minimum_required (VERSION 3.17) -add_subdirectory (restore_files) +add_subdirectory (standalone_cli_tools) find_package(xrootdclient REQUIRED) find_package(Protobuf3 REQUIRED) @@ -36,22 +36,6 @@ add_executable(cta-admin CtaAdminCmd.cpp CtaAdminCmdParse.cpp CtaAdminTextFormat target_link_libraries(cta-admin XrdSsiPbEosCta XrdSsiLib XrdUtils ctacommon) set_property (TARGET cta-admin APPEND PROPERTY INSTALL_RPATH ${PROTOBUF3_RPATH}) -# -# cta-send-event CLOSEW|PREPARE|ABORT_PREPARE -# injects a workflow event into the CTA Frontend -# -add_executable(cta-send-event CtaSendEvent.cpp) -target_link_libraries(cta-send-event ctacommon XrdSsiPbEosCta XrdSsiLib XrdUtils) -set_property(TARGET cta-send-event APPEND PROPERTY INSTALL_RPATH ${PROTOBUF3_RPATH}) - -# -# verify-file <archiveFileId> <vid> -# recalls a file from tape without writing a disk copy -# -add_executable(cta-verify-file CtaVerifyFile.cpp) -target_link_libraries(cta-verify-file ctacommon XrdSsiPbEosCta XrdSsiLib XrdUtils) -set_property (TARGET cta-verify-file APPEND PROPERTY INSTALL_RPATH ${PROTOBUF3_RPATH}) - # # cta-wfe-test archive|retrieve|delete <options> allows testing of the SSI WorkFlow Engine hooks # without invoking EOS. @@ -65,7 +49,5 @@ set_property (TARGET cta-wfe-test APPEND PROPERTY INSTALL_RPATH ${PROTOBUF3_RPAT install(TARGETS cta-admin DESTINATION usr/bin) install(FILES cta-admin.1cta DESTINATION usr/share/man/man1) -install(TARGETS cta-send-event DESTINATION usr/bin) install(FILES cta-send-closew.sh DESTINATION usr/bin) -install(TARGETS cta-verify-file DESTINATION usr/bin) install(FILES cta-cli.conf.example DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/cta) diff --git a/cmdline/CtaCmdOptions.hpp b/cmdline/CtaCmdOptions.hpp deleted file mode 100644 index 8a3e5ed164..0000000000 --- a/cmdline/CtaCmdOptions.hpp +++ /dev/null @@ -1,94 +0,0 @@ -/* - * @project The CERN Tape Archive (CTA) - * @copyright Copyright © 2021-2022 CERN - * @license This program is free software, distributed under the terms of the GNU General Public - * Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". You can - * redistribute it and/or modify it under the terms of the GPL Version 3, 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. - * - * In applying this licence, CERN does not waive the privileges and immunities - * granted to it by virtue of its status as an Intergovernmental Organization or - * submit itself to any jurisdiction. - */ - -#pragma once - -/*! -* Simple command line option class for simpler commands like cta-verify-file or cta-send-event -*/ -class StringOption { -public: - /*! - * Constructor - */ - StringOption(const std::string &long_opt, const std::string &short_opt, const bool is_optional) : - m_long_opt(long_opt), - m_short_opt(short_opt), - m_is_optional(is_optional), - m_is_present(false), - m_value("") {} - - /*! - * Check if the supplied key matches the option - */ - bool operator==(const std::string &option) const { - return option == m_short_opt || option == m_long_opt; - } - - /*! - * Return whether the option is optional - */ - bool is_optional() const { - return m_is_optional; - } - - /*! - * Return whether the option is present on the command line - */ - bool is_present() const { - return m_is_present; - } - - /*! - * Sets the option as present on the command line - */ - void set_present() { - m_is_present = true; - } - - /*! - * Return the value of the option given from the command line - */ - const std::string &get_value() const { - return m_value; - } - - /*! - * Return the name of the option (it's long command option) - */ - const std::string &get_name() const { - return m_long_opt; - } - - /*! - * Sets the value of the option from the command line - */ - void set_value(const std::string &mValue) { - m_value = mValue; - } - -private: - - //member variables - const std::string m_long_opt; //!< Long command option - const std::string m_short_opt; //!< Short command option - const bool m_is_optional; //!< Option is optional or compulsory - bool m_is_present; //!< Option is present on the command line - std::string m_value; //!< Option value -}; - - diff --git a/cmdline/standalone_cli_tools/CMakeLists.txt b/cmdline/standalone_cli_tools/CMakeLists.txt new file mode 100644 index 0000000000..1112c75327 --- /dev/null +++ b/cmdline/standalone_cli_tools/CMakeLists.txt @@ -0,0 +1,49 @@ +# @project The CERN Tape Archive (CTA) +# @copyright Copyright © 2015-2022 CERN +# @license This program is free software, distributed under the terms of the GNU General Public +# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". You can +# redistribute it and/or modify it under the terms of the GPL Version 3, 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. +# +# In applying this licence, CERN does not waive the privileges and immunities +# granted to it by virtue of its status as an Intergovernmental Organization or +# submit itself to any jurisdiction. + +cmake_minimum_required (VERSION 3.17) + +add_subdirectory (restore_files) + +find_package(xrootdclient REQUIRED) +find_package(Protobuf3 REQUIRED) + +# XRootD SSI +include_directories(${XROOTD_INCLUDE_DIR} ${XROOTD_INCLUDE_DIR}/private) + +# XRootD SSI Protocol Buffer bindings +include_directories(${XRD_SSI_PB_DIR}/include ${XRD_SSI_PB_DIR}/eos_cta/include) + +# Compiled protocol buffers +include_directories(${CMAKE_BINARY_DIR}/eos_cta ${PROTOBUF3_INCLUDE_DIRS}) + +# +# cta-send-event CLOSEW|PREPARE|ABORT_PREPARE +# injects a workflow event into the CTA Frontend +# +add_executable(cta-send-event CtaSendEvent.cpp common/CmdLineArgs.cpp) +target_link_libraries(cta-send-event ctacommon XrdSsiPbEosCta XrdSsiLib XrdUtils) +set_property(TARGET cta-send-event APPEND PROPERTY INSTALL_RPATH ${PROTOBUF3_RPATH}) + +# +# verify-file <archiveFileId> <vid> +# recalls a file from tape without writing a disk copy +# +add_executable(cta-verify-file CtaVerifyFile.cpp common/CmdLineArgs.cpp) +target_link_libraries(cta-verify-file ctacommon XrdSsiPbEosCta XrdSsiLib XrdUtils) +set_property (TARGET cta-verify-file APPEND PROPERTY INSTALL_RPATH ${PROTOBUF3_RPATH}) + +install(TARGETS cta-send-event DESTINATION usr/bin) +install(TARGETS cta-verify-file DESTINATION usr/bin) \ No newline at end of file diff --git a/cmdline/CtaSendEvent.cpp b/cmdline/standalone_cli_tools/CtaSendEvent.cpp similarity index 83% rename from cmdline/CtaSendEvent.cpp rename to cmdline/standalone_cli_tools/CtaSendEvent.cpp index 4ae38728de..987d7c170a 100644 --- a/cmdline/CtaSendEvent.cpp +++ b/cmdline/standalone_cli_tools/CtaSendEvent.cpp @@ -25,7 +25,7 @@ #include <common/checksum/ChecksumBlobSerDeser.hpp> #include "CtaFrontendApi.hpp" #include "version.h" -#include "CtaCmdOptions.hpp" +#include "common/CmdLineArgs.hpp" const std::string config_file = "/etc/cta/cta-cli.conf"; @@ -52,48 +52,6 @@ const std::runtime_error Usage("Usage: eos --json fileinfo /eos/path | cta-send- "-i/--eos.instance <instance> [-e/--eos.endpoint <url>] " "-u/--request.user <user> -g/--request.group <group>"); -StringOption option_instance {"--eos.instance", "-i", false}; -StringOption option_endpoint {"--eos.endpoint", "-e", true}; -StringOption option_user {"--request.user", "-u", false}; -StringOption option_group {"--request.group", "-g", false}; - - -std::map<std::string, StringOption*> option_map = { - {"-i", &option_instance}, - {"--eos.instance", &option_instance}, - {"-e", &option_endpoint}, - {"--eos.endpoint", &option_endpoint}, - {"-u", &option_user}, - {"--request.user", &option_user}, - {"-g", &option_group}, - {"--request.group", &option_group}, -}; - - -void validate_cmd() { - for (auto &it: option_map) { - auto option = it.second; - if (!option->is_optional() && !option->is_present()) { - std::cout << "Error: Option " << option->get_name() << " is mandatory but not present." << std::endl; - throw Usage; - } - } -} - -void parse_cmd(const int argc, const char *const *const argv) { - for (int i = 2; i < argc; i += 2) { - auto search = option_map.find(argv[i]); - if (search == option_map.end()) { - std::cout << "Error: Unknown option: " << argv[i] << std::endl; - throw Usage; - } - auto option = search->second; - option->set_present(); - option->set_value(argv[i + 1]); - } -} - - // remove leading spaces and quotes void ltrim(std::string &s) { s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int ch) { @@ -151,16 +109,15 @@ void parseFileInfo(std::istream &in, AttrMap &attr, AttrMap &xattr) * @param[in] wf_command The workflow command (CLOSEW or PREPARE) */ void fillNotification(cta::eos::Notification ¬ification, const std::string &wf_command, - const int argc, const char *const *const argv) + const int argc, char *const *const argv) { - parse_cmd(argc, argv); - validate_cmd(); + cta::cliTool::CmdLineArgs cmdLineArgs(argc, argv, cta::cliTool::StandaloneCliTool::CTA_SEND_EVENT); - const std::string &eos_instance = option_instance.get_value(); - const std::string &eos_endpoint = option_endpoint.is_present() ?option_endpoint.get_value() : "localhost:1095"; - const std::string &requester_user = option_user.get_value(); - const std::string &requester_group = option_group.get_value(); + const std::string &eos_instance = cmdLineArgs.m_diskInstance.value(); + const std::string &eos_endpoint = cmdLineArgs.m_eosEndpoint.has_value() ? cmdLineArgs.m_eosEndpoint.value() : "localhost:1095"; + const std::string &requester_user = cmdLineArgs.m_requestUser.value(); + const std::string &requester_group = cmdLineArgs.m_requestGroup.value(); // Set the event type if(wf_command == "CLOSEW") { @@ -236,7 +193,7 @@ void fillNotification(cta::eos::Notification ¬ification, const std::string &w /* * Sends a Notification to the CTA XRootD SSI server */ -int exceptionThrowingMain(int argc, const char *const *const argv) +int exceptionThrowingMain(int argc, char *const *const argv) { if(argc % 2) { throw Usage; @@ -299,8 +256,7 @@ int exceptionThrowingMain(int argc, const char *const *const argv) /* * Start here */ -int main(int argc, const char **argv) -{ +int main(int argc, char *const *const argv) { try { return exceptionThrowingMain(argc, argv); } catch (XrdSsiPb::PbException &ex) { diff --git a/cmdline/CtaVerifyFile.cpp b/cmdline/standalone_cli_tools/CtaVerifyFile.cpp similarity index 67% rename from cmdline/CtaVerifyFile.cpp rename to cmdline/standalone_cli_tools/CtaVerifyFile.cpp index 0c4af66dbf..d740a71d1e 100644 --- a/cmdline/CtaVerifyFile.cpp +++ b/cmdline/standalone_cli_tools/CtaVerifyFile.cpp @@ -21,7 +21,9 @@ #include "CtaFrontendApi.hpp" #include "version.h" -#include "CtaCmdOptions.hpp" +#include "common/CmdLineArgs.hpp" + +using namespace cta::cliTool; const std::string config_file = "/etc/cta/cta-cli.conf"; @@ -43,53 +45,6 @@ void RequestCallback<cta::xrd::Alert>::operator()(const cta::xrd::Alert &alert) // Attribute map type typedef std::map<std::string, std::string> AttrMap; -// Usage exception -const std::runtime_error Usage("Usage: cta-verify-file <archiveFileID> [-v <vid>] " - "[-i <instance>] [-r.user <user>] [-r.group <group>]\n" - "cta-verify-file <archiveFileID> [--vid <id>] " - "[--instance <instance>] [--request.user <user>] [--request.group <group>]"); - -StringOption option_instance {"--instance", "-i", true}; -StringOption option_request_user {"--request.user", "-r.user", true}; -StringOption option_request_group {"--request.group", "-r.group", true}; -StringOption option_vid {"--vid", "-v", true}; - -std::vector<StringOption*> verify_options = {&option_instance, &option_request_user, &option_request_group, &option_vid}; - -std::map<std::string, StringOption*> option_map = { - {"-i", &option_instance}, - {"--instance", &option_instance}, - {"-r.user", &option_request_user}, - {"--request.user", &option_request_user}, - {"-r.group", &option_request_group}, - {"--request.group", &option_request_group}, - {"-v", &option_vid}, - {"--vid", &option_vid}, -}; - -void validate_cmd() { - for (auto &it: option_map) { - auto option = it.second; - if (!option->is_optional() && !option->is_present()) { - std::cout << "Error: Option " << option->get_name() << " is mandatory but not present." << std::endl; - throw Usage; - } - } -} - -void parse_cmd(const int argc, const char *const *const argv) { - for (int i = 2; i < argc; i += 2) { - auto search = option_map.find(argv[i]); - if (search == option_map.end()) { - std::cout << "Error: Unknown option: " << argv[i] << std::endl; - throw Usage; - } - auto option = search->second; - option->set_present(); - option->set_value(argv[i + 1]); - } -} - /* * Fill a Notification message from the command-line parameters and stdin * @@ -97,7 +52,7 @@ void parse_cmd(const int argc, const char *const *const argv) { * @param[in] argc Number of arguments passed on the command line * @param[in] argv Command line arguments array */ -void fillNotification(cta::eos::Notification ¬ification, const int argc, const char *const *const argv) +void fillNotification(cta::eos::Notification ¬ification, const int argc, char *const *const argv, const CmdLineArgs &cmdLineArgs) { XrdSsiPb::Config config(config_file, "eos"); for (const auto &conf_option : std::vector<std::string>({ "instance", "requester.user", "requester.group" })) { @@ -108,27 +63,31 @@ void fillNotification(cta::eos::Notification ¬ification, const int argc, cons notification.mutable_wf()->mutable_instance()->set_name(config.getOptionValueStr("instance").second); notification.mutable_cli()->mutable_user()->set_username(config.getOptionValueStr("requester.user").second); notification.mutable_cli()->mutable_user()->set_groupname(config.getOptionValueStr("requester.group").second); + + if(cmdLineArgs.m_help) { cmdLineArgs.printUsage(std::cout); exit(0); } - parse_cmd(argc, argv); - validate_cmd(); + if(!cmdLineArgs.m_archiveFileId && !cmdLineArgs.m_vid) { + cmdLineArgs.printUsage(std::cout); + throw std::runtime_error("ERROR: Usage"); + } - if (option_instance.is_present()) { - notification.mutable_wf()->mutable_instance()->set_name(option_instance.get_value()); + if (cmdLineArgs.m_diskInstance) { + notification.mutable_wf()->mutable_instance()->set_name(cmdLineArgs.m_diskInstance.value()); } - if (option_request_user.is_present()) { - notification.mutable_cli()->mutable_user()->set_username(option_request_user.get_value()); + if (cmdLineArgs.m_requestUser) { + notification.mutable_cli()->mutable_user()->set_username(cmdLineArgs.m_requestUser.value()); } - if (option_request_group.is_present()) { - notification.mutable_cli()->mutable_user()->set_groupname(option_request_group.get_value()); + if (cmdLineArgs.m_requestGroup) { + notification.mutable_cli()->mutable_user()->set_groupname(cmdLineArgs.m_requestGroup.value()); } - std::string archiveFileId(argv[1]); + const std::string archiveFileId(std::to_string(cmdLineArgs.m_archiveFileId.value())); // WF notification.mutable_wf()->set_event(cta::eos::Workflow::PREPARE); notification.mutable_wf()->set_requester_instance("cta-verify-file"); notification.mutable_wf()->set_verify_only(true); - notification.mutable_wf()->set_vid(option_vid.get_value()); + notification.mutable_wf()->set_vid(cmdLineArgs.m_vid.value()); // Transport @@ -151,13 +110,13 @@ void fillNotification(cta::eos::Notification ¬ification, const int argc, cons /* * Sends a Notification to the CTA XRootD SSI server */ -int exceptionThrowingMain(int argc, const char *const *const argv) +int exceptionThrowingMain(int argc, char *const *const argv) { + using namespace cta::cliTool; + std::string vid; - if (argc == 1 || argc % 2) { // Since all options need values associated, argc should always be even - throw Usage; - } + cta::cliTool::CmdLineArgs cmdLineArgs(argc, argv, StandaloneCliTool::CTA_VERIFY_FILE); // Verify that the Google Protocol Buffer header and linked library versions are compatible GOOGLE_PROTOBUF_VERIFY_VERSION; @@ -184,7 +143,7 @@ int exceptionThrowingMain(int argc, const char *const *const argv) config.getEnv("log", "XrdSsiPbLogLevel"); // Parse the command line arguments: fill the Notification fields - fillNotification(notification, argc, argv); + fillNotification(notification, argc, argv, cmdLineArgs); // Obtain a Service Provider XrdSsiPbServiceType cta_service(config); @@ -215,8 +174,7 @@ int exceptionThrowingMain(int argc, const char *const *const argv) /* * Start here */ -int main(int argc, const char **argv) -{ +int main(int argc, char *const *const argv) { try { return exceptionThrowingMain(argc, argv); } catch (XrdSsiPb::PbException &ex) { diff --git a/cmdline/restore_files/RestoreFilesCmdLineArgs.cpp b/cmdline/standalone_cli_tools/common/CmdLineArgs.cpp similarity index 51% rename from cmdline/restore_files/RestoreFilesCmdLineArgs.cpp rename to cmdline/standalone_cli_tools/common/CmdLineArgs.cpp index d8665b129f..a6523c10aa 100644 --- a/cmdline/restore_files/RestoreFilesCmdLineArgs.cpp +++ b/cmdline/standalone_cli_tools/common/CmdLineArgs.cpp @@ -15,50 +15,94 @@ * submit itself to any jurisdiction. */ -#include "RestoreFilesCmdLineArgs.hpp" +#include "cmdline/standalone_cli_tools/common/CmdLineArgs.hpp" #include "common/exception/CommandLineNotParsed.hpp" +#include <climits> +#include <fstream> #include <getopt.h> -#include <ostream> -#include <sstream> -#include <iostream> +#include <map> #include <string> -#include <limits.h> -#include <fstream> - namespace cta { -namespace admin{ +namespace cliTool{ + + +//------------------------------------------------------------------------------ +// Options for each tool +//------------------------------------------------------------------------------ +static struct option restoreFilesLongOption[] = { + {"id", required_argument, nullptr, 'I'}, + {"instance", required_argument, nullptr, 'i'}, + {"fxid", required_argument, nullptr, 'f'}, + {"fxidfile", required_argument, nullptr, 'F'}, + {"vid", required_argument, nullptr, 'v'}, + {"copynb", required_argument, nullptr, 'c'}, + {"help", no_argument, nullptr, 'h'}, + {"debug", no_argument, nullptr, 'd'}, + {nullptr, 0, nullptr, 0} +}; + +static struct option sendFileLongOption[] = { + {"instance", required_argument, nullptr, 'i'}, + {"eos.endpoint", required_argument, nullptr, 'e'}, + {"request.user", required_argument, nullptr, 'u'}, + {"request.group", required_argument, nullptr, 'g'}, + {nullptr, 0, nullptr, 0} +}; + +static struct option verifyFileLongOption[] = { + {"id", required_argument, nullptr, 'I'}, + {"instance", required_argument, nullptr, 'i'}, + {"request.user", required_argument, nullptr, 'u'}, + {"request.group", required_argument, nullptr, 'g'}, + {"vid", required_argument, nullptr, 'v'}, + {"help", no_argument, nullptr, 'h'}, + {nullptr, 0, nullptr, 0} +}; + +std::map<StandaloneCliTool, const option*> longopts = { + {StandaloneCliTool::RESTORE_FILES, restoreFilesLongOption}, + {StandaloneCliTool::CTA_SEND_EVENT, sendFileLongOption}, + {StandaloneCliTool::CTA_VERIFY_FILE, verifyFileLongOption}, +}; + +std::map<StandaloneCliTool, const char*> shortopts = { + {StandaloneCliTool::RESTORE_FILES, "I:i:f:F:v:c:hd:"}, + {StandaloneCliTool::CTA_SEND_EVENT, "i:e:u:g:"}, + {StandaloneCliTool::CTA_VERIFY_FILE, "I:i:u:g:v:h:"}, +}; //------------------------------------------------------------------------------ // constructor //------------------------------------------------------------------------------ -RestoreFilesCmdLineArgs::RestoreFilesCmdLineArgs(const int argc, char *const *const argv): -m_help(false), m_debug(false) { - - static struct option longopts[] = { - {"id", required_argument, nullptr, 'I'}, - {"instance", required_argument, nullptr, 'i'}, - {"fxid", required_argument, nullptr, 'f'}, - {"fxidfile", required_argument, nullptr, 'F'}, - {"vid", required_argument, nullptr, 'v'}, - {"copynb", required_argument, nullptr, 'c'}, - {"help", no_argument, nullptr, 'h'}, - {"debug", no_argument, nullptr, 'd'}, - {nullptr, 0, nullptr, 0} - }; +CmdLineArgs::CmdLineArgs(const int &argc, char *const *const &argv, const StandaloneCliTool &standaloneCliTool): +m_help(false), m_debug(false), m_standaloneCliTool{standaloneCliTool} { opterr = 0; int opt = 0; - int opt_index = 3; + int opt_index; - while ((opt = getopt_long(argc, argv, "I:i:f:F:v:c:hd", longopts, &opt_index)) != -1) { + switch (standaloneCliTool) { + case StandaloneCliTool::RESTORE_FILES: + opt_index = 3; + break; + case StandaloneCliTool::CTA_SEND_EVENT: + opt_index = 3; + break; + case StandaloneCliTool::CTA_VERIFY_FILE: + opt_index = 2; + break; + default: + opt_index = 3; + break; + } + + while ((opt = getopt_long(argc, argv, shortopts[m_standaloneCliTool], longopts[m_standaloneCliTool], &opt_index)) != -1) { switch(opt) { case 'I': { - int64_t archiveId = std::stol(std::string(optarg)); - if(archiveId < 0) throw std::out_of_range("archive id value cannot be negative"); - m_archiveFileId = archiveId; + m_archiveFileId = std::stol(std::string(optarg)); break; } case 'i': @@ -108,10 +152,25 @@ m_help(false), m_debug(false) { m_debug = true; break; } + case 'e': + { + m_eosEndpoint = std::string(optarg); + break; + } + case 'u': + { + m_requestUser = std::string(optarg); + break; + } + case 'g': + { + m_requestGroup = std::string(optarg); + break; + } case ':': // Missing parameter { exception::CommandLineNotParsed ex; - ex.getMessage() << "The -" << (char)optopt << " option requires a parameter"; + ex.getMessage() << "The -" << static_cast<char>(optopt) << " option requires a parameter"; throw ex; } case '?': // Unknown option @@ -120,8 +179,9 @@ m_help(false), m_debug(false) { if(0 == optopt) { ex.getMessage() << "Unknown command-line option"; } else { - ex.getMessage() << "Unknown command-line option: -" << (char)optopt; + ex.getMessage() << "Unknown command-line option: -" << static_cast<char>(optopt) << std::endl; } + printUsage(ex.getMessage()); throw ex; } default: @@ -129,7 +189,7 @@ m_help(false), m_debug(false) { exception::CommandLineNotParsed ex; ex.getMessage() << "getopt_long returned the following unknown value: 0x" << - std::hex << (int)opt; + std::hex << static_cast<int>(optopt); throw ex; } } @@ -139,7 +199,7 @@ m_help(false), m_debug(false) { //------------------------------------------------------------------------------ // readFidListFromFile //------------------------------------------------------------------------------ -void RestoreFilesCmdLineArgs::readFidListFromFile(const std::string &filename, std::list<std::uint64_t> &fidList) { +void CmdLineArgs::readFidListFromFile(const std::string &filename, std::list<std::uint64_t> &fidList) { std::ifstream file(filename); if (file.fail()) { throw std::runtime_error("Unable to open file " + filename); @@ -182,12 +242,28 @@ void RestoreFilesCmdLineArgs::readFidListFromFile(const std::string &filename, s //------------------------------------------------------------------------------ // printUsage //------------------------------------------------------------------------------ -void RestoreFilesCmdLineArgs::printUsage(std::ostream &os) { - os << "Usage:" << std::endl << - " cta-restore-deleted-files [--id/-I <archive_file_id>] [--instance/-i <disk_instance>]" << std::endl << - " [--fxid/-f <eos_fxid>] [--fxidfile/-F <filename>]" << std::endl << - " [--vid/-v <vid>] [--copynb/-c <copy_number>] [--debug/-d]" << std::endl; +void CmdLineArgs::printUsage(std::ostream &os) const { + switch (m_standaloneCliTool) { + case StandaloneCliTool::RESTORE_FILES: + os << " Usage:" << std::endl << + " cta-restore-deleted-files [--id/-I <archive_file_id>] [--instance/-i <disk_instance>]" << std::endl << + " [--fxid/-f <eos_fxid>] [--fxidfile/-F <filename>]" << std::endl << + " [--vid/-v <vid>] [--copynb/-c <copy_number>] [--debug/-d]" << std::endl; + break; + case StandaloneCliTool::CTA_SEND_EVENT: + os << " Usage:" << std::endl << + " eos --json fileinfo /eos/path | cta-send-event CLOSEW|PREPARE " << std::endl << + " -i/--eos.instance <instance> [-e/--eos.endpoint <url>]" << std::endl << + " -u/--request.user <user> -g/--request.group <group>" << std::endl; + break; + case StandaloneCliTool::CTA_VERIFY_FILE : + os << " Usage:" << std::endl << + " cta-verify-file --id/-I <archiveFileID> --vid/-v <vid> [--instance/-i <instance>] [--request.user/-u <user>] [request.group/-g <group>]\n" << std::endl; + break; + default: + break; + } } } // namespace admin -} // namespace cta +} // namespace cta \ No newline at end of file diff --git a/cmdline/restore_files/RestoreFilesCmdLineArgs.hpp b/cmdline/standalone_cli_tools/common/CmdLineArgs.hpp similarity index 75% rename from cmdline/restore_files/RestoreFilesCmdLineArgs.hpp rename to cmdline/standalone_cli_tools/common/CmdLineArgs.hpp index 40c5997cda..a90bf727b1 100644 --- a/cmdline/restore_files/RestoreFilesCmdLineArgs.hpp +++ b/cmdline/standalone_cli_tools/common/CmdLineArgs.hpp @@ -21,15 +21,25 @@ #include <list> #include <optional> +#include <string> namespace cta { -namespace admin { +namespace cliTool { + +/** +* Enum value for each of the tools +*/ +enum class StandaloneCliTool { + RESTORE_FILES, + CTA_SEND_EVENT, + CTA_VERIFY_FILE +}; /** * Structure to store the command-line arguments of the command-line tool * named cta-restore-deleted-archive. */ -struct RestoreFilesCmdLineArgs { +struct CmdLineArgs { /** * True if the usage message should be printed. */ @@ -55,6 +65,11 @@ struct RestoreFilesCmdLineArgs { */ std::optional<std::list<uint64_t>> m_eosFids; + /** + * Fids of the files to restore + */ + std::optional<std::string> m_eosInstance; + /** * Vid of the tape of the files to restore */ @@ -65,14 +80,35 @@ struct RestoreFilesCmdLineArgs { */ std::optional<uint64_t> m_copyNumber; + /** + * Eos endpoint + */ + std::optional<std::string> m_eosEndpoint; + + /** + * Request user + */ + std::optional<std::string> m_requestUser; + + /** + * Request user + */ + std::optional<std::string> m_requestGroup; + + /** + * The tool parsing the arguments + */ + StandaloneCliTool m_standaloneCliTool; + /** * Constructor that parses the specified command-line arguments. * * @param argc The number of command-line arguments including the name of the * executable. * @param argv The vector of command-line arguments. + * @param standaloneCliTool The tool calling the constructor */ - RestoreFilesCmdLineArgs(const int argc, char *const *const argv); + CmdLineArgs(const int &argc, char *const *const &argv, const StandaloneCliTool &standaloneCliTool); /** * Read a list of eos file ids from a file and write the options to a list @@ -87,9 +123,9 @@ struct RestoreFilesCmdLineArgs { * * @param os The output stream to which the usage message is to be printed. */ - static void printUsage(std::ostream &os); + void printUsage(std::ostream &os) const; }; // class RestoreFilesCmdLineArgs } // namespace admin -} // namespace cta +} // namespace cta \ No newline at end of file diff --git a/cmdline/restore_files/CmdLineTool.cpp b/cmdline/standalone_cli_tools/common/CmdLineTool.cpp similarity index 88% rename from cmdline/restore_files/CmdLineTool.cpp rename to cmdline/standalone_cli_tools/common/CmdLineTool.cpp index fab6ead755..5ae584bf85 100644 --- a/cmdline/restore_files/CmdLineTool.cpp +++ b/cmdline/standalone_cli_tools/common/CmdLineTool.cpp @@ -15,13 +15,15 @@ * submit itself to any jurisdiction. */ -#include "cmdline/restore_files/CmdLineTool.hpp" +#include "cmdline/standalone_cli_tools/common/CmdLineTool.hpp" #include "common/exception/CommandLineNotParsed.hpp" +#include <iostream> +#include <string> #include <unistd.h> namespace cta { -namespace admin { +namespace cliTool { //------------------------------------------------------------------------------ // constructor @@ -72,14 +74,12 @@ std::string CmdLineTool::getHostname() { // main //------------------------------------------------------------------------------ int CmdLineTool::main(const int argc, char *const *const argv) { - bool cmdLineNotParsed = false; std::string errorMessage; try { return exceptionThrowingMain(argc, argv); } catch(exception::CommandLineNotParsed &ue) { errorMessage = ue.getMessage().str(); - cmdLineNotParsed = true; } catch(exception::Exception &ex) { errorMessage = ex.getMessage().str(); } catch(std::exception &se) { @@ -87,15 +87,8 @@ int CmdLineTool::main(const int argc, char *const *const argv) { } catch(...) { errorMessage = "An unknown exception was thrown"; } - - // Reaching this point means the command has failed, an exception was throw - // and errorMessage has been set accordingly - - m_err << "Aborting: " << errorMessage << std::endl; - if(cmdLineNotParsed) { - m_err << std::endl; - printUsage(m_err); - } + + std::cout << errorMessage << std::endl; return 1; } diff --git a/cmdline/restore_files/CmdLineTool.hpp b/cmdline/standalone_cli_tools/common/CmdLineTool.hpp similarity index 92% rename from cmdline/restore_files/CmdLineTool.hpp rename to cmdline/standalone_cli_tools/common/CmdLineTool.hpp index e71ced1fcb..5da1bdb277 100644 --- a/cmdline/restore_files/CmdLineTool.hpp +++ b/cmdline/standalone_cli_tools/common/CmdLineTool.hpp @@ -21,7 +21,7 @@ #include <ostream> namespace cta { -namespace admin { +namespace cliTool { /** * Abstract class implementing common code and data structures for a @@ -64,13 +64,6 @@ protected: */ virtual int exceptionThrowingMain(const int argc, char *const *const argv) = 0; - /** - * Prints the usage message of the command-line tool. - * - * @param os The output stream to which the usage message is to be printed. - */ - virtual void printUsage(std::ostream &os) = 0; - /** * Standard input stream. */ diff --git a/cmdline/restore_files/CMakeLists.txt b/cmdline/standalone_cli_tools/restore_files/CMakeLists.txt similarity index 91% rename from cmdline/restore_files/CMakeLists.txt rename to cmdline/standalone_cli_tools/restore_files/CMakeLists.txt index dea348c803..20a0246972 100644 --- a/cmdline/restore_files/CMakeLists.txt +++ b/cmdline/standalone_cli_tools/restore_files/CMakeLists.txt @@ -27,7 +27,7 @@ include_directories(${XRD_SSI_PB_DIR}/include ${XRD_SSI_PB_DIR}/eos_cta/include) # Compiled protocol buffers include_directories(${CMAKE_BINARY_DIR}/eos_cta ${PROTOBUF3_INCLUDE_DIRS}) -add_executable(cta-restore-deleted-files RestoreFilesCmdLineArgs.cpp RestoreFilesCmdMain.cpp CmdLineTool.cpp RestoreFilesCmd.cpp) +add_executable(cta-restore-deleted-files RestoreFilesCmdMain.cpp ../common/CmdLineTool.cpp ../common/CmdLineArgs.cpp RestoreFilesCmd.cpp ../../CtaAdminCmdParse.cpp) target_link_libraries(cta-restore-deleted-files ${PROTOBUF3_LIBRARIES} ${GRPC_LIBRARY} ${GRPC_GRPC++_LIBRARY} XrdSsiPbEosCta XrdSsiLib XrdUtils ctacommon EosCtaGrpc EosGrpcClient) set_property (TARGET cta-restore-deleted-files APPEND PROPERTY INSTALL_RPATH ${PROTOBUF3_RPATH}) diff --git a/cmdline/restore_files/RestoreFilesCmd.cpp b/cmdline/standalone_cli_tools/restore_files/RestoreFilesCmd.cpp similarity index 94% rename from cmdline/restore_files/RestoreFilesCmd.cpp rename to cmdline/standalone_cli_tools/restore_files/RestoreFilesCmd.cpp index c32cc2fc0f..c50b323dab 100644 --- a/cmdline/restore_files/RestoreFilesCmd.cpp +++ b/cmdline/standalone_cli_tools/restore_files/RestoreFilesCmd.cpp @@ -15,8 +15,8 @@ * submit itself to any jurisdiction. */ -#include "cmdline/restore_files/RestoreFilesCmd.hpp" -#include "cmdline/restore_files/RestoreFilesCmdLineArgs.hpp" +#include "cmdline/standalone_cli_tools/restore_files/RestoreFilesCmd.hpp" +#include "cmdline/CtaAdminCmdParse.hpp" #include "common/utils/utils.hpp" #include "common/checksum/ChecksumBlob.hpp" #include "CtaFrontendApi.hpp" @@ -99,7 +99,7 @@ void IStreamBuffer<cta::xrd::Data>::DataCallback(cta::xrd::Data record) const namespace cta{ -namespace admin { +namespace cliTool { /*! * RestoreFilesCmdException @@ -136,9 +136,9 @@ RestoreFilesCmd::RestoreFilesCmd(std::istream &inStream, std::ostream &outStream // exceptionThrowingMain //------------------------------------------------------------------------------ int RestoreFilesCmd::exceptionThrowingMain(const int argc, char *const *const argv) { - RestoreFilesCmdLineArgs cmdLineArgs(argc, argv); + CmdLineArgs cmdLineArgs(argc, argv, StandaloneCliTool::RESTORE_FILES); if (cmdLineArgs.m_help) { - printUsage(m_out); + cmdLineArgs.printUsage(m_out); return 0; } @@ -190,7 +190,7 @@ int RestoreFilesCmd::exceptionThrowingMain(const int argc, char *const *const ar //------------------------------------------------------------------------------ void RestoreFilesCmd::readAndSetConfiguration( const std::string &userName, - const RestoreFilesCmdLineArgs &cmdLineArgs) { + const CmdLineArgs &cmdLineArgs) { m_vid = cmdLineArgs.m_vid; m_diskInstance = cmdLineArgs.m_diskInstance; @@ -291,40 +291,40 @@ void RestoreFilesCmd::listDeletedFilesCta() const { request.set_client_cta_version(CTA_VERSION); request.set_client_xrootd_ssi_protobuf_interface_version(XROOTD_SSI_PROTOBUF_INTERFACE_VERSION); - admincmd.set_cmd(AdminCmd::CMD_RECYCLETAPEFILE); - admincmd.set_subcmd(AdminCmd::SUBCMD_LS); + admincmd.set_cmd(cta::admin::AdminCmd::CMD_RECYCLETAPEFILE); + admincmd.set_subcmd(cta::admin::AdminCmd::SUBCMD_LS); if (m_vid) { params.push_back(cta::log::Param("tapeVid", m_vid.value())); - auto key = OptionString::VID; + auto key = cta::admin::OptionString::VID; auto new_opt = admincmd.add_option_str(); new_opt->set_key(key); new_opt->set_value(m_vid.value()); } if (m_diskInstance) { params.push_back(cta::log::Param("diskInstance", m_diskInstance.value())); - auto key = OptionString::INSTANCE; + auto key = cta::admin::OptionString::INSTANCE; auto new_opt = admincmd.add_option_str(); new_opt->set_key(key); new_opt->set_value(m_diskInstance.value()); } if (m_archiveFileId) { params.push_back(cta::log::Param("archiveFileId", m_archiveFileId.value())); - auto key = OptionUInt64::ARCHIVE_FILE_ID; + auto key = cta::admin::OptionUInt64::ARCHIVE_FILE_ID; auto new_opt = admincmd.add_option_uint64(); new_opt->set_key(key); new_opt->set_value(m_archiveFileId.value()); } if (m_copyNumber) { params.push_back(cta::log::Param("copyNb", m_copyNumber.value())); - auto key = OptionUInt64::COPY_NUMBER; + auto key = cta::admin::OptionUInt64::COPY_NUMBER; auto new_opt = admincmd.add_option_uint64(); new_opt->set_key(key); new_opt->set_value(m_copyNumber.value()); } if (m_eosFids) { std::stringstream ss; - auto key = OptionStrList::FILE_ID; + auto key = cta::admin::OptionStrList::FILE_ID; auto new_opt = admincmd.add_option_str_list(); new_opt->set_key(key); for (auto &fid : m_eosFids.value()) { @@ -369,7 +369,7 @@ void RestoreFilesCmd::listDeletedFilesCta() const { //------------------------------------------------------------------------------ // restoreDeletedFileCopyCta //------------------------------------------------------------------------------ -void RestoreFilesCmd::restoreDeletedFileCopyCta(const RecycleTapeFileLsItem &file) const { +void RestoreFilesCmd::restoreDeletedFileCopyCta(const cta::admin::RecycleTapeFileLsItem &file) const { std::list<cta::log::Param> params; params.push_back(cta::log::Param("userName", getUsername())); @@ -385,35 +385,35 @@ void RestoreFilesCmd::restoreDeletedFileCopyCta(const RecycleTapeFileLsItem &fil request.set_client_cta_version(CTA_VERSION); request.set_client_xrootd_ssi_protobuf_interface_version(XROOTD_SSI_PROTOBUF_INTERFACE_VERSION); - admincmd.set_cmd(AdminCmd::CMD_RECYCLETAPEFILE); - admincmd.set_subcmd(AdminCmd::SUBCMD_RESTORE); + admincmd.set_cmd(cta::admin::AdminCmd::CMD_RECYCLETAPEFILE); + admincmd.set_subcmd(cta::admin::AdminCmd::SUBCMD_RESTORE); { - auto key = OptionString::VID; + auto key = cta::admin::OptionString::VID; auto new_opt = admincmd.add_option_str(); new_opt->set_key(key); new_opt->set_value(file.vid()); } { - auto key = OptionString::INSTANCE; + auto key = cta::admin::OptionString::INSTANCE; auto new_opt = admincmd.add_option_str(); new_opt->set_key(key); new_opt->set_value(file.disk_instance()); } { - auto key = OptionUInt64::ARCHIVE_FILE_ID; + auto key = cta::admin::OptionUInt64::ARCHIVE_FILE_ID; auto new_opt = admincmd.add_option_uint64(); new_opt->set_key(key); new_opt->set_value(file.archive_file_id()); } { - auto key = OptionUInt64::COPY_NUMBER; + auto key = cta::admin::OptionUInt64::COPY_NUMBER; auto new_opt = admincmd.add_option_uint64(); new_opt->set_key(key); new_opt->set_value(file.copy_nb()); } { - auto key = OptionString::FXID; + auto key = cta::admin::OptionString::FXID; auto new_opt = admincmd.add_option_str(); // Convert diskFileId from base 10 to base 16 before transmitting to CTA @@ -430,6 +430,9 @@ void RestoreFilesCmd::restoreDeletedFileCopyCta(const RecycleTapeFileLsItem &fil } m_log(cta::log::DEBUG, "Restoring file copy in CTA catalogue", params); + // This validation will also be done at the server side + cta::admin::validateCmd(admincmd); + // Send the Request to the Service and get a Response cta::xrd::Response response; m_serviceProviderPtr->Send(request, response); @@ -523,7 +526,7 @@ uint64_t RestoreFilesCmd::containerExistsEos(const std::string &diskInstance, co return cid; } -bool RestoreFilesCmd::fileWasDeletedByRM(const RecycleTapeFileLsItem &file) const { +bool RestoreFilesCmd::fileWasDeletedByRM(const cta::admin::RecycleTapeFileLsItem &file) const { return file.reason_log().rfind("(Deleted using cta-admin tapefile rm)", 0) == 0; } @@ -544,10 +547,10 @@ bool RestoreFilesCmd::archiveFileExistsCTA(const uint64_t &archiveFileId) const request.set_client_cta_version(CTA_VERSION); request.set_client_xrootd_ssi_protobuf_interface_version(XROOTD_SSI_PROTOBUF_INTERFACE_VERSION); - admincmd.set_cmd(AdminCmd::CMD_TAPEFILE); - admincmd.set_subcmd(AdminCmd::SUBCMD_LS); + admincmd.set_cmd(cta::admin::AdminCmd::CMD_TAPEFILE); + admincmd.set_subcmd(cta::admin::AdminCmd::SUBCMD_LS); - auto key = OptionUInt64::ARCHIVE_FILE_ID; + auto key = cta::admin::OptionUInt64::ARCHIVE_FILE_ID; auto new_opt = admincmd.add_option_uint64(); new_opt->set_key(key); new_opt->set_value(archiveFileId); @@ -642,7 +645,7 @@ void RestoreFilesCmd::getCurrentEosIds(const std::string &diskInstance) const { //------------------------------------------------------------------------------ // restoreDeletedFileEos //------------------------------------------------------------------------------ -uint64_t RestoreFilesCmd::restoreDeletedFileEos(const RecycleTapeFileLsItem &rtfls_item) const { +uint64_t RestoreFilesCmd::restoreDeletedFileEos(const cta::admin::RecycleTapeFileLsItem &rtfls_item) const { std::list<cta::log::Param> params; params.push_back(cta::log::Param("userName", getUsername())); @@ -733,17 +736,10 @@ uint64_t RestoreFilesCmd::restoreDeletedFileEos(const RecycleTapeFileLsItem &rtf } -//------------------------------------------------------------------------------ -// printUsage -//------------------------------------------------------------------------------ -void RestoreFilesCmd::printUsage(std::ostream &os) { - RestoreFilesCmdLineArgs::printUsage(os); -} - //------------------------------------------------------------------------------ // getFxidFromCTA //------------------------------------------------------------------------------ -std::pair<std::string,std::string> RestoreFilesCmd::getInstanceAndFidFromCTA(const RecycleTapeFileLsItem& file) { +std::pair<std::string,std::string> RestoreFilesCmd::getInstanceAndFidFromCTA(const cta::admin::RecycleTapeFileLsItem& file) { { std::list<cta::log::Param> params; params.push_back(cta::log::Param("archiveFileId", file.archive_file_id())); @@ -755,10 +751,10 @@ std::pair<std::string,std::string> RestoreFilesCmd::getInstanceAndFidFromCTA(con request.set_client_cta_version(CTA_VERSION); request.set_client_xrootd_ssi_protobuf_interface_version(XROOTD_SSI_PROTOBUF_INTERFACE_VERSION); - admincmd.set_cmd(AdminCmd::CMD_TAPEFILE); - admincmd.set_subcmd(AdminCmd::SUBCMD_LS); + admincmd.set_cmd(cta::admin::AdminCmd::CMD_TAPEFILE); + admincmd.set_subcmd(cta::admin::AdminCmd::SUBCMD_LS); auto new_opt = admincmd.add_option_uint64(); - new_opt->set_key(OptionUInt64::ARCHIVE_FILE_ID); + new_opt->set_key(cta::admin::OptionUInt64::ARCHIVE_FILE_ID); new_opt->set_value(file.archive_file_id()); // Send the Request to the Service and get a Response diff --git a/cmdline/restore_files/RestoreFilesCmd.hpp b/cmdline/standalone_cli_tools/restore_files/RestoreFilesCmd.hpp similarity index 92% rename from cmdline/restore_files/RestoreFilesCmd.hpp rename to cmdline/standalone_cli_tools/restore_files/RestoreFilesCmd.hpp index d3675103e5..512397cd1d 100644 --- a/cmdline/restore_files/RestoreFilesCmd.hpp +++ b/cmdline/standalone_cli_tools/restore_files/RestoreFilesCmd.hpp @@ -17,8 +17,8 @@ #pragma once -#include "cmdline/restore_files/CmdLineTool.hpp" -#include "cmdline/restore_files/RestoreFilesCmdLineArgs.hpp" +#include "cmdline/standalone_cli_tools/common/CmdLineTool.hpp" +#include "cmdline/standalone_cli_tools/common/CmdLineArgs.hpp" #include "eos_grpc_client/GrpcEndpoint.hpp" #include "catalogue/Catalogue.hpp" #include "common/log/StdoutLogger.hpp" @@ -29,7 +29,7 @@ #include "CtaFrontendApi.hpp" namespace cta { -namespace admin { +namespace cliTool { class RestoreFilesCmd: public CmdLineTool { public: @@ -60,7 +60,7 @@ public: * @param username The name of the user running the command-line tool. * @param cmdLineArgs The arguments parsed from the command line. */ - void readAndSetConfiguration(const std::string &userName, const RestoreFilesCmdLineArgs &cmdLineArgs); + void readAndSetConfiguration(const std::string &userName, const CmdLineArgs &cmdLineArgs); /** * Populate the namespace endpoint configuration from a keytab file @@ -84,7 +84,7 @@ public: * Restores the deleted file present in the cta catalogue recycle bin * @param file the deleted tape file */ - void restoreDeletedFileCopyCta(const RecycleTapeFileLsItem &file) const; + void restoreDeletedFileCopyCta(const cta::admin::RecycleTapeFileLsItem &file) const; /** * Adds a container in the eos namespace, if it does not exist @@ -117,7 +117,7 @@ public: * @param diskInstance eos disk instance * @param diskFileId the eos file id to check */ - bool fileWasDeletedByRM(const RecycleTapeFileLsItem &file) const; + bool fileWasDeletedByRM(const cta::admin::RecycleTapeFileLsItem &file) const; /** * Returns true (i.e. not zero) if an archive file with given id exists in the cta catalogue @@ -136,14 +136,7 @@ public: * Restores the deleted file present in the eos namespace * @param file the deleted tape file */ - uint64_t restoreDeletedFileEos(const RecycleTapeFileLsItem &file) const; - - /** - * Prints the usage message of the command-line tool. - * - * @param os The output stream to which the usage message is to be printed. - */ - void printUsage(std::ostream &os) override; + uint64_t restoreDeletedFileEos(const cta::admin::RecycleTapeFileLsItem &file) const; private: /** @@ -152,7 +145,7 @@ private: * @param file The restored tape file in CTA * @return Tuple of EOS disk instance and file ID (fid) as a decimal string */ - std::pair<std::string,std::string> getInstanceAndFidFromCTA(const RecycleTapeFileLsItem& file); + std::pair<std::string,std::string> getInstanceAndFidFromCTA(const cta::admin::RecycleTapeFileLsItem& file); /** * Query EOS for the archiveFileId and checksum of the restored file diff --git a/cmdline/restore_files/RestoreFilesCmdMain.cpp b/cmdline/standalone_cli_tools/restore_files/RestoreFilesCmdMain.cpp similarity index 96% rename from cmdline/restore_files/RestoreFilesCmdMain.cpp rename to cmdline/standalone_cli_tools/restore_files/RestoreFilesCmdMain.cpp index d19f11440b..f22ca7ac5e 100644 --- a/cmdline/restore_files/RestoreFilesCmdMain.cpp +++ b/cmdline/standalone_cli_tools/restore_files/RestoreFilesCmdMain.cpp @@ -40,7 +40,7 @@ int main(const int argc, char *const *const argv) { } cta::log::StdoutLogger log(hostName, "cta-restore-deleted-files"); - cta::admin::RestoreFilesCmd cmd(std::cin, std::cout, std::cerr, log); + cta::cliTool::RestoreFilesCmd cmd(std::cin, std::cout, std::cerr, log); int ret = cmd.main(argc, argv); // Delete all global objects allocated by libprotobuf google::protobuf::ShutdownProtobufLibrary(); diff --git a/cmdline/restore_files/cta-restore-deleted-files.1cta b/cmdline/standalone_cli_tools/restore_files/cta-restore-deleted-files.1cta similarity index 100% rename from cmdline/restore_files/cta-restore-deleted-files.1cta rename to cmdline/standalone_cli_tools/restore_files/cta-restore-deleted-files.1cta diff --git a/continuousintegration/docker/ctafrontend/cc7/etc/cta/cta-frontend-xrootd.conf b/continuousintegration/docker/ctafrontend/cc7/etc/cta/cta-frontend-xrootd.conf index eac3b76818..54bbaceeca 100644 --- a/continuousintegration/docker/ctafrontend/cc7/etc/cta/cta-frontend-xrootd.conf +++ b/continuousintegration/docker/ctafrontend/cc7/etc/cta/cta-frontend-xrootd.conf @@ -33,7 +33,7 @@ cta.log.ssi warning cta.verification.mount_policy verification # Keytab containing gRPC endpoints and tokens for each disk instance -#cta.ns.config /etc/cta/eos.grpc.keytab +cta.ns.config /etc/cta/eos.grpc.keytab # # XRootD/SSI options diff --git a/continuousintegration/orchestration/tests/README_restore_files.md b/continuousintegration/orchestration/tests/README_restore_files.md new file mode 100644 index 0000000000..745ddbce75 --- /dev/null +++ b/continuousintegration/orchestration/tests/README_restore_files.md @@ -0,0 +1,27 @@ +# Restore Files Unit Test +The test checks if the restore tool restores a deleted file from the recycle bin. The steps are: +- Creates a new file +- Deletes the file +- Restores the file +- Checks consistency: archive id, checksum and file size for deleted and restored file +- Checks consistency: fxid for restored file in EOS and CTA + +## How to Run Test +The test can be run with the following command: + +`./restore_files.sh -n <kubernetes-instance>` + +In addition, the tool must be run from the folder: + +`~/CTA/continuousintegration/orchestration/tests` + +There must also be a keytab file provided in `/etc/cta/eos.grpc.keytab`. Use the same token as on the eos side. The file should be on the form: + +``` +# disk instance endpoint (host:port) gRPC token +eosdev <eoshostname>.cern.ch:50051 <token> +``` + +In `continuousintegration/docker/ctafrontend/cc7/etc/cta/cta-frontend-xrootd.conf` an option should specify the path to the file: + +`cta.ns.config /etc/cta/eos.grpc.keytab` \ No newline at end of file diff --git a/continuousintegration/orchestration/tests/common/archive_file.sh b/continuousintegration/orchestration/tests/common/archive_file.sh new file mode 100644 index 0000000000..bd9a88da51 --- /dev/null +++ b/continuousintegration/orchestration/tests/common/archive_file.sh @@ -0,0 +1,87 @@ +#!/bin/bash + +# @project The CERN Tape Archive (CTA) +# @copyright Copyright © 2022 CERN +# @license This program is free software, distributed under the terms of the GNU General Public +# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". You can +# redistribute it and/or modify it under the terms of the GPL Version 3, 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. +# +# In applying this licence, CERN does not waive the privileges and immunities +# granted to it by virtue of its status as an Intergovernmental Organization or +# submit itself to any jurisdiction. + +EOSINSTANCE=ctaeos + +usage() { cat <<EOF 1>&2 +Usage: $0 -f <filename> +EOF +exit 1 +} + +while getopts "n:" o; do + case "${o}" in + n) + TEST_FILE_NAME=${OPTARG} + ;; + *) + usage + ;; + esac +done +shift $((OPTIND-1)) + +if [ -z "${TEST_FILE_NAME}" ]; then + usage +fi + +if [ ! -z "${error}" ]; then + echo -e "ERROR:\n${error}" + exit 1 +fi + +# get some common useful helpers for krb5 +. /root/client_helper.sh + +eospower_kdestroy +eospower_kinit + +echo "xrdcp /etc/group root://${EOSINSTANCE}//eos/ctaeos/cta/${TEST_FILE_NAME}" +xrdcp /etc/group root://${EOSINSTANCE}//eos/ctaeos/cta/${TEST_FILE_NAME} + +SECONDS_PASSED=0 +WAIT_FOR_ARCHIVED_FILE_TIMEOUT=90 +while test 0 == `eos root://${EOSINSTANCE} info /eos/ctaeos/cta/${TEST_FILE_NAME} | awk '{print $4;}' | grep tape | wc -l`; do + echo "Waiting for file to be archived to tape: Seconds passed = ${SECONDS_PASSED}" + sleep 1 + let SECONDS_PASSED=SECONDS_PASSED+1 + + if test ${SECONDS_PASSED} == ${WAIT_FOR_ARCHIVED_FILE_TIMEOUT}; then + echo "Timed out after ${WAIT_FOR_ARCHIVED_FILE_TIMEOUT} seconds waiting for file to be archived to tape" + exit 1 + fi +done + +echo +echo "FILE ARCHIVED TO TAPE" +echo +eos root://${EOSINSTANCE} info /eos/ctaeos/cta/${TEST_FILE_NAME} +echo +echo "Information about the testing file:" +echo "********" + eos root://${EOSINSTANCE} attr ls /eos/ctaeos/cta/${TEST_FILE_NAME} + eos root://${EOSINSTANCE} ls -l /eos/ctaeos/cta/${TEST_FILE_NAME} + eos root://${EOSINSTANCE} info /eos/ctaeos/cta/${TEST_FILE_NAME} +echo +echo "Removing disk replica as poweruser1:powerusers (12001:1200)" + +XrdSecPROTOCOL=sss eos -r 0 0 root://${EOSINSTANCE} file drop /eos/ctaeos/cta/${TEST_FILE_NAME} 1 +echo +echo "Information about the testing file without disk replica" + eos root://${EOSINSTANCE} ls -l /eos/ctaeos/cta/${TEST_FILE_NAME} + eos root://${EOSINSTANCE} info /eos/ctaeos/cta/${TEST_FILE_NAME} +echo diff --git a/continuousintegration/orchestration/tests/common/delete_file.sh b/continuousintegration/orchestration/tests/common/delete_file.sh new file mode 100644 index 0000000000..c34048922e --- /dev/null +++ b/continuousintegration/orchestration/tests/common/delete_file.sh @@ -0,0 +1,58 @@ +#!/bin/bash + +# @project The CERN Tape Archive (CTA) +# @copyright Copyright © 2022 CERN +# @license This program is free software, distributed under the terms of the GNU General Public +# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". You can +# redistribute it and/or modify it under the terms of the GPL Version 3, 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. +# +# In applying this licence, CERN does not waive the privileges and immunities +# granted to it by virtue of its status as an Intergovernmental Organization or +# submit itself to any jurisdiction. + +usage() { cat <<EOF 1>&2 +Usage: $0 -i <eosinstance> -f <filename> +EOF +exit 1 +} + +while getopts "i:f:" o; do + case "${o}" in + i) + EOSINSTANCE=${OPTARG} + ;; + f) + TEST_FILE_NAME=${OPTARG} + ;; + *) + usage + ;; + esac +done +shift $((OPTIND-1)) + +if [ ! -z "${error}" ]; then + echo -e "ERROR:\n${error}" + exit 1 +fi + +echo "bash eos root://${EOSINSTANCE} rm /eos/ctaeos/cta/${TEST_FILE_NAME}" +eos root://${EOSINSTANCE} rm /eos/ctaeos/cta/${TEST_FILE_NAME} + +SECONDS_PASSED=0 +WAIT_FOR_RETRIEVED_FILE_TIMEOUT=10 +while test true = `xrdfs root://${EOSINSTANCE} query prepare 0 /eos/ctaeos/${TEST_FILE_NAME} | jq . | jq '.responses[0] | .path_exists'`; do + echo "Waiting for file to be deleted from tape: Seconds passed = ${SECONDS_PASSED}" + sleep 1 + let SECONDS_PASSED=SECONDS_PASSED+1 + + if test ${SECONDS_PASSED} == ${WAIT_FOR_RETRIEVED_FILE_TIMEOUT}; then + echo "Timed out after ${WAIT_FOR_RETRIEVED_FILE_TIMEOUT} seconds waiting for file to be deleted" + exit 1 + fi +done diff --git a/continuousintegration/orchestration/tests/restore_files.sh b/continuousintegration/orchestration/tests/restore_files.sh new file mode 100755 index 0000000000..3ab6378cf3 --- /dev/null +++ b/continuousintegration/orchestration/tests/restore_files.sh @@ -0,0 +1,180 @@ +#!/bin/bash + +# @project The CERN Tape Archive (CTA) +# @copyright Copyright © 2022 CERN +# @license This program is free software, distributed under the terms of the GNU General Public +# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". You can +# redistribute it and/or modify it under the terms of the GPL Version 3, 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. +# +# In applying this licence, CERN does not waive the privileges and immunities +# granted to it by virtue of its status as an Intergovernmental Organization or +# submit itself to any jurisdiction. + +EOSINSTANCE=ctaeos +LOGFILE_PATH=/var/log/restore_files.log +TEST_FILE_NAME=`uuidgen` +WAIT_FOR_RETRIEVED_FILE_TIMEOUT=10 + +usage() { cat <<EOF 1>&2 +Usage: $0 -n <namespace> +EOF +exit 1 +} + +while getopts "n:" o; do + case "${o}" in + n) + NAMESPACE=${OPTARG} + ;; + *) + usage + ;; + esac +done +shift $((OPTIND-1)) + +if [ -z "${NAMESPACE}" ]; then + usage +fi + +if [ ! -z "${error}" ]; then + echo -e "ERROR:\n${error}" + exit 1 +fi + +FRONTEND_IP=$(kubectl -n ${NAMESPACE} get pods ctafrontend -o json | jq .status.podIP | tr -d '"') + +echo +echo "ADD FRONTEND GATEWAY TO EOS" +echo "kubectl -n ${NAMESPACE} exec ctaeos -- bash eos root://${EOSINSTANCE} -r 0 0 vid add gateway ${FRONTEND_IP} grpc" +kubectl -n ${NAMESPACE} exec ctaeos -- eos -r 0 0 vid add gateway ${FRONTEND_IP} grpc +eos vid set map -grpc key:<your key aks any uuid string> vuid:2 vgid:2 + +echo +echo "eos vid ls" +kubectl -n ${NAMESPACE} exec ctaeos -- eos root://${EOSINSTANCE} vid ls + +echo +echo "Launching restore_files_client.sh on client pod" +echo " Archiving file: xrdcp as user1" +kubectl -n ${NAMESPACE} cp common/archive_file.sh client:/root/archive_file.sh +kubectl -n ${NAMESPACE} cp client_helper.sh client:/root/client_helper.sh +kubectl -n ${NAMESPACE} exec client -- bash /root/archive_file.sh -n ${TEST_FILE_NAME} || exit 1 + +echo +METADATA_FILE_PATH=$(mktemp -d).json +echo "SEND FILE METADATA TO JSON FILE: ${METADATA_FILE_PATH}" +touch ${METADATA_FILE_PATH} +kubectl -n ${NAMESPACE} exec client -- eos -j root://${EOSINSTANCE} file info /eos/ctaeos/cta/${TEST_FILE_NAME} | jq . > ${METADATA_FILE_PATH} + +# Extract values from the meta data used for restoring and testing +FXID=$(jq -r '.fxid' ${METADATA_FILE_PATH}) +FILE_SIZE=$(jq -r '.size' ${METADATA_FILE_PATH}) +ARCHIVE_FILE_ID=$(jq -r '.xattr | .["sys.archive.file_id"]' ${METADATA_FILE_PATH}) +CHECKSUM=$(jq -r '.checksumvalue' ${METADATA_FILE_PATH}) + +echo +echo "DELETE ARCHIVED FILE" +kubectl -n ${NAMESPACE} cp common/delete_file.sh client:/root/delete_file.sh +kubectl -n ${NAMESPACE} exec client -- bash /root/delete_file.sh -i ${EOSINSTANCE} -f ${TEST_FILE_NAME} + +echo +echo "VALIDATE THAT THE FILE IS IN THE RECYCLE BIN" +echo "kubectl -n ${NAMESPACE} exec ctacli -- cta-admin rtf ls --fxid ${FXID} || exit 1" +kubectl -n ${NAMESPACE} exec ctacli -- cta-admin rtf ls --fxid ${FXID} || exit 1 + +echo +echo "COPY REQUIRED FILES TO FRONTEND POD" +echo "sudo kubectl cp ${NAMESPACE}/ctacli:/etc/cta/cta-cli.conf /etc/cta/cta-cli.conf" +echo "sudo kubectl cp /etc/cta/cta-cli.conf ${NAMESPACE}/ctafrontend:/etc/cta/cta-cli.conf" +sudo kubectl cp ${NAMESPACE}/ctacli:/etc/cta/cta-cli.conf /etc/cta/cta-cli.conf +sudo kubectl cp /etc/cta/cta-cli.conf ${NAMESPACE}/ctafrontend:/etc/cta/cta-cli.conf + +echo +echo "ENABLE CTAFRONTEND TO EXECUTE CTA ADMIN COMMANDS" +kubectl -n ${NAMESPACE} exec ctacli -- cta-admin admin add --username ctafrontend --comment "for restore files test" +kubectl -n ${NAMESPACE} exec ctacli -- cta-admin admin add --username ctaeos --comment "for restore files test" + +echo +echo "RESTORE FILES" +kubectl -n ${NAMESPACE} cp client_helper.sh ctafrontend:/root/client_helper.sh +kubectl cp ~/CTA-build/cmdline/standalone_cli_tools/restore_files/cta-restore-deleted-files ${NAMESPACE}/ctafrontend:/usr/bin/cta-restore-deleted-files +kubectl cp restore_files_ctafrontend.sh ${NAMESPACE}/ctafrontend:/root/restore_files_ctafrontend.sh +kubectl -n ${NAMESPACE} exec ctafrontend -- chmod +x /root/restore_files_ctafrontend.sh +kubectl -n ${NAMESPACE} exec ctafrontend -- bash -c "XrdSecPROTOCOL=sss XrdSecSSSKT=/etc/cta/eos.sss.keytab /root/restore_files_ctafrontend.sh -I ${ARCHIVE_FILE_ID} -f ${TEST_FILE_NAME} -i ${EOSINSTANCE}" + +SECONDS_PASSED=0 +WAIT_FOR_RETRIEVED_FILE_TIMEOUT=10 +while kubectl -n ${NAMESPACE} exec client -- test `false = xrdfs root://${EOSINSTANCE} query prepare 0 /eos/ctaeos/cta/${TEST_FILE_NAME} | jq . | jq '.responses[0] | .path_exists'`; do + echo "Waiting for file with name:${TEST_FILE_NAME} to be restored on EOS side: Seconds passed = ${SECONDS_PASSED}" + sleep 1 + let SECONDS_PASSED=SECONDS_PASSED+1 + + if test ${SECONDS_PASSED} == ${WAIT_FOR_RETRIEVED_FILE_TIMEOUT}; then + echo "Timed out after ${WAIT_FOR_RETRIEVED_FILE_TIMEOUT} seconds waiting for file to be restored at EOS side" + exit 1 + fi +done + +echo +METADATA_FILE_AFTER_RESTORE_PATH=$(mktemp -d).json +echo "SEND FILE METADATA TO JSON FILE: ${METADATA_FILE_AFTER_RESTORE_PATH}" +touch ${METADATA_FILE_AFTER_RESTORE_PATH} +kubectl -n ${NAMESPACE} exec ctacli -- cta-admin --json tf ls --id ${ARCHIVE_FILE_ID} --instance ${EOSINSTANCE} | jq '.[0]' |& tee ${METADATA_FILE_AFTER_RESTORE_PATH} +kubectl -n ${NAMESPACE} exec ctacli -- cta-admin --json tf ls --id ${ARCHIVE_FILE_ID} --instance ${EOSINSTANCE} | jq '.[0]' | sudo tee -a ${LOGFILE_PATH} + +# Extract values from the meta data from the restored file +FILE_SIZE_AFTER_RESTORE=$(jq -r '.af | .["size"]' ${METADATA_FILE_AFTER_RESTORE_PATH}) +ARCHIVE_FILE_ID_AFTER_RESTORE=$(jq -r '.af | .["archiveId"]' ${METADATA_FILE_AFTER_RESTORE_PATH}) +CHECKSUM_AFTER_RESTORE=$(jq -r '.af | .checksum[0] | .["value"]' ${METADATA_FILE_AFTER_RESTORE_PATH}) +FXID_AFTER_RESTORE=$(jq -r '.df | .["diskId"]' ${METADATA_FILE_AFTER_RESTORE_PATH}) + +EOS_METADATA_AFTER_RESTORE_PATH=$(mktemp -d).json +echo "SEND EOS METADATA TO JSON FILE: ${EOS_METADATA_AFTER_RESTORE_PATH}" +touch ${EOS_METADATA_AFTER_RESTORE_PATH} +kubectl -n ${NAMESPACE} exec client -- eos -j root://${EOSINSTANCE} file info /eos/ctaeos/cta/${TEST_FILE_NAME} | jq . |& tee ${EOS_METADATA_AFTER_RESTORE_PATH} +kubectl -n ${NAMESPACE} exec client -- eos -j root://${EOSINSTANCE} file info /eos/ctaeos/cta/${TEST_FILE_NAME} | jq . | sudo tee -a ${LOGFILE_PATH} + +EOS_NS_FXID_AFTER_RESTORE=$(jq -r '.fxid' ${EOS_METADATA_AFTER_RESTORE_PATH}) +EOS_NS_FXID_AFTER_RESTORE_DEC=$(( 16#$EOS_NS_FXID_AFTER_RESTORE )) + +if test ${CHECKSUM} != ${CHECKSUM_AFTER_RESTORE}; then + echo "ERROR: Checksum for original file and restored file does match" + exit 1 +fi + +if test ${ARCHIVE_FILE_ID} != ${ARCHIVE_FILE_ID_AFTER_RESTORE}; then + echo "ERROR: archive file id for original file and restored file does match" + exit 1 +fi + +if test ${FILE_SIZE} != ${FILE_SIZE_AFTER_RESTORE}; then + echo "ERROR: file size for original file and restored file does match" + exit 1 +fi + +echo "CTA fxid: ${FXID_AFTER_RESTORE}" +echo "EOS fxid: ${EOS_NS_FXID_AFTER_RESTORE_DEC}" +if test ${FXID_AFTER_RESTORE} != ${EOS_NS_FXID_AFTER_RESTORE_DEC}; then + echo "ERROR: fxid does not match in EOS and CTA" + echo "${FXID_AFTER_RESTORE} does not match ${EOS_NS_FXID_AFTER_RESTORE_DEC}" + exit 1 +fi + +echo +echo "ALL TESTS PASSED FOR cta-restore-deleted-files" + +echo +echo "CLEAN UP TEMPORARY FILES AND REMOVE TEMPORARY CTA ADMIN ACCESS" +echo "kubectl -n ${NAMESPACE} exec ctacli -- cta-admin admin rm --username ctafrontend" +echo "kubectl -n ${NAMESPACE} exec ctacli -- cta-admin admin rm --username ctaeos" +sudo rm ${METADATA_FILE_AFTER_RESTORE_PATH} +sudo rm ${METADATA_FILE_PATH} +sudo rm ${EOS_METADATA_AFTER_RESTORE_PATH} +kubectl -n ${NAMESPACE} exec ctacli -- cta-admin admin rm --username ctafrontend +kubectl -n ${NAMESPACE} exec ctacli -- cta-admin admin rm --username ctaeos diff --git a/continuousintegration/orchestration/tests/restore_files_ctafrontend.sh b/continuousintegration/orchestration/tests/restore_files_ctafrontend.sh new file mode 100644 index 0000000000..5b581cc818 --- /dev/null +++ b/continuousintegration/orchestration/tests/restore_files_ctafrontend.sh @@ -0,0 +1,57 @@ +#!/bin/bash + +# @project The CERN Tape Archive (CTA) +# @copyright Copyright © 2022 CERN +# @license This program is free software, distributed under the terms of the GNU General Public +# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". You can +# redistribute it and/or modify it under the terms of the GPL Version 3, 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. +# +# In applying this licence, CERN does not waive the privileges and immunities +# granted to it by virtue of its status as an Intergovernmental Organization or +# submit itself to any jurisdiction. + +EOSINSTANCE=ctaeos + +usage() { cat <<EOF 1>&2 +Usage: $0 -f <archive_file_id> +EOF +exit 1 +} + +while getopts "I:f:i:" o; do + case "${o}" in + I) + ARCHIVE_FILE_ID=${OPTARG} + ;; + f) + TEST_FILE_NAME=${OPTARG} + ;; + i) + EOSINSTANCE=${OPTARG} + ;; + *) + usage + ;; + esac +done +shift $((OPTIND-1)) + +if [ -z "${ARCHIVE_FILE_ID}" ]; then + usage +fi + +if [ ! -z "${error}" ]; then + echo -e "ERROR:\n${error}" + exit 1 +fi + +echo +echo "RESTORE DELETED FILE" +echo "./cta-restore-deleted-files --id ${ARCHIVE_FILE_ID} --copynb 1 --debug" +chmod +x /usr/bin/cta-restore-deleted-files +./usr/bin/cta-restore-deleted-files --id ${ARCHIVE_FILE_ID} --copynb 1 --debug -- GitLab