Commit 34faad05 authored by Cedric Caffy's avatar Cedric Caffy
Browse files

cta-taped disables the tape when the cleaning does not work solves issue #224

parent 446bc8bc
......@@ -917,6 +917,21 @@ std::string getCurrentLocalTime() {
return std::string(buff) + std::string(buff2);
}
//-----------------------------------------------------------------------------
// getCurrentLocalTime
//-----------------------------------------------------------------------------
std::string getCurrentLocalTime(const std::string & format){
::timeval tv;
::gettimeofday(&tv, nullptr);
::time_t now = (::time_t)tv.tv_sec;
struct ::tm * localNow;
::time(&now);
localNow = ::localtime(&now);
char buff[80];
::strftime(buff,sizeof(buff), format.c_str(), localNow);
return std::string(buff);
}
std::string extractPathFromXrootdPath(const std::string& path){
XrdCl::URL urlInfo(path.c_str());
return urlInfo.GetPath();
......
......@@ -401,6 +401,14 @@ namespace utils {
*/
std::string getCurrentLocalTime();
/**
* Returns the current time formatted according to the string passed in parameter
* @param format the format of the time the user wants to have as an output
* The format should be compliant with http://www.cplusplus.com/reference/ctime/strftime/
* @return the current time formatted according to the string passed in parameter
*/
std::string getCurrentLocalTime(const std::string & format);
/**
* Remove the root:// part of the path passed in parameter
* and return the corresponding string
......
......@@ -22,6 +22,8 @@
*****************************************************************************/
#include "castor/tape/tapeserver/daemon/CleanerSession.hpp"
#include "catalogue/Catalogue.hpp"
#include <exception>
//------------------------------------------------------------------------------
// constructor
......@@ -35,7 +37,8 @@ castor::tape::tapeserver::daemon::CleanerSession::CleanerSession(
const std::string &vid,
const bool waitMediaInDrive,
const uint32_t waitMediaInDriveTimeout,
const std::string & externalEncryptionKeyScript):
const std::string & externalEncryptionKeyScript,
cta::catalogue::Catalogue & catalogue):
m_capUtils(capUtils),
m_mc(mc),
m_log(log),
......@@ -44,7 +47,9 @@ castor::tape::tapeserver::daemon::CleanerSession::CleanerSession(
m_vid(vid),
m_waitMediaInDrive(waitMediaInDrive),
m_waitMediaInDriveTimeout(waitMediaInDriveTimeout),
m_encryptionControl(externalEncryptionKeyScript) {}
m_encryptionControl(externalEncryptionKeyScript),
m_catalogue(catalogue)
{}
//------------------------------------------------------------------------------
// execute
......@@ -87,6 +92,48 @@ castor::tape::tapeserver::daemon::Session::EndOfSessionAction
cleanDrive(drive);
} catch(...) {
logAndClearTapeAlerts(drive);
//As we failed to clean the drive (unmount the tape or rewinding impossible),
//we set the tape as disabled so that it will not be mounted for future retrieves
//otherwise, we will go in an infinite loop of mounting with errors.
//Gitlab ticket reference : https://gitlab.cern.ch/cta/CTA/issues/224
if(!m_vid.empty()){
//Get the message exception to log it into the comment section of the tape table
auto currException = std::current_exception();
std::string currentExceptionMsg = "";
try {
std::rethrow_exception(currException);
} catch(cta::exception::Exception &ex){
currentExceptionMsg = ex.getMessageValue();
} catch(std::exception & ex){
currentExceptionMsg = ex.what();
} catch (...) {
currentExceptionMsg = "Unknown exception";
}
std::string hostname = cta::utils::getShortHostname();
std::string tapeDrive = m_driveConfig.unitName;
std::list<cta::log::Param> params = {
cta::log::Param("tapeVid", m_vid),
cta::log::Param("tapeDrive", tapeDrive),
cta::log::Param("logicalLibrary", m_driveConfig.logicalLibrary),
cta::log::Param("host",hostname),
cta::log::Param("exceptionMsg", currentExceptionMsg)};
m_log(cta::log::ERR,"In CleanerSession::exceptionThrowingExecute(), failed to clean the Drive with a tape mounted. Disabling the tape.",params);
cta::common::dataStructures::SecurityIdentity admin;
admin.username = c_defaultUserNameUpdate;
admin.host = tapeDrive + "@" + hostname;
try{
m_catalogue.setTapeDisabled(admin, m_vid, true);
std::string comment = cta::utils::getCurrentLocalTime("%F %T") + ":" + currentExceptionMsg;
m_catalogue.modifyTapeComment(admin,m_vid,comment);
} catch(cta::exception::Exception &ex) {
cta::log::Param param("exceptionMsg",ex.getMessageValue());
params.push_back(param);
m_log(cta::log::ERR,"In CleanerSession::exceptionThrowingExecute(), failed to disable the tape.",params);
}
}
throw;
}
......
......@@ -33,6 +33,7 @@
#include "tapeserver/castor/tape/tapeserver/file/Structures.hpp"
#include "tapeserver/castor/tape/tapeserver/SCSI/Device.hpp"
#include "tapeserver/castor/tape/tapeserver/daemon/EncryptionControl.hpp"
#include "catalogue/Catalogue.hpp"
#include <memory>
......@@ -62,6 +63,7 @@ namespace daemon {
* the media to be ready for operations inside the drive.
* @param externalEncryptionKeyScript path to the operator provided script
* for encryption control.
* @param catalogue the CTA catalogue
*/
CleanerSession(
cta::server::ProcessCap &capUtils,
......@@ -72,7 +74,8 @@ namespace daemon {
const std::string &vid,
const bool waitMediaInDrive,
const uint32_t waitMediaInDriveTimeout,
const std::string & externalEncryptionKeyScript);
const std::string & externalEncryptionKeyScript,
cta::catalogue::Catalogue & catalogue);
/**
* Execute the session and return the type of action to be performed
......@@ -132,6 +135,16 @@ namespace daemon {
* Encryption helper object
*/
EncryptionControl m_encryptionControl;
/**
* CTA catalogue
*/
cta::catalogue::Catalogue & m_catalogue;
/**
* Variable used to log UPDATE_USER_NAME in the DB
*/
const std::string c_defaultUserNameUpdate = "cta-taped";
/**
* Execute the session and return the type of action to be performed
......
......@@ -910,19 +910,10 @@ int DriveHandler::runChild() {
sleep(1);
return castor::tape::tapeserver::daemon::Session::MARK_DRIVE_AS_DOWN;
}
std::unique_ptr<cta::catalogue::Catalogue> catalogue;
try {
log::ScopedParamContainer params(lc);
params.add("fileCatalogConfigFile", m_tapedConfig.fileCatalogConfigFile.value());
lc.log(log::DEBUG, "In DriveHandler::runChild(): will get catalogue login information.");
const cta::rdbms::Login catalogueLogin = cta::rdbms::Login::parseFile(m_tapedConfig.fileCatalogConfigFile.value());
const uint64_t nbConns = 1;
const uint64_t nbArchiveFileListingConns = 0;
lc.log(log::DEBUG, "In DriveHandler::runChild(): will connect to catalogue.");
auto catalogueFactory = cta::catalogue::CatalogueFactoryFactory::create(m_sessionEndContext.logger(),
catalogueLogin, nbConns, nbArchiveFileListingConns);
catalogue=catalogueFactory->create();
osdb.reset(new cta::OStoreDBWithAgent(*backend, backendPopulator->getAgentReference(), *catalogue, lc.logger()));
if(!m_catalogue)
m_catalogue = createCatalogue("DriveHandler::runChild()");
osdb.reset(new cta::OStoreDBWithAgent(*backend, backendPopulator->getAgentReference(), *m_catalogue, lc.logger()));
} catch(cta::exception::Exception &ex) {
log::ScopedParamContainer param(lc);
param.add("errorMessage", ex.getMessageValue());
......@@ -932,7 +923,7 @@ int DriveHandler::runChild() {
return castor::tape::tapeserver::daemon::Session::MARK_DRIVE_AS_DOWN;
}
lc.log(log::DEBUG, "In DriveHandler::runChild(): will create scheduler.");
cta::Scheduler scheduler(*catalogue, *osdb, m_tapedConfig.mountCriteria.value().maxFiles,
cta::Scheduler scheduler(*m_catalogue, *osdb, m_tapedConfig.mountCriteria.value().maxFiles,
m_tapedConfig.mountCriteria.value().maxBytes);
// Before launching the transfer session, we validate that the scheduler is reachable.
lc.log(log::DEBUG, "In DriveHandler::runChild(): will ping scheduler.");
......@@ -1032,7 +1023,7 @@ int DriveHandler::runChild() {
// sleep(1);
// return castor::tape::tapeserver::daemon::Session::MARK_DRIVE_AS_DOWN;
// }
castor::tape::tapeserver::daemon::CleanerSession cleanerSession(
capUtils,
mediaChangerFacade,
......@@ -1042,7 +1033,8 @@ int DriveHandler::runChild() {
m_previousVid,
true,
60,
"");
"",
*m_catalogue);
return cleanerSession.execute();
} else {
// The next session will be a normal session (no crash with a mounted tape before).
......@@ -1159,6 +1151,9 @@ SubprocessHandler::ProcessingStatus DriveHandler::shutdown() {
// Capabilities management.
cta::server::ProcessCap capUtils;
// Mounting management.
if(!m_catalogue)
m_catalogue = createCatalogue("DriveHandler::shutdown()");
cta::mediachanger::MediaChangerFacade mediaChangerFacade(m_processManager.logContext().logger());
castor::tape::System::realWrapper sWrapper;
castor::tape::tapeserver::daemon::CleanerSession cleanerSession(
......@@ -1170,7 +1165,8 @@ SubprocessHandler::ProcessingStatus DriveHandler::shutdown() {
m_sessionVid,
true,
60,
"");
"",
*m_catalogue);
cleanerSession.execute();
}
}
......@@ -1184,6 +1180,20 @@ SubprocessHandler::ProcessingStatus DriveHandler::shutdown() {
return m_processingStatus;
}
std::unique_ptr<cta::catalogue::Catalogue> DriveHandler::createCatalogue(const std::string & methodCaller){
log::ScopedParamContainer params(m_processManager.logContext());
params.add("fileCatalogConfigFile", m_tapedConfig.fileCatalogConfigFile.value());
params.add("caller",methodCaller);
m_processManager.logContext().log(log::DEBUG, "In DriveHandler::createCatalogue(): will get catalogue login information.");
const cta::rdbms::Login catalogueLogin = cta::rdbms::Login::parseFile(m_tapedConfig.fileCatalogConfigFile.value());
const uint64_t nbConns = 1;
const uint64_t nbArchiveFileListingConns = 0;
m_processManager.logContext().log(log::DEBUG, "In DriveHandler::createCatalogue(): will connect to catalogue.");
auto catalogueFactory = cta::catalogue::CatalogueFactoryFactory::create(m_sessionEndContext.logger(),
catalogueLogin, nbConns, nbArchiveFileListingConns);
return std::move(catalogueFactory->create());
}
//------------------------------------------------------------------------------
// DriveHandler::~DriveHandler
//------------------------------------------------------------------------------
......
......@@ -25,6 +25,7 @@
#include "tapeserver/daemon/WatchdogMessage.pb.h"
#include "tapeserver/session/SessionState.hpp"
#include "tapeserver/session/SessionType.hpp"
#include "catalogue/Catalogue.hpp"
#include <memory>
namespace cta { namespace tape { namespace daemon {
......@@ -136,6 +137,10 @@ private:
void processLogs(serializers::WatchdogMessage & message);
/** Helper function accumulating bytes transferred */
void processBytes(serializers::WatchdogMessage & message);
std::unique_ptr<cta::catalogue::Catalogue> createCatalogue(const std::string & methodCaller);
std::unique_ptr<cta::catalogue::Catalogue> m_catalogue;
};
// TODO: remove/merge ChildProcess.
......
Supports Markdown
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