Commit 41b4704e authored by Eric Cano's avatar Eric Cano
Browse files

Added tape alert error counts to the tape log input.

Migrations now abort in the presence of tape alerts.
parent a6af1306
......@@ -163,6 +163,133 @@ std::string castor::tape::SCSI::tapeAlertToString(uint16_t parameterCode)
}
}
std::string castor::tape::SCSI::tapeAlertToCompactString(uint16_t parameterCode)
{
std::stringstream ret;
ret << std::hex << std::nouppercase << std::showbase;
ret << "tapeAlert";
if (parameterCode < 1 || parameterCode > 64) {
ret << "Unexpected" << parameterCode;
return ret.str();
} else if (parameterCode >= 0x28 && parameterCode <= 0x2e) {
ret << "Obsolete" << parameterCode;
return ret.str();
}
switch(parameterCode) {
/* This list is hand compacted from the one in castor::tape::SCSI::tapeAlertToString
*/
case 0x01:
return "tapeAlertReadWarning";
case 0x02:
return "tapeAlertWriteWarning";
case 0x03:
return "tapeAlertHardError";
case 0x04:
return "tapeAlertMedium";
case 0x05:
return "tapeAlertReadFailure";
case 0x06:
return "tapeAlertWriteFailure";
case 0x07:
return "tapeAlertMediumLife";
case 0x08:
return "tapeAlertNotDataGrade";
case 0x09:
return "tapeAlertWriteProtect";
case 0x0A:
return "tapeAlertVolumePemovalPrevented";
case 0x0B:
return "tapeAlertCleaningVolume";
case 0x0C:
return "tapeAlertUnsupportedFormat";
case 0x0D:
return "tapeAlertRecoverableMechanicalCartridgeFailure";
case 0x0E:
return "tapeAlertUnrecoverableMechanicalCartridgeFailure";
case 0x0F:
return "tapeAlertMemoryChipInCartridgeFailure";
case 0x10:
return "tapeAlertForcedEject";
case 0x11:
return "tapeAlertReadOnlyFormat";
case 0x12:
return "tapeAlertTapeDirectoryCorruptedOnLoad";
case 0x13:
return "tapeAlertNearingMediumLife";
case 0x14:
return "tapeAlertCleaningRequired";
case 0x15:
return "tapeAlertCleaningRequested";
case 0x16:
return "tapeAlertExpiredCleaningVolume";
case 0x17:
return "tapeAlertInvalidCleaningVolume";
case 0x18:
return "tapeAlertRetensionRequested";
case 0x19:
return "tapeAlertMultiPortInterfaceErrorOnAPrimaryPort";
case 0x1A:
return "tapeAlertCoolingFanFailure";
case 0x1B:
return "tapeAlertPowerSupplyFailure";
case 0x1C:
return "tapeAlertPowerConsumption";
case 0x1D:
return "tapeAlertDrivePreventiveMaintenanceRequired";
case 0x1E:
return "tapeAlertHardwareA";
case 0x1F:
return "tapeAlertHardwareB";
case 0x20:
return "tapeAlertPrimaryInterface";
case 0x21:
return "tapeAlertEjectVolume";
case 0x22:
return "tapeAlertMicrocodeUpdateFail";
case 0x23:
return "tapeAlertDriveHumidity";
case 0x24:
return "tapeAlertDriveTemperature";
case 0x25:
return "tapeAlertDriveVoltage";
case 0x26:
return "tapeAlertPredictiveFailure";
case 0x27:
return "tapeAlertDiagnosticsRequired";
case 0x2F:
return "tapeAlertExternalDataEncryptionControlCommunicationFailure";
case 0x30:
return "tapeAlertExternalDataEncryptionControlKeyManagerReturnedAnError";
case 0x31:
return "tapeAlertDiminishedNativeCapacity";
case 0x32:
return "tapeAlertLostStatistics";
case 0x33:
return "tapeAlertTapeDirectoryInvalidAtUnload";
case 0x34:
return "tapeAlertTapeSystemAreaWriteFailure";
case 0x35:
return "tapeAlertTapeSystemAreaReadFailure";
case 0x36:
return "tapeAlertNoStartOfData";
case 0x37:
return "tapeAlertLoadingOrThreadingFailure";
case 0x38:
return "tapeAlertUnrecoverableUnloadFailure";
case 0x39:
return "tapeAlertAutomationInterfaceFailure";
case 0x3A:
return "tapeAlertMicrocodeFailure";
case 0x3B:
return "tapeAlertWORMVolumeIntegrityCheckFailed";
case 0x3C:
return "tapeAlertWORMVolumeOverwriteAttempted";
default:
ret << "ReservedCode" << parameterCode;
return ret.str();
}
}
/**
* Turn a SCSI status code into a string
* @param status
......
......@@ -211,6 +211,11 @@ namespace SCSI {
*/
std::string tapeAlertToString(uint16_t parameterCode);
/**
* Helper function turning tape alerts to mixed case compact strings.
*/
std::string tapeAlertToCompactString(uint16_t parameterCode);
class Status {
public:
enum {
......
......@@ -84,6 +84,8 @@ public:
virtual void push(TapeReadTask* t){
m_tasks.push(t);
}
virtual void countTapeLogError(const std::string & error) {};
};
TEST(castor_tape_tapeserver_daemon, RecallTaskInjectorNominal) {
......
......@@ -125,6 +125,11 @@ private:
/// Reference to the watchdog, used in run()
RecallWatchDog& m_watchdog;
/// Helper virtual function to access the watchdog from parent class
virtual void countTapeLogError(const std::string & error) {
m_watchdog.addToErrorCount(error);
}
}; // class TapeReadSingleThread
......
......@@ -180,11 +180,13 @@ protected:
/**
* After waiting for the drive, we will dump the tape alert log content, if
* not empty
* @return true if any alert was detected
*/
void logTapeAlerts() {
bool logTapeAlerts() {
std::vector<std::string> tapeAlerts = m_drive.getTapeAlerts();
if (tapeAlerts.empty()) return;
if (tapeAlerts.empty()) return false;
size_t alertNumber = 0;
// Log tape alerts in the logs.
for (std::vector<std::string>::iterator ta=tapeAlerts.begin();
ta!=tapeAlerts.end();ta++)
{
......@@ -194,7 +196,23 @@ protected:
.add("tapeAlertCount", tapeAlerts.size());
m_logContext.log(LOG_WARNING, "Tape alert detected");
}
// Add tape alerts in the tape log parameters
std::vector<std::string> tapeAlertsCompact = m_drive.getTapeAlertsCompact();
for (std::vector<std::string>::iterator tac=tapeAlertsCompact.begin();
tac!=tapeAlertsCompact.end();tac++)
{
countTapeLogError(std::string("Error_")+*tac);
}
return true;
}
/**
* Helper virtual function allowing the access to the m_watchdog member
* in the inherited classes (TapeReadSingleThread and TapeWriteSingleThread)
* @param error
*/
virtual void countTapeLogError(const std::string & error) = 0;
public:
Session::EndOfSessionAction getHardwareStatus() const {
......
......@@ -162,7 +162,9 @@ void castor::tape::tapeserver::daemon::TapeWriteSingleThread::run() {
currentErrorToCount = "Error_tapeLoad";
waitForDrive();
currentErrorToCount = "Error_checkingTapeAlert";
logTapeAlerts();
if (logTapeAlerts()) {
throw castor::exception::Exception("Aborting migration session in presence of tape alerts");
}
currentErrorToCount = "Error_tapeNotWriteable";
isTapeWritable();
......
......@@ -222,6 +222,15 @@ private:
*/
MigrationWatchDog & m_watchdog;
protected:
/***
* Helper virtual function to access the watchdog from parent class
*/
virtual void countTapeLogError(const std::string & error) {
m_watchdog.addToErrorCount(error);
}
private:
/**
* Pointer to the task injector allowing termination signaling
*/
......
......@@ -241,12 +241,12 @@ drive::positionInfo drive::DriveGeneric::getPositionInfo()
/**
* Get tape alert information from the drive. There is a quite long list of possible tape alerts.
* They are described in SSC-4, section 4.2.20: TapeAlert application client interface.
* Section is 4.2.17 in SSC-3.
* @return list of tape alerts descriptions. They are simply used for logging.
* Section is 4.2.17 in SSC-3. This version gives a list of numerical codes.
* @return list of tape alerts codes.
*/
std::vector<std::string> drive::DriveGeneric::getTapeAlerts() {
std::vector<uint16_t> drive::DriveGeneric::getTapeAlertCodes(){
/* return vector */
std::vector<std::string> ret;
std::vector<uint16_t> ret;
/* We don't know how many elements we'll get. Prepare a 100 parameters array */
SCSI::Structures::tapeAlertLogPage_t<100> tal;
/* Prepare a sense buffer of 255 bytes */
......@@ -272,9 +272,43 @@ std::vector<std::string> drive::DriveGeneric::getTapeAlerts() {
* return strings. */
for (size_t i = 0; i < tal.parameterNumber(); i++) {
if (tal.parameters[i].flag)
ret.push_back(SCSI::tapeAlertToString(
SCSI::Structures::toU16(tal.parameters[i].parameterCode)
));
ret.push_back(SCSI::Structures::toU16(tal.parameters[i].parameterCode));
}
return ret;
}
/**
* Get tape alert information from the drive. There is a quite long list of possible tape alerts.
* They are described in SSC-4, section 4.2.20: TapeAlert application client interface.
* Section is 4.2.17 in SSC-3. This version gives the standard strings from SSC-4.
* @return list of tape alerts descriptions. They are simply used for logging.
*/
std::vector<std::string> drive::DriveGeneric::getTapeAlerts(){
/* return vector */
std::vector<std::string> ret;
/* The tape alerts */
std::vector<uint16_t> tacs = getTapeAlertCodes();
/* convert tape alert codes to strings */
for (std::vector<uint16_t>::iterator code = tacs.begin(); code!= tacs.end(); code++) {
ret.push_back(SCSI::tapeAlertToString(*code));
}
return ret;
}
/**
* Get tape alert information from the drive. There is a quite long list of possible tape alerts.
* They are described in SSC-4, section 4.2.20: TapeAlert application client interface.
* Section is 4.2.17 in SSC-3. This version gives the standard strings from SSC-4.
* @return list of tape alerts descriptions, shortened in single words with mixed case.
*/
std::vector<std::string> drive::DriveGeneric::getTapeAlertsCompact(){
/* return vector */
std::vector<std::string> ret;
/* The tape alerts */
std::vector<uint16_t> tacs = getTapeAlertCodes();
/* convert tape alert codes to strings */
for (std::vector<uint16_t>::iterator code = tacs.begin(); code!= tacs.end(); code++) {
ret.push_back(SCSI::tapeAlertToCompactString(*code));
}
return ret;
}
......
......@@ -88,13 +88,26 @@ namespace drive {
* on the dirty data still in the write buffer.
*/
virtual positionInfo getPositionInfo() ;
private:
/**
* Utility getting the tape alert codes in a vector.
* @return vector of the tape alert codes.
*/
std::vector<uint16_t> getTapeAlertCodes();
public:
/**
* Get tape alert information from the drive. There is a quite long list of possible tape alerts.
* They are described in SSC-4, section 4.2.20: TapeAlert application client interface
* @return list of tape alerts descriptions. They are simply used for logging.
*/
virtual std::vector<std::string> getTapeAlerts() ;
virtual std::vector<std::string> getTapeAlerts();
/**
* Get tape alert information from the drive. This is the same as getTapeAlerts,
* but providing the alert strings in compact form (mixed case single word).
*/
virtual std::vector<std::string> getTapeAlertsCompact();
/**
* Set the tape density and compression.
......
......@@ -156,6 +156,7 @@ namespace drive {
virtual void positionToLogicalObject(uint32_t blockId) = 0;
virtual positionInfo getPositionInfo() = 0;
virtual std::vector<std::string> getTapeAlerts() = 0;
virtual std::vector<std::string> getTapeAlertsCompact () = 0;
virtual void setDensityAndCompression(bool compression = true,
unsigned char densityCode = 0) = 0;
virtual driveStatus getDriveStatus() = 0;
......
......@@ -82,6 +82,11 @@ std::vector<std::string> castor::tape::tapeserver::drive::FakeDrive::getTapeAler
std::vector<std::string> empty;
return empty;
}
std::vector<std::string> castor::tape::tapeserver::drive::FakeDrive::getTapeAlertsCompact() {
std::vector<std::string> empty;
return empty;
}
void castor::tape::tapeserver::drive::FakeDrive::setDensityAndCompression(bool compression, unsigned char densityCode) {
throw castor::exception::Exception("FakeDrive::setDensityAndCompression Not implemented");
}
......
......@@ -64,6 +64,7 @@ namespace drive {
virtual void positionToLogicalObject(uint32_t blockId) ;
virtual positionInfo getPositionInfo() ;
virtual std::vector<std::string> getTapeAlerts() ;
virtual std::vector<std::string> getTapeAlertsCompact() ;
virtual void setDensityAndCompression(bool compression = true,
unsigned char densityCode = 0) ;
virtual driveStatus getDriveStatus() ;
......
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