VirtualBox

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

Last change on this file since 63180 was 63142, checked in by vboxsync, 9 years ago

ValidationKit: Make it possible to set a different timeout when creating a disk image (the default 60 seconds is not enough for large fixed sized images)

  • Property svn:eol-style set to LF
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 35.0 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# $Id: tdStorageBenchmark1.py 63142 2016-08-08 09:06:14Z 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.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: 63142 $"
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
87 def prepare(self, cMsTimeout = 30000):
88 """ Prepares the testcase """
89
90 sTargetOs = self.dCfg.get('TargetOs', 'linux');
91 sIoEngine, fDirectIo = self.kdHostIoEngine.get(sTargetOs);
92 if sIoEngine is None:
93 return False;
94
95 cfgBuf = StringIO.StringIO();
96 cfgBuf.write('[global]\n');
97 cfgBuf.write('bs=' + self.dCfg.get('RecordSize', '4k') + '\n');
98 cfgBuf.write('ioengine=' + sIoEngine + '\n');
99 cfgBuf.write('iodepth=' + self.dCfg.get('QueueDepth', '32') + '\n');
100 cfgBuf.write('size=' + self.dCfg.get('TestsetSize', '2g') + '\n');
101 if fDirectIo:
102 cfgBuf.write('direct=1\n');
103 else:
104 cfgBuf.write('direct=0\n');
105 cfgBuf.write('directory=' + self.dCfg.get('FilePath', '/mnt') + '\n');
106
107 cfgBuf.write('[seq-write]\n');
108 cfgBuf.write('rw=write\n');
109 cfgBuf.write('stonewall\n');
110
111 cfgBuf.write('[rand-write]\n');
112 cfgBuf.write('rw=randwrite\n');
113 cfgBuf.write('stonewall\n');
114
115 cfgBuf.write('[seq-read]\n');
116 cfgBuf.write('rw=read\n');
117 cfgBuf.write('stonewall\n');
118
119 cfgBuf.write('[rand-read]\n');
120 cfgBuf.write('rw=randread\n');
121 cfgBuf.write('stonewall\n');
122
123 self.sCfgFileId = self.oExecutor.copyString(cfgBuf.getvalue(), 'aio-test', cMsTimeout);
124 return self.sCfgFileId is not None;
125
126 def run(self, cMsTimeout = 30000):
127 """ Runs the testcase """
128 _ = cMsTimeout
129 fRc, sOutput = self.oExecutor.execBinary('fio', (self.sCfgFileId,));
130 # @todo: Parse output.
131 _ = sOutput;
132 return fRc;
133
134 def cleanup(self):
135 """ Cleans up any leftovers from the testcase. """
136
137 def reportResult(self):
138 """
139 Reports the test results to the test manager.
140 """
141 return True;
142
143class IozoneTest(object):
144 """
145 I/O zone testcase.
146 """
147 def __init__(self, oExecutor, dCfg = None):
148 self.oExecutor = oExecutor;
149 self.sResult = None;
150 self.lstTests = [ ('initial writers', 'FirstWrite'),
151 ('rewriters', 'Rewrite'),
152 ('re-readers', 'ReRead'),
153 ('stride readers', 'StrideRead'),
154 ('reverse readers', 'ReverseRead'),
155 ('random readers', 'RandomRead'),
156 ('mixed workload', 'MixedWorkload'),
157 ('random writers', 'RandomWrite'),
158 ('pwrite writers', 'PWrite'),
159 ('pread readers', 'PRead'),
160 ('fwriters', 'FWrite'),
161 ('freaders', 'FRead'),
162 ('readers', 'FirstRead')];
163 self.sRecordSize = dCfg.get('RecordSize', '4k');
164 self.sTestsetSize = dCfg.get('TestsetSize', '2g');
165 self.sQueueDepth = dCfg.get('QueueDepth', '32');
166 self.sFilePath = dCfg.get('FilePath', '/mnt/iozone');
167 self.fDirectIo = True;
168
169 sTargetOs = dCfg.get('TargetOs');
170 if sTargetOs == 'solaris':
171 self.fDirectIo = False;
172
173 def prepare(self, cMsTimeout = 30000):
174 """ Prepares the testcase """
175 _ = cMsTimeout;
176 return True; # Nothing to do.
177
178 def run(self, cMsTimeout = 30000):
179 """ Runs the testcase """
180 tupArgs = ('-r', self.sRecordSize, '-s', self.sTestsetSize, \
181 '-t', '1', '-T', '-F', self.sFilePath + '/iozone.tmp');
182 if self.fDirectIo:
183 tupArgs += ('-I',);
184 fRc, sOutput = self.oExecutor.execBinary('iozone', tupArgs);
185 if fRc:
186 self.sResult = sOutput;
187
188 _ = cMsTimeout;
189 return fRc;
190
191 def cleanup(self):
192 """ Cleans up any leftovers from the testcase. """
193 return True;
194
195 def reportResult(self):
196 """
197 Reports the test results to the test manager.
198 """
199
200 fRc = True;
201 if self.sResult is not None:
202 try:
203 asLines = self.sResult.splitlines();
204 for sLine in asLines:
205 sLine = sLine.strip();
206 if sLine.startswith('Children') is True:
207 # Extract the value
208 idxValue = sLine.rfind('=');
209 if idxValue is -1:
210 raise Exception('IozoneTest: Invalid state');
211
212 idxValue += 1;
213 while sLine[idxValue] == ' ':
214 idxValue += 1;
215
216 # Get the reported value, cut off after the decimal point
217 # it is not supported by the testmanager yet and is not really
218 # relevant anyway.
219 idxValueEnd = idxValue;
220 while sLine[idxValueEnd].isdigit():
221 idxValueEnd += 1;
222
223 for sNeedle, sTestVal in self.lstTests:
224 if sLine.rfind(sNeedle) is not -1:
225 reporter.testValue(sTestVal, sLine[idxValue:idxValueEnd],
226 constants.valueunit.g_asNames[constants.valueunit.KILOBYTES_PER_SEC]);
227 break;
228 except:
229 fRc = False;
230 else:
231 fRc = False;
232
233 return fRc;
234
235
236class tdStorageBenchmark(vbox.TestDriver): # pylint: disable=R0902
237 """
238 Storage benchmark.
239 """
240
241 # Global storage configs for the testbox
242 kdStorageCfgs = {
243 'testboxstor1.de.oracle.com': r'c[3-9]t\dd0\Z',
244 'adaris': [ '/dev/sda' ]
245 };
246
247 def __init__(self):
248 vbox.TestDriver.__init__(self);
249 self.asRsrcs = None;
250 self.oGuestToGuestVM = None;
251 self.oGuestToGuestSess = None;
252 self.oGuestToGuestTxs = None;
253 self.asTestVMsDef = ['tst-storage', 'tst-storage32'];
254 self.asTestVMs = self.asTestVMsDef;
255 self.asSkipVMs = [];
256 self.asVirtModesDef = ['hwvirt', 'hwvirt-np', 'raw',]
257 self.asVirtModes = self.asVirtModesDef
258 self.acCpusDef = [1, 2,]
259 self.acCpus = self.acCpusDef;
260 self.asStorageCtrlsDef = ['AHCI', 'IDE', 'LsiLogicSAS', 'LsiLogic', 'BusLogic', 'NVMe'];
261 self.asStorageCtrls = self.asStorageCtrlsDef;
262 self.asDiskFormatsDef = ['VDI', 'VMDK', 'VHD', 'QED', 'Parallels', 'QCOW', 'iSCSI'];
263 self.asDiskFormats = self.asDiskFormatsDef;
264 self.asDiskVariantsDef = ['Dynamic', 'Fixed', 'Split2G'];
265 self.asDiskVariants = self.asDiskVariantsDef;
266 self.asTestsDef = ['iozone', 'fio'];
267 self.asTests = self.asTestsDef;
268 self.asIscsiTargetsDef = [ ]; # @todo: Configure one target for basic iSCSI testing
269 self.asIscsiTargets = self.asIscsiTargetsDef;
270 self.fTestHost = False;
271 self.fUseScratch = False;
272 self.fRecreateStorCfg = True;
273 self.oStorCfg = None;
274
275 #
276 # Overridden methods.
277 #
278 def showUsage(self):
279 rc = vbox.TestDriver.showUsage(self);
280 reporter.log('');
281 reporter.log('tdStorageBenchmark1 Options:');
282 reporter.log(' --virt-modes <m1[:m2[:]]');
283 reporter.log(' Default: %s' % (':'.join(self.asVirtModesDef)));
284 reporter.log(' --cpu-counts <c1[:c2[:]]');
285 reporter.log(' Default: %s' % (':'.join(str(c) for c in self.acCpusDef)));
286 reporter.log(' --storage-ctrls <type1[:type2[:...]]>');
287 reporter.log(' Default: %s' % (':'.join(self.asStorageCtrlsDef)));
288 reporter.log(' --disk-formats <type1[:type2[:...]]>');
289 reporter.log(' Default: %s' % (':'.join(self.asDiskFormatsDef)));
290 reporter.log(' --disk-variants <variant1[:variant2[:...]]>');
291 reporter.log(' Default: %s' % (':'.join(self.asDiskVariantsDef)));
292 reporter.log(' --iscsi-targets <target1[:target2[:...]]>');
293 reporter.log(' Default: %s' % (':'.join(self.asIscsiTargets)));
294 reporter.log(' --tests <test1[:test2[:...]]>');
295 reporter.log(' Default: %s' % (':'.join(self.asTests)));
296 reporter.log(' --test-vms <vm1[:vm2[:...]]>');
297 reporter.log(' Test the specified VMs in the given order. Use this to change');
298 reporter.log(' the execution order or limit the choice of VMs');
299 reporter.log(' Default: %s (all)' % (':'.join(self.asTestVMsDef)));
300 reporter.log(' --skip-vms <vm1[:vm2[:...]]>');
301 reporter.log(' Skip the specified VMs when testing.');
302 reporter.log(' --test-host');
303 reporter.log(' Do all configured tests on the host first and report the results');
304 reporter.log(' to get a baseline');
305 reporter.log(' --use-scratch');
306 reporter.log(' Use the scratch directory for testing instead of setting up');
307 reporter.log(' fresh volumes on dedicated disks (for development)');
308 reporter.log(' --always-wipe-storage-cfg');
309 reporter.log(' Recreate the host storage config before each test');
310 reporter.log(' --dont-wipe-storage-cfg');
311 reporter.log(' Don\' recreate the host storage config before each test');
312 return rc;
313
314 def parseOption(self, asArgs, iArg): # pylint: disable=R0912,R0915
315 if asArgs[iArg] == '--virt-modes':
316 iArg += 1;
317 if iArg >= len(asArgs): raise base.InvalidOption('The "--virt-modes" takes a colon separated list of modes');
318 self.asVirtModes = asArgs[iArg].split(':');
319 for s in self.asVirtModes:
320 if s not in self.asVirtModesDef:
321 raise base.InvalidOption('The "--virt-modes" value "%s" is not valid; valid values are: %s' \
322 % (s, ' '.join(self.asVirtModesDef)));
323 elif asArgs[iArg] == '--cpu-counts':
324 iArg += 1;
325 if iArg >= len(asArgs): raise base.InvalidOption('The "--cpu-counts" takes a colon separated list of cpu counts');
326 self.acCpus = [];
327 for s in asArgs[iArg].split(':'):
328 try: c = int(s);
329 except: raise base.InvalidOption('The "--cpu-counts" value "%s" is not an integer' % (s,));
330 if c <= 0: raise base.InvalidOption('The "--cpu-counts" value "%s" is zero or negative' % (s,));
331 self.acCpus.append(c);
332 elif asArgs[iArg] == '--storage-ctrls':
333 iArg += 1;
334 if iArg >= len(asArgs):
335 raise base.InvalidOption('The "--storage-ctrls" takes a colon separated list of Storage controller types');
336 self.asStorageCtrls = asArgs[iArg].split(':');
337 elif asArgs[iArg] == '--disk-formats':
338 iArg += 1;
339 if iArg >= len(asArgs): raise base.InvalidOption('The "--disk-formats" takes a colon separated list of disk formats');
340 self.asDiskFormats = asArgs[iArg].split(':');
341 elif asArgs[iArg] == '--disk-variants':
342 iArg += 1;
343 if iArg >= len(asArgs):
344 raise base.InvalidOption('The "--disk-variants" takes a colon separated list of disk variants');
345 self.asDiskVariants = asArgs[iArg].split(':');
346 elif asArgs[iArg] == '--iscsi-targets':
347 iArg += 1;
348 if iArg >= len(asArgs):
349 raise base.InvalidOption('The "--iscsi-targets" takes a colon separated list of iscsi targets');
350 self.asIscsiTargets = asArgs[iArg].split(':');
351 elif asArgs[iArg] == '--tests':
352 iArg += 1;
353 if iArg >= len(asArgs): raise base.InvalidOption('The "--tests" takes a colon separated list of disk formats');
354 self.asTests = asArgs[iArg].split(':');
355 elif asArgs[iArg] == '--test-vms':
356 iArg += 1;
357 if iArg >= len(asArgs): raise base.InvalidOption('The "--test-vms" takes colon separated list');
358 self.asTestVMs = asArgs[iArg].split(':');
359 for s in self.asTestVMs:
360 if s not in self.asTestVMsDef:
361 raise base.InvalidOption('The "--test-vms" value "%s" is not valid; valid values are: %s' \
362 % (s, ' '.join(self.asTestVMsDef)));
363 elif asArgs[iArg] == '--skip-vms':
364 iArg += 1;
365 if iArg >= len(asArgs): raise base.InvalidOption('The "--skip-vms" takes colon separated list');
366 self.asSkipVMs = asArgs[iArg].split(':');
367 for s in self.asSkipVMs:
368 if s not in self.asTestVMsDef:
369 reporter.log('warning: The "--test-vms" value "%s" does not specify any of our test VMs.' % (s));
370 elif asArgs[iArg] == '--test-host':
371 self.fTestHost = True;
372 elif asArgs[iArg] == '--use-scratch':
373 self.fUseScratch = True;
374 elif asArgs[iArg] == '--always-wipe-storage-cfg':
375 self.fRecreateStorCfg = True;
376 elif asArgs[iArg] == '--dont-wipe-storage-cfg':
377 self.fRecreateStorCfg = False;
378 else:
379 return vbox.TestDriver.parseOption(self, asArgs, iArg);
380 return iArg + 1;
381
382 def completeOptions(self):
383 # Remove skipped VMs from the test list.
384 for sVM in self.asSkipVMs:
385 try: self.asTestVMs.remove(sVM);
386 except: pass;
387
388 return vbox.TestDriver.completeOptions(self);
389
390 def getResourceSet(self):
391 # Construct the resource list the first time it's queried.
392 if self.asRsrcs is None:
393 self.asRsrcs = [];
394 if 'tst-storage' in self.asTestVMs:
395 self.asRsrcs.append('5.0/storage/tst-storage.vdi');
396 if 'tst-storage32' in self.asTestVMs:
397 self.asRsrcs.append('5.0/storage/tst-storage32.vdi');
398
399 return self.asRsrcs;
400
401 def actionConfig(self):
402
403 # Make sure vboxapi has been imported so we can use the constants.
404 if not self.importVBoxApi():
405 return False;
406
407 #
408 # Configure the VMs we're going to use.
409 #
410
411 # Linux VMs
412 if 'tst-storage' in self.asTestVMs:
413 oVM = self.createTestVM('tst-storage', 1, '5.0/storage/tst-storage.vdi', sKind = 'ArchLinux_64', fIoApic = True, \
414 eNic0AttachType = vboxcon.NetworkAttachmentType_NAT, \
415 eNic0Type = vboxcon.NetworkAdapterType_Am79C973);
416 if oVM is None:
417 return False;
418
419 if 'tst-storage32' in self.asTestVMs:
420 oVM = self.createTestVM('tst-storage32', 1, '5.0/storage/tst-storage32.vdi', sKind = 'ArchLinux', fIoApic = True, \
421 eNic0AttachType = vboxcon.NetworkAttachmentType_NAT, \
422 eNic0Type = vboxcon.NetworkAdapterType_Am79C973);
423 if oVM is None:
424 return False;
425
426 return True;
427
428 def actionExecute(self):
429 """
430 Execute the testcase.
431 """
432 fRc = self.test1();
433 return fRc;
434
435
436 #
437 # Test execution helpers.
438 #
439
440 def prepareStorage(self, oStorCfg):
441 """
442 Prepares the host storage for disk images or direct testing on the host.
443 """
444 # Create a basic pool with the default configuration.
445 sMountPoint = None;
446 fRc, sPoolId = oStorCfg.createStoragePool();
447 if fRc:
448 fRc, sMountPoint = oStorCfg.createVolume(sPoolId);
449 if not fRc:
450 sMountPoint = None;
451 oStorCfg.cleanup();
452
453 return sMountPoint;
454
455 def cleanupStorage(self, oStorCfg):
456 """
457 Cleans up any created storage space for a test.
458 """
459 return oStorCfg.cleanup();
460
461 def getGuestDisk(self, oSession, oTxsSession, eStorageController):
462 """
463 Gets the path of the disk in the guest to use for testing.
464 """
465 lstDisks = None;
466
467 # The naming scheme for NVMe is different and we don't have
468 # to query the guest for unformatted disks here because the disk with the OS
469 # is not attached to a NVMe controller.
470 if eStorageController == vboxcon.StorageControllerType_NVMe:
471 lstDisks = [ '/dev/nvme0n1' ];
472 else:
473 # Find a unformatted disk (no partition).
474 # @todo: This is a hack because LIST and STAT are not yet implemented
475 # in TXS (get to this eventually)
476 lstBlkDev = [ '/dev/sda', '/dev/sdb' ];
477 for sBlkDev in lstBlkDev:
478 fRc = oTxsSession.syncExec('/usr/bin/ls', ('ls', sBlkDev + '1'));
479 if not fRc:
480 lstDisks = [ sBlkDev ];
481 break;
482
483 _ = oSession;
484 return lstDisks;
485
486 def getDiskFormatVariantsForTesting(self, sDiskFmt, asVariants):
487 """
488 Returns a list of disk variants for testing supported by the given
489 disk format and selected for testing.
490 """
491 lstDskFmts = self.oVBoxMgr.getArray(self.oVBox.systemProperties, 'mediumFormats');
492 for oDskFmt in lstDskFmts:
493 if oDskFmt.id == sDiskFmt:
494 lstDskVariants = [];
495 lstCaps = self.oVBoxMgr.getArray(oDskFmt, 'capabilities');
496 for eCap in lstCaps:
497 if eCap == vboxcon.MediumFormatCapabilities_CreateDynamic \
498 and 'Dynamic' in asVariants:
499 lstDskVariants.append('Dynamic');
500 elif eCap == vboxcon.MediumFormatCapabilities_CreateFixed \
501 and 'Fixed' in asVariants:
502 lstDskVariants.append('Fixed');
503 elif eCap == vboxcon.MediumFormatCapabilities_CreateSplit2G \
504 and 'Split2G' in asVariants:
505 lstDskVariants.append('Split2G');
506 elif eCap == vboxcon.MediumFormatCapabilities_TcpNetworking:
507 lstDskVariants.append('Network'); # Solely for iSCSI to get a non empty list
508
509 return lstDskVariants;
510
511 return [];
512
513 def convDiskToMediumVariant(self, sDiskVariant):
514 """
515 Returns a tuple of medium variant flags matching the given disk variant.
516 """
517 tMediumVariant = None;
518 if sDiskVariant == 'Dynamic':
519 tMediumVariant = (vboxcon.MediumVariant_Standard, );
520 elif sDiskVariant == 'Fixed':
521 tMediumVariant = (vboxcon.MediumVariant_Fixed, );
522 elif sDiskVariant == 'Split2G':
523 tMediumVariant = (vboxcon.MediumVariant_Fixed, vboxcon.MediumVariant_VmdkSplit2G);
524
525 return tMediumVariant;
526
527 def testBenchmark(self, sTargetOs, sBenchmark, sMountpoint, oExecutor):
528 """
529 Runs the given benchmark on the test host.
530 """
531 # Create a basic config
532 dCfg = {
533 'RecordSize': '64k',
534 'TestsetSize': '100m',
535 'QueueDepth': '32',
536 'FilePath': sMountpoint,
537 'TargetOs': sTargetOs
538 };
539
540 oTst = None;
541 if sBenchmark == 'iozone':
542 oTst = IozoneTest(oExecutor, dCfg);
543 elif sBenchmark == 'fio':
544 oTst = FioTest(oExecutor, dCfg); # pylint: disable=R0204
545
546 if oTst is not None:
547 reporter.testStart(sBenchmark);
548 fRc = oTst.prepare();
549 if fRc:
550 fRc = oTst.run();
551 if fRc:
552 fRc = oTst.reportResult();
553 else:
554 reporter.testFailure('Running the testcase failed');
555 else:
556 reporter.testFailure('Preparing the testcase failed');
557
558 oTst.cleanup();
559 reporter.testDone();
560
561 return fRc;
562
563 def testBenchmarks(self, sTargetOs, sMountPoint, oExecutor):
564 """
565 Runs all the configured benchmarks on the target.
566 """
567 for sTest in self.asTests:
568 self.testBenchmark(sTargetOs, sTest, sMountPoint, oExecutor);
569
570 def test1OneCfg(self, sVmName, eStorageController, sDiskFormat, sDiskVariant, \
571 sDiskPath, cCpus, fHwVirt, fNestedPaging):
572 """
573 Runs the specified VM thru test #1.
574
575 Returns a success indicator on the general test execution. This is not
576 the actual test result.
577 """
578 oVM = self.getVmByName(sVmName);
579
580 # Reconfigure the VM
581 fRc = True;
582 oSession = self.openSession(oVM);
583 if oSession is not None:
584 # Attach HD
585 fRc = oSession.ensureControllerAttached(_ControllerTypeToName(eStorageController));
586 fRc = fRc and oSession.setStorageControllerType(eStorageController, _ControllerTypeToName(eStorageController));
587
588 iDevice = 0;
589 if eStorageController == vboxcon.StorageControllerType_PIIX3 or \
590 eStorageController == vboxcon.StorageControllerType_PIIX4:
591 iDevice = 1; # Master is for the OS.
592
593 if sDiskFormat == "iSCSI":
594 listNames = [];
595 listValues = [];
596 listValues = sDiskPath.split('|');
597 listNames.append('TargetAddress');
598 listNames.append('TargetName');
599 listNames.append('LUN');
600
601 if self.fpApiVer >= 5.0:
602 oHd = oSession.oVBox.createMedium(sDiskFormat, sDiskPath, vboxcon.AccessMode_ReadWrite, \
603 vboxcon.DeviceType_HardDisk);
604 else:
605 oHd = oSession.oVBox.createHardDisk(sDiskFormat, sDiskPath);
606 oHd.type = vboxcon.MediumType_Normal;
607 oHd.setProperties(listNames, listValues);
608
609 # Attach it.
610 if fRc is True:
611 try:
612 if oSession.fpApiVer >= 4.0:
613 oSession.o.machine.attachDevice(_ControllerTypeToName(eStorageController), \
614 0, iDevice, vboxcon.DeviceType_HardDisk, oHd);
615 else:
616 oSession.o.machine.attachDevice(_ControllerTypeToName(eStorageController), \
617 0, iDevice, vboxcon.DeviceType_HardDisk, oHd.id);
618 except:
619 reporter.errorXcpt('attachDevice("%s",%s,%s,HardDisk,"%s") failed on "%s"' \
620 % (_ControllerTypeToName(eStorageController), 1, 0, oHd.id, oSession.sName) );
621 fRc = False;
622 else:
623 reporter.log('attached "%s" to %s' % (sDiskPath, oSession.sName));
624 else:
625 tMediumVariant = self.convDiskToMediumVariant(sDiskVariant);
626 fRc = fRc and oSession.createAndAttachHd(sDiskPath, sDiskFormat, _ControllerTypeToName(eStorageController), \
627 cb = 30*1024*1024*1024, iPort = 0, iDevice = iDevice, \
628 fImmutable = False, cMsTimeout = 3600 * 1000, \
629 tMediumVariant = tMediumVariant);
630 fRc = fRc and oSession.enableVirtEx(fHwVirt);
631 fRc = fRc and oSession.enableNestedPaging(fNestedPaging);
632 fRc = fRc and oSession.setCpuCount(cCpus);
633 fRc = fRc and oSession.saveSettings();
634 fRc = oSession.close() and fRc and True; # pychecker hack.
635 oSession = None;
636 else:
637 fRc = False;
638
639 # Start up.
640 if fRc is True:
641 self.logVmInfo(oVM);
642 oSession, oTxsSession = self.startVmAndConnectToTxsViaTcp(sVmName, fCdWait = False, fNatForwardingForTxs = True);
643 if oSession is not None:
644 self.addTask(oSession);
645
646 # Fudge factor - Allow the guest to finish starting up.
647 self.sleep(5);
648
649 # Prepare the storage on the guest
650 lstBinaryPaths = ['/bin', '/sbin', '/usr/bin', '/usr/sbin' ];
651 oExecVm = remoteexecutor.RemoteExecutor(oTxsSession, lstBinaryPaths, '${SCRATCH}');
652 oStorCfgVm = storagecfg.StorageCfg(oExecVm, 'linux', self.getGuestDisk(oSession, oTxsSession, \
653 eStorageController));
654
655 sMountPoint = self.prepareStorage(oStorCfgVm);
656 if sMountPoint is not None:
657 self.testBenchmarks('linux', sMountPoint, oExecVm);
658 self.cleanupStorage(oStorCfgVm);
659 else:
660 reporter.testFailure('Failed to prepare storage for the guest benchmark');
661
662 # cleanup.
663 self.removeTask(oTxsSession);
664 self.terminateVmBySession(oSession)
665 else:
666 fRc = False;
667
668 # Remove disk
669 oSession = self.openSession(oVM);
670 if oSession is not None:
671 try:
672 oSession.o.machine.detachDevice(_ControllerTypeToName(eStorageController), 0, iDevice);
673
674 # Remove storage controller if it is not an IDE controller.
675 if eStorageController is not vboxcon.StorageControllerType_PIIX3 \
676 and eStorageController is not vboxcon.StorageControllerType_PIIX4:
677 oSession.o.machine.removeStorageController(_ControllerTypeToName(eStorageController));
678
679 oSession.saveSettings();
680 self.oVBox.deleteHdByLocation(sDiskPath);
681 oSession.saveSettings();
682 oSession.close();
683 oSession = None;
684 except:
685 reporter.errorXcpt('failed to detach/delete disk %s from storage controller' % (sDiskPath));
686 else:
687 fRc = False;
688
689 return fRc;
690
691 def testBenchmarkOneVM(self, sVmName, sMountPoint = None):
692 """
693 Runs one VM thru the various benchmark configurations.
694 """
695 reporter.testStart(sVmName);
696 fRc = True;
697 for sStorageCtrl in self.asStorageCtrls:
698 reporter.testStart(sStorageCtrl);
699
700 if sStorageCtrl == 'AHCI':
701 eStorageCtrl = vboxcon.StorageControllerType_IntelAhci;
702 elif sStorageCtrl == 'IDE':
703 eStorageCtrl = vboxcon.StorageControllerType_PIIX4;
704 elif sStorageCtrl == 'LsiLogicSAS':
705 eStorageCtrl = vboxcon.StorageControllerType_LsiLogicSas;
706 elif sStorageCtrl == 'LsiLogic':
707 eStorageCtrl = vboxcon.StorageControllerType_LsiLogic;
708 elif sStorageCtrl == 'BusLogic':
709 if sVmName == 'tst-storage': # Broken for 64bit Linux
710 reporter.testDone(True);
711 continue;
712 eStorageCtrl = vboxcon.StorageControllerType_BusLogic;
713 elif sStorageCtrl == 'NVMe':
714 eStorageCtrl = vboxcon.StorageControllerType_NVMe;
715 else:
716 eStorageCtrl = None;
717
718 for sDiskFormat in self.asDiskFormats:
719 reporter.testStart('%s' % (sDiskFormat));
720
721 if sDiskFormat == "iSCSI":
722 asPaths = self.asIscsiTargets;
723 else:
724 if self.fUseScratch:
725 asPaths = [ self.sScratchPath ];
726 else:
727 # Create a new default storage config on the host
728 if self.fRecreateStorCfg:
729 sMountPoint = self.prepareStorage(self.oStorCfg);
730 if sMountPoint is not None:
731 # Create a directory where every normal user can write to.
732 self.oStorCfg.mkDirOnVolume(sMountPoint, 'test', 0777);
733 asPaths = [ sMountPoint + '/test' ];
734 else:
735 asPaths = [];
736 fRc = False;
737 reporter.testFailure('Failed to prepare storage for VM');
738
739 asVariants = self.getDiskFormatVariantsForTesting(sDiskFormat, self.asDiskVariants);
740 for sVariant in asVariants:
741 reporter.testStart('%s' % (sVariant));
742 for sPath in asPaths:
743 if sDiskFormat == "iSCSI":
744 sPath = sPath;
745 else:
746 sPath = sPath + "/test.disk";
747
748 for cCpus in self.acCpus:
749 if cCpus == 1: reporter.testStart('1 cpu');
750 else: reporter.testStart('%u cpus' % (cCpus));
751
752 for sVirtMode in self.asVirtModes:
753 if sVirtMode == 'raw' and (cCpus > 1 or sVmName == 'tst-storage'):
754 continue;
755 hsVirtModeDesc = {};
756 hsVirtModeDesc['raw'] = 'Raw-mode';
757 hsVirtModeDesc['hwvirt'] = 'HwVirt';
758 hsVirtModeDesc['hwvirt-np'] = 'NestedPaging';
759 reporter.testStart(hsVirtModeDesc[sVirtMode]);
760
761 fHwVirt = sVirtMode != 'raw';
762 fNestedPaging = sVirtMode == 'hwvirt-np';
763 fRc = self.test1OneCfg(sVmName, eStorageCtrl, sDiskFormat, sVariant, sPath, \
764 cCpus, fHwVirt, fNestedPaging) and fRc and True; # pychecker hack.
765 reporter.testDone(); # Virt mode
766
767 reporter.testDone(); # CPU count
768 reporter.testDone(); # Disk variant
769
770 # Cleanup storage area
771 if sDiskFormat != 'iSCSI' and not self.fUseScratch and self.fRecreateStorCfg:
772 self.cleanupStorage(self.oStorCfg);
773
774 reporter.testDone(); # Disk format
775 reporter.testDone(); # Controller
776 reporter.testDone(); # VM
777 return fRc;
778
779 def test1(self):
780 """
781 Executes test #1.
782 """
783
784 fRc = True;
785 oDiskCfg = self.kdStorageCfgs.get(socket.gethostname().lower());
786
787 # Test the host first if requested
788 if oDiskCfg is not None:
789 lstBinaryPaths = ['/bin', '/sbin', '/usr/bin', '/usr/sbin', \
790 '/opt/csw/bin', '/usr/ccs/bin', '/usr/sfw/bin'];
791 oExecutor = remoteexecutor.RemoteExecutor(None, lstBinaryPaths, self.sScratchPath);
792 self.oStorCfg = storagecfg.StorageCfg(oExecutor, utils.getHostOs(), oDiskCfg);
793
794 # Try to cleanup any leftovers from a previous run first.
795 fRc = self.oStorCfg.cleanupLeftovers();
796 if not fRc:
797 reporter.error('Failed to cleanup any leftovers from a previous run');
798
799 if self.fTestHost:
800 reporter.testStart('Host');
801 if self.fUseScratch:
802 sMountPoint = self.sScratchPath;
803 else:
804 sMountPoint = self.prepareStorage(self.oStorCfg);
805 if sMountPoint is not None:
806 self.testBenchmarks(utils.getHostOs(), sMountPoint, oExecutor);
807 self.cleanupStorage(self.oStorCfg);
808 else:
809 reporter.testFailure('Failed to prepare host storage');
810 fRc = False;
811 reporter.testDone();
812 else:
813 # Create the storage space first if it is not done before every test.
814 sMountPoint = None;
815 if not self.fRecreateStorCfg:
816 reporter.testStart('Create host storage');
817 sMountPoint = self.prepareStorage(self.oStorCfg);
818 if sMountPoint is None:
819 reporter.testFailure('Failed to prepare host storage');
820 fRc = False;
821 reporter.testDone();
822
823 if fRc:
824 # Loop thru the test VMs.
825 for sVM in self.asTestVMs:
826 # run test on the VM.
827 if not self.testBenchmarkOneVM(sVM, sMountPoint):
828 fRc = False;
829 else:
830 fRc = False;
831
832 return fRc;
833
834if __name__ == '__main__':
835 sys.exit(tdStorageBenchmark().main(sys.argv));
836
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