VirtualBox

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

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

ValidationKit/tdStorageBenchmark1: Upload the raw benchmark output including stderr

  • Property svn:eol-style set to LF
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 51.4 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# $Id: tdStorageBenchmark1.py 65731 2017-02-10 13:25:41Z vboxsync $
4
5"""
6VirtualBox Validation Kit - Storage benchmark.
7"""
8
9__copyright__ = \
10"""
11Copyright (C) 2012-2016 Oracle Corporation
12
13This file is part of VirtualBox Open Source Edition (OSE), as
14available from http://www.215389.xyz. 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: 65731 $"
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
109 cfgBuf.write('[seq-write]\n');
110 cfgBuf.write('rw=write\n');
111 cfgBuf.write('stonewall\n');
112
113 cfgBuf.write('[rand-write]\n');
114 cfgBuf.write('rw=randwrite\n');
115 cfgBuf.write('stonewall\n');
116
117 cfgBuf.write('[seq-read]\n');
118 cfgBuf.write('rw=read\n');
119 cfgBuf.write('stonewall\n');
120
121 cfgBuf.write('[rand-read]\n');
122 cfgBuf.write('rw=randread\n');
123 cfgBuf.write('stonewall\n');
124
125 self.sCfgFileId = self.oExecutor.copyString(cfgBuf.getvalue(), 'aio-test', cMsTimeout);
126 return self.sCfgFileId is not None;
127
128 def run(self, cMsTimeout = 30000):
129 """ Runs the testcase """
130 _ = cMsTimeout
131 fRc, sOutput, sError = self.oExecutor.execBinary('fio', (self.sCfgFileId,), cMsTimeout = cMsTimeout);
132 if fRc:
133 self.sResult = sOutput;
134 else:
135 self.sError = ('Binary: fio\n' +
136 '\nOutput:\n\n' +
137 sOutput +
138 '\nError:\n\n' +
139 sError);
140 return fRc;
141
142 def cleanup(self):
143 """ Cleans up any leftovers from the testcase. """
144
145 def reportResult(self):
146 """
147 Reports the test results to the test manager.
148 """
149 return True;
150
151 def getErrorReport(self):
152 """
153 Returns the error report in case the testcase failed.
154 """
155 return self.sError;
156
157class IozoneTest(object):
158 """
159 I/O zone testcase.
160 """
161 def __init__(self, oExecutor, dCfg = None):
162 self.oExecutor = oExecutor;
163 self.sResult = None;
164 self.sError = None;
165 self.lstTests = [ ('initial writers', 'FirstWrite'),
166 ('rewriters', 'Rewrite'),
167 ('re-readers', 'ReRead'),
168 ('stride readers', 'StrideRead'),
169 ('reverse readers', 'ReverseRead'),
170 ('random readers', 'RandomRead'),
171 ('mixed workload', 'MixedWorkload'),
172 ('random writers', 'RandomWrite'),
173 ('pwrite writers', 'PWrite'),
174 ('pread readers', 'PRead'),
175 ('fwriters', 'FWrite'),
176 ('freaders', 'FRead'),
177 ('readers', 'FirstRead')];
178 self.sRecordSize = dCfg.get('RecordSize', '4k');
179 self.sTestsetSize = dCfg.get('TestsetSize', '2g');
180 self.sQueueDepth = dCfg.get('QueueDepth', '32');
181 self.sFilePath = dCfg.get('FilePath', '/mnt/iozone');
182 self.fDirectIo = True;
183
184 sTargetOs = dCfg.get('TargetOs');
185 if sTargetOs == 'solaris':
186 self.fDirectIo = False;
187
188 def prepare(self, cMsTimeout = 30000):
189 """ Prepares the testcase """
190 _ = cMsTimeout;
191 return True; # Nothing to do.
192
193 def run(self, cMsTimeout = 30000):
194 """ Runs the testcase """
195 tupArgs = ('-r', self.sRecordSize, '-s', self.sTestsetSize, \
196 '-t', '1', '-T', '-F', self.sFilePath + '/iozone.tmp');
197 if self.fDirectIo:
198 tupArgs += ('-I',);
199 fRc, sOutput, sError = self.oExecutor.execBinary('iozone', tupArgs, cMsTimeout = cMsTimeout);
200 if fRc:
201 self.sResult = sOutput;
202 else:
203 self.sError = ('Binary: iozone\n' +
204 '\nOutput:\n\n' +
205 sOutput +
206 '\nError:\n\n' +
207 sError);
208
209 _ = cMsTimeout;
210 return fRc;
211
212 def cleanup(self):
213 """ Cleans up any leftovers from the testcase. """
214 return True;
215
216 def reportResult(self):
217 """
218 Reports the test results to the test manager.
219 """
220
221 fRc = True;
222 if self.sResult is not None:
223 try:
224 asLines = self.sResult.splitlines();
225 for sLine in asLines:
226 sLine = sLine.strip();
227 if sLine.startswith('Children') is True:
228 # Extract the value
229 idxValue = sLine.rfind('=');
230 if idxValue is -1:
231 raise Exception('IozoneTest: Invalid state');
232
233 idxValue += 1;
234 while sLine[idxValue] == ' ':
235 idxValue += 1;
236
237 # Get the reported value, cut off after the decimal point
238 # it is not supported by the testmanager yet and is not really
239 # relevant anyway.
240 idxValueEnd = idxValue;
241 while sLine[idxValueEnd].isdigit():
242 idxValueEnd += 1;
243
244 for sNeedle, sTestVal in self.lstTests:
245 if sLine.rfind(sNeedle) is not -1:
246 reporter.testValue(sTestVal, sLine[idxValue:idxValueEnd],
247 constants.valueunit.g_asNames[constants.valueunit.KILOBYTES_PER_SEC]);
248 break;
249 except:
250 fRc = False;
251 else:
252 fRc = False;
253
254 return fRc;
255
256 def getErrorReport(self):
257 """
258 Returns the error report in case the testcase failed.
259 """
260 return self.sError;
261
262class StorTestCfgMgr(object):
263 """
264 Manages the different testcases.
265 """
266
267 def __init__(self, aasTestLvls, aasTestsBlacklist, fnIsCfgSupported = None):
268 self.aasTestsBlacklist = aasTestsBlacklist;
269 self.at3TestLvls = [];
270 self.iTestLvl = 0;
271 self.fnIsCfgSupported = fnIsCfgSupported;
272 for asTestLvl in aasTestLvls:
273 if isinstance(asTestLvl, tuple):
274 asTestLvl, fnTestFmt = asTestLvl;
275 self.at3TestLvls.append((0, fnTestFmt, asTestLvl));
276 else:
277 self.at3TestLvls.append((0, None, asTestLvl));
278
279 self.at3TestLvls.reverse();
280
281 # Get the first non blacklisted test.
282 asTestCfg = self.getCurrentTestCfg();
283 while len(asTestCfg) > 0 and self.isTestCfgBlacklisted(asTestCfg):
284 asTestCfg = self.advanceTestCfg();
285
286 iLvl = 0;
287 for sCfg in asTestCfg:
288 reporter.testStart('%s' % (self.getTestIdString(sCfg, iLvl)));
289 iLvl += 1;
290
291 def __del__(self):
292 # Make sure the tests are marked as done.
293 while self.iTestLvl < len(self.at3TestLvls):
294 reporter.testDone();
295 self.iTestLvl += 1;
296
297 def getTestIdString(self, oCfg, iLvl):
298 """
299 Returns a potentially formatted string for the test name.
300 """
301
302 # The order of the test levels is reversed so get the level starting
303 # from the end.
304 _, fnTestFmt, _ = self.at3TestLvls[len(self.at3TestLvls) - 1 - iLvl];
305 if fnTestFmt is not None:
306 return fnTestFmt(oCfg);
307 else:
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 len(asTestCfg) > 0 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 len(asTestCfg) > 0:
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': 100
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
504 #
505 # Overridden methods.
506 #
507 def showUsage(self):
508 rc = vbox.TestDriver.showUsage(self);
509 reporter.log('');
510 reporter.log('tdStorageBenchmark1 Options:');
511 reporter.log(' --virt-modes <m1[:m2[:]]');
512 reporter.log(' Default: %s' % (':'.join(self.asVirtModesDef)));
513 reporter.log(' --cpu-counts <c1[:c2[:]]');
514 reporter.log(' Default: %s' % (':'.join(str(c) for c in self.acCpusDef)));
515 reporter.log(' --storage-ctrls <type1[:type2[:...]]>');
516 reporter.log(' Default: %s' % (':'.join(self.asStorageCtrlsDef)));
517 reporter.log(' --host-io-cache <setting1[:setting2[:...]]>');
518 reporter.log(' Default: %s' % (':'.join(self.asHostIoCacheDef)));
519 reporter.log(' --disk-formats <type1[:type2[:...]]>');
520 reporter.log(' Default: %s' % (':'.join(self.asDiskFormatsDef)));
521 reporter.log(' --disk-variants <variant1[:variant2[:...]]>');
522 reporter.log(' Default: %s' % (':'.join(self.asDiskVariantsDef)));
523 reporter.log(' --iscsi-targets <target1[:target2[:...]]>');
524 reporter.log(' Default: %s' % (':'.join(self.asIscsiTargetsDef)));
525 reporter.log(' --tests <test1[:test2[:...]]>');
526 reporter.log(' Default: %s' % (':'.join(self.asTestsDef)));
527 reporter.log(' --test-sets <set1[:set2[:...]]>');
528 reporter.log(' Default: %s' % (':'.join(self.asTestSetsDef)));
529 reporter.log(' --diff-levels <number of diffs>');
530 reporter.log(' Default: %s' % (self.cDiffLvlsDef));
531 reporter.log(' --test-vms <vm1[:vm2[:...]]>');
532 reporter.log(' Test the specified VMs in the given order. Use this to change');
533 reporter.log(' the execution order or limit the choice of VMs');
534 reporter.log(' Default: %s (all)' % (':'.join(self.asTestVMsDef)));
535 reporter.log(' --skip-vms <vm1[:vm2[:...]]>');
536 reporter.log(' Skip the specified VMs when testing.');
537 reporter.log(' --test-host');
538 reporter.log(' Do all configured tests on the host first and report the results');
539 reporter.log(' to get a baseline');
540 reporter.log(' --use-scratch');
541 reporter.log(' Use the scratch directory for testing instead of setting up');
542 reporter.log(' fresh volumes on dedicated disks (for development)');
543 reporter.log(' --always-wipe-storage-cfg');
544 reporter.log(' Recreate the host storage config before each test');
545 reporter.log(' --dont-wipe-storage-cfg');
546 reporter.log(' Don\'t recreate the host storage config before each test');
547 reporter.log(' --report-benchmark-results');
548 reporter.log(' Report all benchmark results');
549 reporter.log(' --dont-report-benchmark-results');
550 reporter.log(' Don\'t report any benchmark results');
551 reporter.log(' --io-log-path <path>');
552 reporter.log(' Default: %s' % (self.sIoLogPathDef));
553 reporter.log(' --enable-io-log');
554 reporter.log(' Whether to enable I/O logging for each test');
555 return rc;
556
557 def parseOption(self, asArgs, iArg): # pylint: disable=R0912,R0915
558 if asArgs[iArg] == '--virt-modes':
559 iArg += 1;
560 if iArg >= len(asArgs): raise base.InvalidOption('The "--virt-modes" takes a colon separated list of modes');
561 self.asVirtModes = asArgs[iArg].split(':');
562 for s in self.asVirtModes:
563 if s not in self.asVirtModesDef:
564 raise base.InvalidOption('The "--virt-modes" value "%s" is not valid; valid values are: %s' \
565 % (s, ' '.join(self.asVirtModesDef)));
566 elif asArgs[iArg] == '--cpu-counts':
567 iArg += 1;
568 if iArg >= len(asArgs): raise base.InvalidOption('The "--cpu-counts" takes a colon separated list of cpu counts');
569 self.acCpus = [];
570 for s in asArgs[iArg].split(':'):
571 try: c = int(s);
572 except: raise base.InvalidOption('The "--cpu-counts" value "%s" is not an integer' % (s,));
573 if c <= 0: raise base.InvalidOption('The "--cpu-counts" value "%s" is zero or negative' % (s,));
574 self.acCpus.append(c);
575 elif asArgs[iArg] == '--storage-ctrls':
576 iArg += 1;
577 if iArg >= len(asArgs):
578 raise base.InvalidOption('The "--storage-ctrls" takes a colon separated list of Storage controller types');
579 self.asStorageCtrls = asArgs[iArg].split(':');
580 elif asArgs[iArg] == '--host-io-cache':
581 iArg += 1;
582 if iArg >= len(asArgs):
583 raise base.InvalidOption('The "--host-io-cache" takes a colon separated list of I/O cache settings');
584 self.asHostIoCache = asArgs[iArg].split(':');
585 elif asArgs[iArg] == '--disk-formats':
586 iArg += 1;
587 if iArg >= len(asArgs): raise base.InvalidOption('The "--disk-formats" takes a colon separated list of disk formats');
588 self.asDiskFormats = asArgs[iArg].split(':');
589 elif asArgs[iArg] == '--disk-variants':
590 iArg += 1;
591 if iArg >= len(asArgs):
592 raise base.InvalidOption('The "--disk-variants" takes a colon separated list of disk variants');
593 self.asDiskVariants = asArgs[iArg].split(':');
594 elif asArgs[iArg] == '--iscsi-targets':
595 iArg += 1;
596 if iArg >= len(asArgs):
597 raise base.InvalidOption('The "--iscsi-targets" takes a colon separated list of iscsi targets');
598 self.asIscsiTargets = asArgs[iArg].split(':');
599 elif asArgs[iArg] == '--tests':
600 iArg += 1;
601 if iArg >= len(asArgs): raise base.InvalidOption('The "--tests" takes a colon separated list of tests to run');
602 self.asTests = asArgs[iArg].split(':');
603 elif asArgs[iArg] == '--test-sets':
604 iArg += 1;
605 if iArg >= len(asArgs): raise base.InvalidOption('The "--test-sets" takes a colon separated list of test sets');
606 self.asTestSets = asArgs[iArg].split(':');
607 elif asArgs[iArg] == '--diff-levels':
608 iArg += 1;
609 if iArg >= len(asArgs): raise base.InvalidOption('The "--diff-levels" takes an integer');
610 try: self.cDiffLvls = int(asArgs[iArg]);
611 except: raise base.InvalidOption('The "--diff-levels" value "%s" is not an integer' % (asArgs[iArg],));
612 elif asArgs[iArg] == '--test-vms':
613 iArg += 1;
614 if iArg >= len(asArgs): raise base.InvalidOption('The "--test-vms" takes colon separated list');
615 self.asTestVMs = asArgs[iArg].split(':');
616 for s in self.asTestVMs:
617 if s not in self.asTestVMsDef:
618 raise base.InvalidOption('The "--test-vms" value "%s" is not valid; valid values are: %s' \
619 % (s, ' '.join(self.asTestVMsDef)));
620 elif asArgs[iArg] == '--skip-vms':
621 iArg += 1;
622 if iArg >= len(asArgs): raise base.InvalidOption('The "--skip-vms" takes colon separated list');
623 self.asSkipVMs = asArgs[iArg].split(':');
624 for s in self.asSkipVMs:
625 if s not in self.asTestVMsDef:
626 reporter.log('warning: The "--test-vms" value "%s" does not specify any of our test VMs.' % (s));
627 elif asArgs[iArg] == '--test-host':
628 self.fTestHost = True;
629 elif asArgs[iArg] == '--use-scratch':
630 self.fUseScratch = True;
631 elif asArgs[iArg] == '--always-wipe-storage-cfg':
632 self.fRecreateStorCfg = True;
633 elif asArgs[iArg] == '--dont-wipe-storage-cfg':
634 self.fRecreateStorCfg = False;
635 elif asArgs[iArg] == '--report-benchmark-results':
636 self.fReportBenchmarkResults = True;
637 elif asArgs[iArg] == '--dont-report-benchmark-results':
638 self.fReportBenchmarkResults = False;
639 elif asArgs[iArg] == '--io-log-path':
640 if iArg >= len(asArgs): raise base.InvalidOption('The "--io-log-path" takes a path argument');
641 self.sIoLogPath = asArgs[iArg];
642 elif asArgs[iArg] == '--enable-io-log':
643 self.fIoLog = True;
644 else:
645 return vbox.TestDriver.parseOption(self, asArgs, iArg);
646 return iArg + 1;
647
648 def completeOptions(self):
649 # Remove skipped VMs from the test list.
650 for sVM in self.asSkipVMs:
651 try: self.asTestVMs.remove(sVM);
652 except: pass;
653
654 return vbox.TestDriver.completeOptions(self);
655
656 def getResourceSet(self):
657 # Construct the resource list the first time it's queried.
658 if self.asRsrcs is None:
659 self.asRsrcs = [];
660 if 'tst-storage' in self.asTestVMs:
661 self.asRsrcs.append('5.0/storage/tst-storage.vdi');
662 if 'tst-storage32' in self.asTestVMs:
663 self.asRsrcs.append('5.0/storage/tst-storage32.vdi');
664
665 return self.asRsrcs;
666
667 def actionConfig(self):
668
669 # Make sure vboxapi has been imported so we can use the constants.
670 if not self.importVBoxApi():
671 return False;
672
673 #
674 # Configure the VMs we're going to use.
675 #
676
677 # Linux VMs
678 if 'tst-storage' in self.asTestVMs:
679 oVM = self.createTestVM('tst-storage', 1, '5.0/storage/tst-storage.vdi', sKind = 'ArchLinux_64', fIoApic = True, \
680 eNic0AttachType = vboxcon.NetworkAttachmentType_NAT, \
681 eNic0Type = vboxcon.NetworkAdapterType_Am79C973);
682 if oVM is None:
683 return False;
684
685 if 'tst-storage32' in self.asTestVMs:
686 oVM = self.createTestVM('tst-storage32', 1, '5.0/storage/tst-storage32.vdi', sKind = 'ArchLinux', fIoApic = True, \
687 eNic0AttachType = vboxcon.NetworkAttachmentType_NAT, \
688 eNic0Type = vboxcon.NetworkAdapterType_Am79C973);
689 if oVM is None:
690 return False;
691
692 return True;
693
694 def actionExecute(self):
695 """
696 Execute the testcase.
697 """
698 fRc = self.test1();
699 return fRc;
700
701
702 #
703 # Test execution helpers.
704 #
705
706 def prepareStorage(self, oStorCfg):
707 """
708 Prepares the host storage for disk images or direct testing on the host.
709 """
710 # Create a basic pool with the default configuration.
711 sMountPoint = None;
712 fRc, sPoolId = oStorCfg.createStoragePool();
713 if fRc:
714 fRc, sMountPoint = oStorCfg.createVolume(sPoolId);
715 if not fRc:
716 sMountPoint = None;
717 oStorCfg.cleanup();
718
719 return sMountPoint;
720
721 def cleanupStorage(self, oStorCfg):
722 """
723 Cleans up any created storage space for a test.
724 """
725 return oStorCfg.cleanup();
726
727 def getGuestDisk(self, oSession, oTxsSession, eStorageController):
728 """
729 Gets the path of the disk in the guest to use for testing.
730 """
731 lstDisks = None;
732
733 # The naming scheme for NVMe is different and we don't have
734 # to query the guest for unformatted disks here because the disk with the OS
735 # is not attached to a NVMe controller.
736 if eStorageController == vboxcon.StorageControllerType_NVMe:
737 lstDisks = [ '/dev/nvme0n1' ];
738 else:
739 # Find a unformatted disk (no partition).
740 # @todo: This is a hack because LIST and STAT are not yet implemented
741 # in TXS (get to this eventually)
742 lstBlkDev = [ '/dev/sda', '/dev/sdb' ];
743 for sBlkDev in lstBlkDev:
744 fRc = oTxsSession.syncExec('/usr/bin/ls', ('ls', sBlkDev + '1'));
745 if not fRc:
746 lstDisks = [ sBlkDev ];
747 break;
748
749 _ = oSession;
750 return lstDisks;
751
752 def getDiskFormatVariantsForTesting(self, sDiskFmt, asVariants):
753 """
754 Returns a list of disk variants for testing supported by the given
755 disk format and selected for testing.
756 """
757 lstDskFmts = self.oVBoxMgr.getArray(self.oVBox.systemProperties, 'mediumFormats');
758 for oDskFmt in lstDskFmts:
759 if oDskFmt.id == sDiskFmt:
760 lstDskVariants = [];
761 lstCaps = self.oVBoxMgr.getArray(oDskFmt, 'capabilities');
762
763 if vboxcon.MediumFormatCapabilities_CreateDynamic in lstCaps \
764 and 'Dynamic' in asVariants:
765 lstDskVariants.append('Dynamic');
766
767 if vboxcon.MediumFormatCapabilities_CreateFixed in lstCaps \
768 and 'Fixed' in asVariants:
769 lstDskVariants.append('Fixed');
770
771 if vboxcon.MediumFormatCapabilities_CreateSplit2G in lstCaps \
772 and vboxcon.MediumFormatCapabilities_CreateDynamic in lstCaps \
773 and 'DynamicSplit2G' in asVariants:
774 lstDskVariants.append('DynamicSplit2G');
775
776 if vboxcon.MediumFormatCapabilities_CreateSplit2G in lstCaps \
777 and vboxcon.MediumFormatCapabilities_CreateFixed in lstCaps \
778 and 'FixedSplit2G' in asVariants:
779 lstDskVariants.append('FixedSplit2G');
780
781 if vboxcon.MediumFormatCapabilities_TcpNetworking in lstCaps \
782 and 'Network' in asVariants:
783 lstDskVariants.append('Network'); # Solely for iSCSI to get a non empty list
784
785 return lstDskVariants;
786
787 return [];
788
789 def convDiskToMediumVariant(self, sDiskVariant):
790 """
791 Returns a tuple of medium variant flags matching the given disk variant.
792 """
793 tMediumVariant = None;
794 if sDiskVariant == 'Dynamic':
795 tMediumVariant = (vboxcon.MediumVariant_Standard, );
796 elif sDiskVariant == 'Fixed':
797 tMediumVariant = (vboxcon.MediumVariant_Fixed, );
798 elif sDiskVariant == 'DynamicSplit2G':
799 tMediumVariant = (vboxcon.MediumVariant_Standard, vboxcon.MediumVariant_VmdkSplit2G);
800 elif sDiskVariant == 'FixedSplit2G':
801 tMediumVariant = (vboxcon.MediumVariant_Fixed, vboxcon.MediumVariant_VmdkSplit2G);
802
803 return tMediumVariant;
804
805 def getStorageCtrlFromName(self, sStorageCtrl):
806 """
807 Resolves the storage controller string to the matching constant.
808 """
809 eStorageCtrl = None;
810
811 if sStorageCtrl == 'AHCI':
812 eStorageCtrl = vboxcon.StorageControllerType_IntelAhci;
813 elif sStorageCtrl == 'IDE':
814 eStorageCtrl = vboxcon.StorageControllerType_PIIX4;
815 elif sStorageCtrl == 'LsiLogicSAS':
816 eStorageCtrl = vboxcon.StorageControllerType_LsiLogicSas;
817 elif sStorageCtrl == 'LsiLogic':
818 eStorageCtrl = vboxcon.StorageControllerType_LsiLogic;
819 elif sStorageCtrl == 'BusLogic':
820 eStorageCtrl = vboxcon.StorageControllerType_BusLogic;
821 elif sStorageCtrl == 'NVMe':
822 eStorageCtrl = vboxcon.StorageControllerType_NVMe;
823
824 return eStorageCtrl;
825
826 def getStorageDriverFromEnum(self, eStorageCtrl, fHardDisk):
827 """
828 Returns the appropriate driver name for the given storage controller
829 and a flag whether the driver has the generic SCSI driver attached.
830 """
831 if eStorageCtrl == vboxcon.StorageControllerType_IntelAhci:
832 if fHardDisk:
833 return ('ahci', False);
834 else:
835 return ('ahci', True);
836 elif eStorageCtrl == vboxcon.StorageControllerType_PIIX4:
837 return ('piix3ide', False);
838 elif eStorageCtrl == vboxcon.StorageControllerType_LsiLogicSas:
839 return ('lsilogicsas', True);
840 elif eStorageCtrl == vboxcon.StorageControllerType_LsiLogic:
841 return ('lsilogicscsi', True);
842 elif eStorageCtrl == vboxcon.StorageControllerType_BusLogic:
843 return ('buslogic', True);
844 elif eStorageCtrl == vboxcon.StorageControllerType_NVMe:
845 return ('nvme', False);
846
847 return ('<invalid>', False);
848
849 def isTestCfgSupported(self, asTestCfg):
850 """
851 Returns whether a specific test config is supported.
852 """
853
854 # Check whether the disk variant is supported by the selected format.
855 asVariants = self.getDiskFormatVariantsForTesting(asTestCfg[self.kiDiskFmt], [ asTestCfg[self.kiDiskVar] ]);
856 if len(asVariants) == 0:
857 return False;
858
859 # For iSCSI check whether we have targets configured.
860 if asTestCfg[self.kiDiskFmt] == 'iSCSI' and len(self.asIscsiTargets) == 0:
861 return False;
862
863 # Check for virt mode, CPU count and selected VM.
864 if asTestCfg[self.kiVirtMode] == 'raw' \
865 and (asTestCfg[self.kiCpuCount] > 1 or asTestCfg[self.kiVmName] == 'tst-storage'):
866 return False;
867
868 # IDE does not support the no host I/O cache setting
869 if asTestCfg[self.kiHostIoCache] == 'no-hostiocache' \
870 and asTestCfg[self.kiStorageCtrl] == 'IDE':
871 return False;
872
873 return True;
874
875 def fnFormatCpuString(self, cCpus):
876 """
877 Formats the CPU count to be readable.
878 """
879 if cCpus == 1:
880 return '1 cpu';
881 else:
882 return '%u cpus' % (cCpus);
883
884 def fnFormatVirtMode(self, sVirtMode):
885 """
886 Formats the virtualization mode to be a little less cryptic for use in test
887 descriptions.
888 """
889 return self.kdVirtModeDescs[sVirtMode];
890
891 def fnFormatHostIoCache(self, sHostIoCache):
892 """
893 Formats the host I/O cache mode to be a little less cryptic for use in test
894 descriptions.
895 """
896 return self.kdHostIoCacheDescs[sHostIoCache];
897
898 def testBenchmark(self, sTargetOs, sBenchmark, sMountpoint, oExecutor, dTestSet, \
899 cMsTimeout = 3600000):
900 """
901 Runs the given benchmark on the test host.
902 """
903
904 dTestSet['FilePath'] = sMountpoint;
905 dTestSet['TargetOs'] = sTargetOs;
906
907 oTst = None;
908 if sBenchmark == 'iozone':
909 oTst = IozoneTest(oExecutor, dTestSet);
910 elif sBenchmark == 'fio':
911 oTst = FioTest(oExecutor, dTestSet); # pylint: disable=R0204
912
913 if oTst is not None:
914 fRc = oTst.prepare();
915 if fRc:
916 fRc = oTst.run(cMsTimeout);
917 if fRc:
918 if self.fReportBenchmarkResults:
919 fRc = oTst.reportResult();
920 else:
921 reporter.testFailure('Running the testcase failed');
922 reporter.addLogString(oTst.getErrorReport(), sBenchmark + '.log',
923 'log/release/client', 'Benchmark raw output');
924 else:
925 reporter.testFailure('Preparing the testcase failed');
926
927 oTst.cleanup();
928
929 return fRc;
930
931 def createHd(self, oSession, sDiskFormat, sDiskVariant, iDiffLvl, oHdParent, \
932 sDiskPath, cbDisk):
933 """
934 Creates a new disk with the given parameters returning the medium object
935 on success.
936 """
937
938 oHd = None;
939 if sDiskFormat == "iSCSI" and iDiffLvl == 0:
940 listNames = [];
941 listValues = [];
942 listValues = self.asIscsiTargets[0].split('|');
943 listNames.append('TargetAddress');
944 listNames.append('TargetName');
945 listNames.append('LUN');
946
947 if self.fpApiVer >= 5.0:
948 oHd = oSession.oVBox.createMedium(sDiskFormat, sDiskPath, vboxcon.AccessMode_ReadWrite, \
949 vboxcon.DeviceType_HardDisk);
950 else:
951 oHd = oSession.oVBox.createHardDisk(sDiskFormat, sDiskPath);
952 oHd.type = vboxcon.MediumType_Normal;
953 oHd.setProperties(listNames, listValues);
954 else:
955 if iDiffLvl == 0:
956 tMediumVariant = self.convDiskToMediumVariant(sDiskVariant);
957 oHd = oSession.createBaseHd(sDiskPath + '/base.disk', sDiskFormat, cbDisk, \
958 cMsTimeout = 3600 * 1000, tMediumVariant = tMediumVariant);
959 else:
960 sDiskPath = sDiskPath + '/diff_%u.disk' % (iDiffLvl);
961 oHd = oSession.createDiffHd(oHdParent, sDiskPath, None);
962
963 return oHd;
964
965 def testOneCfg(self, sVmName, eStorageController, sHostIoCache, sDiskFormat, # pylint: disable=R0913,R0914,R0915
966 sDiskVariant, sDiskPath, cCpus, sIoTest, sVirtMode, sTestSet):
967 """
968 Runs the specified VM thru test #1.
969
970 Returns a success indicator on the general test execution. This is not
971 the actual test result.
972 """
973 oVM = self.getVmByName(sVmName);
974
975 dTestSet = self.kdTestSets.get(sTestSet);
976 cbDisk = dTestSet.get('DiskSizeGb') * 1024*1024*1024;
977 fHwVirt = sVirtMode != 'raw';
978 fNestedPaging = sVirtMode == 'hwvirt-np';
979
980 fRc = True;
981 if sDiskFormat == 'iSCSI':
982 sDiskPath = self.asIscsiTargets[0];
983 elif self.fUseScratch:
984 sDiskPath = self.sScratchPath;
985 else:
986 # If requested recreate the storage space to start with a clean config
987 # for benchmarks
988 if self.fRecreateStorCfg:
989 sMountPoint = self.prepareStorage(self.oStorCfg);
990 if sMountPoint is not None:
991 # Create a directory where every normal user can write to.
992 self.oStorCfg.mkDirOnVolume(sMountPoint, 'test', 0777);
993 sDiskPath = sMountPoint + '/test';
994 else:
995 fRc = False;
996 reporter.testFailure('Failed to prepare storage for VM');
997
998 if not fRc:
999 return fRc;
1000
1001 lstDisks = []; # List of disks we have to delete afterwards.
1002
1003 for iDiffLvl in range(self.cDiffLvls + 1):
1004 sIoLogFile = None;
1005
1006 if iDiffLvl == 0:
1007 reporter.testStart('Base');
1008 else:
1009 reporter.testStart('Diff %u' % (iDiffLvl));
1010
1011 # Reconfigure the VM
1012 oSession = self.openSession(oVM);
1013 if oSession is not None:
1014 # Attach HD
1015 fRc = oSession.ensureControllerAttached(_ControllerTypeToName(eStorageController));
1016 fRc = fRc and oSession.setStorageControllerType(eStorageController, _ControllerTypeToName(eStorageController));
1017
1018 if sHostIoCache == 'hostiocache':
1019 fRc = fRc and oSession.setStorageControllerHostIoCache(_ControllerTypeToName(eStorageController), True);
1020 elif sHostIoCache == 'no-hostiocache':
1021 fRc = fRc and oSession.setStorageControllerHostIoCache(_ControllerTypeToName(eStorageController), False);
1022
1023 iDevice = 0;
1024 if eStorageController == vboxcon.StorageControllerType_PIIX3 or \
1025 eStorageController == vboxcon.StorageControllerType_PIIX4:
1026 iDevice = 1; # Master is for the OS.
1027
1028 oHdParent = None;
1029 if iDiffLvl > 0:
1030 oHdParent = lstDisks[0];
1031 oHd = self.createHd(oSession, sDiskFormat, sDiskVariant, iDiffLvl, oHdParent, sDiskPath, cbDisk);
1032 if oHd is not None:
1033 lstDisks.insert(0, oHd);
1034 try:
1035 if oSession.fpApiVer >= 4.0:
1036 oSession.o.machine.attachDevice(_ControllerTypeToName(eStorageController), \
1037 0, iDevice, vboxcon.DeviceType_HardDisk, oHd);
1038 else:
1039 oSession.o.machine.attachDevice(_ControllerTypeToName(eStorageController), \
1040 0, iDevice, vboxcon.DeviceType_HardDisk, oHd.id);
1041 except:
1042 reporter.errorXcpt('attachDevice("%s",%s,%s,HardDisk,"%s") failed on "%s"' \
1043 % (_ControllerTypeToName(eStorageController), 1, 0, oHd.id, oSession.sName) );
1044 fRc = False;
1045 else:
1046 reporter.log('attached "%s" to %s' % (sDiskPath, oSession.sName));
1047 else:
1048 fRc = False;
1049
1050 # Set up the I/O logging config if enabled
1051 if fRc and self.fIoLog:
1052 try:
1053 oSession.o.machine.setExtraData('VBoxInternal2/EnableDiskIntegrityDriver', '1');
1054
1055 iLun = 0;
1056 if eStorageController == vboxcon.StorageControllerType_PIIX3 or \
1057 eStorageController == vboxcon.StorageControllerType_PIIX4:
1058 iLun = 1
1059 sDrv, fDrvScsi = self.getStorageDriverFromEnum(eStorageController, True);
1060 if fDrvScsi:
1061 sCfgmPath = 'VBoxInternal/Devices/%s/0/LUN#%u/AttachedDriver/Config' % (sDrv, iLun);
1062 else:
1063 sCfgmPath = 'VBoxInternal/Devices/%s/0/LUN#%u/Config' % (sDrv, iLun);
1064
1065 sIoLogFile = '%s/%s.iolog' % (self.sIoLogPath, sDrv);
1066 print sCfgmPath;
1067 print sIoLogFile;
1068 oSession.o.machine.setExtraData('%s/IoLog' % (sCfgmPath,), sIoLogFile);
1069 except:
1070 reporter.logXcpt();
1071
1072 fRc = fRc and oSession.enableVirtEx(fHwVirt);
1073 fRc = fRc and oSession.enableNestedPaging(fNestedPaging);
1074 fRc = fRc and oSession.setCpuCount(cCpus);
1075 fRc = fRc and oSession.saveSettings();
1076 fRc = oSession.close() and fRc and True; # pychecker hack.
1077 oSession = None;
1078 else:
1079 fRc = False;
1080
1081 # Start up.
1082 if fRc is True:
1083 self.logVmInfo(oVM);
1084 oSession, oTxsSession = self.startVmAndConnectToTxsViaTcp(sVmName, fCdWait = False, fNatForwardingForTxs = True);
1085 if oSession is not None:
1086 self.addTask(oSession);
1087
1088 # Fudge factor - Allow the guest to finish starting up.
1089 self.sleep(5);
1090
1091 # Prepare the storage on the guest
1092 lstBinaryPaths = ['/bin', '/sbin', '/usr/bin', '/usr/sbin' ];
1093 oExecVm = remoteexecutor.RemoteExecutor(oTxsSession, lstBinaryPaths, '${SCRATCH}');
1094 oStorCfgVm = storagecfg.StorageCfg(oExecVm, 'linux', self.getGuestDisk(oSession, oTxsSession, \
1095 eStorageController));
1096
1097 sMountPoint = self.prepareStorage(oStorCfgVm);
1098 if sMountPoint is not None:
1099 self.testBenchmark('linux', sIoTest, sMountPoint, oExecVm, dTestSet, \
1100 cMsTimeout = 3 * 3600 * 1000); # 3 hours max (Benchmark and QED takes a lot of time)
1101 self.cleanupStorage(oStorCfgVm);
1102 else:
1103 reporter.testFailure('Failed to prepare storage for the guest benchmark');
1104
1105 # cleanup.
1106 self.removeTask(oTxsSession);
1107 self.terminateVmBySession(oSession);
1108
1109 # Add the I/O log if it exists and the test failed
1110 if reporter.testErrorCount() > 0 \
1111 and sIoLogFile is not None \
1112 and os.path.exists(sIoLogFile):
1113 reporter.addLogFile(sIoLogFile, 'misc/other', 'I/O log');
1114 os.remove(sIoLogFile);
1115
1116 else:
1117 fRc = False;
1118
1119 # Remove disk
1120 oSession = self.openSession(oVM);
1121 if oSession is not None:
1122 try:
1123 oSession.o.machine.detachDevice(_ControllerTypeToName(eStorageController), 0, iDevice);
1124
1125 # Remove storage controller if it is not an IDE controller.
1126 if eStorageController is not vboxcon.StorageControllerType_PIIX3 \
1127 and eStorageController is not vboxcon.StorageControllerType_PIIX4:
1128 oSession.o.machine.removeStorageController(_ControllerTypeToName(eStorageController));
1129
1130 oSession.saveSettings();
1131 oSession.saveSettings();
1132 oSession.close();
1133 oSession = None;
1134 except:
1135 reporter.errorXcpt('failed to detach/delete disk %s from storage controller' % (sDiskPath));
1136 else:
1137 fRc = False;
1138
1139 reporter.testDone();
1140
1141 # Delete all disks
1142 for oHd in lstDisks:
1143 self.oVBox.deleteHdByMedium(oHd);
1144
1145 # Cleanup storage area
1146 if sDiskFormat != 'iSCSI' and not self.fUseScratch and self.fRecreateStorCfg:
1147 self.cleanupStorage(self.oStorCfg);
1148
1149 return fRc;
1150
1151 def testStorage(self, sDiskPath = None):
1152 """
1153 Runs the storage testcase through the selected configurations
1154 """
1155
1156 aasTestCfgs = [];
1157 aasTestCfgs.insert(self.kiVmName, self.asTestVMs);
1158 aasTestCfgs.insert(self.kiStorageCtrl, self.asStorageCtrls);
1159 aasTestCfgs.insert(self.kiHostIoCache, (self.asHostIoCache, self.fnFormatHostIoCache));
1160 aasTestCfgs.insert(self.kiDiskFmt, self.asDiskFormats);
1161 aasTestCfgs.insert(self.kiDiskVar, self.asDiskVariants);
1162 aasTestCfgs.insert(self.kiCpuCount, (self.acCpus, self.fnFormatCpuString));
1163 aasTestCfgs.insert(self.kiVirtMode, (self.asVirtModes, self.fnFormatVirtMode));
1164 aasTestCfgs.insert(self.kiIoTest, self.asTests);
1165 aasTestCfgs.insert(self.kiTestSet, self.asTestSets);
1166
1167 aasTestsBlacklist = [];
1168 aasTestsBlacklist.append(['tst-storage', 'BusLogic']); # 64bit Linux is broken with BusLogic
1169
1170 oTstCfgMgr = StorTestCfgMgr(aasTestCfgs, aasTestsBlacklist, self.isTestCfgSupported);
1171
1172 fRc = True;
1173 asTestCfg = oTstCfgMgr.getCurrentTestCfg();
1174 while len(asTestCfg) > 0:
1175 fRc = self.testOneCfg(asTestCfg[self.kiVmName], self.getStorageCtrlFromName(asTestCfg[self.kiStorageCtrl]), \
1176 asTestCfg[self.kiHostIoCache], asTestCfg[self.kiDiskFmt], asTestCfg[self.kiDiskVar],
1177 sDiskPath, asTestCfg[self.kiCpuCount], asTestCfg[self.kiIoTest], \
1178 asTestCfg[self.kiVirtMode], asTestCfg[self.kiTestSet]) and fRc and True; # pychecker hack.
1179
1180 asTestCfg = oTstCfgMgr.getNextTestCfg();
1181
1182 return fRc;
1183
1184 def test1(self):
1185 """
1186 Executes test #1.
1187 """
1188
1189 fRc = True;
1190 oDiskCfg = self.kdStorageCfgs.get(socket.gethostname().lower());
1191
1192 # Test the host first if requested
1193 if oDiskCfg is not None or self.fUseScratch:
1194 lstBinaryPaths = ['/bin', '/sbin', '/usr/bin', '/usr/sbin', \
1195 '/opt/csw/bin', '/usr/ccs/bin', '/usr/sfw/bin'];
1196 oExecutor = remoteexecutor.RemoteExecutor(None, lstBinaryPaths, self.sScratchPath);
1197 if not self.fUseScratch:
1198 self.oStorCfg = storagecfg.StorageCfg(oExecutor, utils.getHostOs(), oDiskCfg);
1199
1200 # Try to cleanup any leftovers from a previous run first.
1201 fRc = self.oStorCfg.cleanupLeftovers();
1202 if not fRc:
1203 reporter.error('Failed to cleanup any leftovers from a previous run');
1204
1205 if self.fTestHost:
1206 reporter.testStart('Host');
1207 if self.fUseScratch:
1208 sMountPoint = self.sScratchPath;
1209 else:
1210 sMountPoint = self.prepareStorage(self.oStorCfg);
1211 if sMountPoint is not None:
1212 for sIoTest in self.asTests:
1213 reporter.testStart(sIoTest);
1214 for sTestSet in self.asTestSets:
1215 reporter.testStart(sTestSet);
1216 dTestSet = self.kdTestSets.get(sTestSet);
1217 self.testBenchmark(utils.getHostOs(), sIoTest, sMountPoint, oExecutor, dTestSet);
1218 reporter.testDone();
1219 reporter.testDone();
1220 self.cleanupStorage(self.oStorCfg);
1221 else:
1222 reporter.testFailure('Failed to prepare host storage');
1223 fRc = False;
1224 reporter.testDone();
1225 else:
1226 # Create the storage space first if it is not done before every test.
1227 sMountPoint = None;
1228 if self.fUseScratch:
1229 sMountPoint = self.sScratchPath;
1230 elif not self.fRecreateStorCfg:
1231 reporter.testStart('Create host storage');
1232 sMountPoint = self.prepareStorage(self.oStorCfg);
1233 if sMountPoint is None:
1234 reporter.testFailure('Failed to prepare host storage');
1235 fRc = False;
1236 self.oStorCfg.mkDirOnVolume(sMountPoint, 'test', 0777);
1237 sMountPoint = sMountPoint + '/test';
1238 reporter.testDone();
1239
1240 if fRc:
1241 # Run the storage tests.
1242 if not self.testStorage(sMountPoint):
1243 fRc = False;
1244
1245 if not self.fRecreateStorCfg and not self.fUseScratch:
1246 self.cleanupStorage(self.oStorCfg);
1247 else:
1248 fRc = False;
1249
1250 return fRc;
1251
1252if __name__ == '__main__':
1253 sys.exit(tdStorageBenchmark().main(sys.argv));
1254
Note: See TracBrowser for help on using the repository browser.

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