VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/tests/storage/tdStorageBenchmark1.py@ 67039

Last change on this file since 67039 was 67039, checked in by vboxsync, 8 years ago

ValidationKit: eliminate buggy task handling (oSession is always added by starting the VM and remmoved when terminating it, and oTxsSession can only be removed if it was added before)

  • Property svn:eol-style set to LF
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 51.7 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# $Id: tdStorageBenchmark1.py 67039 2017-05-23 11:33:27Z vboxsync $
4
5"""
6VirtualBox Validation Kit - Storage benchmark.
7"""
8
9__copyright__ = \
10"""
11Copyright (C) 2012-2017 Oracle Corporation
12
13This file is part of VirtualBox Open Source Edition (OSE), as
14available from http://www.virtualbox.org. This file is free software;
15you can redistribute it and/or modify it under the terms of the GNU
16General Public License (GPL) as published by the Free Software
17Foundation, in version 2 as it comes in the "COPYING" file of the
18VirtualBox OSE distribution. VirtualBox OSE is distributed in the
19hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
20
21The contents of this file may alternatively be used under the terms
22of the Common Development and Distribution License Version 1.0
23(CDDL) only, as it comes in the "COPYING.CDDL" file of the
24VirtualBox OSE distribution, in which case the provisions of the
25CDDL are applicable instead of those of the GPL.
26
27You may elect to license modified versions of this file under the
28terms and conditions of either the GPL or the CDDL or both.
29"""
30__version__ = "$Revision: 67039 $"
31
32
33# Standard Python imports.
34import os;
35import socket;
36import sys;
37import StringIO;
38
39# Only the main script needs to modify the path.
40try: __file__
41except: __file__ = sys.argv[0];
42g_ksValidationKitDir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))));
43sys.path.append(g_ksValidationKitDir);
44
45# Validation Kit imports.
46from common import constants;
47from common import utils;
48from testdriver import reporter;
49from testdriver import base;
50from testdriver import vbox;
51from testdriver import vboxcon;
52
53import remoteexecutor;
54import storagecfg;
55
56def _ControllerTypeToName(eControllerType):
57 """ Translate a controller type to a name. """
58 if eControllerType == vboxcon.StorageControllerType_PIIX3 or eControllerType == vboxcon.StorageControllerType_PIIX4:
59 sType = "IDE Controller";
60 elif eControllerType == vboxcon.StorageControllerType_IntelAhci:
61 sType = "SATA Controller";
62 elif eControllerType == vboxcon.StorageControllerType_LsiLogicSas:
63 sType = "SAS Controller";
64 elif eControllerType == vboxcon.StorageControllerType_LsiLogic or eControllerType == vboxcon.StorageControllerType_BusLogic:
65 sType = "SCSI Controller";
66 elif eControllerType == vboxcon.StorageControllerType_NVMe:
67 sType = "NVMe Controller";
68 else:
69 sType = "Storage Controller";
70 return sType;
71
72class FioTest(object):
73 """
74 Flexible I/O tester testcase.
75 """
76
77 kdHostIoEngine = {
78 'solaris': ('solarisaio', False),
79 'linux': ('libaio', True)
80 };
81
82 def __init__(self, oExecutor, dCfg = None):
83 self.oExecutor = oExecutor;
84 self.sCfgFileId = None;
85 self.dCfg = dCfg;
86 self.sError = None;
87 self.sResult = None;
88
89 def prepare(self, cMsTimeout = 30000):
90 """ Prepares the testcase """
91
92 sTargetOs = self.dCfg.get('TargetOs', 'linux');
93 sIoEngine, fDirectIo = self.kdHostIoEngine.get(sTargetOs);
94 if sIoEngine is None:
95 return False;
96
97 cfgBuf = StringIO.StringIO();
98 cfgBuf.write('[global]\n');
99 cfgBuf.write('bs=' + self.dCfg.get('RecordSize', '4k') + '\n');
100 cfgBuf.write('ioengine=' + sIoEngine + '\n');
101 cfgBuf.write('iodepth=' + self.dCfg.get('QueueDepth', '32') + '\n');
102 cfgBuf.write('size=' + self.dCfg.get('TestsetSize', '2g') + '\n');
103 if fDirectIo:
104 cfgBuf.write('direct=1\n');
105 else:
106 cfgBuf.write('direct=0\n');
107 cfgBuf.write('directory=' + self.dCfg.get('FilePath', '/mnt') + '\n');
108 cfgBuf.write('filename=fio.test.file');
109
110 cfgBuf.write('[seq-write]\n');
111 cfgBuf.write('rw=write\n');
112 cfgBuf.write('stonewall\n');
113
114 cfgBuf.write('[rand-write]\n');
115 cfgBuf.write('rw=randwrite\n');
116 cfgBuf.write('stonewall\n');
117
118 cfgBuf.write('[seq-read]\n');
119 cfgBuf.write('rw=read\n');
120 cfgBuf.write('stonewall\n');
121
122 cfgBuf.write('[rand-read]\n');
123 cfgBuf.write('rw=randread\n');
124 cfgBuf.write('stonewall\n');
125
126 self.sCfgFileId = self.oExecutor.copyString(cfgBuf.getvalue(), 'aio-test', cMsTimeout);
127 return self.sCfgFileId is not None;
128
129 def run(self, cMsTimeout = 30000):
130 """ Runs the testcase """
131 _ = cMsTimeout
132 fRc, sOutput, sError = self.oExecutor.execBinary('fio', (self.sCfgFileId,), cMsTimeout = cMsTimeout);
133 if fRc:
134 self.sResult = sOutput;
135 else:
136 self.sError = ('Binary: fio\n' +
137 '\nOutput:\n\n' +
138 sOutput +
139 '\nError:\n\n' +
140 sError);
141 return fRc;
142
143 def cleanup(self):
144 """ Cleans up any leftovers from the testcase. """
145
146 def reportResult(self):
147 """
148 Reports the test results to the test manager.
149 """
150 return True;
151
152 def getErrorReport(self):
153 """
154 Returns the error report in case the testcase failed.
155 """
156 return self.sError;
157
158class IozoneTest(object):
159 """
160 I/O zone testcase.
161 """
162 def __init__(self, oExecutor, dCfg = None):
163 self.oExecutor = oExecutor;
164 self.sResult = None;
165 self.sError = None;
166 self.lstTests = [ ('initial writers', 'FirstWrite'),
167 ('rewriters', 'Rewrite'),
168 ('re-readers', 'ReRead'),
169 ('stride readers', 'StrideRead'),
170 ('reverse readers', 'ReverseRead'),
171 ('random readers', 'RandomRead'),
172 ('mixed workload', 'MixedWorkload'),
173 ('random writers', 'RandomWrite'),
174 ('pwrite writers', 'PWrite'),
175 ('pread readers', 'PRead'),
176 ('fwriters', 'FWrite'),
177 ('freaders', 'FRead'),
178 ('readers', 'FirstRead')];
179 self.sRecordSize = dCfg.get('RecordSize', '4k');
180 self.sTestsetSize = dCfg.get('TestsetSize', '2g');
181 self.sQueueDepth = dCfg.get('QueueDepth', '32');
182 self.sFilePath = dCfg.get('FilePath', '/mnt/iozone');
183 self.fDirectIo = True;
184
185 sTargetOs = dCfg.get('TargetOs');
186 if sTargetOs == 'solaris':
187 self.fDirectIo = False;
188
189 def prepare(self, cMsTimeout = 30000):
190 """ Prepares the testcase """
191 _ = cMsTimeout;
192 return True; # Nothing to do.
193
194 def run(self, cMsTimeout = 30000):
195 """ Runs the testcase """
196 tupArgs = ('-r', self.sRecordSize, '-s', self.sTestsetSize, \
197 '-t', '1', '-T', '-F', self.sFilePath + '/iozone.tmp');
198 if self.fDirectIo:
199 tupArgs += ('-I',);
200 fRc, sOutput, sError = self.oExecutor.execBinary('iozone', tupArgs, cMsTimeout = cMsTimeout);
201 if fRc:
202 self.sResult = sOutput;
203 else:
204 self.sError = ('Binary: iozone\n' +
205 '\nOutput:\n\n' +
206 sOutput +
207 '\nError:\n\n' +
208 sError);
209
210 _ = cMsTimeout;
211 return fRc;
212
213 def cleanup(self):
214 """ Cleans up any leftovers from the testcase. """
215 return True;
216
217 def reportResult(self):
218 """
219 Reports the test results to the test manager.
220 """
221
222 fRc = True;
223 if self.sResult is not None:
224 try:
225 asLines = self.sResult.splitlines();
226 for sLine in asLines:
227 sLine = sLine.strip();
228 if sLine.startswith('Children') is True:
229 # Extract the value
230 idxValue = sLine.rfind('=');
231 if idxValue == -1:
232 raise Exception('IozoneTest: Invalid state');
233
234 idxValue += 1;
235 while sLine[idxValue] == ' ':
236 idxValue += 1;
237
238 # Get the reported value, cut off after the decimal point
239 # it is not supported by the testmanager yet and is not really
240 # relevant anyway.
241 idxValueEnd = idxValue;
242 while sLine[idxValueEnd].isdigit():
243 idxValueEnd += 1;
244
245 for sNeedle, sTestVal in self.lstTests:
246 if sLine.rfind(sNeedle) != -1:
247 reporter.testValue(sTestVal, sLine[idxValue:idxValueEnd],
248 constants.valueunit.g_asNames[constants.valueunit.KILOBYTES_PER_SEC]);
249 break;
250 except:
251 fRc = False;
252 else:
253 fRc = False;
254
255 return fRc;
256
257 def getErrorReport(self):
258 """
259 Returns the error report in case the testcase failed.
260 """
261 return self.sError;
262
263class StorTestCfgMgr(object):
264 """
265 Manages the different testcases.
266 """
267
268 def __init__(self, aasTestLvls, aasTestsBlacklist, fnIsCfgSupported = None):
269 self.aasTestsBlacklist = aasTestsBlacklist;
270 self.at3TestLvls = [];
271 self.iTestLvl = 0;
272 self.fnIsCfgSupported = fnIsCfgSupported;
273 for asTestLvl in aasTestLvls:
274 if isinstance(asTestLvl, tuple):
275 asTestLvl, fnTestFmt = asTestLvl;
276 self.at3TestLvls.append((0, fnTestFmt, asTestLvl));
277 else:
278 self.at3TestLvls.append((0, None, asTestLvl));
279
280 self.at3TestLvls.reverse();
281
282 # Get the first non blacklisted test.
283 asTestCfg = self.getCurrentTestCfg();
284 while asTestCfg and self.isTestCfgBlacklisted(asTestCfg):
285 asTestCfg = self.advanceTestCfg();
286
287 iLvl = 0;
288 for sCfg in asTestCfg:
289 reporter.testStart('%s' % (self.getTestIdString(sCfg, iLvl)));
290 iLvl += 1;
291
292 def __del__(self):
293 # Make sure the tests are marked as done.
294 while self.iTestLvl < len(self.at3TestLvls):
295 reporter.testDone();
296 self.iTestLvl += 1;
297
298 def getTestIdString(self, oCfg, iLvl):
299 """
300 Returns a potentially formatted string for the test name.
301 """
302
303 # The order of the test levels is reversed so get the level starting
304 # from the end.
305 _, fnTestFmt, _ = self.at3TestLvls[len(self.at3TestLvls) - 1 - iLvl];
306 if fnTestFmt is not None:
307 return fnTestFmt(oCfg);
308 return oCfg;
309
310 def isTestCfgBlacklisted(self, asTestCfg):
311 """
312 Returns whether the given test config is black listed.
313 """
314 fBlacklisted = False;
315
316 for asTestBlacklist in self.aasTestsBlacklist:
317 iLvl = 0;
318 fBlacklisted = True;
319 while iLvl < len(asTestBlacklist) and iLvl < len(asTestCfg):
320 if asTestBlacklist[iLvl] != asTestCfg[iLvl] and asTestBlacklist[iLvl] != '*':
321 fBlacklisted = False;
322 break;
323
324 iLvl += 1;
325
326 if not fBlacklisted and self.fnIsCfgSupported is not None:
327 fBlacklisted = not self.fnIsCfgSupported(asTestCfg);
328
329 return fBlacklisted;
330
331 def advanceTestCfg(self):
332 """
333 Advances to the next test config and returns it as an
334 array of strings or an empty config if there is no test left anymore.
335 """
336 iTestCfg, fnTestFmt, asTestCfg = self.at3TestLvls[self.iTestLvl];
337 iTestCfg += 1;
338 self.at3TestLvls[self.iTestLvl] = (iTestCfg, fnTestFmt, asTestCfg);
339 while iTestCfg == len(asTestCfg) and self.iTestLvl < len(self.at3TestLvls):
340 self.at3TestLvls[self.iTestLvl] = (0, fnTestFmt, asTestCfg);
341 self.iTestLvl += 1;
342 if self.iTestLvl < len(self.at3TestLvls):
343 iTestCfg, fnTestFmt, asTestCfg = self.at3TestLvls[self.iTestLvl];
344 iTestCfg += 1;
345 self.at3TestLvls[self.iTestLvl] = (iTestCfg, fnTestFmt, asTestCfg);
346 if iTestCfg < len(asTestCfg):
347 self.iTestLvl = 0;
348 break;
349 else:
350 break; # We reached the end of our tests.
351
352 return self.getCurrentTestCfg();
353
354 def getCurrentTestCfg(self):
355 """
356 Returns the current not black listed test config as an array of strings.
357 """
358 asTestCfg = [];
359
360 if self.iTestLvl < len(self.at3TestLvls):
361 for t3TestLvl in self.at3TestLvls:
362 iTestCfg, _, asTestLvl = t3TestLvl;
363 asTestCfg.append(asTestLvl[iTestCfg]);
364
365 asTestCfg.reverse()
366
367 return asTestCfg;
368
369 def getNextTestCfg(self, fSkippedLast = False):
370 """
371 Returns the next not blacklisted test config or an empty list if
372 there is no test left.
373 """
374 asTestCfgCur = self.getCurrentTestCfg();
375
376 asTestCfg = self.advanceTestCfg();
377 while asTestCfg and self.isTestCfgBlacklisted(asTestCfg):
378 asTestCfg = self.advanceTestCfg();
379
380 # Compare the current and next config and close the approriate test
381 # categories.
382 reporter.testDone(fSkippedLast);
383 if asTestCfg:
384 idxSame = 0;
385 while asTestCfgCur[idxSame] == asTestCfg[idxSame]:
386 idxSame += 1;
387
388 for i in range(idxSame, len(asTestCfg) - 1):
389 reporter.testDone();
390
391 for i in range(idxSame, len(asTestCfg)):
392 reporter.testStart('%s' % (self.getTestIdString(asTestCfg[i], i)));
393
394 else:
395 # No more tests, mark all tests as done
396 for i in range(0, len(asTestCfgCur) - 1):
397 reporter.testDone();
398
399 return asTestCfg;
400
401class tdStorageBenchmark(vbox.TestDriver): # pylint: disable=R0902
402 """
403 Storage benchmark.
404 """
405
406 # Global storage configs for the testbox
407 kdStorageCfgs = {
408 'testboxstor1.de.oracle.com': r'c[3-9]t\dd0\Z',
409 'adaris': [ '/dev/sda' ]
410 };
411
412 # Available test sets.
413 kdTestSets = {
414 # Mostly for developing and debugging the testcase.
415 'Fast': {
416 'RecordSize': '64k',
417 'TestsetSize': '100m',
418 'QueueDepth': '32',
419 'DiskSizeGb': 2
420 },
421 # For quick functionality tests where benchmark results are not required.
422 'Functionality': {
423 'RecordSize': '64k',
424 'TestsetSize': '2g',
425 'QueueDepth': '32',
426 'DiskSizeGb': 10
427 },
428 # For benchmarking the I/O stack.
429 'Benchmark': {
430 'RecordSize': '64k',
431 'TestsetSize': '20g',
432 'QueueDepth': '32',
433 'DiskSizeGb': 30
434 },
435 # For stress testing which takes a lot of time.
436 'Stress': {
437 'RecordSize': '64k',
438 'TestsetSize': '2t',
439 'QueueDepth': '32',
440 'DiskSizeGb': 10000
441 },
442 };
443
444 # Dictionary mapping the virtualization mode mnemonics to a little less cryptic
445 # strings used in test descriptions.
446 kdVirtModeDescs = {
447 'raw' : 'Raw-mode',
448 'hwvirt' : 'HwVirt',
449 'hwvirt-np' : 'NestedPaging'
450 };
451
452 kdHostIoCacheDescs = {
453 'default' : 'HostCacheDef',
454 'hostiocache' : 'HostCacheOn',
455 'no-hostiocache' : 'HostCacheOff'
456 };
457
458 # Array indexes for the test configs.
459 kiVmName = 0;
460 kiStorageCtrl = 1;
461 kiHostIoCache = 2;
462 kiDiskFmt = 3;
463 kiDiskVar = 4;
464 kiCpuCount = 5;
465 kiVirtMode = 6;
466 kiIoTest = 7;
467 kiTestSet = 8;
468
469 def __init__(self):
470 vbox.TestDriver.__init__(self);
471 self.asRsrcs = None;
472 self.asTestVMsDef = ['tst-storage', 'tst-storage32'];
473 self.asTestVMs = self.asTestVMsDef;
474 self.asSkipVMs = [];
475 self.asVirtModesDef = ['hwvirt', 'hwvirt-np', 'raw',]
476 self.asVirtModes = self.asVirtModesDef;
477 self.acCpusDef = [1, 2];
478 self.acCpus = self.acCpusDef;
479 self.asStorageCtrlsDef = ['AHCI', 'IDE', 'LsiLogicSAS', 'LsiLogic', 'BusLogic', 'NVMe'];
480 self.asStorageCtrls = self.asStorageCtrlsDef;
481 self.asHostIoCacheDef = ['default', 'hostiocache', 'no-hostiocache'];
482 self.asHostIoCache = self.asHostIoCacheDef;
483 self.asDiskFormatsDef = ['VDI', 'VMDK', 'VHD', 'QED', 'Parallels', 'QCOW', 'iSCSI'];
484 self.asDiskFormats = self.asDiskFormatsDef;
485 self.asDiskVariantsDef = ['Dynamic', 'Fixed', 'DynamicSplit2G', 'FixedSplit2G', 'Network'];
486 self.asDiskVariants = self.asDiskVariantsDef;
487 self.asTestsDef = ['iozone', 'fio'];
488 self.asTests = self.asTestsDef;
489 self.asTestSetsDef = ['Fast', 'Functionality', 'Benchmark', 'Stress'];
490 self.asTestSets = self.asTestSetsDef;
491 self.asIscsiTargetsDef = [ ]; # @todo: Configure one target for basic iSCSI testing
492 self.asIscsiTargets = self.asIscsiTargetsDef;
493 self.cDiffLvlsDef = 0;
494 self.cDiffLvls = self.cDiffLvlsDef;
495 self.fTestHost = False;
496 self.fUseScratch = False;
497 self.fRecreateStorCfg = True;
498 self.fReportBenchmarkResults = True;
499 self.oStorCfg = None;
500 self.sIoLogPathDef = self.sScratchPath;
501 self.sIoLogPath = self.sIoLogPathDef;
502 self.fIoLog = False;
503 self.fUseRamDiskDef = False;
504 self.fUseRamDisk = self.fUseRamDiskDef;
505
506 #
507 # Overridden methods.
508 #
509 def showUsage(self):
510 rc = vbox.TestDriver.showUsage(self);
511 reporter.log('');
512 reporter.log('tdStorageBenchmark1 Options:');
513 reporter.log(' --virt-modes <m1[:m2[:]]');
514 reporter.log(' Default: %s' % (':'.join(self.asVirtModesDef)));
515 reporter.log(' --cpu-counts <c1[:c2[:]]');
516 reporter.log(' Default: %s' % (':'.join(str(c) for c in self.acCpusDef)));
517 reporter.log(' --storage-ctrls <type1[:type2[:...]]>');
518 reporter.log(' Default: %s' % (':'.join(self.asStorageCtrlsDef)));
519 reporter.log(' --host-io-cache <setting1[:setting2[:...]]>');
520 reporter.log(' Default: %s' % (':'.join(self.asHostIoCacheDef)));
521 reporter.log(' --disk-formats <type1[:type2[:...]]>');
522 reporter.log(' Default: %s' % (':'.join(self.asDiskFormatsDef)));
523 reporter.log(' --disk-variants <variant1[:variant2[:...]]>');
524 reporter.log(' Default: %s' % (':'.join(self.asDiskVariantsDef)));
525 reporter.log(' --iscsi-targets <target1[:target2[:...]]>');
526 reporter.log(' Default: %s' % (':'.join(self.asIscsiTargetsDef)));
527 reporter.log(' --tests <test1[:test2[:...]]>');
528 reporter.log(' Default: %s' % (':'.join(self.asTestsDef)));
529 reporter.log(' --test-sets <set1[:set2[:...]]>');
530 reporter.log(' Default: %s' % (':'.join(self.asTestSetsDef)));
531 reporter.log(' --diff-levels <number of diffs>');
532 reporter.log(' Default: %s' % (self.cDiffLvlsDef));
533 reporter.log(' --test-vms <vm1[:vm2[:...]]>');
534 reporter.log(' Test the specified VMs in the given order. Use this to change');
535 reporter.log(' the execution order or limit the choice of VMs');
536 reporter.log(' Default: %s (all)' % (':'.join(self.asTestVMsDef)));
537 reporter.log(' --skip-vms <vm1[:vm2[:...]]>');
538 reporter.log(' Skip the specified VMs when testing.');
539 reporter.log(' --test-host');
540 reporter.log(' Do all configured tests on the host first and report the results');
541 reporter.log(' to get a baseline');
542 reporter.log(' --use-scratch');
543 reporter.log(' Use the scratch directory for testing instead of setting up');
544 reporter.log(' fresh volumes on dedicated disks (for development)');
545 reporter.log(' --always-wipe-storage-cfg');
546 reporter.log(' Recreate the host storage config before each test');
547 reporter.log(' --dont-wipe-storage-cfg');
548 reporter.log(' Don\'t recreate the host storage config before each test');
549 reporter.log(' --report-benchmark-results');
550 reporter.log(' Report all benchmark results');
551 reporter.log(' --dont-report-benchmark-results');
552 reporter.log(' Don\'t report any benchmark results');
553 reporter.log(' --io-log-path <path>');
554 reporter.log(' Default: %s' % (self.sIoLogPathDef));
555 reporter.log(' --enable-io-log');
556 reporter.log(' Whether to enable I/O logging for each test');
557 reporter.log(' --use-ramdisk');
558 reporter.log(' Default: %s' % (self.fUseRamDiskDef));
559 return rc;
560
561 def parseOption(self, asArgs, iArg): # pylint: disable=R0912,R0915
562 if asArgs[iArg] == '--virt-modes':
563 iArg += 1;
564 if iArg >= len(asArgs): raise base.InvalidOption('The "--virt-modes" takes a colon separated list of modes');
565 self.asVirtModes = asArgs[iArg].split(':');
566 for s in self.asVirtModes:
567 if s not in self.asVirtModesDef:
568 raise base.InvalidOption('The "--virt-modes" value "%s" is not valid; valid values are: %s' \
569 % (s, ' '.join(self.asVirtModesDef)));
570 elif asArgs[iArg] == '--cpu-counts':
571 iArg += 1;
572 if iArg >= len(asArgs): raise base.InvalidOption('The "--cpu-counts" takes a colon separated list of cpu counts');
573 self.acCpus = [];
574 for s in asArgs[iArg].split(':'):
575 try: c = int(s);
576 except: raise base.InvalidOption('The "--cpu-counts" value "%s" is not an integer' % (s,));
577 if c <= 0: raise base.InvalidOption('The "--cpu-counts" value "%s" is zero or negative' % (s,));
578 self.acCpus.append(c);
579 elif asArgs[iArg] == '--storage-ctrls':
580 iArg += 1;
581 if iArg >= len(asArgs):
582 raise base.InvalidOption('The "--storage-ctrls" takes a colon separated list of Storage controller types');
583 self.asStorageCtrls = asArgs[iArg].split(':');
584 elif asArgs[iArg] == '--host-io-cache':
585 iArg += 1;
586 if iArg >= len(asArgs):
587 raise base.InvalidOption('The "--host-io-cache" takes a colon separated list of I/O cache settings');
588 self.asHostIoCache = asArgs[iArg].split(':');
589 elif asArgs[iArg] == '--disk-formats':
590 iArg += 1;
591 if iArg >= len(asArgs): raise base.InvalidOption('The "--disk-formats" takes a colon separated list of disk formats');
592 self.asDiskFormats = asArgs[iArg].split(':');
593 elif asArgs[iArg] == '--disk-variants':
594 iArg += 1;
595 if iArg >= len(asArgs):
596 raise base.InvalidOption('The "--disk-variants" takes a colon separated list of disk variants');
597 self.asDiskVariants = asArgs[iArg].split(':');
598 elif asArgs[iArg] == '--iscsi-targets':
599 iArg += 1;
600 if iArg >= len(asArgs):
601 raise base.InvalidOption('The "--iscsi-targets" takes a colon separated list of iscsi targets');
602 self.asIscsiTargets = asArgs[iArg].split(':');
603 elif asArgs[iArg] == '--tests':
604 iArg += 1;
605 if iArg >= len(asArgs): raise base.InvalidOption('The "--tests" takes a colon separated list of tests to run');
606 self.asTests = asArgs[iArg].split(':');
607 elif asArgs[iArg] == '--test-sets':
608 iArg += 1;
609 if iArg >= len(asArgs): raise base.InvalidOption('The "--test-sets" takes a colon separated list of test sets');
610 self.asTestSets = asArgs[iArg].split(':');
611 elif asArgs[iArg] == '--diff-levels':
612 iArg += 1;
613 if iArg >= len(asArgs): raise base.InvalidOption('The "--diff-levels" takes an integer');
614 try: self.cDiffLvls = int(asArgs[iArg]);
615 except: raise base.InvalidOption('The "--diff-levels" value "%s" is not an integer' % (asArgs[iArg],));
616 elif asArgs[iArg] == '--test-vms':
617 iArg += 1;
618 if iArg >= len(asArgs): raise base.InvalidOption('The "--test-vms" takes colon separated list');
619 self.asTestVMs = asArgs[iArg].split(':');
620 for s in self.asTestVMs:
621 if s not in self.asTestVMsDef:
622 raise base.InvalidOption('The "--test-vms" value "%s" is not valid; valid values are: %s' \
623 % (s, ' '.join(self.asTestVMsDef)));
624 elif asArgs[iArg] == '--skip-vms':
625 iArg += 1;
626 if iArg >= len(asArgs): raise base.InvalidOption('The "--skip-vms" takes colon separated list');
627 self.asSkipVMs = asArgs[iArg].split(':');
628 for s in self.asSkipVMs:
629 if s not in self.asTestVMsDef:
630 reporter.log('warning: The "--test-vms" value "%s" does not specify any of our test VMs.' % (s));
631 elif asArgs[iArg] == '--test-host':
632 self.fTestHost = True;
633 elif asArgs[iArg] == '--use-scratch':
634 self.fUseScratch = True;
635 elif asArgs[iArg] == '--always-wipe-storage-cfg':
636 self.fRecreateStorCfg = True;
637 elif asArgs[iArg] == '--dont-wipe-storage-cfg':
638 self.fRecreateStorCfg = False;
639 elif asArgs[iArg] == '--report-benchmark-results':
640 self.fReportBenchmarkResults = True;
641 elif asArgs[iArg] == '--dont-report-benchmark-results':
642 self.fReportBenchmarkResults = False;
643 elif asArgs[iArg] == '--io-log-path':
644 if iArg >= len(asArgs): raise base.InvalidOption('The "--io-log-path" takes a path argument');
645 self.sIoLogPath = asArgs[iArg];
646 elif asArgs[iArg] == '--enable-io-log':
647 self.fIoLog = True;
648 elif asArgs[iArg] == '--use-ramdisk':
649 self.fUseRamDisk = True;
650 else:
651 return vbox.TestDriver.parseOption(self, asArgs, iArg);
652 return iArg + 1;
653
654 def completeOptions(self):
655 # Remove skipped VMs from the test list.
656 for sVM in self.asSkipVMs:
657 try: self.asTestVMs.remove(sVM);
658 except: pass;
659
660 return vbox.TestDriver.completeOptions(self);
661
662 def getResourceSet(self):
663 # Construct the resource list the first time it's queried.
664 if self.asRsrcs is None:
665 self.asRsrcs = [];
666 if 'tst-storage' in self.asTestVMs:
667 self.asRsrcs.append('5.0/storage/tst-storage.vdi');
668 if 'tst-storage32' in self.asTestVMs:
669 self.asRsrcs.append('5.0/storage/tst-storage32.vdi');
670
671 return self.asRsrcs;
672
673 def actionConfig(self):
674
675 # Make sure vboxapi has been imported so we can use the constants.
676 if not self.importVBoxApi():
677 return False;
678
679 #
680 # Configure the VMs we're going to use.
681 #
682
683 # Linux VMs
684 if 'tst-storage' in self.asTestVMs:
685 oVM = self.createTestVM('tst-storage', 1, '5.0/storage/tst-storage.vdi', sKind = 'ArchLinux_64', fIoApic = True, \
686 eNic0AttachType = vboxcon.NetworkAttachmentType_NAT, \
687 eNic0Type = vboxcon.NetworkAdapterType_Am79C973);
688 if oVM is None:
689 return False;
690
691 if 'tst-storage32' in self.asTestVMs:
692 oVM = self.createTestVM('tst-storage32', 1, '5.0/storage/tst-storage32.vdi', sKind = 'ArchLinux', fIoApic = True, \
693 eNic0AttachType = vboxcon.NetworkAttachmentType_NAT, \
694 eNic0Type = vboxcon.NetworkAdapterType_Am79C973);
695 if oVM is None:
696 return False;
697
698 return True;
699
700 def actionExecute(self):
701 """
702 Execute the testcase.
703 """
704 fRc = self.test1();
705 return fRc;
706
707
708 #
709 # Test execution helpers.
710 #
711
712 def prepareStorage(self, oStorCfg, fRamDisk = False, cbPool = None):
713 """
714 Prepares the host storage for disk images or direct testing on the host.
715 """
716 # Create a basic pool with the default configuration.
717 sMountPoint = None;
718 fRc, sPoolId = oStorCfg.createStoragePool(cbPool = cbPool, fRamDisk = fRamDisk);
719 if fRc:
720 fRc, sMountPoint = oStorCfg.createVolume(sPoolId);
721 if not fRc:
722 sMountPoint = None;
723 oStorCfg.cleanup();
724
725 return sMountPoint;
726
727 def cleanupStorage(self, oStorCfg):
728 """
729 Cleans up any created storage space for a test.
730 """
731 return oStorCfg.cleanup();
732
733 def getGuestDisk(self, oSession, oTxsSession, eStorageController):
734 """
735 Gets the path of the disk in the guest to use for testing.
736 """
737 lstDisks = None;
738
739 # The naming scheme for NVMe is different and we don't have
740 # to query the guest for unformatted disks here because the disk with the OS
741 # is not attached to a NVMe controller.
742 if eStorageController == vboxcon.StorageControllerType_NVMe:
743 lstDisks = [ '/dev/nvme0n1' ];
744 else:
745 # Find a unformatted disk (no partition).
746 # @todo: This is a hack because LIST and STAT are not yet implemented
747 # in TXS (get to this eventually)
748 lstBlkDev = [ '/dev/sda', '/dev/sdb' ];
749 for sBlkDev in lstBlkDev:
750 fRc = oTxsSession.syncExec('/usr/bin/ls', ('ls', sBlkDev + '1'));
751 if not fRc:
752 lstDisks = [ sBlkDev ];
753 break;
754
755 _ = oSession;
756 return lstDisks;
757
758 def getDiskFormatVariantsForTesting(self, sDiskFmt, asVariants):
759 """
760 Returns a list of disk variants for testing supported by the given
761 disk format and selected for testing.
762 """
763 lstDskFmts = self.oVBoxMgr.getArray(self.oVBox.systemProperties, 'mediumFormats');
764 for oDskFmt in lstDskFmts:
765 if oDskFmt.id == sDiskFmt:
766 lstDskVariants = [];
767 lstCaps = self.oVBoxMgr.getArray(oDskFmt, 'capabilities');
768
769 if vboxcon.MediumFormatCapabilities_CreateDynamic in lstCaps \
770 and 'Dynamic' in asVariants:
771 lstDskVariants.append('Dynamic');
772
773 if vboxcon.MediumFormatCapabilities_CreateFixed in lstCaps \
774 and 'Fixed' in asVariants:
775 lstDskVariants.append('Fixed');
776
777 if vboxcon.MediumFormatCapabilities_CreateSplit2G in lstCaps \
778 and vboxcon.MediumFormatCapabilities_CreateDynamic in lstCaps \
779 and 'DynamicSplit2G' in asVariants:
780 lstDskVariants.append('DynamicSplit2G');
781
782 if vboxcon.MediumFormatCapabilities_CreateSplit2G in lstCaps \
783 and vboxcon.MediumFormatCapabilities_CreateFixed in lstCaps \
784 and 'FixedSplit2G' in asVariants:
785 lstDskVariants.append('FixedSplit2G');
786
787 if vboxcon.MediumFormatCapabilities_TcpNetworking in lstCaps \
788 and 'Network' in asVariants:
789 lstDskVariants.append('Network'); # Solely for iSCSI to get a non empty list
790
791 return lstDskVariants;
792
793 return [];
794
795 def convDiskToMediumVariant(self, sDiskVariant):
796 """
797 Returns a tuple of medium variant flags matching the given disk variant.
798 """
799 tMediumVariant = None;
800 if sDiskVariant == 'Dynamic':
801 tMediumVariant = (vboxcon.MediumVariant_Standard, );
802 elif sDiskVariant == 'Fixed':
803 tMediumVariant = (vboxcon.MediumVariant_Fixed, );
804 elif sDiskVariant == 'DynamicSplit2G':
805 tMediumVariant = (vboxcon.MediumVariant_Standard, vboxcon.MediumVariant_VmdkSplit2G);
806 elif sDiskVariant == 'FixedSplit2G':
807 tMediumVariant = (vboxcon.MediumVariant_Fixed, vboxcon.MediumVariant_VmdkSplit2G);
808
809 return tMediumVariant;
810
811 def getStorageCtrlFromName(self, sStorageCtrl):
812 """
813 Resolves the storage controller string to the matching constant.
814 """
815 eStorageCtrl = None;
816
817 if sStorageCtrl == 'AHCI':
818 eStorageCtrl = vboxcon.StorageControllerType_IntelAhci;
819 elif sStorageCtrl == 'IDE':
820 eStorageCtrl = vboxcon.StorageControllerType_PIIX4;
821 elif sStorageCtrl == 'LsiLogicSAS':
822 eStorageCtrl = vboxcon.StorageControllerType_LsiLogicSas;
823 elif sStorageCtrl == 'LsiLogic':
824 eStorageCtrl = vboxcon.StorageControllerType_LsiLogic;
825 elif sStorageCtrl == 'BusLogic':
826 eStorageCtrl = vboxcon.StorageControllerType_BusLogic;
827 elif sStorageCtrl == 'NVMe':
828 eStorageCtrl = vboxcon.StorageControllerType_NVMe;
829
830 return eStorageCtrl;
831
832 def getStorageDriverFromEnum(self, eStorageCtrl, fHardDisk):
833 """
834 Returns the appropriate driver name for the given storage controller
835 and a flag whether the driver has the generic SCSI driver attached.
836 """
837 if eStorageCtrl == vboxcon.StorageControllerType_IntelAhci:
838 if fHardDisk:
839 return ('ahci', False);
840 return ('ahci', True);
841 if eStorageCtrl == vboxcon.StorageControllerType_PIIX4:
842 return ('piix3ide', False);
843 if eStorageCtrl == vboxcon.StorageControllerType_LsiLogicSas:
844 return ('lsilogicsas', True);
845 if eStorageCtrl == vboxcon.StorageControllerType_LsiLogic:
846 return ('lsilogicscsi', True);
847 if eStorageCtrl == vboxcon.StorageControllerType_BusLogic:
848 return ('buslogic', True);
849 if eStorageCtrl == vboxcon.StorageControllerType_NVMe:
850 return ('nvme', False);
851
852 return ('<invalid>', False);
853
854 def isTestCfgSupported(self, asTestCfg):
855 """
856 Returns whether a specific test config is supported.
857 """
858
859 # Check whether the disk variant is supported by the selected format.
860 asVariants = self.getDiskFormatVariantsForTesting(asTestCfg[self.kiDiskFmt], [ asTestCfg[self.kiDiskVar] ]);
861 if not asVariants:
862 return False;
863
864 # For iSCSI check whether we have targets configured.
865 if asTestCfg[self.kiDiskFmt] == 'iSCSI' and not self.asIscsiTargets:
866 return False;
867
868 # Check for virt mode, CPU count and selected VM.
869 if asTestCfg[self.kiVirtMode] == 'raw' \
870 and (asTestCfg[self.kiCpuCount] > 1 or asTestCfg[self.kiVmName] == 'tst-storage'):
871 return False;
872
873 # IDE does not support the no host I/O cache setting
874 if asTestCfg[self.kiHostIoCache] == 'no-hostiocache' \
875 and asTestCfg[self.kiStorageCtrl] == 'IDE':
876 return False;
877
878 return True;
879
880 def fnFormatCpuString(self, cCpus):
881 """
882 Formats the CPU count to be readable.
883 """
884 if cCpus == 1:
885 return '1 cpu';
886 return '%u cpus' % (cCpus);
887
888 def fnFormatVirtMode(self, sVirtMode):
889 """
890 Formats the virtualization mode to be a little less cryptic for use in test
891 descriptions.
892 """
893 return self.kdVirtModeDescs[sVirtMode];
894
895 def fnFormatHostIoCache(self, sHostIoCache):
896 """
897 Formats the host I/O cache mode to be a little less cryptic for use in test
898 descriptions.
899 """
900 return self.kdHostIoCacheDescs[sHostIoCache];
901
902 def testBenchmark(self, sTargetOs, sBenchmark, sMountpoint, oExecutor, dTestSet, \
903 cMsTimeout = 3600000):
904 """
905 Runs the given benchmark on the test host.
906 """
907
908 dTestSet['FilePath'] = sMountpoint;
909 dTestSet['TargetOs'] = sTargetOs;
910
911 oTst = None;
912 if sBenchmark == 'iozone':
913 oTst = IozoneTest(oExecutor, dTestSet);
914 elif sBenchmark == 'fio':
915 oTst = FioTest(oExecutor, dTestSet); # pylint: disable=R0204
916
917 if oTst is not None:
918 fRc = oTst.prepare();
919 if fRc:
920 fRc = oTst.run(cMsTimeout);
921 if fRc:
922 if self.fReportBenchmarkResults:
923 fRc = oTst.reportResult();
924 else:
925 reporter.testFailure('Running the testcase failed');
926 reporter.addLogString(oTst.getErrorReport(), sBenchmark + '.log',
927 'log/release/client', 'Benchmark raw output');
928 else:
929 reporter.testFailure('Preparing the testcase failed');
930
931 oTst.cleanup();
932
933 return fRc;
934
935 def createHd(self, oSession, sDiskFormat, sDiskVariant, iDiffLvl, oHdParent, \
936 sDiskPath, cbDisk):
937 """
938 Creates a new disk with the given parameters returning the medium object
939 on success.
940 """
941
942 oHd = None;
943 if sDiskFormat == "iSCSI" and iDiffLvl == 0:
944 listNames = [];
945 listValues = [];
946 listValues = self.asIscsiTargets[0].split('|');
947 listNames.append('TargetAddress');
948 listNames.append('TargetName');
949 listNames.append('LUN');
950
951 if self.fpApiVer >= 5.0:
952 oHd = oSession.oVBox.createMedium(sDiskFormat, sDiskPath, vboxcon.AccessMode_ReadWrite, \
953 vboxcon.DeviceType_HardDisk);
954 else:
955 oHd = oSession.oVBox.createHardDisk(sDiskFormat, sDiskPath);
956 oHd.type = vboxcon.MediumType_Normal;
957 oHd.setProperties(listNames, listValues);
958 else:
959 if iDiffLvl == 0:
960 tMediumVariant = self.convDiskToMediumVariant(sDiskVariant);
961 oHd = oSession.createBaseHd(sDiskPath + '/base.disk', sDiskFormat, cbDisk, \
962 cMsTimeout = 3600 * 1000, tMediumVariant = tMediumVariant);
963 else:
964 sDiskPath = sDiskPath + '/diff_%u.disk' % (iDiffLvl);
965 oHd = oSession.createDiffHd(oHdParent, sDiskPath, None);
966
967 return oHd;
968
969 def testOneCfg(self, sVmName, eStorageController, sHostIoCache, sDiskFormat, # pylint: disable=R0913,R0914,R0915
970 sDiskVariant, sDiskPath, cCpus, sIoTest, sVirtMode, sTestSet):
971 """
972 Runs the specified VM thru test #1.
973
974 Returns a success indicator on the general test execution. This is not
975 the actual test result.
976 """
977 oVM = self.getVmByName(sVmName);
978
979 dTestSet = self.kdTestSets.get(sTestSet);
980 cbDisk = dTestSet.get('DiskSizeGb') * 1024*1024*1024;
981 fHwVirt = sVirtMode != 'raw';
982 fNestedPaging = sVirtMode == 'hwvirt-np';
983
984 fRc = True;
985 if sDiskFormat == 'iSCSI':
986 sDiskPath = self.asIscsiTargets[0];
987 elif self.fUseScratch:
988 sDiskPath = self.sScratchPath;
989 else:
990 # If requested recreate the storage space to start with a clean config
991 # for benchmarks
992 if self.fRecreateStorCfg:
993 sMountPoint = self.prepareStorage(self.oStorCfg, self.fUseRamDisk, cbDisk);
994 if sMountPoint is not None:
995 # Create a directory where every normal user can write to.
996 self.oStorCfg.mkDirOnVolume(sMountPoint, 'test', 0777);
997 sDiskPath = sMountPoint + '/test';
998 else:
999 fRc = False;
1000 reporter.testFailure('Failed to prepare storage for VM');
1001
1002 if not fRc:
1003 return fRc;
1004
1005 lstDisks = []; # List of disks we have to delete afterwards.
1006
1007 for iDiffLvl in range(self.cDiffLvls + 1):
1008 sIoLogFile = None;
1009
1010 if iDiffLvl == 0:
1011 reporter.testStart('Base');
1012 else:
1013 reporter.testStart('Diff %u' % (iDiffLvl));
1014
1015 # Reconfigure the VM
1016 oSession = self.openSession(oVM);
1017 if oSession is not None:
1018 # Attach HD
1019 fRc = oSession.ensureControllerAttached(_ControllerTypeToName(eStorageController));
1020 fRc = fRc and oSession.setStorageControllerType(eStorageController, _ControllerTypeToName(eStorageController));
1021
1022 if sHostIoCache == 'hostiocache':
1023 fRc = fRc and oSession.setStorageControllerHostIoCache(_ControllerTypeToName(eStorageController), True);
1024 elif sHostIoCache == 'no-hostiocache':
1025 fRc = fRc and oSession.setStorageControllerHostIoCache(_ControllerTypeToName(eStorageController), False);
1026
1027 iDevice = 0;
1028 if eStorageController == vboxcon.StorageControllerType_PIIX3 or \
1029 eStorageController == vboxcon.StorageControllerType_PIIX4:
1030 iDevice = 1; # Master is for the OS.
1031
1032 oHdParent = None;
1033 if iDiffLvl > 0:
1034 oHdParent = lstDisks[0];
1035 oHd = self.createHd(oSession, sDiskFormat, sDiskVariant, iDiffLvl, oHdParent, sDiskPath, cbDisk);
1036 if oHd is not None:
1037 lstDisks.insert(0, oHd);
1038 try:
1039 if oSession.fpApiVer >= 4.0:
1040 oSession.o.machine.attachDevice(_ControllerTypeToName(eStorageController), \
1041 0, iDevice, vboxcon.DeviceType_HardDisk, oHd);
1042 else:
1043 oSession.o.machine.attachDevice(_ControllerTypeToName(eStorageController), \
1044 0, iDevice, vboxcon.DeviceType_HardDisk, oHd.id);
1045 except:
1046 reporter.errorXcpt('attachDevice("%s",%s,%s,HardDisk,"%s") failed on "%s"' \
1047 % (_ControllerTypeToName(eStorageController), 1, 0, oHd.id, oSession.sName) );
1048 fRc = False;
1049 else:
1050 reporter.log('attached "%s" to %s' % (sDiskPath, oSession.sName));
1051 else:
1052 fRc = False;
1053
1054 # Set up the I/O logging config if enabled
1055 if fRc and self.fIoLog:
1056 try:
1057 oSession.o.machine.setExtraData('VBoxInternal2/EnableDiskIntegrityDriver', '1');
1058
1059 iLun = 0;
1060 if eStorageController == vboxcon.StorageControllerType_PIIX3 or \
1061 eStorageController == vboxcon.StorageControllerType_PIIX4:
1062 iLun = 1
1063 sDrv, fDrvScsi = self.getStorageDriverFromEnum(eStorageController, True);
1064 if fDrvScsi:
1065 sCfgmPath = 'VBoxInternal/Devices/%s/0/LUN#%u/AttachedDriver/Config' % (sDrv, iLun);
1066 else:
1067 sCfgmPath = 'VBoxInternal/Devices/%s/0/LUN#%u/Config' % (sDrv, iLun);
1068
1069 sIoLogFile = '%s/%s.iolog' % (self.sIoLogPath, sDrv);
1070 print sCfgmPath;
1071 print sIoLogFile;
1072 oSession.o.machine.setExtraData('%s/IoLog' % (sCfgmPath,), sIoLogFile);
1073 except:
1074 reporter.logXcpt();
1075
1076 fRc = fRc and oSession.enableVirtEx(fHwVirt);
1077 fRc = fRc and oSession.enableNestedPaging(fNestedPaging);
1078 fRc = fRc and oSession.setCpuCount(cCpus);
1079 fRc = fRc and oSession.saveSettings();
1080 fRc = oSession.close() and fRc and True; # pychecker hack.
1081 oSession = None;
1082 else:
1083 fRc = False;
1084
1085 # Start up.
1086 if fRc is True:
1087 self.logVmInfo(oVM);
1088 oSession, oTxsSession = self.startVmAndConnectToTxsViaTcp(sVmName, fCdWait = False, fNatForwardingForTxs = True);
1089 if oSession is not None:
1090 self.addTask(oTxsSession);
1091
1092 # Fudge factor - Allow the guest to finish starting up.
1093 self.sleep(5);
1094
1095 # Prepare the storage on the guest
1096 lstBinaryPaths = ['/bin', '/sbin', '/usr/bin', '/usr/sbin' ];
1097 oExecVm = remoteexecutor.RemoteExecutor(oTxsSession, lstBinaryPaths, '${SCRATCH}');
1098 oStorCfgVm = storagecfg.StorageCfg(oExecVm, 'linux', self.getGuestDisk(oSession, oTxsSession, \
1099 eStorageController));
1100
1101 sMountPoint = self.prepareStorage(oStorCfgVm);
1102 if sMountPoint is not None:
1103 self.testBenchmark('linux', sIoTest, sMountPoint, oExecVm, dTestSet, \
1104 cMsTimeout = 3 * 3600 * 1000); # 3 hours max (Benchmark and QED takes a lot of time)
1105 self.cleanupStorage(oStorCfgVm);
1106 else:
1107 reporter.testFailure('Failed to prepare storage for the guest benchmark');
1108
1109 # cleanup.
1110 self.removeTask(oTxsSession);
1111 self.terminateVmBySession(oSession);
1112
1113 # Add the I/O log if it exists and the test failed
1114 if reporter.testErrorCount() > 0 \
1115 and sIoLogFile is not None \
1116 and os.path.exists(sIoLogFile):
1117 reporter.addLogFile(sIoLogFile, 'misc/other', 'I/O log');
1118 os.remove(sIoLogFile);
1119
1120 else:
1121 fRc = False;
1122
1123 # Remove disk
1124 oSession = self.openSession(oVM);
1125 if oSession is not None:
1126 try:
1127 oSession.o.machine.detachDevice(_ControllerTypeToName(eStorageController), 0, iDevice);
1128
1129 # Remove storage controller if it is not an IDE controller.
1130 if eStorageController is not vboxcon.StorageControllerType_PIIX3 \
1131 and eStorageController is not vboxcon.StorageControllerType_PIIX4:
1132 oSession.o.machine.removeStorageController(_ControllerTypeToName(eStorageController));
1133
1134 oSession.saveSettings();
1135 oSession.saveSettings();
1136 oSession.close();
1137 oSession = None;
1138 except:
1139 reporter.errorXcpt('failed to detach/delete disk %s from storage controller' % (sDiskPath));
1140 else:
1141 fRc = False;
1142
1143 reporter.testDone();
1144
1145 # Delete all disks
1146 for oHd in lstDisks:
1147 self.oVBox.deleteHdByMedium(oHd);
1148
1149 # Cleanup storage area
1150 if sDiskFormat != 'iSCSI' and not self.fUseScratch and self.fRecreateStorCfg:
1151 self.cleanupStorage(self.oStorCfg);
1152
1153 return fRc;
1154
1155 def testStorage(self, sDiskPath = None):
1156 """
1157 Runs the storage testcase through the selected configurations
1158 """
1159
1160 aasTestCfgs = [];
1161 aasTestCfgs.insert(self.kiVmName, self.asTestVMs);
1162 aasTestCfgs.insert(self.kiStorageCtrl, self.asStorageCtrls);
1163 aasTestCfgs.insert(self.kiHostIoCache, (self.asHostIoCache, self.fnFormatHostIoCache));
1164 aasTestCfgs.insert(self.kiDiskFmt, self.asDiskFormats);
1165 aasTestCfgs.insert(self.kiDiskVar, self.asDiskVariants);
1166 aasTestCfgs.insert(self.kiCpuCount, (self.acCpus, self.fnFormatCpuString));
1167 aasTestCfgs.insert(self.kiVirtMode, (self.asVirtModes, self.fnFormatVirtMode));
1168 aasTestCfgs.insert(self.kiIoTest, self.asTests);
1169 aasTestCfgs.insert(self.kiTestSet, self.asTestSets);
1170
1171 aasTestsBlacklist = [];
1172 aasTestsBlacklist.append(['tst-storage', 'BusLogic']); # 64bit Linux is broken with BusLogic
1173
1174 oTstCfgMgr = StorTestCfgMgr(aasTestCfgs, aasTestsBlacklist, self.isTestCfgSupported);
1175
1176 fRc = True;
1177 asTestCfg = oTstCfgMgr.getCurrentTestCfg();
1178 while asTestCfg:
1179 fRc = self.testOneCfg(asTestCfg[self.kiVmName], self.getStorageCtrlFromName(asTestCfg[self.kiStorageCtrl]), \
1180 asTestCfg[self.kiHostIoCache], asTestCfg[self.kiDiskFmt], asTestCfg[self.kiDiskVar],
1181 sDiskPath, asTestCfg[self.kiCpuCount], asTestCfg[self.kiIoTest], \
1182 asTestCfg[self.kiVirtMode], asTestCfg[self.kiTestSet]) and fRc and True; # pychecker hack.
1183
1184 asTestCfg = oTstCfgMgr.getNextTestCfg();
1185
1186 return fRc;
1187
1188 def test1(self):
1189 """
1190 Executes test #1.
1191 """
1192
1193 fRc = True;
1194 oDiskCfg = self.kdStorageCfgs.get(socket.gethostname().lower());
1195
1196 # Test the host first if requested
1197 if oDiskCfg is not None or self.fUseScratch:
1198 lstBinaryPaths = ['/bin', '/sbin', '/usr/bin', '/usr/sbin', \
1199 '/opt/csw/bin', '/usr/ccs/bin', '/usr/sfw/bin'];
1200 oExecutor = remoteexecutor.RemoteExecutor(None, lstBinaryPaths, self.sScratchPath);
1201 if not self.fUseScratch:
1202 self.oStorCfg = storagecfg.StorageCfg(oExecutor, utils.getHostOs(), oDiskCfg);
1203
1204 # Try to cleanup any leftovers from a previous run first.
1205 fRc = self.oStorCfg.cleanupLeftovers();
1206 if not fRc:
1207 reporter.error('Failed to cleanup any leftovers from a previous run');
1208
1209 if self.fTestHost:
1210 reporter.testStart('Host');
1211 if self.fUseScratch:
1212 sMountPoint = self.sScratchPath;
1213 else:
1214 sMountPoint = self.prepareStorage(self.oStorCfg);
1215 if sMountPoint is not None:
1216 for sIoTest in self.asTests:
1217 reporter.testStart(sIoTest);
1218 for sTestSet in self.asTestSets:
1219 reporter.testStart(sTestSet);
1220 dTestSet = self.kdTestSets.get(sTestSet);
1221 self.testBenchmark(utils.getHostOs(), sIoTest, sMountPoint, oExecutor, dTestSet);
1222 reporter.testDone();
1223 reporter.testDone();
1224 self.cleanupStorage(self.oStorCfg);
1225 else:
1226 reporter.testFailure('Failed to prepare host storage');
1227 fRc = False;
1228 reporter.testDone();
1229 else:
1230 # Create the storage space first if it is not done before every test.
1231 sMountPoint = None;
1232 if self.fUseScratch:
1233 sMountPoint = self.sScratchPath;
1234 elif not self.fRecreateStorCfg:
1235 reporter.testStart('Create host storage');
1236 sMountPoint = self.prepareStorage(self.oStorCfg);
1237 if sMountPoint is None:
1238 reporter.testFailure('Failed to prepare host storage');
1239 fRc = False;
1240 self.oStorCfg.mkDirOnVolume(sMountPoint, 'test', 0777);
1241 sMountPoint = sMountPoint + '/test';
1242 reporter.testDone();
1243
1244 if fRc:
1245 # Run the storage tests.
1246 if not self.testStorage(sMountPoint):
1247 fRc = False;
1248
1249 if not self.fRecreateStorCfg and not self.fUseScratch:
1250 self.cleanupStorage(self.oStorCfg);
1251 else:
1252 fRc = False;
1253
1254 return fRc;
1255
1256if __name__ == '__main__':
1257 sys.exit(tdStorageBenchmark().main(sys.argv));
1258
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette