Commit 4582de61 authored by Steven Murray's avatar Steven Murray
Browse files

This is the first attempt at adding the bare minimum of tapeserverd to the CTA project

Please note that you will have to install the following CASTOR rpms
in order to compile:

  castor
  castor-devel
  castor-lib
  castor-lib-server
  castor-lib-tape
parent 15587fb4
......@@ -16,100 +16,88 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*
*
* @author Castor Dev team, castor-dev@cern.ch
*****************************************************************************/
#include "Ctape_api.h"
#include "Ctape_constants.h"
#include "tape/TpConfigCmdLine.hpp"
#include "tape/TpConfigException.hpp"
#include "castor/mediachanger/AcsLibrarySlot.hpp"
#include "castor/utils/utils.hpp"
#include <sstream>
//------------------------------------------------------------------------------
// constructor
//------------------------------------------------------------------------------
tape::TpConfigCmdLine::TpConfigCmdLine() throw() : status(0) {
castor::mediachanger::AcsLibrarySlot::AcsLibrarySlot() throw():
LibrarySlot(TAPE_LIBRARY_TYPE_ACS),
m_acs(0),
m_lsm(0),
m_panel(0),
m_drive(0) {
m_str = librarySlotToString(0, 0, 0, 0);
}
//------------------------------------------------------------------------------
// constructor
// librarySlotToString
//------------------------------------------------------------------------------
tape::TpConfigCmdLine::TpConfigCmdLine(const std::string &unitName,
const int status) throw() : unitName(unitName), status(status) {
std::string castor::mediachanger::AcsLibrarySlot::librarySlotToString(
const uint32_t acs, const uint32_t lsm, const uint32_t panel,
const uint32_t drive) const {
std::ostringstream oss;
oss << "acs" << acs << "," << lsm << "," << panel << "," << drive;
return oss.str();
}
//------------------------------------------------------------------------------
// parseCmdLine
//------------------------------------------------------------------------------
tape::TpConfigCmdLine tape::TpConfigCmdLine::parse(const int argc,
const char **argv) {
switch(argc) {
case 2: return parseShortVersion(argc, argv);
case 3: return parseLongVersion(argc, argv);
default:
{
std::ostringstream oss;
oss << "Wrong number of command-line arguments"
": expected=1 or 2 actual=" << (argc - 1);
throw TpConfigException(oss.str(), USERR);
}
}
// constructor
//------------------------------------------------------------------------------
castor::mediachanger::AcsLibrarySlot::AcsLibrarySlot(const uint32_t acs,
const uint32_t lsm, const uint32_t panel, const uint32_t drive) throw():
LibrarySlot(TAPE_LIBRARY_TYPE_ACS),
m_acs(acs),
m_lsm(lsm),
m_panel(panel),
m_drive(drive) {
m_str = librarySlotToString(acs, lsm, panel, drive);
}
//------------------------------------------------------------------------------
// parseShortVersion
// destructor
//------------------------------------------------------------------------------
tape::TpConfigCmdLine tape::TpConfigCmdLine::parseShortVersion(const int argc,
const char **argv) {
const int nbentries = CA_MAXNBDRIVES;
char hostname[CA_MAXHOSTNAMELEN+1];
struct drv_status drv_status[CA_MAXNBDRIVES];
if (0 > gethostname (hostname, sizeof(hostname))) {
throw TpConfigException("Call to gethostname() failed", SYERR);
}
const int nbDrives = Ctape_status (hostname, drv_status, nbentries);
if (0 > nbDrives) {
throw TpConfigException("Call to Ctape_status() failed", SYERR);
}
castor::mediachanger::AcsLibrarySlot::~AcsLibrarySlot() throw() {
}
if(1 != nbDrives) {
std::ostringstream oss;
oss << "Short version of command line can only be used if there"
" is one and only one drive connected to the tape server"
": nbDrives=" << nbDrives;
throw TpConfigException(oss.str(), USERR);
}
//------------------------------------------------------------------------------
// clone
//------------------------------------------------------------------------------
castor::mediachanger::LibrarySlot *castor::mediachanger::AcsLibrarySlot::
clone() {
return new AcsLibrarySlot(*this);
}
return TpConfigCmdLine(drv_status[0].drive, parseStatus(argv[1]));
//------------------------------------------------------------------------------
// getAcs
//------------------------------------------------------------------------------
uint32_t castor::mediachanger::AcsLibrarySlot::getAcs() const throw () {
return m_acs;
}
//------------------------------------------------------------------------------
// parseStatus
//------------------------------------------------------------------------------
int tape::TpConfigCmdLine::parseStatus(const std::string &str) {
if(str == "up") {
return CONF_UP;
} else if (str == "down") {
return CONF_DOWN;
} else {
std::ostringstream oss;
oss << "Invalid status: expected=up or down actual=" << str;
throw TpConfigException(oss.str(), USERR);
}
// getLsm
//------------------------------------------------------------------------------
uint32_t castor::mediachanger::AcsLibrarySlot::getLsm() const throw () {
return m_lsm;
}
//------------------------------------------------------------------------------
// parseCmdLineLongVersion
// getPanel
//------------------------------------------------------------------------------
tape::TpConfigCmdLine tape::TpConfigCmdLine::parseLongVersion(const int argc,
const char **argv) {
const std::string unitName = argv[1];
const int status = parseStatus(argv[2]);
uint32_t castor::mediachanger::AcsLibrarySlot::getPanel() const throw () {
return m_panel;
}
return TpConfigCmdLine(unitName, status);
//------------------------------------------------------------------------------
// getDrive
//------------------------------------------------------------------------------
uint32_t castor::mediachanger::AcsLibrarySlot::getDrive() const throw () {
return m_drive;
}
/******************************************************************************
*
* This file is part of the Castor project.
* See http://castor.web.cern.ch/castor
*
* Copyright (C) 2003 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 2
* 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* @author Castor Dev team, castor-dev@cern.ch
*****************************************************************************/
#pragma once
#include "castor/exception/InvalidArgument.hpp"
#include "castor/mediachanger/LibrarySlot.hpp"
#include <stdint.h>
namespace castor {
namespace mediachanger {
/**
* Class reprsenting a slot in an ACS tape-library.
*/
class AcsLibrarySlot: public LibrarySlot {
public:
/**
* Default constructor that sets all integer members to 0.
*/
AcsLibrarySlot() throw();
/**
* Constructor.
*
* @param acs The acs component of the library slot.
* @param lsm The lsm component of the library slot.
* @param panel The panel component of the library slot.
* @param drive The drive component of the library slot.
*/
AcsLibrarySlot(const uint32_t acs, const uint32_t lsm,
const uint32_t panel, const uint32_t drive) throw();
/**
* Destructor.
*/
~AcsLibrarySlot() throw();
/**
* Creates a clone of this object.
*
* @return The clone.
*/
LibrarySlot *clone();
/**
* Gets the acs component of the library slot.
*
* @return the acs component of the library slot.
*/
uint32_t getAcs() const throw();
/**
* Gets the lsm component of the library slot.
*
* @return the lsm component of the library slot.
*/
uint32_t getLsm() const throw();
/**
* Gets the panel component of the library slot.
*
* @return the panel component of the library slot.
*/
uint32_t getPanel() const throw();
/**
* Gets the drive component of the library slot.
*
* @return the drive component of the library slot.
*/
uint32_t getDrive() const throw();
private:
/**
* The acs component of the library slot.
*/
uint32_t m_acs;
/**
* The lsm component of the library slot.
*/
uint32_t m_lsm;
/**
* The panel component of the library slot.
*/
uint32_t m_panel;
/**
* The drive component of the library slot.
*/
uint32_t m_drive;
/**
* Returns the string representation of the specified ACS library slot.
*
* @param acs The acs component of the library slot.
* @param lsm The lsm component of the library slot.
* @param panel The panel component of the library slot.
* @param drive The drive component of the library slot.
* @return The string representation.
*/
std::string librarySlotToString(const uint32_t acs, const uint32_t lsm,
const uint32_t panel, const uint32_t drive) const;
}; // class AcsProxy
} // namespace mediachanger
} // namespace castor
/******************************************************************************
*
* This file is part of the Castor project.
* See http://castor.web.cern.ch/castor
*
* Copyright (C) 2003 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 2
* 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*
*
* @author Castor Dev team, castor-dev@cern.ch
*****************************************************************************/
#include "castor/mediachanger/AcsLibrarySlot.hpp"
#include <gtest/gtest.h>
#include <memory>
namespace unitTests {
class castor_mediachanger_AcsLibrarySlotTest : public ::testing::Test {
protected:
virtual void SetUp() {
}
virtual void TearDown() {
}
};
TEST_F(castor_mediachanger_AcsLibrarySlotTest, goodDay) {
using namespace castor::mediachanger;
AcsLibrarySlot slot(11, 22, 33, 44);
ASSERT_EQ(TAPE_LIBRARY_TYPE_ACS, slot.getLibraryType());
ASSERT_EQ(std::string("acs11,22,33,44"), slot.str());
ASSERT_EQ((uint32_t)11, slot.getAcs());
ASSERT_EQ((uint32_t)22, slot.getLsm());
ASSERT_EQ((uint32_t)33, slot.getPanel());
ASSERT_EQ((uint32_t)44, slot.getDrive());
}
TEST_F(castor_mediachanger_AcsLibrarySlotTest, clone) {
using namespace castor::mediachanger;
std::unique_ptr<AcsLibrarySlot> slot1;
ASSERT_NO_THROW(slot1.reset(new AcsLibrarySlot(11, 22, 33, 44)));
ASSERT_EQ(TAPE_LIBRARY_TYPE_ACS, slot1->getLibraryType());
ASSERT_EQ(std::string("acs11,22,33,44"), slot1->str());
ASSERT_EQ((uint32_t)11, slot1->getAcs());
ASSERT_EQ((uint32_t)22, slot1->getLsm());
ASSERT_EQ((uint32_t)33, slot1->getPanel());
ASSERT_EQ((uint32_t)44, slot1->getDrive());
std::unique_ptr<AcsLibrarySlot> slot2;
ASSERT_NO_THROW(slot2.reset((AcsLibrarySlot*)slot1->clone()));
ASSERT_EQ(TAPE_LIBRARY_TYPE_ACS, slot2->getLibraryType());
ASSERT_EQ(std::string("acs11,22,33,44"), slot2->str());
ASSERT_EQ((uint32_t)11, slot2->getAcs());
ASSERT_EQ((uint32_t)22, slot2->getLsm());
ASSERT_EQ((uint32_t)33, slot2->getPanel());
ASSERT_EQ((uint32_t)44, slot2->getDrive());
}
} // namespace unitTests
#
# castor/tape/label/CMakeLists.txt
#
# This file is part of the Castor project.
# See http://castor.web.cern.ch/castor
#
......@@ -18,22 +15,22 @@
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
#
# Steven.Murray@cern.ch
# @author Castor Dev team, castor-dev@cern.ch
#
cmake_minimum_required (VERSION 2.6)
################################################################################
# Rules to build and install castor-tape-label
################################################################################
set (LABEL_SRC_FILES
LabelCmd.cpp
LabelMain.cpp
ParsedTpLabelCommandLine.cpp)
add_executable (castor-tape-label ${LABEL_SRC_FILES})
target_link_libraries (castor-tape-label
castorclient
castorlegacymsg
castormediachanger
tpclient)
install (TARGETS castor-tape-label DESTINATION ${CASTOR_DEST_BIN_DIR})
CastorInstallExeManPage (castor-tape-label)
include_directories(${CMAKE_SOURCE_DIR}/tapeserver)
set (MEDIA_CHANGER_LIB_SRC_FILES
AcsLibrarySlot.cpp
LibrarySlot.cpp
LibrarySlotParser.cpp
ManualLibrarySlot.cpp
MediaChangerFacade.cpp
MmcProxy.cpp
MmcProxyDummy.cpp
MmcProxyLog.cpp
MmcProxyNotSupported.cpp
ScsiLibrarySlot.cpp
TapeLibraryType.cpp)
add_library(castormediachanger ${MEDIA_CHANGER_LIB_SRC_FILES})
......@@ -20,16 +20,29 @@
*
* @author Castor Dev team, castor-dev@cern.ch
*****************************************************************************/
#include "castor/tape/tpcp/WriteTpCommand.hpp"
#include "castor/mediachanger/CmdLine.hpp"
#include "castor/exception/InvalidArgument.hpp"
#include "castor/exception/MissingOperand.hpp"
//------------------------------------------------------------------------------
// main
// handleMissingParameter
//------------------------------------------------------------------------------
int main(int argc, char **argv) {
castor::tape::tpcp::WriteTpCommand command;
void castor::mediachanger::CmdLine::handleMissingParameter(const int opt) {
castor::exception::MissingOperand ex;
ex.getMessage() << "The -" << (char)opt << " option requires a parameter";
throw ex;
}
return command.main(argc, argv);
//------------------------------------------------------------------------------
// handleUnknownOption
//------------------------------------------------------------------------------
void castor::mediachanger::CmdLine::handleUnknownOption(const int opt) {
castor::exception::InvalidArgument ex;
if(0 == optopt) {
ex.getMessage() << "Unknown command-line option";
} else {
ex.getMessage() << "Unknown command-line option: -" << (char)opt;
}
throw ex;
}
......@@ -23,41 +23,33 @@
#pragma once
#include "castor/utils/utils.hpp"
#include "Castor_limits.h"
#include <string>
namespace castor {
namespace tape {
namespace label {
namespace mediachanger {
/**
* Data type used to store the results of parsing the tplabel command-line.
* Class containing the code common to the parsed command-line of the ACS
* command-line tools provided by CASTOR.
*/
struct ParsedTpLabelCommandLine {
class CmdLine {
protected:
/**
* The filename of the "file list" file.
* Handles the specified parameter that is missing a parameter.
*
* @param opt The option.
*/
char drive[CA_MAXUNMLEN+1];
void handleMissingParameter(const int opt);
/**
* The VID of the tape to be mounted.
* Handles the specified unknown option.
*
* @param opt The option.
*/
char vid[CA_MAXVIDLEN+1];
bool driveIsSet;
bool vidIsSet;
bool helpIsSet;
bool forceIsSet;
bool debugIsSet;
void handleUnknownOption(const int opt);
/**
* Constructor.
*/
ParsedTpLabelCommandLine() throw();
}; // struct ParsedTpLabelCommandLine
}; // class CmdLine
} // namespace label
} // namespace tape
} // namespace mediachanger
} // namespace castor
/******************************************************************************
*
* This file is part of the Castor project.
* See http://castor.web.cern.ch/castor
*
* Copyright (C) 2003 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 2
* 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*
*
* @author Castor Dev team, castor-dev@cern.ch
*****************************************************************************/
#include "castor/exception/Exception.hpp"
#include "castor/exception/MissingOperand.hpp"
#include "castor/mediachanger/DismountCmdLine.hpp"
#include "castor/mediachanger/LibrarySlotParser.hpp"
#include <getopt.h>
//-----------------------------------------------------------------------------
// constructor
//-----------------------------------------------------------------------------
castor::mediachanger::DismountCmdLine::DismountCmdLine() throw():
m_debug(false),
m_help(false),
m_driveLibrarySlot(0),
m_force(false) {
}
//------------------------------------------------------------------------------
// constructor
//------------------------------------------------------------------------------
castor::mediachanger::DismountCmdLine::DismountCmdLine(const int argc,
char *const *const argv):
m_debug(false),
m_help(false),
m_driveLibrarySlot(0),
m_force(false) {
static struct option longopts[] = {
{"debug", 0, NULL, 'd'},
{"help" , 0, NULL, 'h'},
{"force", 0, NULL, 'f'},
{NULL , 0, NULL, 0}
};
// Prevent getopt() from printing an error message if it does not recognize
// an option character
opterr = 0;
int opt = 0;
while((opt = getopt_long(argc, argv, ":dhf", longopts, NULL)) != -1) {
processOption(opt);
}
// There is no need to continue parsing when the help option is set
if(m_help) {
return;
}
// Calculate the number of non-option ARGV-elements
const int nbArgs = argc - optind;
// Check that both VID and DRIVE_SLOT has been specified
if(nbArgs < 2) {
castor::exception::MissingOperand ex;
ex.getMessage() << "Both VID and DRIVE_SLOT must be specified";
throw ex;
}
// Parse the VID command-line argument
m_vid = argv[optind];
// Move on to the next command-line argument
optind++;
// Parse the DRIVE_SLOT command-line argument
const std::string driveLibrarySlot = argv[optind];
m_driveLibrarySlot = LibrarySlotParser::parse(driveLibrarySlot);
}
//-----------------------------------------------------------------------------
// copy constructor
//-----------------------------------------------------------------------------