Commit 41570ec8 authored by Anastasia Karachaliou's avatar Anastasia Karachaliou
Browse files

Added XRootdSSiRmcd subdirectory

parent 09b1271f
......@@ -147,6 +147,7 @@ ELSE(DEFINED PackageOnly)
add_subdirectory(rdbms)
add_subdirectory(scheduler)
add_subdirectory(tapeserver)
add_subdirectory(XRootdSSiRmcd)
#Generate version information
configure_file(${PROJECT_SOURCE_DIR}/version.hpp.in
......
# XRootD SSI/Protocol Buffer Interface Project
# Copyright 2018 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/>.
cmake_minimum_required (VERSION 2.6)
find_package(xrootdclient REQUIRED)
find_package(xrootd REQUIRED)
find_package(Protobuf3 REQUIRED)
add_subdirectory(protobuf)
#
# XRootD SSI
#
include_directories(${XROOTD_INCLUDE_DIR} ${XROOTD_INCLUDE_DIR}/private)
#
# XRootD SSI Protocol Buffer bindings
#
include_directories(${CMAKE_SOURCE_DIR}/)
include_directories (${CMAKE_SOURCE_DIR}/xrootd-ssi-protobuf-interface/include)
#
# Compiled protocol buffers
#
include_directories(${CMAKE_BINARY_DIR}/XRootdSSiRmcd ${PROTOBUF3_INCLUDE_DIRS})
#
# Test Client
#
add_executable(cta-xsmc RmcdClient.cpp)
target_link_libraries(cta-xsmc XrdSsi-4 XrdSsiLib XrdSsiPbRmcd XrdUtils)
set_property(TARGET cta-xsmc APPEND PROPERTY INSTALL_RPATH ${PROTOBUF3_RPATH})
install (TARGETS cta-xsmc DESTINATION /usr/bin)
install (FILES cta-xsmc-mount.1cta DESTINATION /usr/share/man/man1)
install (FILES cta-xsmc-dismount.1cta DESTINATION /usr/share/man/man1)
#
# XRootD SSI plugin for Test Server
#
add_library(XrdSsiRmcd MODULE
RmcdServiceProvider.cpp
RmcdRequestProc.cpp
rmc_send_scsi_cmd.cpp
serrno.cpp
rmc_smcsubr.cpp
)
target_link_libraries(XrdSsiRmcd XrdSsi-4 XrdSsiLib XrdSsiPbRmcd XrdUtils)
set_property(TARGET XrdSsiRmcd APPEND PROPERTY INSTALL_RPATH ${PROTOBUF3_RPATH})
install(TARGETS XrdSsiRmcd DESTINATION usr/${CMAKE_INSTALL_LIBDIR})
install (FILES cta-xrmcd.conf DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/cta)
install (FILES cta-xrmcd.logrotate DESTINATION /etc/logrotate.d RENAME cta-xrmcd)
install (FILES cta-xrmcd.sysconfig DESTINATION /etc/sysconfig RENAME cta-xrmcd)
install (FILES cta-xrmcd.service DESTINATION /etc/systemd/system)
/*
* Castor_limits.h,v 1.27 2004/02/12 15:38:08 obarring Exp
*/
/*
* Copyright (C) 1999-2003 by CERN/IT/PDP/DM
* All rights reserved
*/
/*
* @(#)Castor_limits.h,v 1.27 2004/02/12 15:38:08 CERN IT-PDP/DM Jean-Philippe Baud
*/
#pragma once
/* all maximum lengths defined below do not include the trailing null */
#define CA_MAXACLENTRIES 300 /* maximum number of ACL entries for a file/dir */
#define CA_MAXCLASNAMELEN 15 /* maximum length for a fileclass name */
#define CA_MAXCOMMENTLEN 255 /* maximum length for user comments in metadata */
#define CA_MAXDENLEN 8 /* maximum length for a alphanumeric density */
#define CA_MAXDGNLEN 6 /* maximum length for a device group name */
#define CA_MAXDVNLEN 63 /* maximum length for a device name */
#define CA_MAXDVTLEN 8 /* maximum length for a device type */
#define CA_MAXFIDLEN 17 /* maximum length for a fid (DSN) */
#define CA_MAXFSEQLEN 14 /* maximum length for a fseq string */
#define CA_MAXGRPNAMELEN 2 /* maximum length for a group name */
#define CA_MAXGUIDLEN 36 /* maximum length for a guid */
#define CA_MAXHOSTNAMELEN 63 /* maximum length for a hostname */
#define CA_MAXSVCCLASSNAMELEN 63 /* maximum length for a svc class name */
#define CA_MAXLBLTYPLEN 3 /* maximum length for a label type */
#define CA_MAXLINELEN 1023 /* maximum length for a line in a log */
#define CA_MAXMANUFLEN 12 /* maximum length for a cartridge manufacturer */
#define CA_MAXMIGPNAMELEN 15 /* maximum length for a migration policy name */
#define CA_MAXMIGRNAMELEN 15 /* maximum length for a migrator name */
#define CA_MAXMLLEN 1 /* maximum length for a cartridge media_letter */
#define CA_MAXMODELLEN 6 /* maximum length for a cartridge model */
#define CA_MAXNAMELEN 255 /* maximum length for a pathname component */
#define CA_MAXNBDRIVES 4 /* maximum number of tape drives per server */
#define CA_MAXPATHLEN 1023 /* maximum length for a pathname */
#define CA_MAXPOOLNAMELEN 15 /* maximum length for a pool name */
#define CA_MAXPROTOLEN 7 /* maximum length for a protocol name */
#define CA_MAXRBTNAMELEN 17 /* maximum length for a robot name */
#define CA_MAXRECFMLEN 3 /* maximum length for a record format */
#define CA_MAXREGEXPLEN 63 /* Maximum length for a regular expression */
#define CA_MAXCSECNAMELEN 512 /* Maximum length for a Csec authorization id */
#define CA_MAXCSECPROTOLEN 20 /* Maximum length for a Csec mechanism */
#define CA_MAXSFNLEN 1103 /* maximum length for a replica */
#define CA_MAXSHORTHOSTLEN 10 /* maximum length for a hostname without domain */
#define CA_MAXSNLEN 24 /* maximum length for a cartridge serial nb */
#define CA_MAXSTGRIDLEN 77 /* maximum length for a stager full request id */
/* must be >= nb digits in CA_MAXSTGREQID +
CA_MAXHOSTNAMELEN + 8 */
#define CA_MAXSTGREQID 999999 /* maximum value for a stager request id */
#define CA_MAXSYMLINKS 5 /* maximum number of symbolic links */
#define CA_MAXTAGLEN 255 /* maximum length for a volume tag */
#define CA_MAXTAPELIBLEN 8 /* maximum length for a tape library name */
#define CA_MAXUNMLEN 8 /* maximum length for a drive name */
#define CA_MAXUSRNAMELEN 14 /* maximum length for a login name */
#define CA_MAXVIDLEN 6 /* maximum length for a VID */
#define CA_MAXVSNLEN 6 /* maximum length for a VSN */
#define CA_MAXCKSUMNAMELEN 15 /* maximum length for a checksum algorithm name */
#define CA_MAXCKSUMLEN 32 /* maximum length for a checksum value in an asci form */
#define CA_MAXDMPROTNAMELEN 15 /* maximum length for Disk Mover protocol name */
#define CA_MAXJOBIDLEN 36 /* Maximum length for the representation of the Cuuid */
#define CA_MAXUSERTAGLEN 63 /* Maximum length for a user tag (stage request) */
#define CA_MAXRFSLINELEN 2047 /* maximum length for the requested filesystem string */
/* Max allowed uid/gif */
#define CA_MAXUID 0x7FFFFFFF /* Maximum uid */
#define CA_MAXGID 0x7FFFFFFF /* Maximum gid */
/*!
* @project XRootD SSI/Protocol Buffer Interface Project
* @brief XRootD SSI/Google Protocol Buffer bindings for the rmc_test client/server
* @copyright Copyright 2018 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 "XrdSsiPbServiceClientSide.hpp" //!< XRootD SSI/Protocol Buffer Service, client-side bindings
#include "protobuf/rmc_test.pb.h" //!< Auto-generated message types from .proto file
/*!
* Bind the type of the XrdSsiService to the types defined in the .proto file
*/
typedef XrdSsiPb::ServiceClientSide<rmc_test::Request, //!< XrdSSi Request message type
rmc_test::Response, //!< XrdSsi Metadata message type
rmc_test::Data, //!< XrdSsi Data message type
rmc_test::Alert> //!< XrdSsi Alert message type
XrdSsiPbServiceType;
/*!
* Bind the type of the XrdSsiRequest to the types defined in the .proto file
*/
typedef XrdSsiPb::Request<rmc_test::Request, //!< XrdSSi Request message type
rmc_test::Response, //!< XrdSsi Metadata message type
rmc_test::Data, //!< XrdSsi Data message type
rmc_test::Alert> //!< XrdSsi Alert message type
XrdSsiPbRequestType;
/*!
* @project XRootD SSI/Protocol Buffer Interface Project
* @brief Command-line rmc_test client for XRootD SSI/Protocol Buffers
* @copyright Copyright 2018 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/>.
*/
#include <sstream>
#include <iostream>
#include <iomanip>
#include <algorithm>
#include "XrdSsiPbIStreamBuffer.hpp"
#include "RmcdClient.hpp"
#include <getopt.h>
bool is_metadata_done = false;
// note: this implementation does not disable this overload for array types
template<typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args)
{
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
// Define XRootD SSI callbacks
namespace XrdSsiPb {
/*
* Alert callback.
*
* Defines how Alert messages should be logged
*/
template<>
void RequestCallback<rmc_test::Alert>::operator()(const rmc_test::Alert &alert)
{
Log::Msg(Log::INFO, LOG_SUFFIX, "Alert received:");
// Output message in Json format
Log::DumpProtobuf(Log::INFO, &alert);
}
} // namespace XrdSsiPb
//
// RmcdClient implementation
//
const std::string DEFAULT_ENDPOINT = "localhost:10956";
// Change console text colour
const char* const TEXT_RED = "\x1b[31;1m";
const char* const TEXT_NORMAL = "\x1b[0m\n";
// Convert string to bool
bool to_bool(std::string str) {
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
if(str == "true") return true;
if(str == "false") return false;
throw std::runtime_error(str + " is not a valid boolean value");
}
void RmcdClientCmd::throwUsage(const std::string &error_txt) const
{
std::stringstream help;
if(error_txt != "") {
help << m_execname << ": " << error_txt << std::endl << std::endl;
}
help << "Usage:\n"
"\n"
"rmcd-client [cmdOptions]\n"
"Where cmdOptions can be one of those:\n"
"\n"
"\tmount -V vid -D drive_ordinal\n"
"\tdismount\n"
"\timport\n"
"\texport\n"
"\tread_elem [-N nbelem] [-S starting_slot] [-v]\n"
"\tfind_cartridge V [-N nbelem] [-V vid] [-v]\n"
"\tget_geom\n"
"\n";
throw std::runtime_error(help.str());
}
void RmcdClientCmd::mountUsage(const std::string &error_txt) const
{
std::stringstream help;
if(error_txt != "") {
help << m_execname << ": " << error_txt << std::endl << std::endl;
}
help <<"Usage:\n"
"\n"
" mount [options] -V VID -D DRIVE_SLOT\n"
"\n"
"Where:\n"
"\n"
" VID The VID of the volume to be mounted.\n"
" DRIVE_SLOT The slot in the tape library where the drive is located.\n"
" The format of DRIVE_SLOT is as follows:\n"
"\n"
" ACS:LSM:panel:transport\n"
"\n"
"Options:\n"
" -h|--help Print this help message and exit.\n"
"\n"
" -t|--timeout SECONDS Time to wait for the mount to conclude. SECONDS\n"
" must be an integer value greater than 0. The\n"
" default value of SECONDS is "
"\n";
throw std::runtime_error(help.str());
}
void RmcdClientCmd::dismountUsage(const std::string &error_txt) const
{
std::stringstream help;
if(error_txt != "") {
help << m_execname << ": " << error_txt << std::endl << std::endl;
}
help <<"Usage:\n"
"\n"
" dismount [options] -V VID -D DRIVE_SLOT\n"
"\n"
"Where:\n"
"\n"
" VID The VID of the volume to be dismounted.\n"
" DRIVE_SLOT The slot in the tape library where the drive is located.\n"
" The format of DRIVE_SLOT is as follows:\n"
"\n"
" ACS:LSM:panel:transport\n"
"\n"
"Options:\n"
" -h|--help Print this help message and exit.\n"
"\n"
" -t|--timeout SECONDS Time to wait for the dismount to conclude. SECONDS\n"
" must be an integer value greater than 0. The\n"
" default value of SECONDS is "
"\n";
throw std::runtime_error(help.str());
}
RmcdClientCmd::RmcdClientCmd(int argc, char *const *const argv) :
m_execname(argv[0]),
m_endpoint(DEFAULT_ENDPOINT)
{
// Strip path from execname
size_t p = m_execname.find_last_of('/');
if(p != std::string::npos) m_execname.erase(0, p+1);
// Parse the command
if(argc<2) {
RmcdClientCmd::throwUsage("Missing command option");
return;
}
std::string cmdOptions(argv[1]);
if(cmdOptions == "help") {
throwUsage("help");
}
else if(cmdOptions == "mount") {
if(argc==3) {
std::string cmdh(argv[2]);
if(cmdh == "help") {
mountUsage("helping in mount");
return;
}
}
processMount(argc, argv);
} else if(cmdOptions == "dismount") {
if(argc==3) {
std::string cmdh(argv[2]);
if(cmdh == "help") {
dismountUsage("helping in dismount");
return;
}
}
processDismount(argc, argv);
} else {
throwUsage("Unrecognized command: ");
}
// Read environment variables
XrdSsiPb::Config config;
// If XRDDEBUG=1, switch on all logging
if(getenv("XRDDEBUG")) {
config.set("log", "all");
}
// XrdSsiPbLogLevel gives more fine-grained control over log level
config.getEnv("log", "XrdSsiPbLogLevel");
// Default response timeout
config.getEnv("request_timeout", "XRD_REQUESTTIMEOUT");
// Obtain a Service Provider
std::string resource("/rmc_test");
m_rmc_test_service_ptr = make_unique<XrdSsiPbServiceType>(m_endpoint, resource, config);
}
void RmcdClientCmd::processMount(int argc, char *const *const argv) {
int errflg = 0;
int drvord = -1;
int n;
char vid[7];
char *dp;
char c=0;
static struct option longopts[] = {
{ "help", no_argument, NULL, 'h'},
{ "Vid", required_argument, NULL, 'V'},
{ "Drive_original", required_argument, NULL, 'D' },
{ NULL, 0, NULL, '\0' }
};
memset (vid, '\0', sizeof(vid));
if (argc<6) {
RmcdClientCmd::mountUsage("less arguments provided");
return;
}
if(*argv[2]!= '-') {
RmcdClientCmd::mountUsage("Unrecognised command format given\n");
}
while ((c = getopt_long(argc, argv, "hV:D:",longopts, NULL))!= -1) {
switch (c) {
case 'h':
RmcdClientCmd::mountUsage("help");
break;
case 'D': /* drive ordinal */
{
drvord = strtol (optarg, &dp, 10);
if (*dp != '\0' || drvord < 0) {
errflg++;
}
strcpy (dp, optarg);
printf("drive slot = %s\n",dp);
m_request.mutable_mount()->set_drvord(drvord);
break;
}
case 'V': /* vid */
{
n = strlen (optarg);
if (n > 6) {
errflg++;
} else {
strcpy (vid, optarg);
printf("vid = %s\n",vid);
m_request.mutable_mount()->set_vid(vid);}
break;
}
case '?': /* Unrecognized option */
default:{
RmcdClientCmd::mountUsage("Unrecognised commands\n");
break;
}
}
}
}
void RmcdClientCmd::processDismount(int argc, char *const *const argv) {
int errflg = 0;
int drvord = -1;
int n;
char vid[7];
char *dp;
char c;
static struct option longopts[] = {
{ "help", required_argument, NULL, 'h'},
{ "Vid", required_argument, NULL, 'V'},
{ "Drive_original", required_argument, NULL, 'D' },
{ NULL, 0, NULL, '\0' }
};
memset (vid, '\0', sizeof(vid));
if (argc<6) {
RmcdClientCmd::dismountUsage("less arguments provided");
return;
}
if(*argv[2]!= '-') {
RmcdClientCmd::dismountUsage("Unrecognised command format given\n");
}
while ((c = getopt_long(argc, argv, "hV:D:",longopts, NULL))!= -1) {
switch (c) {
case 'h':
RmcdClientCmd::dismountUsage("help");
break;
case 'D': { /* drive ordinal */
drvord = strtol (optarg, &dp, 10);
if (*dp != '\0' || drvord < 0) {
errflg++;}
strcpy (dp, optarg);
printf("drive slot = %s\n",dp);
m_request.mutable_dismount()->set_drvord(drvord);
break;
}
case 'V': { /* vid */
n = strlen (optarg);
if (n > 6) {
errflg++;
} else {
strcpy (vid, optarg);
printf("vid = %s\n",vid);
m_request.mutable_dismount()->set_vid(vid);}
break;
}
case '?':
default:{
RmcdClientCmd::dismountUsage("Unrecognised command");
break;
}
}
}
}
void RmcdClientCmd::Send()
{
// Send the Request to the Service and get a Response
rmc_test::Response response;
m_rmc_test_service_ptr->Send(m_request, response);
// Handle responses
switch(response.type())
{
using namespace rmc_test;
case Response::RSP_SUCCESS: std::cout << response.message_txt(); break;
case Response::RSP_ERR_PROTOBUF: throw XrdSsiPb::PbException(response.message_txt());
case Response::RSP_ERR_USER:
case Response::RSP_ERR_SERVER: throw std::runtime_error(response.message_txt());
default: throw XrdSsiPb::PbException("Invalid response type.");
}
is_metadata_done = true;
}
/*!
* Start here
*
* @param argc[in] The number of command-line arguments
* @param argv[in] The command-line arguments
*
* @retval 0 Success
* @retval 1 The client threw an exception
*/
int main(int argc, char **argv)
{
try {
// Test uninitialised logging : logging is not available until the rmc_test_service object is
// instantiated, so this message should be silently ignored
XrdSsiPb::Log::Msg(XrdSsiPb::Log::ERROR, "main", "Logging is not initialised");
// Parse the command line arguments
RmcdClientCmd cmd(argc, argv);
// Send the protocol buffer
cmd.Send();
// Delete all global objects allocated by libprotobuf
google::protobuf::ShutdownProtobufLibrary();
return 0;
} catch (XrdSsiPb::PbException &ex) {
std::cerr << "Error in Google Protocol Buffers: " << ex.what() << std::endl;
} catch (XrdSsiPb::XrdSsiException &ex) {
std::cerr << "Error from XRootD SSI Framework: " << ex.what() << std::endl;
} catch (std::runtime_error &ex) {
std::cerr << ex.what() << std::endl;
} catch (std::exception &ex) {
std::cerr << "Caught exception: " << ex.what() << std::endl;
} catch (...) {
std::cerr << "Caught an unknown exception" << std::endl;
}
return 1;
}
/*!
* @project XRootD SSI/Protocol Buffer Interface Project
* @brief Command-line rmc_test client for XRootD SSI/Protocol Buffers
* @copyright Copyright 2018 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