Commit 30b8cb21 authored by Daniele Kruse's avatar Daniele Kruse
Browse files

added the Cleaner Session to unload and dismount cartridges from drives which...

added the Cleaner Session to unload and dismount cartridges from drives which have been left in dirty state
parent c85a1d1a
......@@ -18,6 +18,7 @@ add_library(castorTapeServerDaemon
LabelCmdAcceptHandler.cpp
LabelCmdConnectionHandler.cpp
LabelSession.cpp
CleanerSession.cpp
MigrationMemoryManager.cpp
MigrationReportPacker.cpp
MigrationTaskInjector.cpp
......
/******************************************************************************
*
* 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/tape/tapeserver/daemon/CleanerSession.hpp"
//------------------------------------------------------------------------------
// constructor
//------------------------------------------------------------------------------
castor::tape::tapeserver::daemon::CleanerSession::CleanerSession(
legacymsg::RmcProxy &rmc,
castor::log::Logger &log,
const utils::DriveConfig &driveConfig,
System::virtualWrapper &sysWrapper):
m_rmc(rmc),
m_log(log),
m_driveConfig(driveConfig),
m_sysWrapper(sysWrapper) {
}
//------------------------------------------------------------------------------
// clean
//------------------------------------------------------------------------------
int castor::tape::tapeserver::daemon::CleanerSession::clean() {
castor::tape::SCSI::DeviceVector dv(m_sysWrapper);
castor::tape::SCSI::DeviceInfo driveInfo = dv.findBySymlink(m_driveConfig.devFilename);
// Instantiate the drive object
std::auto_ptr<castor::tape::drives::DriveInterface> drive(
castor::tape::drives::DriveFactory(driveInfo, m_sysWrapper));
if(NULL == drive.get()) {
castor::exception::Exception ex;
ex.getMessage() <<
"Cleaner session ended with error. Failed to instantiate drive object";
throw ex;
}
//temporization to allow for actions to complete
try {
drive->waitUntilReady(60); //wait 1 minute for a possible ongoing mount to complete or for an IO operation to complete
} catch (castor::exception::Exception &ex) {
log::Param params[] = {log::Param("message", ex.getMessage().str())};
m_log(LOG_INFO, "Cleaner session caught a non-fatal exception while waiting for the drive to become ready. One of the reasons we get here is if the drive has no tape inside.", params);
}
//here we check if the drive contains a tape: if not, there's nothing to clean
bool driveHasTapeInPlace = drive->hasTapeInPlace();
if(driveHasTapeInPlace) { //a tape is still mounted in the drive
castor::tape::tapeFile::VOL1 vol1;
try {
drive->rewind();
drive->readExactBlock((void * )&vol1, sizeof(vol1), "[CleanerSession::clean()] - Reading header VOL1");
vol1.verify();
} catch(castor::exception::Exception &ne) {
castor::exception::Exception ex;
ex.getMessage() << "Cleaner session could not rewind the tape or read its label. Giving up now. Reason: " << ne.getMessage().str();
m_log(LOG_ERR, ex.getMessage().str());
return 1; //Tells caller to put the drive down
}
try {
drive->unloadTape();
} catch (castor::exception::Exception &ex) {
log::Param params[] = {log::Param("message", ex.getMessage().str())};
m_log(LOG_INFO, "Cleaner session could not unload the tape. Will still try to unmount it in case it is already unloaded.", params);
}
try {
m_rmc.unmountTape(vol1.getVSN(), m_driveConfig.librarySlot);
} catch(castor::exception::Exception &ne) {
castor::exception::Exception ex;
ex.getMessage() << "Cleaner session could not unmount the tape. Giving up now. Reason: " << ne.getMessage().str();
m_log(LOG_ERR, ex.getMessage().str());
return 1; //Tells caller to put the drive down
}
return 0; //Tells caller the drive can stay up
}
else { //the drive is empty here we don't care about the drive being ready or not
return 0; //Tells caller the drive can stay up
}
}
/******************************************************************************
*
* 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/legacymsg/RmcProxy.hpp"
#include "castor/log/LogContext.hpp"
#include "castor/log/Logger.hpp"
#include "castor/tape/tapeserver/drive/Drive.hpp"
#include "castor/tape/tapeserver/file/Structures.hpp"
#include "castor/tape/tapeserver/SCSI/Device.hpp"
#include "castor/tape/utils/DriveConfig.hpp"
#include <memory>
namespace castor {
namespace tape {
namespace tapeserver {
namespace daemon {
/**
* Class responsible for cleaning up a tape drive left in a (possibly) dirty state.
*/
class CleanerSession {
public:
/**
* Constructor
*
* @param rmc Proxy object representing the rmcd daemon.
* @param log Object representing the API to the CASTOR logging system.
* @param driveConfig Configuration of the tape drive to be cleaned.
* @param sysWrapper Object representing the operating system.
*/
CleanerSession(
legacymsg::RmcProxy &rmc,
castor::log::Logger &log,
const utils::DriveConfig &driveConfig,
System::virtualWrapper &sysWrapper);
/**
* Cleans the drive by unloading any tape present and unmounting it
*
* @return 0 in case of success (drive can stay UP) or 1 in case of failure (drive needs to be put down by the caller)
*/
int clean();
private:
/**
* The object representing the rmcd daemon.
*/
legacymsg::RmcProxy &m_rmc;
/**
* The logging object
*/
castor::log::Logger & m_log;
/**
* The configuration of the tape drive to be cleaned.
*/
const utils::DriveConfig m_driveConfig;
/**
* The system wrapper used to find the device and instantiate the drive object
*/
System::virtualWrapper & m_sysWrapper;
}; // class CleanerSession
} // namespace daemon
} // namespace tapeserver
} // namespace tape
} // namespace castor
\ No newline at end of file
......@@ -157,7 +157,6 @@ void castor::tape::tapeserver::daemon::LabelSession::executeLabel() {
task << "label tape " << m_request.vid << " for gid=" << m_request.gid <<
" uid=" << m_request.uid << " in drive " << m_request.drive;
utils::TpconfigLines::const_iterator configLine;
std::auto_ptr<castor::tape::drives::DriveInterface> drive;
log::Param params[] = {
......
......@@ -55,9 +55,9 @@ namespace daemon {
* @param rmc Proxy object representing the rmcd daemon.
* @param clientRequest The request to label a tape received from the label
* tape command.
* @param log Object reprsenting the API to the CASTOR logging system.
* @param log Object representing the API to the CASTOR logging system.
* @param sysWrapper Object representing the operating system.
* @param driveConfig the configiuration of the tape-drive to be used to
* @param driveConfig the configuration of the tape-drive to be used to
* label a tape.
* @param force The flag that, if set to true, allows labeling a non-blank
* tape.
......
......@@ -69,6 +69,7 @@ void drives::DriveGeneric::UpdateDriveStatus() {
if(GMT_EOD(m_mtInfo.mt_gstat)) m_driveStatus.eod=true; else m_driveStatus.eod=false;
if(GMT_WR_PROT(m_mtInfo.mt_gstat)) m_driveStatus.writeProtection=true; else m_driveStatus.writeProtection=false;
if(GMT_ONLINE(m_mtInfo.mt_gstat)) m_driveStatus.ready=true; else m_driveStatus.ready=false;
if(GMT_DR_OPEN(m_mtInfo.mt_gstat)) m_driveStatus.hasTapeInPlace=false; else m_driveStatus.hasTapeInPlace=true;
}
/**
......@@ -986,3 +987,7 @@ bool drives::FakeDrive::isAtEOD() {
bool drives::FakeDrive::isTapeBlank() {
return m_tape.empty();
}
bool drives::FakeDrive::hasTapeInPlace() {
return true;
}
......@@ -87,6 +87,7 @@ namespace drives {
/* TODO: Error condition */
bool eod;
bool bot;
bool hasTapeInPlace;
};
class tapeError {
......@@ -164,6 +165,7 @@ namespace drives {
virtual bool isAtBOT() = 0;
virtual bool isAtEOD() = 0;
virtual bool isTapeBlank() = 0;
virtual bool hasTapeInPlace() = 0;
/**
* Member string allowing the convenient storage of the string describing
* drive location for the mount system (we get the information from TPCONFIG
......@@ -222,6 +224,7 @@ namespace drives {
virtual bool isAtBOT() ;
virtual bool isAtEOD() ;
virtual bool isTapeBlank();
virtual bool hasTapeInPlace();
};
/**
......@@ -333,6 +336,12 @@ namespace drives {
ex.getMessage()<<timeoutSecond<<" seconds";
throw ex;
}
virtual bool hasTapeInPlace() {
UpdateDriveStatus();
return m_driveStatus.hasTapeInPlace;
}
virtual bool isWriteProtected() {
UpdateDriveStatus();
return m_driveStatus.writeProtection;
......
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