Skip to content
Snippets Groups Projects
Commit 2af6c0ed authored by Michael Davis's avatar Michael Davis
Browse files

[cta-admin] Uses XrdSsi Config class to read cta-cli.conf

parent 63704d7b
No related branches found
No related tags found
No related merge requests found
...@@ -32,7 +32,7 @@ include_directories(${CMAKE_BINARY_DIR}/eos_cta ${PROTOBUF3_INCLUDE_DIRS}) ...@@ -32,7 +32,7 @@ include_directories(${CMAKE_BINARY_DIR}/eos_cta ${PROTOBUF3_INCLUDE_DIRS})
# #
# cta-admin <admin_command> is the SSI version of "cta <admin_command>" # cta-admin <admin_command> is the SSI version of "cta <admin_command>"
# #
add_executable(cta-admin CtaAdminCmd.cpp CtaAdminCmdParse.cpp Configuration.cpp) add_executable(cta-admin CtaAdminCmd.cpp CtaAdminCmdParse.cpp)
target_link_libraries(cta-admin XrdSsiPbEosCta XrdSsi-4 XrdSsiLib XrdUtils) target_link_libraries(cta-admin XrdSsiPbEosCta XrdSsi-4 XrdSsiLib XrdUtils)
set_property (TARGET cta-admin APPEND PROPERTY INSTALL_RPATH ${PROTOBUF3_RPATH}) set_property (TARGET cta-admin APPEND PROPERTY INSTALL_RPATH ${PROTOBUF3_RPATH})
...@@ -43,7 +43,7 @@ set_property (TARGET cta-admin APPEND PROPERTY INSTALL_RPATH ${PROTOBUF3_RPATH}) ...@@ -43,7 +43,7 @@ set_property (TARGET cta-admin APPEND PROPERTY INSTALL_RPATH ${PROTOBUF3_RPATH})
# Previously this was the eoscta_stub which was called by a script invoked by the EOS WFE. # Previously this was the eoscta_stub which was called by a script invoked by the EOS WFE.
# #
find_package(cryptopp REQUIRED) find_package(cryptopp REQUIRED)
add_executable(cta-wfe-test EosCtaStub.cpp Configuration.cpp) add_executable(cta-wfe-test EosCtaStub.cpp)
target_link_libraries(cta-wfe-test cryptopp ctacommon XrdSsiPbEosCta XrdSsi-4 XrdSsiLib XrdUtils) target_link_libraries(cta-wfe-test cryptopp ctacommon XrdSsiPbEosCta XrdSsi-4 XrdSsiLib XrdUtils)
set_property (TARGET cta-wfe-test APPEND PROPERTY INSTALL_RPATH ${PROTOBUF3_RPATH}) set_property (TARGET cta-wfe-test APPEND PROPERTY INSTALL_RPATH ${PROTOBUF3_RPATH})
......
/*
* 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 "Configuration.hpp"
#include <fstream>
#include <stdexcept>
#include <exception>
namespace cta {
namespace cmdline {
//------------------------------------------------------------------------------
// s_fileFormat
//------------------------------------------------------------------------------
const char *Configuration::s_fileFormat = "<FQDN>:<port>";
//------------------------------------------------------------------------------
// constructor
//------------------------------------------------------------------------------
Configuration::Configuration(
const std::string &filename):
filename(filename) {
frontendHostAndPort = parseFile(filename);
}
//------------------------------------------------------------------------------
// parseFile
//------------------------------------------------------------------------------
std::string Configuration::parseFile(const std::string &filename) {
try {
std::ifstream file(filename);
if (!file) {
throw std::runtime_error("Failed to open ");
}
return parseStream(file);
} catch(std::exception &ex) {
throw std::runtime_error(std::string("Failed to parse configuration file " +
filename + ": " + ex.what()));
}
}
//------------------------------------------------------------------------------
// parseFile
//------------------------------------------------------------------------------
std::string Configuration::getFrontendHostAndPort() throw() {
return frontendHostAndPort;
}
//------------------------------------------------------------------------------
// parseStream
//------------------------------------------------------------------------------
std::string Configuration::parseStream(std::istream &inputStream) {
const std::list<std::string> lines = readNonEmptyLines(inputStream);
if(1 != lines.size()) {
throw std::runtime_error("There should only be one and only one line "
"containing a frontend hostname and port");
}
const std::string frontendHostAndPort = lines.front();
std::vector<std::string> configurationLine;
splitString(frontendHostAndPort, ' ', configurationLine);
if(1 != configurationLine.size()) {
throw std::runtime_error(std::string("There should not be any space in the "
"host configuration: Correct"
" format is ") + s_fileFormat);
}
std::vector<std::string> components;
splitString(frontendHostAndPort, ':', components);
if(2 != components.size()) {
throw std::runtime_error(std::string("Port not found in the configuration:"
" Correct format is ") + s_fileFormat);
}
const std::string &hostname = components[0];
const std::string &port = components[1];
if(!onlyContainsNumerals(port)) {
throw std::runtime_error(std::string("Port must only contain numerals: "
"value=") + port);
}
if(4 > hostname.length()) {
throw std::runtime_error(std::string("Hostname too short: "
"value=") + hostname);
}
return frontendHostAndPort;
}
//-----------------------------------------------------------------------------
// splitString
//-----------------------------------------------------------------------------
void Configuration::splitString(const std::string &str, const char separator,
std::vector<std::string> &result) {
if(str.empty()) {
return;
}
std::string::size_type beginIndex = 0;
std::string::size_type endIndex = str.find(separator);
while(endIndex != std::string::npos) {
result.push_back(str.substr(beginIndex, endIndex - beginIndex));
beginIndex = ++endIndex;
endIndex = str.find(separator, endIndex);
}
// If no separator could not be found then simply append the whole input
// string to the result
if(endIndex == std::string::npos) {
result.push_back(str.substr(beginIndex, str.length()));
}
}
//------------------------------------------------------------------------------
// onlyContainsNumerals
//------------------------------------------------------------------------------
bool Configuration::onlyContainsNumerals(const std::string &str) throw() {
for(std::string::const_iterator itor = str.begin(); itor != str.end();
itor++) {
if(*itor < '0' || *itor > '9') {
return false;
}
}
return true;
}
//-----------------------------------------------------------------------------
// trimString
//-----------------------------------------------------------------------------
std::string Configuration::trimString(const std::string &s) throw() {
const std::string& spaces="\t\n\v\f\r ";
// Find first non white character
size_t beginpos = s.find_first_not_of(spaces);
std::string::const_iterator it1;
if (std::string::npos != beginpos) {
it1 = beginpos + s.begin();
} else {
it1 = s.begin();
}
// Find last non white chararacter
std::string::const_iterator it2;
size_t endpos = s.find_last_not_of(spaces);
if (std::string::npos != endpos) {
it2 = endpos + 1 + s.begin();
} else {
it2 = s.end();
}
return std::string(it1, it2);
}
//------------------------------------------------------------------------------
// readNonEmptyLines
//------------------------------------------------------------------------------
std::list<std::string> Configuration::readNonEmptyLines(std::istream &inputStream) {
std::list<std::string> lines;
std::string line;
while(std::getline(inputStream, line)) {
// Remove the newline character if there is one
{
const std::string::size_type newlinePos = line.find("\n");
if(newlinePos != std::string::npos) {
line = line.substr(0, newlinePos);
}
}
// If there is a comment, then remove it from the line
{
const std::string::size_type startOfComment = line.find("#");
if(startOfComment != std::string::npos) {
line = line.substr(0, startOfComment);
}
}
// Left and right trim the line of whitespace
line = Configuration::trimString(std::string(line));
// If the line is not empty
if(!line.empty()) {
lines.push_back(line);
}
}
return lines;
}
} // namesapce cmdline
} // namespace cta
/*
* 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 <istream>
#include <list>
#include <string>
#include <vector>
namespace cta {
namespace cmdline {
/**
* A set of configuration details.
*/
class Configuration {
public:
/**
* Constructor.
*
* @param filename The configuration file name.
*/
Configuration(const std::string &filename);
private:
/**
* The frontend hostname and port to connect.
*/
std::string frontendHostAndPort;
/**
* The configuration file name.
*/
const std::string filename;
/**
* Reads and parses the configuration information from the specified file.
*
* The input stream must contain one and only one configuration string.
*
* The format of the configuration string is:
*
* <host>.cern.ch:<port>
*
* The file can contain multiple empty lines.
*
* The file can contain multiple comment lines where a comment
* line starts with optional whitespace and a hash character '#'.
*
* @param filename The name of the file containing the configuration
* information.
* @return The configuration information.
*/
std::string parseFile(const std::string &filename);
/**
* Reads and parses the configuration information from the specified file.
*
* The input stream must contain one and only one configuration string.
*
* The format of the configuration string is:
*
* <host>.cern.ch:<port>
*
* The file can contain multiple empty lines.
*
* The file can contain multiple comment lines where a comment
* line starts with optional whitespace and a hash character '#'.
*
* @param filename The name of the file containing the configuration
* information.
* @return The configuration information.
*/
std::string parseStream(std::istream &inputStream);
/**
* Reads the entire contents of the specified stream and returns a list of the
* non-empty lines.
*
* A line is considered not empty if it contains characters that are not white
* space and are not part of a comment.
*
* @param is The input stream.
* @return A list of the non-empty lines.
*/
std::list<std::string> readNonEmptyLines(std::istream &inputStream);
/**
* Returns the result of trimming both left and right white-space from the
* specified string.
*
* @param s The string to be trimmed.
* @return The result of trimming the string.
*/
std::string trimString(const std::string &s) throw();
/**
* Splits the specified string into a vector of strings using the specified
* separator.
*
* Please note that the string to be split is NOT modified.
*
* @param str The string to be split.
* @param separator The separator to be used to split the specified string.
* @param result The vector when the result of spliting the string will be
* stored.
*/
void splitString(const std::string &str, const char separator, std::vector<std::string> &result);
/**
* Returns true if the specified string only contains numerals else false.
*
* @return True if the specified string only contains numerals else false.
*/
static bool onlyContainsNumerals(const std::string &str) throw();
/**
* Human readable description of the format of the database
* login/configuration file.
*/
static const char *s_fileFormat;
public:
/**
* Returns the value of the configuration parameters.
*
* @return The frontend host and port from the configuration.
*/
std::string getFrontendHostAndPort() throw();
}; // class Configuration
} // namespace cmdline
} // namespace cta
...@@ -24,7 +24,6 @@ ...@@ -24,7 +24,6 @@
#include <XrdSsiPbLog.hpp> #include <XrdSsiPbLog.hpp>
#include <XrdSsiPbIStreamBuffer.hpp> #include <XrdSsiPbIStreamBuffer.hpp>
#include "cmdline/Configuration.hpp"
#include "CtaAdminCmd.hpp" #include "CtaAdminCmd.hpp"
...@@ -147,15 +146,14 @@ void CtaAdminCmd::send() const ...@@ -147,15 +146,14 @@ void CtaAdminCmd::send() const
throwUsage(ex.what()); throwUsage(ex.what());
} }
// Get socket address of CTA Frontend endpoint
cta::cmdline::Configuration cliConf("/etc/cta/cta-cli.conf");
std::string endpoint = cliConf.getFrontendHostAndPort();
// Set configuration options // Set configuration options
XrdSsiPb::Config config; XrdSsiPb::Config config("/etc/cta/cta-cli.conf", "cta");
config.set("resource", "/ctafrontend");
config.set("response_bufsize", StreamBufferSize); // default value = 1024 bytes config.set("response_bufsize", StreamBufferSize); // default value = 1024 bytes
config.set("request_timeout", DefaultRequestTimeout); // default value = 10s config.set("request_timeout", DefaultRequestTimeout); // default value = 10s
config.getEnv("request_timeout", "XRD_REQUESTTIMEOUT"); // environment variable can override default
// Allow environment variables to override config file
config.getEnv("request_timeout", "XRD_REQUESTTIMEOUT");
// If XRDDEBUG=1, switch on all logging // If XRDDEBUG=1, switch on all logging
if(getenv("XRDDEBUG")) { if(getenv("XRDDEBUG")) {
...@@ -165,7 +163,7 @@ void CtaAdminCmd::send() const ...@@ -165,7 +163,7 @@ void CtaAdminCmd::send() const
config.getEnv("log", "XrdSsiPbLogLevel"); config.getEnv("log", "XrdSsiPbLogLevel");
// Obtain a Service Provider // Obtain a Service Provider
XrdSsiPbServiceType cta_service(endpoint, Resource, config); XrdSsiPbServiceType cta_service(config);
// Send the Request to the Service and get a Response // Send the Request to the Service and get a Response
cta::xrd::Response response; cta::xrd::Response response;
......
...@@ -63,7 +63,6 @@ private: ...@@ -63,7 +63,6 @@ private:
/* /*
* Member variables * Member variables
*/ */
const std::string Resource = "/ctafrontend"; //!< XRootD SSI Resource name
const std::string StreamBufferSize = "1024"; //!< Buffer size for Data/Stream Responses const std::string StreamBufferSize = "1024"; //!< Buffer size for Data/Stream Responses
const std::string DefaultRequestTimeout = "10"; //!< Default Request Timeout. Can be overridden by const std::string DefaultRequestTimeout = "10"; //!< Default Request Timeout. Can be overridden by
//!< XRD_REQUESTTIMEOUT environment variable. //!< XRD_REQUESTTIMEOUT environment variable.
......
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
#include <XrdSsiPbLog.hpp> #include <XrdSsiPbLog.hpp>
#include "common/dataStructures/FrontendReturnCode.hpp" #include "common/dataStructures/FrontendReturnCode.hpp"
#include "cmdline/Configuration.hpp"
#include "CtaFrontendApi.hpp" #include "CtaFrontendApi.hpp"
...@@ -259,13 +258,12 @@ int exceptionThrowingMain(int argc, const char *const *const argv) ...@@ -259,13 +258,12 @@ int exceptionThrowingMain(int argc, const char *const *const argv)
// Parse the command line arguments: fill the Notification fields // Parse the command line arguments: fill the Notification fields
fillNotification(notification, argc, argv); fillNotification(notification, argc, argv);
// Get socket address of CTA Frontend endpoint
cta::cmdline::Configuration cliConf("/etc/cta/cta-cli.conf");
std::string endpoint = cliConf.getFrontendHostAndPort();
// Set configuration options // Set configuration options
XrdSsiPb::Config config; XrdSsiPb::Config config("/etc/cta/cta-cli.conf", "cta");
config.getEnv("request_timeout", "XRD_REQUESTTIMEOUT"); // environment variable can override default config.set("resource", "/ctafrontend");
// Allow environment variables to override config file
config.getEnv("request_timeout", "XRD_REQUESTTIMEOUT");
// If XRDDEBUG=1, switch on all logging // If XRDDEBUG=1, switch on all logging
if(getenv("XRDDEBUG")) { if(getenv("XRDDEBUG")) {
...@@ -275,8 +273,7 @@ int exceptionThrowingMain(int argc, const char *const *const argv) ...@@ -275,8 +273,7 @@ int exceptionThrowingMain(int argc, const char *const *const argv)
config.getEnv("log", "XrdSsiPbLogLevel"); config.getEnv("log", "XrdSsiPbLogLevel");
// Obtain a Service Provider // Obtain a Service Provider
std::string resource("/ctafrontend"); XrdSsiPbServiceType cta_service(config);
XrdSsiPbServiceType cta_service(endpoint, resource);
// Send the Request to the Service and get a Response // Send the Request to the Service and get a Response
cta::xrd::Response response; cta::xrd::Response response;
......
# The CTA frontend address in the form <FQDN>:<TCPPort> # The CTA frontend address in the form <FQDN>:<TCPPort>
<host>.cern.ch:10955 cta.endpoint <host>.cern.ch:10955
Subproject commit ceb96f82573becd825370fed391eae0b0bcf2dc5 Subproject commit 8251f8652a956ec7df6e51e853aeeebf1d333ea0
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment