diff --git a/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.cpp b/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.cpp index f2880070783ccae4919c5a1ed418ebbdc99c050d..8eb6a2e81bbaa7b1193e7200be27bca7f99cb61b 100644 --- a/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.cpp +++ b/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.cpp @@ -33,7 +33,27 @@ namespace castor::tape::tapeserver { drive::DriveInterface * drive::createDrive(SCSI::DeviceInfo di, System::virtualWrapper& sw) { - if (std::string::npos != di.product.find("MHVTL") || std::string::npos != di.vendor.find("MHVTL")) { + // For now we need this code as we can only determine that the drive + // is an mhVTL drive from the serial number and that information is + // not available in the sysfs of the device. + int fd = -1; + std::string serialNumber = ""; + + try { + cta::exception::Errnum::throwOnMinusOne(fd = sw.open(di.nst_dev.c_str(), O_RDWR | O_NONBLOCK), + std::string("Could not open device file: ") + di.nst_dev); + serialNumber = getSerialNumber(fd, sw); + } catch (cta::exception::Errnum&) { + // This code can throw in case we are dealing with a VIRTUAL drive. + // Do nothing and continue. + } + + // Close the fd + if (fd != -1) { + sw.close(fd); + } + + if (std::string::npos != di.product.find("MHVTL") || std::string::npos != serialNumber.find("MHVTL")) { return new DriveMHVTL(di, sw); } else if (std::string::npos != di.product.find("T10000")) { return new DriveT10000(di, sw); @@ -55,6 +75,31 @@ drive::DriveInterface * drive::createDrive(SCSI::DeviceInfo di, } } +std::string drive::getSerialNumber(const int& fd, System::virtualWrapper& sw) { + SCSI::Structures::inquiryCDB_t cdb; + SCSI::Structures::inquiryUnitSerialNumberData_t inquirySerialData; + SCSI::Structures::senseData_t<255> senseBuff; + SCSI::Structures::LinuxSGIO_t sgh; + + cdb.EVPD = 1; /* Enable Vital Product Data */ + cdb.pageCode = SCSI::inquiryVPDPages::unitSerialNumber; + SCSI::Structures::setU16(cdb.allocationLength, sizeof(inquirySerialData)); + + sgh.setCDB(&cdb); + sgh.setDataBuffer(&inquirySerialData); + sgh.setSenseBuffer(&senseBuff); + sgh.dxfer_direction = SG_DXFER_FROM_DEV; + + /* Manage both system error and SCSI errors. */ + cta::exception::Errnum::throwOnMinusOne(sw.ioctl(fd, SG_IO, &sgh), + "Failed SG_IO ioctl in DriveGeneric::getSerialNumber"); + SCSI::ExceptionLauncher(sgh, "SCSI error in getSerialNumber:"); + std::string serialNumber; + serialNumber.append(inquirySerialData.productSerialNumber, inquirySerialData.pageLength); + + return serialNumber; +} + drive::DriveGeneric::DriveGeneric(SCSI::DeviceInfo di, System::virtualWrapper& sw) : m_SCSIInfo(di), m_tapeFD(-1), m_sysWrapper(sw), m_lbpToUse(lbpToUse::disabled) { /* Open the device files */ diff --git a/tapeserver/castor/tape/tapeserver/drive/DriveInterface.hpp b/tapeserver/castor/tape/tapeserver/drive/DriveInterface.hpp index bffd81070009eb2de84c6157b0d545827adb83c0..869eefac7a99ca813e2cc76ba8b9c441a5056673 100644 --- a/tapeserver/castor/tape/tapeserver/drive/DriveInterface.hpp +++ b/tapeserver/castor/tape/tapeserver/drive/DriveInterface.hpp @@ -281,4 +281,6 @@ class DriveInterface { DriveInterface * createDrive(SCSI::DeviceInfo di, System::virtualWrapper & sw); +std::string getSerialNumber(const int& fd, System::virtualWrapper& sw); + } // namespace castor::tape::tapeserver::drive diff --git a/tapeserver/castor/tape/tapeserver/drive/DriveTest.cpp b/tapeserver/castor/tape/tapeserver/drive/DriveTest.cpp index 73a80d22efd76ccf21e892ab3e2c470f6cf87c62..88860eb90c8f8e9fad56443c96b13c403846b46f 100644 --- a/tapeserver/castor/tape/tapeserver/drive/DriveTest.cpp +++ b/tapeserver/castor/tape/tapeserver/drive/DriveTest.cpp @@ -43,15 +43,15 @@ TEST(castor_tape_drive_Drive, OpensCorrectly) { EXPECT_CALL(sysWrapper, readdir(_)).Times(AtLeast(30)); EXPECT_CALL(sysWrapper, closedir(_)).Times(AtLeast(4)); EXPECT_CALL(sysWrapper, realpath(_, _)).Times(6); - EXPECT_CALL(sysWrapper, open(_, _)).Times(42); + EXPECT_CALL(sysWrapper, open(_, _)).Times(46); EXPECT_CALL(sysWrapper, read(_, _, _)).Times(76); EXPECT_CALL(sysWrapper, write(_, _, _)).Times(0); EXPECT_CALL(sysWrapper, ioctl(_,_,An<mtget*>())).Times(0); - EXPECT_CALL(sysWrapper, close(_)).Times(42); + EXPECT_CALL(sysWrapper, close(_)).Times(46); EXPECT_CALL(sysWrapper, readlink(_, _, _)).Times(6); EXPECT_CALL(sysWrapper, stat(_,_)).Times(14); + EXPECT_CALL(sysWrapper, ioctl(_, _, An<sg_io_hdr_t*>())).Times(4); - /* Test: detect devices, then open the device files */ castor::tape::SCSI::DeviceVector dl(sysWrapper); /* Check we detected things properly */ @@ -91,19 +91,20 @@ TEST(castor_tape_drive_Drive, getPositionInfoAndPositionToLogicalObject) { EXPECT_CALL(sysWrapper, readdir(_)).Times(AtLeast(30)); EXPECT_CALL(sysWrapper, closedir(_)).Times(AtLeast(4)); EXPECT_CALL(sysWrapper, realpath(_, _)).Times(6); - EXPECT_CALL(sysWrapper, open(_, _)).Times(42); + EXPECT_CALL(sysWrapper, open(_, _)).Times(46); EXPECT_CALL(sysWrapper, read(_, _, _)).Times(76); EXPECT_CALL(sysWrapper, write(_, _, _)).Times(0); EXPECT_CALL(sysWrapper, ioctl(_,_,An<mtget*>())).Times(0); - EXPECT_CALL(sysWrapper, close(_)).Times(42); + EXPECT_CALL(sysWrapper, close(_)).Times(46); EXPECT_CALL(sysWrapper, readlink(_, _, _)).Times(6); EXPECT_CALL(sysWrapper, stat(_,_)).Times(14); - + /* Test: detect devices, then open the device files */ castor::tape::SCSI::DeviceVector dl(sysWrapper); for (std::vector<castor::tape::SCSI::DeviceInfo>::iterator i = dl.begin(); i != dl.end(); i++) { if (castor::tape::SCSI::Types::tape == i->type) { + EXPECT_CALL(sysWrapper, ioctl(_, _, An<sg_io_hdr_t*>())).Times(1); std::unique_ptr<castor::tape::tapeserver::drive::DriveInterface> drive ( castor::tape::tapeserver::drive::createDrive(*i, sysWrapper)); castor::tape::tapeserver::drive::positionInfo posInfo; @@ -147,11 +148,11 @@ TEST(castor_tape_drive_Drive, setDensityAndCompression) { EXPECT_CALL(sysWrapper, readdir(_)).Times(AtLeast(30)); EXPECT_CALL(sysWrapper, closedir(_)).Times(AtLeast(4)); EXPECT_CALL(sysWrapper, realpath(_, _)).Times(6); - EXPECT_CALL(sysWrapper, open(_, _)).Times(42); + EXPECT_CALL(sysWrapper, open(_, _)).Times(46); EXPECT_CALL(sysWrapper, read(_, _, _)).Times(76); EXPECT_CALL(sysWrapper, write(_, _, _)).Times(0); EXPECT_CALL(sysWrapper, ioctl(_,_,An<mtget*>())).Times(0); - EXPECT_CALL(sysWrapper, close(_)).Times(42); + EXPECT_CALL(sysWrapper, close(_)).Times(46); EXPECT_CALL(sysWrapper, readlink(_, _, _)).Times(6); EXPECT_CALL(sysWrapper, stat(_,_)).Times(14); @@ -160,6 +161,7 @@ TEST(castor_tape_drive_Drive, setDensityAndCompression) { for (std::vector<castor::tape::SCSI::DeviceInfo>::iterator i = dl.begin(); i != dl.end(); i++) { if (castor::tape::SCSI::Types::tape == i->type) { + EXPECT_CALL(sysWrapper, ioctl(_, _, An<sg_io_hdr_t*>())).Times(1); std::unique_ptr<castor::tape::tapeserver::drive::DriveInterface> drive ( castor::tape::tapeserver::drive::createDrive(*i, sysWrapper)); @@ -192,18 +194,19 @@ TEST(castor_tape_drive_Drive, setStDriverOptions) { EXPECT_CALL(sysWrapper, readdir(_)).Times(AtLeast(30)); EXPECT_CALL(sysWrapper, closedir(_)).Times(AtLeast(4)); EXPECT_CALL(sysWrapper, realpath(_, _)).Times(6); - EXPECT_CALL(sysWrapper, open(_, _)).Times(42); + EXPECT_CALL(sysWrapper, open(_, _)).Times(46); EXPECT_CALL(sysWrapper, read(_, _, _)).Times(76); EXPECT_CALL(sysWrapper, write(_, _, _)).Times(0); EXPECT_CALL(sysWrapper, ioctl(_,_,An<mtget*>())).Times(0); - EXPECT_CALL(sysWrapper, close(_)).Times(42); + EXPECT_CALL(sysWrapper, close(_)).Times(46); EXPECT_CALL(sysWrapper, readlink(_, _, _)).Times(6); EXPECT_CALL(sysWrapper, stat(_,_)).Times(14); - + /* Test: detect devices, then open the device files */ castor::tape::SCSI::DeviceVector dl(sysWrapper); for (std::vector<castor::tape::SCSI::DeviceInfo>::iterator i = dl.begin(); i != dl.end(); i++) { if (castor::tape::SCSI::Types::tape == i->type) { + EXPECT_CALL(sysWrapper, ioctl(_, _, An<sg_io_hdr_t*>())).Times(1); std::unique_ptr<castor::tape::tapeserver::drive::DriveInterface> drive ( castor::tape::tapeserver::drive::createDrive(*i, sysWrapper)); @@ -227,11 +230,11 @@ TEST(castor_tape_drive_Drive, getDeviceInfo) { EXPECT_CALL(sysWrapper, readdir(_)).Times(AtLeast(30)); EXPECT_CALL(sysWrapper, closedir(_)).Times(AtLeast(4)); EXPECT_CALL(sysWrapper, realpath(_, _)).Times(6); - EXPECT_CALL(sysWrapper, open(_, _)).Times(42); + EXPECT_CALL(sysWrapper, open(_, _)).Times(46); EXPECT_CALL(sysWrapper, read(_, _, _)).Times(76); EXPECT_CALL(sysWrapper, write(_, _, _)).Times(0); EXPECT_CALL(sysWrapper, ioctl(_,_,An<mtget*>())).Times(0); - EXPECT_CALL(sysWrapper, close(_)).Times(42); + EXPECT_CALL(sysWrapper, close(_)).Times(46); EXPECT_CALL(sysWrapper, readlink(_, _, _)).Times(6); EXPECT_CALL(sysWrapper, stat(_,_)).Times(14); @@ -240,6 +243,7 @@ TEST(castor_tape_drive_Drive, getDeviceInfo) { for (std::vector<castor::tape::SCSI::DeviceInfo>::iterator i = dl.begin(); i != dl.end(); i++) { if (castor::tape::SCSI::Types::tape == i->type) { + EXPECT_CALL(sysWrapper, ioctl(_, _, An<sg_io_hdr_t*>())).Times(1); std::unique_ptr<castor::tape::tapeserver::drive::DriveInterface> drive ( castor::tape::tapeserver::drive::createDrive(*i, sysWrapper)); castor::tape::tapeserver::drive::deviceInfo devInfo; @@ -378,19 +382,20 @@ TEST(castor_tape_drive_Drive, getLBPInfo) { EXPECT_CALL(sysWrapper, readdir(_)).Times(AtLeast(30)); EXPECT_CALL(sysWrapper, closedir(_)).Times(AtLeast(3)); EXPECT_CALL(sysWrapper, realpath(_, _)).Times(6); - EXPECT_CALL(sysWrapper, open(_, _)).Times(42); + EXPECT_CALL(sysWrapper, open(_, _)).Times(46); EXPECT_CALL(sysWrapper, read(_, _, _)).Times(76); EXPECT_CALL(sysWrapper, write(_, _, _)).Times(0); EXPECT_CALL(sysWrapper, ioctl(_,_,An<mtget*>())).Times(0); - EXPECT_CALL(sysWrapper, close(_)).Times(42); + EXPECT_CALL(sysWrapper, close(_)).Times(46); EXPECT_CALL(sysWrapper, readlink(_, _, _)).Times(6); - EXPECT_CALL(sysWrapper, stat(_,_)).Times(14); - + EXPECT_CALL(sysWrapper, stat(_, _)).Times(14); + /* Test: detect devices, then open the device files */ castor::tape::SCSI::DeviceVector dl(sysWrapper); for (std::vector<castor::tape::SCSI::DeviceInfo>::iterator i = dl.begin(); i != dl.end(); i++) { if (castor::tape::SCSI::Types::tape == i->type) { + EXPECT_CALL(sysWrapper, ioctl(_, _, An<sg_io_hdr_t*>())).Times(1); std::unique_ptr<castor::tape::tapeserver::drive::DriveInterface> drive ( castor::tape::tapeserver::drive::createDrive(*i, sysWrapper)); castor::tape::tapeserver::drive::LBPInfo LBPdata; @@ -417,19 +422,20 @@ TEST(castor_tape_drive_Drive, setLogicalBlockProtection) { EXPECT_CALL(sysWrapper, readdir(_)).Times(AtLeast(30)); EXPECT_CALL(sysWrapper, closedir(_)).Times(AtLeast(3)); EXPECT_CALL(sysWrapper, realpath(_, _)).Times(6); - EXPECT_CALL(sysWrapper, open(_, _)).Times(42); + EXPECT_CALL(sysWrapper, open(_, _)).Times(46); EXPECT_CALL(sysWrapper, read(_, _, _)).Times(76); EXPECT_CALL(sysWrapper, write(_, _, _)).Times(0); EXPECT_CALL(sysWrapper, ioctl(_,_,An<mtget*>())).Times(0); - EXPECT_CALL(sysWrapper, close(_)).Times(42); + EXPECT_CALL(sysWrapper, close(_)).Times(46); EXPECT_CALL(sysWrapper, readlink(_, _, _)).Times(6); EXPECT_CALL(sysWrapper, stat(_,_)).Times(14); - + /* Test: detect devices, then open the device files */ castor::tape::SCSI::DeviceVector dl(sysWrapper); for (std::vector<castor::tape::SCSI::DeviceInfo>::iterator i = dl.begin(); i != dl.end(); i++) { if (castor::tape::SCSI::Types::tape == i->type) { + EXPECT_CALL(sysWrapper, ioctl(_, _, An<sg_io_hdr_t*>())).Times(1); std::unique_ptr<castor::tape::tapeserver::drive::DriveInterface> drive ( castor::tape::tapeserver::drive::createDrive(*i, sysWrapper)); castor::tape::tapeserver::drive::LBPInfo LBPdata; @@ -462,19 +468,20 @@ TEST(castor_tape_drive_Drive, disableLogicalBlockProtection) { EXPECT_CALL(sysWrapper, readdir(_)).Times(AtLeast(30)); EXPECT_CALL(sysWrapper, closedir(_)).Times(AtLeast(3)); EXPECT_CALL(sysWrapper, realpath(_, _)).Times(6); - EXPECT_CALL(sysWrapper, open(_, _)).Times(42); + EXPECT_CALL(sysWrapper, open(_, _)).Times(46); EXPECT_CALL(sysWrapper, read(_, _, _)).Times(76); EXPECT_CALL(sysWrapper, write(_, _, _)).Times(0); EXPECT_CALL(sysWrapper, ioctl(_,_,An<mtget*>())).Times(0); - EXPECT_CALL(sysWrapper, close(_)).Times(42); + EXPECT_CALL(sysWrapper, close(_)).Times(46); EXPECT_CALL(sysWrapper, readlink(_, _, _)).Times(6); EXPECT_CALL(sysWrapper, stat(_,_)).Times(14); - + /* Test: detect devices, then open the device files */ castor::tape::SCSI::DeviceVector dl(sysWrapper); for (std::vector<castor::tape::SCSI::DeviceInfo>::iterator i = dl.begin(); i != dl.end(); i++) { if (castor::tape::SCSI::Types::tape == i->type) { + EXPECT_CALL(sysWrapper, ioctl(_, _, An<sg_io_hdr_t*>())).Times(1); std::unique_ptr<castor::tape::tapeserver::drive::DriveInterface> drive ( castor::tape::tapeserver::drive::createDrive(*i, sysWrapper)); castor::tape::tapeserver::drive::LBPInfo LBPdata; @@ -507,7 +514,7 @@ TEST(castor_tape_drive_Drive, getReadErrors) { EXPECT_CALL(sysWrapper, read(_, _, _)).Times(AtLeast(76)); EXPECT_CALL(sysWrapper, write(_, _, _)).Times(0); EXPECT_CALL(sysWrapper, ioctl(_, _, An<mtget*>())).Times(0); - EXPECT_CALL(sysWrapper, ioctl(_, _, An<sg_io_hdr_t *>())).Times(4); + EXPECT_CALL(sysWrapper, ioctl(_, _, An<sg_io_hdr_t*>())).Times(8); EXPECT_CALL(sysWrapper, close(_)).Times(AtLeast(42)); EXPECT_CALL(sysWrapper, readlink(_, _, _)).Times(AtLeast(6)); EXPECT_CALL(sysWrapper, stat(_, _)).Times(AtLeast(14)); @@ -550,7 +557,7 @@ TEST(castor_tape_drive_Drive, getWriteErrors) { EXPECT_CALL(sysWrapper, read(_, _, _)).Times(AtLeast(76)); EXPECT_CALL(sysWrapper, write(_, _, _)).Times(0); EXPECT_CALL(sysWrapper, ioctl(_, _, An<mtget*>())).Times(0); - EXPECT_CALL(sysWrapper, ioctl(_, _, An<sg_io_hdr_t *>())).Times(4); + EXPECT_CALL(sysWrapper, ioctl(_, _, An<sg_io_hdr_t*>())).Times(8); EXPECT_CALL(sysWrapper, close(_)).Times(AtLeast(42)); EXPECT_CALL(sysWrapper, readlink(_, _, _)).Times(AtLeast(6)); EXPECT_CALL(sysWrapper, stat(_, _)).Times(AtLeast(14)); @@ -593,7 +600,7 @@ TEST(castor_tape_drive_Drive, getNonMediumErrors) { EXPECT_CALL(sysWrapper, read(_, _, _)).Times(AtLeast(76)); EXPECT_CALL(sysWrapper, write(_, _, _)).Times(0); EXPECT_CALL(sysWrapper, ioctl(_, _, An<mtget*>())).Times(0); - EXPECT_CALL(sysWrapper, ioctl(_, _, An<sg_io_hdr_t *>())).Times(4); + EXPECT_CALL(sysWrapper, ioctl(_, _, An<sg_io_hdr_t*>())).Times(8); EXPECT_CALL(sysWrapper, close(_)).Times(AtLeast(42)); EXPECT_CALL(sysWrapper, readlink(_, _, _)).Times(AtLeast(6)); EXPECT_CALL(sysWrapper, stat(_, _)).Times(AtLeast(14)); @@ -634,7 +641,7 @@ TEST(castor_tape_drive_Drive, getVolumeStats) { EXPECT_CALL(sysWrapper, read(_, _, _)).Times(AtLeast(76)); EXPECT_CALL(sysWrapper, write(_, _, _)).Times(0); EXPECT_CALL(sysWrapper, ioctl(_, _, An<mtget*>())).Times(0); - EXPECT_CALL(sysWrapper, ioctl(_, _, An<sg_io_hdr_t *>())).Times(2); + EXPECT_CALL(sysWrapper, ioctl(_, _, An<sg_io_hdr_t*>())).Times(6); EXPECT_CALL(sysWrapper, close(_)).Times(AtLeast(42)); EXPECT_CALL(sysWrapper, readlink(_, _, _)).Times(AtLeast(6)); EXPECT_CALL(sysWrapper, stat(_, _)).Times(AtLeast(14)); @@ -687,7 +694,7 @@ TEST(castor_tape_drive_Drive, getQualityStats) { EXPECT_CALL(sysWrapper, read(_, _, _)).Times(AtLeast(76)); EXPECT_CALL(sysWrapper, write(_, _, _)).Times(0); EXPECT_CALL(sysWrapper, ioctl(_, _, An<mtget*>())).Times(0); - EXPECT_CALL(sysWrapper, ioctl(_, _, An<sg_io_hdr_t *>())).Times(10); + EXPECT_CALL(sysWrapper, ioctl(_, _, An<sg_io_hdr_t*>())).Times(14); EXPECT_CALL(sysWrapper, close(_)).Times(AtLeast(42)); EXPECT_CALL(sysWrapper, readlink(_, _, _)).Times(AtLeast(6)); EXPECT_CALL(sysWrapper, stat(_, _)).Times(AtLeast(14)); @@ -758,7 +765,7 @@ TEST(castor_tape_drive_Drive, getDriveStats) { EXPECT_CALL(sysWrapper, read(_, _, _)).Times(AtLeast(76)); EXPECT_CALL(sysWrapper, write(_, _, _)).Times(0); EXPECT_CALL(sysWrapper, ioctl(_, _, An<mtget*>())).Times(0); - EXPECT_CALL(sysWrapper, ioctl(_, _, An<sg_io_hdr_t *>())).Times(8); + EXPECT_CALL(sysWrapper, ioctl(_, _, An<sg_io_hdr_t*>())).Times(12); EXPECT_CALL(sysWrapper, close(_)).Times(AtLeast(42)); EXPECT_CALL(sysWrapper, readlink(_, _, _)).Times(AtLeast(6)); EXPECT_CALL(sysWrapper, stat(_, _)).Times(AtLeast(14)); @@ -837,6 +844,7 @@ TEST(castor_tape_drive_Drive, getTapeAlerts) { for (std::vector<castor::tape::SCSI::DeviceInfo>::iterator i = dl.begin(); i != dl.end(); i++) { if (castor::tape::SCSI::Types::tape == i->type) { + EXPECT_CALL(sysWrapper, ioctl(_, _, An<sg_io_hdr_t*>())).Times(1); std::unique_ptr<castor::tape::tapeserver::drive::DriveInterface> drive ( castor::tape::tapeserver::drive::createDrive(*i, sysWrapper)); EXPECT_CALL(sysWrapper, ioctl(_, _, An<sg_io_hdr_t*>())).Times(1);