VirtualBox

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

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

ValidationKit/tests/storage: Add a method to cleanup leftover volumes and pools from a failed previous run (only implemented on Solaris so far)

  • Property svn:eol-style set to LF
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 34.9 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# $Id: tdStorageBenchmark1.py 63008 2016-08-04 20:31:09Z 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: 63008 $"
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 = 300*1024*1024*1024, iPort = 0, iDevice = iDevice, \
628 fImmutable = False, tMediumVariant = tMediumVariant);
629 fRc = fRc and oSession.enableVirtEx(fHwVirt);
630 fRc = fRc and oSession.enableNestedPaging(fNestedPaging);
631 fRc = fRc and oSession.setCpuCount(cCpus);
632 fRc = fRc and oSession.saveSettings();
633 fRc = oSession.close() and fRc and True; # pychecker hack.
634 oSession = None;
635 else:
636 fRc = False;
637
638 # Start up.
639 if fRc is True:
640 self.logVmInfo(oVM);
641 oSession, oTxsSession = self.startVmAndConnectToTxsViaTcp(sVmName, fCdWait = False, fNatForwardingForTxs = True);
642 if oSession is not None:
643 self.addTask(oSession);
644
645 # Fudge factor - Allow the guest to finish starting up.
646 self.sleep(5);
647
648 # Prepare the storage on the guest
649 lstBinaryPaths = ['/bin', '/sbin', '/usr/bin', '/usr/sbin' ];
650 oExecVm = remoteexecutor.RemoteExecutor(oTxsSession, lstBinaryPaths, '${SCRATCH}');
651 oStorCfgVm = storagecfg.StorageCfg(oExecVm, 'linux', self.getGuestDisk(oSession, oTxsSession, \
652 eStorageController));
653
654 sMountPoint = self.prepareStorage(oStorCfgVm);
655 if sMountPoint is not None:
656 self.testBenchmarks('linux', sMountPoint, oExecVm);
657 self.cleanupStorage(oStorCfgVm);
658 else:
659 reporter.testFailure('Failed to prepare storage for the guest benchmark');
660
661 # cleanup.
662 self.removeTask(oTxsSession);
663 self.terminateVmBySession(oSession)
664 else:
665 fRc = False;
666
667 # Remove disk
668 oSession = self.openSession(oVM);
669 if oSession is not None:
670 try:
671 oSession.o.machine.detachDevice(_ControllerTypeToName(eStorageController), 0, iDevice);
672
673 # Remove storage controller if it is not an IDE controller.
674 if eStorageController is not vboxcon.StorageControllerType_PIIX3 \
675 and eStorageController is not vboxcon.StorageControllerType_PIIX4:
676 oSession.o.machine.removeStorageController(_ControllerTypeToName(eStorageController));
677
678 oSession.saveSettings();
679 self.oVBox.deleteHdByLocation(sDiskPath);
680 oSession.saveSettings();
681 oSession.close();
682 oSession = None;
683 except:
684 reporter.errorXcpt('failed to detach/delete disk %s from storage controller' % (sDiskPath));
685 else:
686 fRc = False;
687
688 return fRc;
689
690 def testBenchmarkOneVM(self, sVmName, sMountPoint = None):
691 """
692 Runs one VM thru the various benchmark configurations.
693 """
694 reporter.testStart(sVmName);
695 fRc = True;
696 for sStorageCtrl in self.asStorageCtrls:
697 reporter.testStart(sStorageCtrl);
698
699 if sStorageCtrl == 'AHCI':
700 eStorageCtrl = vboxcon.StorageControllerType_IntelAhci;
701 elif sStorageCtrl == 'IDE':
702 eStorageCtrl = vboxcon.StorageControllerType_PIIX4;
703 elif sStorageCtrl == 'LsiLogicSAS':
704 eStorageCtrl = vboxcon.StorageControllerType_LsiLogicSas;
705 elif sStorageCtrl == 'LsiLogic':
706 eStorageCtrl = vboxcon.StorageControllerType_LsiLogic;
707 elif sStorageCtrl == 'BusLogic':
708 if sVmName == 'tst-storage': # Broken for 64bit Linux
709 reporter.testDone(True);
710 continue;
711 eStorageCtrl = vboxcon.StorageControllerType_BusLogic;
712 elif sStorageCtrl == 'NVMe':
713 eStorageCtrl = vboxcon.StorageControllerType_NVMe;
714 else:
715 eStorageCtrl = None;
716
717 for sDiskFormat in self.asDiskFormats:
718 reporter.testStart('%s' % (sDiskFormat));
719
720 if sDiskFormat == "iSCSI":
721 asPaths = self.asIscsiTargets;
722 else:
723 if self.fUseScratch:
724 asPaths = [ self.sScratchPath ];
725 else:
726 # Create a new default storage config on the host
727 if sMountPoint is None:
728 sMountPoint = self.prepareStorage(self.oStorCfg);
729 if sMountPoint is not None:
730 # Create a directory where every normal user can write to.
731 self.oStorCfg.mkDirOnVolume(sMountPoint, 'test', 0777);
732 asPaths = [ sMountPoint + '/test' ];
733 else:
734 asPaths = [];
735 fRc = False;
736 reporter.testFailure('Failed to prepare storage for VM');
737
738 asVariants = self.getDiskFormatVariantsForTesting(sDiskFormat, self.asDiskVariants);
739 for sVariant in asVariants:
740 reporter.testStart('%s' % (sVariant));
741 for sPath in asPaths:
742 if sDiskFormat == "iSCSI":
743 sPath = sPath;
744 else:
745 sPath = sPath + "/test.disk";
746
747 for cCpus in self.acCpus:
748 if cCpus == 1: reporter.testStart('1 cpu');
749 else: reporter.testStart('%u cpus' % (cCpus));
750
751 for sVirtMode in self.asVirtModes:
752 if sVirtMode == 'raw' and (cCpus > 1 or sVmName == 'tst-storage'):
753 continue;
754 hsVirtModeDesc = {};
755 hsVirtModeDesc['raw'] = 'Raw-mode';
756 hsVirtModeDesc['hwvirt'] = 'HwVirt';
757 hsVirtModeDesc['hwvirt-np'] = 'NestedPaging';
758 reporter.testStart(hsVirtModeDesc[sVirtMode]);
759
760 fHwVirt = sVirtMode != 'raw';
761 fNestedPaging = sVirtMode == 'hwvirt-np';
762 fRc = self.test1OneCfg(sVmName, eStorageCtrl, sDiskFormat, sVariant, sPath, \
763 cCpus, fHwVirt, fNestedPaging) and fRc and True; # pychecker hack.
764 reporter.testDone(); # Virt mode
765
766 reporter.testDone(); # CPU count
767 reporter.testDone(); # Disk variant
768
769 # Cleanup storage area
770 if sDiskFormat != 'iSCSI' and not self.fUseScratch and self.fRecreateStorCfg:
771 self.cleanupStorage(self.oStorCfg);
772
773 reporter.testDone(); # Disk format
774 reporter.testDone(); # Controller
775 reporter.testDone(); # VM
776 return fRc;
777
778 def test1(self):
779 """
780 Executes test #1.
781 """
782
783 fRc = True;
784 oDiskCfg = self.kdStorageCfgs.get(socket.gethostname().lower());
785
786 # Test the host first if requested
787 if oDiskCfg is not None:
788 lstBinaryPaths = ['/bin', '/sbin', '/usr/bin', '/usr/sbin', \
789 '/opt/csw/bin', '/usr/ccs/bin', '/usr/sfw/bin'];
790 oExecutor = remoteexecutor.RemoteExecutor(None, lstBinaryPaths, self.sScratchPath);
791 self.oStorCfg = storagecfg.StorageCfg(oExecutor, utils.getHostOs(), oDiskCfg);
792
793 # Try to cleanup any leftovers from a previous run first.
794 fRc = self.oStorCfg.cleanupLeftovers();
795 if not fRc:
796 reporter.error('Failed to cleanup any leftovers from a previous run');
797
798 if self.fTestHost:
799 reporter.testStart('Host');
800 if self.fUseScratch:
801 sMountPoint = self.sScratchPath;
802 else:
803 sMountPoint = self.prepareStorage(self.oStorCfg);
804 if sMountPoint is not None:
805 self.testBenchmarks(utils.getHostOs(), sMountPoint, oExecutor);
806 self.cleanupStorage(self.oStorCfg);
807 else:
808 reporter.testFailure('Failed to prepare host storage');
809 fRc = False;
810 reporter.testDone();
811 else:
812 # Create the storage space first if it is not done before every test.
813 sMountPoint = None;
814 if not self.fRecreateStorCfg:
815 reporter.testStart('Create host storage');
816 sMountPoint = self.prepareStorage(self.oStorCfg);
817 if sMountPoint is None:
818 reporter.testFailure('Failed to prepare host storage');
819 fRc = False;
820 reporter.testDone();
821
822 if fRc:
823 # Loop thru the test VMs.
824 for sVM in self.asTestVMs:
825 # run test on the VM.
826 if not self.testBenchmarkOneVM(sVM, sMountPoint):
827 fRc = False;
828 else:
829 fRc = False;
830
831 return fRc;
832
833if __name__ == '__main__':
834 sys.exit(tdStorageBenchmark().main(sys.argv));
835
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