DataTransferSessionTest.cpp 51.8 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/******************************************************************************
 *
 * 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
 *****************************************************************************/

24
25
26
27
#define __STDC_CONSTANT_MACROS // For using stdint macros (stdint is included
// by inttypes.h, so we shoot first)
#include <stdint.h>
#include <inttypes.h>
28
#include <gtest/gtest.h>
29

30
#include "castor/legacymsg/RmcProxyDummy.hpp"
31
#include "castor/log/StringLogger.hpp"
32
33
34
#include "castor/mediachanger/MediaChangerFacade.hpp"
#include "castor/mediachanger/MmcProxyDummy.hpp"
#include "castor/messages/AcsProxyDummy.hpp"
35
#include "castor/messages/TapeserverProxyDummy.hpp"
36
#include "castor/server/ProcessCapDummy.hpp"
37
#include "castor/server/Threading.hpp"
38
#include "castor/tape/tapeserver/daemon/DataTransferSession.hpp"
39
#include "castor/tape/tapeserver/daemon/VolumeInfo.hpp"
40
41
#include "castor/tape/tapeserver/system/Wrapper.hpp"
#include "castor/tape/tapeserver/file/File.hpp"
42
#include "castor/tape/tapeserver/drive/FakeDrive.hpp"
43
44
#include "common/exception/Exception.hpp"
#include "common/Utils.hpp"
45
#include "Ctape.h"
46
#include "scheduler/Scheduler.hpp"
47
#include "smc_struct.h"
48
49
#include "nameserver/mockNS/MockNameServer.hpp"
#include "remotens/MockRemoteNS.hpp"
50
#include "remotens/MockRemoteFullFS.hpp"
51
#include "scheduler/DummyScheduler.hpp"
52
#include "scheduler/OStoreDB/OStoreDBFactory.hpp"
53
#include "scheduler/MountType.hpp"
54
55
56
57
#include "nameserver/NameServer.hpp"
#include "scheduler/testingMocks/MockRetrieveMount.hpp"
#include "scheduler/testingMocks/MockArchiveJob.hpp"
#include "scheduler/testingMocks/MockArchiveMount.hpp"
58

59
#include <dirent.h>
60
#include <fcntl.h>
61
#include <stdexcept>
Eric Cano's avatar
Eric Cano committed
62
63
64
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
65
66
#include <unistd.h>
#include <zlib.h>
Eric Cano's avatar
Eric Cano committed
67

68
using namespace castor::tape::tapeserver;
69
using namespace castor::tape::tapeserver::daemon;
70
71
namespace unitTest {

72
73
class castor_tape_tapeserver_daemon_DataTransferSessionTest: public
  ::testing::Test {
74
75
76
protected:

  void SetUp() {
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
    strncpy(m_tmpDir, "/tmp/DataTransferSessionTestXXXXXX", sizeof(m_tmpDir));
    if(!mkdtemp(m_tmpDir)) {
      const std::string errMsg = cta::Utils::errnoToString(errno);
      std::ostringstream msg;
      msg << "Failed to create directory with template"
        " /tmp/DataTransferSessionTestXXXXXX: " << errMsg;
      bzero(m_tmpDir, sizeof(m_tmpDir));
      throw cta::exception::Exception(msg.str());
    }

    struct stat statBuf;
    bzero(&statBuf, sizeof(statBuf));
    if(stat(m_tmpDir, &statBuf)) {
      const std::string errMsg = cta::Utils::errnoToString(errno);
      std::ostringstream msg;
      msg << "Failed to stat directory " << m_tmpDir << ": " << errMsg;
      throw cta::exception::Exception(msg.str());
    }

    std::ostringstream cmd;
    cmd << "touch " << m_tmpDir << "/hello";
    system(cmd.str().c_str());
99
100
101
  }

  void TearDown() {
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
    // If Setup() created a temporary directory
    if(m_tmpDir) {

      // Openn the directory
      std::unique_ptr<DIR, std::function<int(DIR*)>>
        dir(opendir(m_tmpDir), closedir);
      if(NULL == dir.get()) {
        const std::string errMsg = cta::Utils::errnoToString(errno);
        std::ostringstream msg;
        msg << "Failed to open directory " << m_tmpDir << ": " << errMsg;
        throw cta::exception::Exception(msg.str());
      }

      // Delete each of the files within the directory
      struct dirent *entry = NULL;
      while((entry = readdir(dir.get()))) {
        const std::string entryName(entry->d_name);
        if(entryName != "." && entryName != "..") {
          const std::string entryPath = std::string(m_tmpDir) + "/" + entryName;
          if(unlink(entryPath.c_str())) {
            const std::string errMsg = cta::Utils::errnoToString(errno);
            std::ostringstream msg;
            msg << "Failed to unlink " << entryPath;
            throw cta::exception::Exception(msg.str());
          }
        }
      }

      // Delete the now empty directory
      if(rmdir(m_tmpDir)) {
        const std::string errMsg = cta::Utils::errnoToString(errno);
        std::ostringstream msg;
        msg << "Failed to delete directory " << m_tmpDir << ": " << errMsg;
        throw cta::exception::Exception(msg.str());
      }
    }
138
  }
139

140
141
142
143
144
145
146
  /**
   * Temporary directory created with mkdtemp that will be used to contain the
   * destination remote files of the tests that need to create them.
   *
   * Please note that a new temporary directory is created and deleted for each
   * test by the Setup() and TearDown() methods.
   */
147
  char m_tmpDir[100];
148
149
};

150
TEST_F(castor_tape_tapeserver_daemon_DataTransferSessionTest, DataTransferSessionGooddayRecall) {
Eric Cano's avatar
Eric Cano committed
151
152
153
  // 0) Prepare the logger for everyone
  castor::log::StringLogger logger("tapeServerUnitTest");
  
154
  // 1) prepare the fake scheduler
155
  std::string vid = "V12345";
156
  // cta::MountType::Enum mountType = cta::MountType::RETRIEVE;
157
  std::string density = "8000GC";
158

159
160
  // 3) Prepare the necessary environment (logger, plus system wrapper), 
  castor::tape::System::mockWrapper mockSys;
161
162
  mockSys.delegateToFake();
  mockSys.disableGMockCallsCounting();
163
  mockSys.fake.setupForVirtualDriveSLC6();
164
165
166
  //delete is unnecessary
  //pointer with ownership will be passed to the application,
  //which will do the delete 
167
  mockSys.fake.m_pathToDrive["/dev/nst0"] = new castor::tape::tapeserver::drive::FakeDrive;
168
169
170
171

  // 4) Create the scheduler
  cta::MockNameServer ns;
  cta::MockRemoteNS rns;
172
  cta::OStoreDBWrapper<cta::objectstore::BackendVFS> db("Unittest");
173
174
175
176
177
178
179
180
  cta::Scheduler scheduler(ns, db, rns);

  // Always use the same requester
  const cta::SecurityIdentity requester;

  // List to remember the path of each remote file so that the existance of the
  // files can be tested for at the end of the test
  std::list<std::string> remoteFilePaths;
181
  
182
183
184
185
186
187
188
189
190
191
192
193
194
195
  // 5) Create the tapepool, library and tape for the scheduler.
  // Make mounts immediate.
  ASSERT_NO_THROW(scheduler.createAdminUserWithoutAuthorizingRequester(requester, requester.getUser(), ""));
  ASSERT_NO_THROW(scheduler.createAdminHostWithoutAuthorizingRequester(requester, requester.getHost(), ""));
  ASSERT_NO_THROW(scheduler.createTapePool(requester, "TapePool", 1, ""));
  cta::MountCriteria immediateMount;
  immediateMount.maxAge = 0;
  immediateMount.maxBytesQueued = 1;
  immediateMount.maxFilesQueued = 1;
  immediateMount.quota = 10;
  ASSERT_NO_THROW(scheduler.setTapePoolMountCriteria("TapePool", cta::MountCriteriaByDirection(immediateMount, immediateMount)));                   
  ASSERT_NO_THROW(scheduler.createLogicalLibrary(requester, "T10KD6", ""));
  ASSERT_NO_THROW(scheduler.createTape(requester, "V12345", "T10KD6", "TapePool", 10*1000*1000, "8000GC", ""));
  
196
  // 5) Prepare files for reading by writing them to the mock system
197
198
199
  {
    // Label the tape
    castor::tape::tapeFile::LabelSession ls(*mockSys.fake.m_pathToDrive["/dev/nst0"], 
200
        "V12345");
201
202
    mockSys.fake.m_pathToDrive["/dev/nst0"]->rewind();
    // And write to it
203
    castor::tape::tapeserver::daemon::VolumeInfo volInfo;
204
    volInfo.vid="V12345";
205
    castor::tape::tapeFile::WriteSession ws(*mockSys.fake.m_pathToDrive["/dev/nst0"],
206
       volInfo , 0, true);
207
208
209

    // Write a few files on the virtual tape and modify the archive name space
    // so that it is in sync
210
211
212
    uint8_t data[1000];
    castor::tape::SCSI::Structures::zeroStruct(&data);
    for (int fseq=1; fseq <= 10 ; fseq ++) {
213
214
      // Create a path to a remote destination file
      std::ostringstream remoteFilePath;
215
      remoteFilePath << "file://" << m_tmpDir << "/test" << fseq;
216
217
      remoteFilePaths.push_back(remoteFilePath.str());

218
      // Create an archive file entry in the archive namespace
219
220
221
222
      std::ostringstream archiveFilePath;
      archiveFilePath << "/test" << fseq;
      const mode_t archiveFileMode = 0655;
      const uint64_t archiveFileSize = 256*1024;
223
      ASSERT_NO_THROW(ns.createFile(
224
225
226
        requester,
        archiveFilePath.str(),
        archiveFileMode,
227
        archiveFileSize));
228
      std::unique_ptr<cta::ArchiveFileStatus> status = ns.statFile(requester, archiveFilePath.str());
229
      
230
      // Write the file to tape
231
232
233
234
235
      cta::MockRetrieveMount mrm;
      cta::MockNameServer mns;
      cta::MockArchiveMount mam(mns);
      std::unique_ptr<cta::RetrieveJob> ftr(new cta::MockRetrieveJob(mrm));
      std::unique_ptr<cta::ArchiveJob> ftm(new cta::MockArchiveJob(mam, mns));
236
      ftr->nameServerTapeFile.tapeFileLocation.fSeq = fseq;
237
      ftm->nameServerTapeFile.tapeFileLocation.fSeq = fseq;
238
239
      ftr->archiveFile.fileId = status->fileId;
      ftm->archiveFile.fileId = status->fileId;
240
      castor::tape::tapeFile::WriteFile wf(&ws, *ftm, archiveFileSize);
241
      ftr->nameServerTapeFile.tapeFileLocation.blockId = wf.getBlockId();
242
      ftr->remotePath = remoteFilePath.str();
243
244
245
246
      // Write the data (one block)
      wf.write(data, sizeof(data));
      // Close the file
      wf.close();
247

248
249
250
251
      // Create tape file entry in the archive namespace
      cta::NameServerTapeFile tapeFile;
      tapeFile.copyNb = 1;
      tapeFile.tapeFileLocation.fSeq = fseq;
252
      tapeFile.tapeFileLocation.blockId = wf.getBlockId();
253
254
255
256
257
258
259
260
261
262
263
264
      tapeFile.tapeFileLocation.vid = volInfo.vid;
      tapeFile.tapeFileLocation.copyNb = 1;
      tapeFile.size = archiveFileSize;
      tapeFile.compressedSize = archiveFileSize; // No compression
      cta::Checksum tapeFileChecksum(cta::Checksum::CHECKSUMTYPE_ADLER32,
        cta::ByteArray(cta::Utils::getAdler32(data, sizeof data)));
      tapeFile.checksum = tapeFileChecksum;
      ASSERT_NO_THROW(ns.addTapeFile(
        requester,
        archiveFilePath.str(),
        tapeFile));

265
266
267
      // Schedule the retrieval of the file
      std::list<std::string> archiveFilePaths;
      archiveFilePaths.push_back(archiveFilePath.str());
268
      ASSERT_NO_THROW(scheduler.queueRetrieveRequest(
269
270
        requester,
        archiveFilePaths,
271
        remoteFilePath.str()));
272
273
    }
  }
274
275

  // 6) Create the data transfer session
276
  DriveConfig driveConfig("T10D6116", "T10KD6", "/dev/tape_T10D6116", "manual");
277
278
279
280
281
282
  DataTransferConfig castorConf;
  castorConf.bufsz = 1024*1024; // 1 MB memory buffers
  castorConf.nbBufs = 10;
  castorConf.bulkRequestRecallMaxBytes = UINT64_C(100)*1000*1000*1000;
  castorConf.bulkRequestRecallMaxFiles = 1000;
  castorConf.nbDiskThreads = 1;
283
284
285
286
  castor::messages::AcsProxyDummy acs;
  castor::mediachanger::MmcProxyDummy mmc;
  castor::legacymsg::RmcProxyDummy rmc;
  castor::mediachanger::MediaChangerFacade mc(acs, mmc, rmc);
287
  castor::server::ProcessCap capUtils;
288
  castor::messages::TapeserverProxyDummy initialProcess;
289
  DataTransferSession sess("tapeHost", logger, mockSys,
290
    driveConfig, mc, initialProcess, capUtils, castorConf, scheduler);
291
292

  // 7) Run the data transfer session
293
  ASSERT_NO_THROW(sess.execute());
294
295

  // 8) Check the session git the correct VID
296
  ASSERT_EQ("V12345", sess.getVid());
297

298
  // 9) Check the remote files exist and have the correct size
299
300
301
302
  for(auto pathItor = remoteFilePaths.cbegin(); pathItor !=
    remoteFilePaths.cend(); pathItor++) {
    struct stat statBuf;
    bzero(&statBuf, sizeof(statBuf));
303
    const int statRc = stat(pathItor->substr(7).c_str(), &statBuf); //remove the "file://" for stat-ing
304
    ASSERT_EQ(0, statRc);
305
    ASSERT_EQ(1000, statBuf.st_size); //same size of data
306
  }
307
}
308

309
TEST_F(castor_tape_tapeserver_daemon_DataTransferSessionTest, DataTransferSessionWrongRecall) {
310
311
312
  // This test is the same as the previous one, with 
  // wrong parameters set for the recall, so that we fail 
  // to recall the first file and cancel the second.
313
314

  // 0) Prepare the logger for everyone
315
316
  castor::log::StringLogger logger("tapeServerUnitTest");
  
317
  // 1) prepare the fake scheduler
318
  std::string vid = "V12345";
319
  // cta::MountType::Enum mountType = cta::MountType::RETRIEVE;
320
  std::string density = "8000GC";
321

322
323
324
325
326
327
328
329
  // 3) Prepare the necessary environment (logger, plus system wrapper), 
  castor::tape::System::mockWrapper mockSys;
  mockSys.delegateToFake();
  mockSys.disableGMockCallsCounting();
  mockSys.fake.setupForVirtualDriveSLC6();
  //delete is unnecessary
  //pointer with ownership will be passed to the application,
  //which will do the delete 
330
  mockSys.fake.m_pathToDrive["/dev/nst0"] = new castor::tape::tapeserver::drive::FakeDrive;
331
332
333
334

  // 4) Create the scheduler
  cta::MockNameServer ns;
  cta::MockRemoteNS rns;
335
  cta::OStoreDBWrapper<cta::objectstore::BackendVFS> db("Unittest");
336
337
338
339
340
341
342
343
  cta::Scheduler scheduler(ns, db, rns);

  // Always use the same requester
  const cta::SecurityIdentity requester;

  // List to remember the path of each remote file so that the existance of the
  // files can be tested for at the end of the test
  std::list<std::string> remoteFilePaths;
344
  
345
346
347
348
349
350
351
352
353
354
355
356
357
358
  // 5) Create the tapepool, library and tape for the scheduler.
  // Make mounts immediate.
  ASSERT_NO_THROW(scheduler.createAdminUserWithoutAuthorizingRequester(requester, requester.getUser(), ""));
  ASSERT_NO_THROW(scheduler.createAdminHostWithoutAuthorizingRequester(requester, requester.getHost(), ""));
  ASSERT_NO_THROW(scheduler.createTapePool(requester, "TapePool", 1, ""));
  cta::MountCriteria immediateMount;
  immediateMount.maxAge = 0;
  immediateMount.maxBytesQueued = 1;
  immediateMount.maxFilesQueued = 1;
  immediateMount.quota = 10;
  ASSERT_NO_THROW(scheduler.setTapePoolMountCriteria("TapePool", cta::MountCriteriaByDirection(immediateMount, immediateMount)));                   
  ASSERT_NO_THROW(scheduler.createLogicalLibrary(requester, "T10KD6", ""));
  ASSERT_NO_THROW(scheduler.createTape(requester, "V12345", "T10KD6", "TapePool", 10*1000*1000, "8000GC", ""));
  
359
  // 5) Prepare files for reading by writing them to the mock system
360
361
362
  {
    // Label the tape
    castor::tape::tapeFile::LabelSession ls(*mockSys.fake.m_pathToDrive["/dev/nst0"], 
363
        "V12345");
364
365
    mockSys.fake.m_pathToDrive["/dev/nst0"]->rewind();
    // And write to it
366
    castor::tape::tapeserver::daemon::VolumeInfo volInfo;
367
368
369
    volInfo.vid="V12345";
    castor::tape::tapeFile::WriteSession ws(*mockSys.fake.m_pathToDrive["/dev/nst0"],
       volInfo , 0, true);
370
371
372

    // Write a few files on the virtual tape and modify the archive name space
    // so that it is in sync
373
374
    uint8_t data[1000];
    castor::tape::SCSI::Structures::zeroStruct(&data);
375
376
    int fseq=1;
    {
377
378
      // Create a path to a remote destination file
      std::ostringstream remoteFilePath;
379
      remoteFilePath << "file://" << m_tmpDir << "/test" << fseq;
380
381
      remoteFilePaths.push_back(remoteFilePath.str());

382
      // Create an archive file entry in the archive namespace
383
384
385
      std::ostringstream archiveFilePath;
      archiveFilePath << "/test" << fseq;
      const mode_t archiveFileMode = 0655;
386
      const uint64_t archiveFileSize = 1000;
387
      ASSERT_NO_THROW(ns.createFile(
388
389
390
        requester,
        archiveFilePath.str(),
        archiveFileMode,
391
        archiveFileSize));
392
393

      // Write the file to tape
394
395
396
397
398
      cta::MockNameServer mns;
      cta::MockArchiveMount mam(mns);
      cta::MockRetrieveMount mrm;
      std::unique_ptr<cta::RetrieveJob> ftr(new cta::MockRetrieveJob(mrm));
      std::unique_ptr<cta::ArchiveJob> ftm_temp(new cta::MockArchiveJob(mam, mns));
399
      ftr->nameServerTapeFile.tapeFileLocation.fSeq = fseq;
400
      ftm_temp->nameServerTapeFile.tapeFileLocation.fSeq = fseq;
401
402
      ftr->archiveFile.fileId = 1000 + fseq;
      ftm_temp->archiveFile.fileId = 1000 + fseq;
403
      castor::tape::tapeFile::WriteFile wf(&ws, *ftm_temp, archiveFileSize);
404
      ftr->nameServerTapeFile.tapeFileLocation.blockId = wf.getBlockId();
405
      ftr->remotePath = remoteFilePath.str();
406
407
408
409
      // Write the data (one block)
      wf.write(data, sizeof(data));
      // Close the file
      wf.close();
410

411
412
413
414
415
      // Create tape file entry in the archive namespace that is beyond the end
      // of data
      cta::NameServerTapeFile tapeFile;
      tapeFile.copyNb = 1;
      tapeFile.tapeFileLocation.fSeq = fseq + 10000;
416
      tapeFile.tapeFileLocation.blockId = wf.getBlockId() + 10000;
417
418
419
420
421
422
423
424
425
426
427
428
      tapeFile.tapeFileLocation.vid = volInfo.vid;
      tapeFile.tapeFileLocation.copyNb = 1;
      tapeFile.size = archiveFileSize;
      tapeFile.compressedSize = archiveFileSize; // No compression
      cta::Checksum tapeFileChecksum(cta::Checksum::CHECKSUMTYPE_ADLER32,
        cta::ByteArray(cta::Utils::getAdler32(data, sizeof data)));
      tapeFile.checksum = tapeFileChecksum;
      ASSERT_NO_THROW(ns.addTapeFile(
        requester,
        archiveFilePath.str(),
        tapeFile));

429
430
431
      // Schedule the retrieval of the file
      std::list<std::string> archiveFilePaths;
      archiveFilePaths.push_back(archiveFilePath.str());
432
      ASSERT_NO_THROW(scheduler.queueRetrieveRequest(
433
434
        requester,
        archiveFilePaths,
435
        remoteFilePath.str()));
436
437
    }
  }
438
439

  // 6) Create the data transfer session
440
  DriveConfig driveConfig("T10D6116", "T10KD6", "/dev/tape_T10D6116", "manual");
441
442
443
444
445
446
  DataTransferConfig castorConf;
  castorConf.bufsz = 1024*1024; // 1 MB memory buffers
  castorConf.nbBufs = 10;
  castorConf.bulkRequestRecallMaxBytes = UINT64_C(100)*1000*1000*1000;
  castorConf.bulkRequestRecallMaxFiles = 1000;
  castorConf.nbDiskThreads = 1;
447
448
449
450
  castor::messages::AcsProxyDummy acs;
  castor::mediachanger::MmcProxyDummy mmc;
  castor::legacymsg::RmcProxyDummy rmc;
  castor::mediachanger::MediaChangerFacade mc(acs, mmc, rmc);
451
452
  castor::server::ProcessCap capUtils;
  castor::messages::TapeserverProxyDummy initialProcess;
453
  DataTransferSession sess("tapeHost", logger, mockSys,
454
    driveConfig, mc, initialProcess, capUtils, castorConf, scheduler);
455
456
457
458
459

  // 7) Run the data transfer session
  ASSERT_NO_THROW(sess.execute());

  // 8) Check the session git the correct VID
460
  ASSERT_EQ("V12345", sess.getVid());
461
462

  // 9) Check the remote files exist and have the correct size
463
464
  std::string temp = logger.getLog();
  ASSERT_NE(std::string::npos, logger.getLog().find("trying to position beyond the end of data"));
465
}
466

467
TEST_F(castor_tape_tapeserver_daemon_DataTransferSessionTest, DataTransferSessionNoSuchDrive) {
468
469
470
471
472
  
  // 0) Prepare the logger for everyone
  castor::log::StringLogger logger("tapeServerUnitTest");
  
  // 1) prepare the fake scheduler
473
  std::string vid = "V12345";
474
  // cta::MountType::Enum mountType = cta::MountType::RETRIEVE;
475
  std::string density = "8000GC";
476

477
478
479
480
481
  // 3) Prepare the necessary environment (logger, plus system wrapper), 
  castor::tape::System::mockWrapper mockSys;
  mockSys.delegateToFake();
  mockSys.disableGMockCallsCounting();
  mockSys.fake.setupForVirtualDriveSLC6();
482
483
484
485
486
487
488
489
  //delete is unnecessary
  //pointer with ownership will be passed to the application,
  //which will do the delete 
  mockSys.fake.m_pathToDrive["/dev/nst0"] = new castor::tape::tapeserver::drive::FakeDrive;

  // 4) Create the scheduler
  cta::MockNameServer ns;
  cta::MockRemoteNS rns;
490
  cta::OStoreDBWrapper<cta::objectstore::BackendVFS> db("Unittest");
491
492
493
494
495
  cta::Scheduler scheduler(ns, db, rns);

  // Always use the same requester
  const cta::SecurityIdentity requester;
  
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
  // List to remember the path of each remote file so that the existance of the
  // files can be tested for at the end of the test
  std::list<std::string> remoteFilePaths;
  
  // 5) Create the tapepool, library and tape for the scheduler.
  // Make mounts immediate.
  ASSERT_NO_THROW(scheduler.createAdminUserWithoutAuthorizingRequester(requester, requester.getUser(), ""));
  ASSERT_NO_THROW(scheduler.createAdminHostWithoutAuthorizingRequester(requester, requester.getHost(), ""));
  ASSERT_NO_THROW(scheduler.createTapePool(requester, "TapePool", 1, ""));
  cta::MountCriteria immediateMount;
  immediateMount.maxAge = 0;
  immediateMount.maxBytesQueued = 1;
  immediateMount.maxFilesQueued = 1;
  immediateMount.quota = 10;
  ASSERT_NO_THROW(scheduler.setTapePoolMountCriteria("TapePool", cta::MountCriteriaByDirection(immediateMount, immediateMount)));                   
  ASSERT_NO_THROW(scheduler.createLogicalLibrary(requester, "T10KD6", ""));
  ASSERT_NO_THROW(scheduler.createTape(requester, "V12345", "T10KD6", "TapePool", 10*1000*1000, "8000GC", ""));
  
  // 5) Prepare files for reading by writing them to the mock system
  {
    // Label the tape
    castor::tape::tapeFile::LabelSession ls(*mockSys.fake.m_pathToDrive["/dev/nst0"], 
        "V12345");
    mockSys.fake.m_pathToDrive["/dev/nst0"]->rewind();
    // And write to it
    castor::tape::tapeserver::daemon::VolumeInfo volInfo;
    volInfo.vid="V12345";
    castor::tape::tapeFile::WriteSession ws(*mockSys.fake.m_pathToDrive["/dev/nst0"],
       volInfo , 0, true);

    // Write a few files on the virtual tape and modify the archive name space
    // so that it is in sync
    uint8_t data[1000];
    castor::tape::SCSI::Structures::zeroStruct(&data);
    int fseq=1;
    {
      // Create a path to a remote destination file
      std::ostringstream remoteFilePath;
      remoteFilePath << "file://" << m_tmpDir << "/test" << fseq;
      remoteFilePaths.push_back(remoteFilePath.str());

      // Create an archive file entry in the archive namespace
      std::ostringstream archiveFilePath;
      archiveFilePath << "/test" << fseq;
      const mode_t archiveFileMode = 0655;
      const uint64_t archiveFileSize = 1000;
      ASSERT_NO_THROW(ns.createFile(
        requester,
        archiveFilePath.str(),
        archiveFileMode,
        archiveFileSize));

      // Write the file to tape
549
550
551
552
553
      cta::MockNameServer mns;
      cta::MockArchiveMount mam(mns);
      cta::MockRetrieveMount mrm;
      std::unique_ptr<cta::RetrieveJob> ftr(new cta::MockRetrieveJob(mrm));
      std::unique_ptr<cta::ArchiveJob> ftm_temp(new cta::MockArchiveJob(mam, mns));
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
      ftr->nameServerTapeFile.tapeFileLocation.fSeq = fseq;
      ftm_temp->nameServerTapeFile.tapeFileLocation.fSeq = fseq;
      ftr->archiveFile.fileId = 1000 + fseq;
      ftm_temp->archiveFile.fileId = 1000 + fseq;
      castor::tape::tapeFile::WriteFile wf(&ws, *ftm_temp, archiveFileSize);
      ftr->nameServerTapeFile.tapeFileLocation.blockId = wf.getBlockId();
      ftr->remotePath = remoteFilePath.str();
      // Write the data (one block)
      wf.write(data, sizeof(data));
      // Close the file
      wf.close();

      // Create tape file entry in the archive namespace that is beyond the end
      // of data
      cta::NameServerTapeFile tapeFile;
      tapeFile.copyNb = 1;
      tapeFile.tapeFileLocation.fSeq = fseq + 1000;
      tapeFile.tapeFileLocation.blockId = wf.getBlockId();
      tapeFile.tapeFileLocation.vid = volInfo.vid;
      tapeFile.tapeFileLocation.copyNb = 1;
      tapeFile.size = archiveFileSize;
      tapeFile.compressedSize = archiveFileSize; // No compression
      cta::Checksum tapeFileChecksum(cta::Checksum::CHECKSUMTYPE_ADLER32,
        cta::ByteArray(cta::Utils::getAdler32(data, sizeof data)));
      tapeFile.checksum = tapeFileChecksum;
      ASSERT_NO_THROW(ns.addTapeFile(
        requester,
        archiveFilePath.str(),
        tapeFile));

      // Schedule the retrieval of the file
      std::list<std::string> archiveFilePaths;
      archiveFilePaths.push_back(archiveFilePath.str());
      ASSERT_NO_THROW(scheduler.queueRetrieveRequest(
        requester,
        archiveFilePaths,
        remoteFilePath.str()));
    }
  }
  
  DriveConfig driveConfig("T10D6116", "T10KD6", "/dev/noSuchDrive", "manual");
595
596
597
  DataTransferConfig castorConf;
  castorConf.bufsz = 1024;
  castorConf.nbBufs = 10;
598
599
600
601
  castor::messages::AcsProxyDummy acs;
  castor::mediachanger::MmcProxyDummy mmc;
  castor::legacymsg::RmcProxyDummy rmc;
  castor::mediachanger::MediaChangerFacade mc(acs, mmc, rmc);
602
  castor::messages::TapeserverProxyDummy initialProcess;
603
  castor::server::ProcessCapDummy capUtils;
604
  DataTransferSession sess("tapeHost", logger, mockSys,
605
    driveConfig, mc, initialProcess, capUtils, castorConf, scheduler);
606
  ASSERT_NO_THROW(sess.execute());
607
  std::string temp = logger.getLog();
608
  ASSERT_NE(std::string::npos, logger.getLog().find("Could not stat path: /dev/noSuchDrive"));
609
610
}

611
TEST_F(castor_tape_tapeserver_daemon_DataTransferSessionTest, DataTransferSessionFailtoMount) {
612
613
  
  // 0) Prepare the logger for everyone
614
615
  castor::log::StringLogger logger("tapeServerUnitTest");
  
616
  // 1) prepare the fake scheduler
617
  std::string vid = "V12345";
618
  // cta::MountType::Enum mountType = cta::MountType::RETRIEVE;
619
  std::string density = "8000GC";
620

621
622
623
624
625
  // 3) Prepare the necessary environment (logger, plus system wrapper), 
  castor::tape::System::mockWrapper mockSys;
  mockSys.delegateToFake();
  mockSys.disableGMockCallsCounting();
  mockSys.fake.setupForVirtualDriveSLC6();
626
627
628
629
630
631
632
633
  //delete is unnecessary
  //pointer with ownership will be passed to the application,
  //which will do the delete 
  mockSys.fake.m_pathToDrive["/dev/nst0"] = new castor::tape::tapeserver::drive::FakeDrive;

  // 4) Create the scheduler
  cta::MockNameServer ns;
  cta::MockRemoteNS rns;
634
  cta::OStoreDBWrapper<cta::objectstore::BackendVFS> db("Unittest");
635
636
637
638
639
640
641
642
  cta::Scheduler scheduler(ns, db, rns);

  // Always use the same requester
  const cta::SecurityIdentity requester;
  
  // List to remember the path of each remote file so that the existance of the
  // files can be tested for at the end of the test
  std::list<std::string> remoteFilePaths;
643
644
645
646
647
648
649
650
651
652
653
654
655
656
  
  // 5) Create the tapepool, library and tape for the scheduler.
  // Make mounts immediate.
  ASSERT_NO_THROW(scheduler.createAdminUserWithoutAuthorizingRequester(requester, requester.getUser(), ""));
  ASSERT_NO_THROW(scheduler.createAdminHostWithoutAuthorizingRequester(requester, requester.getHost(), ""));
  ASSERT_NO_THROW(scheduler.createTapePool(requester, "TapePool", 1, ""));
  cta::MountCriteria immediateMount;
  immediateMount.maxAge = 0;
  immediateMount.maxBytesQueued = 1;
  immediateMount.maxFilesQueued = 1;
  immediateMount.quota = 10;
  ASSERT_NO_THROW(scheduler.setTapePoolMountCriteria("TapePool", cta::MountCriteriaByDirection(immediateMount, immediateMount)));                   
  ASSERT_NO_THROW(scheduler.createLogicalLibrary(requester, "T10KD6", ""));
  ASSERT_NO_THROW(scheduler.createTape(requester, "V12345", "T10KD6", "TapePool", 10*1000*1000, "8000GC", ""));
657
658
659
660
661
662
663
664
665

  //delete is unnecessary
  //pointer with ownership will be passed to the application,
  //which will do the delete 
  const bool failOnMount=true;
  mockSys.fake.m_pathToDrive["/dev/nst0"] = new castor::tape::tapeserver::drive::FakeDrive(failOnMount);
  
  // We can prepare files for reading on the drive
  {
666
    
667
668
    // Label the tape
    castor::tape::tapeFile::LabelSession ls(*mockSys.fake.m_pathToDrive["/dev/nst0"], 
669
        "V12345");
670
671
    mockSys.fake.m_pathToDrive["/dev/nst0"]->rewind();
    // And write to it
672
    castor::tape::tapeserver::daemon::VolumeInfo volInfo;
673
    volInfo.vid="V12345";
674
675
676
677
678
679
680
    castor::tape::tapeFile::WriteSession ws(*mockSys.fake.m_pathToDrive["/dev/nst0"],
       volInfo , 0, true);

    // Write a few files on the virtual tape and modify the archive name space
    // so that it is in sync
    uint8_t data[1000];
    castor::tape::SCSI::Structures::zeroStruct(&data);
681
    for (int fseq=1; fseq <= 10 ; fseq ++) {
682
683
      // Create a path to a remote destination file
      std::ostringstream remoteFilePath;
684
      remoteFilePath << "file://" << m_tmpDir << "/test" << fseq;
685
686
      remoteFilePaths.push_back(remoteFilePath.str());

687
      // Create an archive file entry in the archive namespace
688
689
690
      std::ostringstream archiveFilePath;
      archiveFilePath << "/test" << fseq;
      const mode_t archiveFileMode = 0655;
691
      const uint64_t archiveFileSize = 1000;
692
      ASSERT_NO_THROW(ns.createFile(
693
694
695
        requester,
        archiveFilePath.str(),
        archiveFileMode,
696
        archiveFileSize));
697
698

      // Write the file to tape
699
700
701
702
703
      cta::MockNameServer  mns;
      cta::MockArchiveMount mam(mns);
      cta::MockRetrieveMount mrm;
      std::unique_ptr<cta::RetrieveJob> ftr(new cta::MockRetrieveJob(mrm));
      std::unique_ptr<cta::ArchiveJob> ftm_temp(new cta::MockArchiveJob(mam, mns));
704
      ftr->nameServerTapeFile.tapeFileLocation.fSeq = fseq;
705
      ftm_temp->nameServerTapeFile.tapeFileLocation.fSeq = fseq;
706
      ftr->archiveFile.fileId = 1000 + fseq;
707
708
      ftm_temp->archiveFile.fileId = 1000 + fseq;
      castor::tape::tapeFile::WriteFile wf(&ws, *ftm_temp, archiveFileSize);
709
710
      ftr->nameServerTapeFile.tapeFileLocation.blockId = wf.getPosition();
      ftr->remotePath = remoteFilePath.str();
711
712
713
714
715
      // Write the data (one block)
      wf.write(data, sizeof(data));
      // Close the file
      wf.close();

716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
      // Create tape file entry in the archive namespace
      cta::NameServerTapeFile tapeFile;
      tapeFile.copyNb = 1;
      tapeFile.tapeFileLocation.fSeq = fseq;
      tapeFile.tapeFileLocation.blockId = wf.getPosition();
      tapeFile.tapeFileLocation.vid = volInfo.vid;
      tapeFile.tapeFileLocation.copyNb = 1;
      tapeFile.size = archiveFileSize;
      tapeFile.compressedSize = archiveFileSize; // No compression
      cta::Checksum tapeFileChecksum(cta::Checksum::CHECKSUMTYPE_ADLER32,
        cta::ByteArray(cta::Utils::getAdler32(data, sizeof data)));
      tapeFile.checksum = tapeFileChecksum;
      ASSERT_NO_THROW(ns.addTapeFile(
        requester,
        archiveFilePath.str(),
        tapeFile));

733
734
735
      // Schedule the retrieval of the file
      std::list<std::string> archiveFilePaths;
      archiveFilePaths.push_back(archiveFilePath.str());
736
      ASSERT_NO_THROW(scheduler.queueRetrieveRequest(
737
738
        requester,
        archiveFilePaths,
739
        remoteFilePath.str()));
740
741
    }
  }
742
  DriveConfig driveConfig("T10D6116", "T10KD6", "/dev/tape_T10D6116", "manual");
743
744
745
746
747
748
749
750
751
752
753
754
  DataTransferConfig castorConf;
  castorConf.bufsz = 1024*1024; // 1 MB memory buffers
  castorConf.nbBufs = 10;
  castorConf.bulkRequestRecallMaxBytes = UINT64_C(100)*1000*1000*1000;
  castorConf.bulkRequestRecallMaxFiles = 1000;
  castorConf.nbDiskThreads = 3;
  castor::messages::AcsProxyDummy acs;
  castor::mediachanger::MmcProxyDummy mmc;
  castor::legacymsg::RmcProxyDummy rmc;
  castor::mediachanger::MediaChangerFacade mc(acs, mmc, rmc);
  castor::server::ProcessCap capUtils;
  castor::messages::TapeserverProxyDummy initialProcess;
755
  DataTransferSession sess("tapeHost", logger, mockSys,
756
    driveConfig, mc, initialProcess, capUtils, castorConf, scheduler);
757
  ASSERT_NO_THROW(sess.execute());
758
  std::string temp = logger.getLog();
759
  ASSERT_NE(std::string::npos, logger.getLog().find("Failed to mount the tape"));
760
761
}

762
TEST_F(castor_tape_tapeserver_daemon_DataTransferSessionTest, DataTransferSessionEmptyOnVolReq) {
763
764
  
  // 0) Prepare the logger for everyone
765
766
  castor::log::StringLogger logger("tapeServerUnitTest");
  
767
  // 1) prepare the fake scheduler
768
  std::string vid = "V12345";
769
  // cta::MountType::Enum mountType = cta::MountType::RETRIEVE;
770
  std::string density = "8000GC";
771

772
773
774
775
776
  // 3) Prepare the necessary environment (logger, plus system wrapper), 
  castor::tape::System::mockWrapper mockSys;
  mockSys.delegateToFake();
  mockSys.disableGMockCallsCounting();
  mockSys.fake.setupForVirtualDriveSLC6();
777
  
778
779
780
  // The drive will not even be opened. so no need for one.
  mockSys.fake.m_pathToDrive["/dev/nst0"] = NULL;
  
781
782
783
  // 4) Create the scheduler
  cta::MockNameServer ns;
  cta::MockRemoteNS rns;
784
  cta::OStoreDBWrapper<cta::objectstore::BackendVFS> db("Unittest");
785
786
787
788
789
  cta::Scheduler scheduler(ns, db, rns);

  // Always use the same requester
  const cta::SecurityIdentity requester;
  
790
  DriveConfig driveConfig("T10D6116", "T10KD6", "/dev/tape_T10D6116", "manual");
791
792
793
794
795
796
797
798
799
800
801
802
  DataTransferConfig castorConf;
  castorConf.bufsz = 1024*1024; // 1 MB memory buffers
  castorConf.nbBufs = 10;
  castorConf.bulkRequestRecallMaxBytes = UINT64_C(100)*1000*1000*1000;
  castorConf.bulkRequestRecallMaxFiles = 1000;
  castorConf.nbDiskThreads = 3;
  castor::messages::AcsProxyDummy acs;
  castor::mediachanger::MmcProxyDummy mmc;
  castor::legacymsg::RmcProxyDummy rmc;
  castor::mediachanger::MediaChangerFacade mc(acs, mmc, rmc);
  castor::server::ProcessCap capUtils;
  castor::messages::TapeserverProxyDummy initialProcess;
803
  DataTransferSession sess("tapeHost", logger, mockSys,
804
    driveConfig, mc, initialProcess, capUtils, castorConf, scheduler);
805
  ASSERT_NO_THROW(sess.execute());
806
807
808
809
810
811
  std::string temp = logger.getLog();
  temp += "";
  ASSERT_EQ("", sess.getVid());
  // We should not have logged any error
  ASSERT_EQ(std::string::npos, logger.getLog().find("LVL=E"));
}
812

813
TEST_F(castor_tape_tapeserver_daemon_DataTransferSessionTest, DataTransferSessionGooddayMigration) {
814
  
Eric Cano's avatar
Eric Cano committed
815
816
817
  // 0) Prepare the logger for everyone
  castor::log::StringLogger logger("tapeServerUnitTest");
  
818
  // 1) prepare the fake scheduler
Eric Cano's avatar
Eric Cano committed
819
820
  std::string vid = "V12345";
  std::string density = "8000GC";
821

Eric Cano's avatar
Eric Cano committed
822
823
824
825
826
827
828
829
  // 3) Prepare the necessary environment (logger, plus system wrapper), 
  castor::tape::System::mockWrapper mockSys;
  mockSys.delegateToFake();
  mockSys.disableGMockCallsCounting();
  mockSys.fake.setupForVirtualDriveSLC6();
  //delete is unnecessary
  //pointer with ownership will be passed to the application,
  //which will do the delete 
830
  mockSys.fake.m_pathToDrive["/dev/nst0"] = new castor::tape::tapeserver::drive::FakeDrive;
831
832
833

  // 4) Create the scheduler
  cta::MockNameServer ns;
834
  cta::MockRemoteFullFS rns;
835
836
837
838
839
840
841
842
843
  cta::OStoreDBWrapper<cta::objectstore::BackendVFS> db("Unittest");
  cta::Scheduler scheduler(ns, db, rns);

  // Always use the same requester
  const cta::SecurityIdentity requester;
  
  // Create the bootstrap admin user and host
  ASSERT_NO_THROW(scheduler.createAdminUserWithoutAuthorizingRequester(requester, requester.getUser(), "admin user"));
  ASSERT_NO_THROW(scheduler.createAdminHostWithoutAuthorizingRequester(requester, requester.getHost(), "admin host"));
Eric Cano's avatar
Eric Cano committed
844
  
845
846
  // create a single copy storage class
  ASSERT_NO_THROW(scheduler.createStorageClass(requester, "SINGLE", 1, 1, "comment"));
Eric Cano's avatar
Eric Cano committed
847
  
848
849
850
851
  // assign it to the root directory
  ASSERT_NO_THROW(scheduler.setDirStorageClass(requester, "/", "SINGLE"));
  
  // create the logical library
852
  ASSERT_NO_THROW(scheduler.createLogicalLibrary(requester, "T10KD6", "the illogical library"));
853
854
855
856
  
  // create the tape pool
  ASSERT_NO_THROW(scheduler.createTapePool(requester, "swimmingpool", 2, "the swimming pool"));
  
857
858
859
860
861
862
863
  cta::MountCriteria immediateMount;
  immediateMount.maxAge = 0;
  immediateMount.maxBytesQueued = 1;
  immediateMount.maxFilesQueued = 1;
  immediateMount.quota = 10;
  ASSERT_NO_THROW(scheduler.setTapePoolMountCriteria("swimmingpool", cta::MountCriteriaByDirection(immediateMount, immediateMount)));
  
864
865
866
867
  // create the route
  ASSERT_NO_THROW(scheduler.createArchiveRoute(requester, "SINGLE", 1, "swimmingpool", "iArchive"));
  
  // create the tape
868
  std::string comment = "the magic tape";
869
  ASSERT_NO_THROW(scheduler.createTape(requester, "V12345", "T10KD6", "swimmingpool", 100000, "8000GC", comment));
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
  
  // List to remember the path of each remote file so that the existence of the
  // files can be tested for at the end of the test
  std::list<std::string> remoteFilePaths;

  //delete is unnecessary
  //pointer with ownership will be passed to the application,
  //which will do the delete
  mockSys.fake.m_pathToDrive["/dev/nst0"] = new castor::tape::tapeserver::drive::FakeDrive();
  
  // We can prepare files for writing on the drive
  {    
    // Label the tape
    castor::tape::tapeFile::LabelSession ls(*mockSys.fake.m_pathToDrive["/dev/nst0"], "V12345");
    mockSys.fake.m_pathToDrive["/dev/nst0"]->rewind();
    
    // schedule the archivals
887
    for(int fseq=1; fseq <= 10 ; fseq ++) { 
888
      // Create a path to a remote source file
889
      std::ostringstream fileName;
890
//      remoteFilePath << "file:" << "/test" << fseq;
891
892
      fileName << "/test" << fseq;
      remoteFilePaths.push_back(fileName.str());
893
      
894
895
896
      // Create the file to be migrated in the fake remote NS
      cta::RemotePath rpath(rns.createFullURL(fileName.str()));
      rns.createFile(rpath.getRaw(), 1000);
897
898
899

      // Schedule the archival of the file
      std::list<std::string> remoteFilePathList;
900
901
      remoteFilePathList.push_back(rns.createFullURL(fileName.str()));
      ASSERT_NO_THROW(scheduler.queueArchiveRequest(requester, remoteFilePathList, fileName.str()));
902
    }
Eric Cano's avatar
Eric Cano committed
903
  }
904
  DriveConfig driveConfig("T10D6116", "T10KD6", "/dev/tape_T10D6116", "manual");
905
906
907
  DataTransferConfig castorConf;
  castorConf.bufsz = 1024*1024; // 1 MB memory buffers
  castorConf.nbBufs = 10;
908
909
  castorConf.bulkRequestRecallMaxBytes = UINT64_C(100)*1000*1000*1000;
  castorConf.bulkRequestRecallMaxFiles = 1000;
910
  castorConf.nbDiskThreads = 1;
911
912
913
914
  castor::messages::AcsProxyDummy acs;
  castor::mediachanger::MmcProxyDummy mmc;
  castor::legacymsg::RmcProxyDummy rmc;
  castor::mediachanger::MediaChangerFacade mc(acs, mmc, rmc);
915
  castor::server::ProcessCap capUtils;
916
  castor::messages::TapeserverProxyDummy initialProcess;
917
  DataTransferSession sess("tapeHost", logger, mockSys, driveConfig, mc, initialProcess, capUtils, castorConf, scheduler);
918
  /*ASSERT_NO_THROW*/(sess.execute());
919
920
921
922
  std::string temp = logger.getLog();
  temp += "";
  ASSERT_EQ("V12345", sess.getVid());
  for(auto i=remoteFilePaths.begin(); i!=remoteFilePaths.end(); i++) {
923
924
    /*ASSERT_NO_THROW*/(ns.statFile(requester, *i));
    std::unique_ptr<cta::ArchiveFileStatus> stat(ns.statFile(requester, *i));
925
926
927
    ASSERT_NE(NULL, (uint64_t)(stat.get()));
    ASSERT_EQ(0100777, stat->mode);
    ASSERT_EQ(1000, stat->size);
928
  }
Eric Cano's avatar
Eric Cano committed
929
930
}

931
932
933
934
//
// This test is the same as the previous one, except that the files are deleted
// from filesystem immediately. The disk tasks will then fail on open.
///
935
TEST_F(castor_tape_tapeserver_daemon_DataTransferSessionTest, DataTransferSessionMissingFilesMigration) {
936
  
937
938
939
  // 0) Prepare the logger for everyone
  castor::log::StringLogger logger("tapeServerUnitTest");
  
940
  // 1) prepare the fake scheduler
941
942
  std::string vid = "V12345";
  std::string density = "8000GC";
943

944
945
946
947
948
949
950
951
  // 3) Prepare the necessary environment (logger, plus system wrapper), 
  castor::tape::System::mockWrapper mockSys;
  mockSys.delegateToFake();
  mockSys.disableGMockCallsCounting();
  mockSys.fake.setupForVirtualDriveSLC6();
  //delete is unnecessary
  //pointer with ownership will be passed to the application,
  //which will do the delete 
952
  mockSys.fake.m_pathToDrive["/dev/nst0"] = new castor::tape::tapeserver::drive::FakeDrive;
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973

  // 4) Create the scheduler
  cta::MockNameServer ns;
  cta::MockRemoteNS rns;
  cta::OStoreDBWrapper<cta::objectstore::BackendVFS> db("Unittest");
  cta::Scheduler scheduler(ns, db, rns);

  // Always use the same requester
  const cta::SecurityIdentity requester;
  
  // Create the bootstrap admin user and host
  ASSERT_NO_THROW(scheduler.createAdminUserWithoutAuthorizingRequester(requester, requester.getUser(), "admin user"));
  ASSERT_NO_THROW(scheduler.createAdminHostWithoutAuthorizingRequester(requester, requester.getHost(), "admin host"));
  
  // create a single copy storage class
  ASSERT_NO_THROW(scheduler.createStorageClass(requester, "SINGLE", 1, 1, "comment"));
  
  // assign it to the root directory
  ASSERT_NO_THROW(scheduler.setDirStorageClass(requester, "/", "SINGLE"));
  
  // create the logical library
974
  ASSERT_NO_THROW(scheduler.createLogicalLibrary(requester, "T10KD6", "the illogical library"));
975
976
977
978
979
980
  
  // create the tape pool
  ASSERT_NO_THROW(scheduler.createTapePool(requester, "swimmingpool", 2, "the swimming pool"));
  
  // create the route
  ASSERT_NO_THROW(scheduler.createArchiveRoute(requester, "SINGLE", 1, "swimmingpool", "iArchive"));
981
  
982
  // create the tape
983
  std::string comment = "the magic tape";
984
  ASSERT_NO_THROW(scheduler.createTape(requester, "V12345", "T10KD6", "swimmingpool", 100000, "8000GC", comment));
985
  
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
  // List to remember the path of each remote file so that the existence of the
  // files can be tested for at the end of the test
  std::list<std::string> remoteFilePaths;

  //delete is unnecessary
  //pointer with ownership will be passed to the application,
  //which will do the delete
  mockSys.fake.m_pathToDrive["/dev/nst0"] = new castor::tape::tapeserver::drive::FakeDrive();
  
  // We can prepare files for writing on the drive
  {    
    // Label the tape
    castor::tape::tapeFile::LabelSession ls(*mockSys.fake.m_pathToDrive["/dev/nst0"], "V12345");
    mockSys.fake.m_pathToDrive["/dev/nst0"]->rewind();