Commit 5c694a9f authored by mvelosob's avatar mvelosob Committed by Miguel Barros
Browse files

#407 - Pass configuration parameters as command line options to cta-verify-file

cta-verify-file command now gets instance, request.user and request.group from the command line instead of /etc/cta/cta-cli.conf
parent f89b48dc
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "CtaFrontendApi.hpp" #include "CtaFrontendApi.hpp"
#include "version.h" #include "version.h"
#include "CtaVerifyFile.hpp"
const std::string config_file = "/etc/cta/cta-cli.conf"; const std::string config_file = "/etc/cta/cta-cli.conf";
...@@ -43,51 +44,89 @@ void RequestCallback<cta::xrd::Alert>::operator()(const cta::xrd::Alert &alert) ...@@ -43,51 +44,89 @@ void RequestCallback<cta::xrd::Alert>::operator()(const cta::xrd::Alert &alert)
typedef std::map<std::string, std::string> AttrMap; typedef std::map<std::string, std::string> AttrMap;
// Usage exception // Usage exception
const std::runtime_error Usage("Usage: cta-verify-file archiveFileID [vid]"); 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>");
VerifyOption option_instance {"--instance", "-i", false};
VerifyOption option_request_user {"--request.user", "-r.user", false};
VerifyOption option_request_group {"--request.group", "-r.group", false};
VerifyOption option_vid {"--vid", "-v", true};
std::vector<VerifyOption*> verify_options = {&option_instance, &option_request_user, &option_request_group, &option_vid};
void validate_cmd()
{
for (auto &option: verify_options) {
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) {
bool matches = false;
for (auto &option: verify_options) {
if (*option == argv[i]) {
option->set_present();
option->set_value(argv[i + 1]);
matches = true;
break;
}
}
if (!matches) {
std::cout << "Error: Unknown option: " << argv[i] << std::endl;
throw Usage;
}
}
}
/* /*
* Fill a Notification message from the command-line parameters and stdin * Fill a Notification message from the command-line parameters and stdin
* *
* @param[out] notification The protobuf to fill * @param[out] notification The protobuf to fill
* @param[in] config The XrdSsiPb object containing the configuration parameters * @param[in] argc Number of arguments passed on the command line
* @param[in] archiveFileId The ID of the file to retrieve * @param[in] argv Command line arguments array
* @param[in] vid If non-empty, restrict PREPARE requests to this tape only
*/ */
void fillNotification(cta::eos::Notification &notification, const std::string &archiveFileId, const std::string &vid) void fillNotification(cta::eos::Notification &notification, const int argc, const char *const *const argv)
{ {
XrdSsiPb::Config config(config_file, "eos"); parse_cmd(argc, argv);
validate_cmd();
// WF std::string archiveFileId(argv[1]);
notification.mutable_wf()->set_event(cta::eos::Workflow::PREPARE);
for(auto &conf_option : std::vector<std::string>({ "instance", "requester.user", "requester.group" })) { // WF
if(!config.getOptionValueStr(conf_option).first) { notification.mutable_wf()->set_event(cta::eos::Workflow::PREPARE);
throw std::runtime_error(conf_option + " must be specified in " + config_file);
}
}
notification.mutable_wf()->mutable_instance()->set_name(config.getOptionValueStr("instance").second);
notification.mutable_wf()->set_requester_instance("cta-verify-file");
notification.mutable_wf()->set_verify_only(true);
notification.mutable_wf()->set_vid(vid);
// CLI notification.mutable_wf()->mutable_instance()->set_name(option_instance.get_value());
notification.mutable_cli()->mutable_user()->set_username(config.getOptionValueStr("requester.user").second); notification.mutable_wf()->set_requester_instance("cta-verify-file");
notification.mutable_cli()->mutable_user()->set_groupname(config.getOptionValueStr("requester.group").second); notification.mutable_wf()->set_verify_only(true);
notification.mutable_wf()->set_vid(option_vid.get_value());
// Transport // CLI
notification.mutable_transport()->set_dst_url("file://dummy"); notification.mutable_cli()->mutable_user()->set_username(option_request_user.get_value());
notification.mutable_cli()->mutable_user()->set_groupname(option_request_group.get_value());
// File // Transport
notification.mutable_file()->set_lpath("dummy"); notification.mutable_transport()->set_dst_url("file://dummy");
// eXtended attributes // File
AttrMap xattrs; notification.mutable_file()->set_lpath("dummy");
xattrs["sys.archive.file_id"] = archiveFileId;
for(auto &xattr : xattrs) { // eXtended attributes
google::protobuf::MapPair<std::string,std::string> mp(xattr.first, xattr.second); AttrMap xattrs;
notification.mutable_file()->mutable_xattr()->insert(mp); xattrs["sys.archive.file_id"] = archiveFileId;
}
for(auto &xattr : xattrs) {
google::protobuf::MapPair<std::string,std::string> mp(xattr.first, xattr.second);
notification.mutable_file()->mutable_xattr()->insert(mp);
}
} }
...@@ -98,9 +137,7 @@ int exceptionThrowingMain(int argc, const char *const *const argv) ...@@ -98,9 +137,7 @@ int exceptionThrowingMain(int argc, const char *const *const argv)
{ {
std::string vid; std::string vid;
if(argc == 3) { if(argc < 6 || argc % 2) { // Since all options need values associated, argc should always be even
vid = argv[2];
} else if(argc != 2) {
throw Usage; throw Usage;
} }
...@@ -129,7 +166,7 @@ int exceptionThrowingMain(int argc, const char *const *const argv) ...@@ -129,7 +166,7 @@ int exceptionThrowingMain(int argc, const char *const *const argv)
config.getEnv("log", "XrdSsiPbLogLevel"); config.getEnv("log", "XrdSsiPbLogLevel");
// Parse the command line arguments: fill the Notification fields // Parse the command line arguments: fill the Notification fields
fillNotification(notification, argv[1], vid); fillNotification(notification, argc, argv);
// Obtain a Service Provider // Obtain a Service Provider
XrdSsiPbServiceType cta_service(config); XrdSsiPbServiceType cta_service(config);
...@@ -162,7 +199,7 @@ int exceptionThrowingMain(int argc, const char *const *const argv) ...@@ -162,7 +199,7 @@ int exceptionThrowingMain(int argc, const char *const *const argv)
*/ */
int main(int argc, const char **argv) int main(int argc, const char **argv)
{ {
try { try {
return exceptionThrowingMain(argc, argv); return exceptionThrowingMain(argc, argv);
} catch (XrdSsiPb::PbException &ex) { } catch (XrdSsiPb::PbException &ex) {
std::cerr << "Error in Google Protocol Buffers: " << ex.what() << std::endl; std::cerr << "Error in Google Protocol Buffers: " << ex.what() << std::endl;
......
/*
* @project The CERN Tape Archive (CTA)
* @copyright Copyright(C) 2015-2021 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
/*!
* Simple command line option class for the verification command
*/
class VerifyOption {
public:
/*!
* Constructor
*/
VerifyOption(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
};
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment