VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/testdriver/vboxtestvms.py@ 56623

Last change on this file since 56623 was 56374, checked in by vboxsync, 10 years ago

ValidationKit: Added option for skipping raw-mode tests based on testbox config or VirtualBox build. (untested)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 42.3 KB
Line 
1# -*- coding: utf-8 -*-
2# $Id: vboxtestvms.py 56374 2015-06-11 18:48:31Z vboxsync $
3
4"""
5VirtualBox Test VMs
6"""
7
8__copyright__ = \
9"""
10Copyright (C) 2010-2015 Oracle Corporation
11
12This file is part of VirtualBox Open Source Edition (OSE), as
13available from http://www.virtualbox.org. This file is free software;
14you can redistribute it and/or modify it under the terms of the GNU
15General Public License (GPL) as published by the Free Software
16Foundation, in version 2 as it comes in the "COPYING" file of the
17VirtualBox OSE distribution. VirtualBox OSE is distributed in the
18hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
19
20The contents of this file may alternatively be used under the terms
21of the Common Development and Distribution License Version 1.0
22(CDDL) only, as it comes in the "COPYING.CDDL" file of the
23VirtualBox OSE distribution, in which case the provisions of the
24CDDL are applicable instead of those of the GPL.
25
26You may elect to license modified versions of this file under the
27terms and conditions of either the GPL or the CDDL or both.
28"""
29__version__ = "$Revision: 56374 $"
30
31# Standard Python imports.
32import re;
33import random;
34import socket;
35
36# Validation Kit imports.
37from testdriver import base;
38from testdriver import reporter;
39from testdriver import vboxcon;
40
41
42# All virtualization modes.
43g_asVirtModes = ['hwvirt', 'hwvirt-np', 'raw',];
44# All virtualization modes except for raw-mode.
45g_asVirtModesNoRaw = ['hwvirt', 'hwvirt-np',];
46# Dictionary mapping the virtualization mode mnemonics to a little less cryptic
47# strings used in test descriptions.
48g_dsVirtModeDescs = {
49 'raw' : 'Raw-mode',
50 'hwvirt' : 'HwVirt',
51 'hwvirt-np' : 'NestedPaging'
52};
53
54# Arch constants.
55g_k32 = 32; # pylint: disable=C0103
56g_k64 = 64; # pylint: disable=C0103
57g_k32_64 = 96; # pylint: disable=C0103
58
59# Array indexes.
60g_iGuestOsType = 0;
61g_iKind = 1;
62g_iArch = 2;
63g_iMinCpu = 3;
64g_iMaxCpu = 4;
65g_iRegEx = 5;
66
67# Table translating from VM name core to a more detailed guest info.
68# pylint: disable=C0301
69g_aaNameToDetails = \
70[
71 [ 'WindowsNT4', 'WindowsNT4', g_k32, 1, 32, ['nt4', 'nt4sp[0-9]']], # max cpus??
72 [ 'Windows2000', 'Windows2000', g_k32, 1, 32, ['w2k', 'w2ksp[0-9]', 'win2k', 'win2ksp[0-9]']], # max cpus??
73 [ 'WindowsXP', 'WindowsXP', g_k32, 1, 32, ['xp', 'xpsp[0-9]']],
74 [ 'WindowsXP_64', 'WindowsXP_64', g_k64, 1, 32, ['xp64', 'xp64sp[0-9]']],
75 [ 'Windows2003', 'Windows2003', g_k32, 1, 32, ['w2k3', 'w2k3sp[0-9]', 'win2k3', 'win2k3sp[0-9]']],
76 [ 'WindowsVista', 'WindowsVista', g_k32, 1, 32, ['vista', 'vistasp[0-9]']],
77 [ 'Windows2008', 'Windows2008', g_k32, 1, 64, ['w2k8', 'w2k8sp[0-9]', 'win2k8', 'win2k8sp[0-9]']], # max cpus/cores??
78 [ 'Windows2008_64', 'Windows2008_64', g_k64, 1, 64, ['w2k8r2', 'w2k8r2sp[0-9]', 'win2k8r2', 'win2k8r2sp[0-9]']], # max cpus/cores??
79 [ 'Windows7', 'Windows7', g_k32, 1, 32, ['w7', 'w7sp[0-9]', 'win7',]], # max cpus/cores??
80 [ 'Windows7_64', 'Windows7_64', g_k64, 1, 64, ['w7-64', 'w7sp[0-9]-64', 'win7-64',]], # max cpus/cores??
81 [ 'Windows8', 'Windows8', g_k32, 1, 32, ['w8', 'w8sp[0-9]', 'win8',]], # max cpus/cores??
82 [ 'Windows8_64', 'Windows8_64', g_k64, 1, 64, ['w8-64', 'w8sp[0-9]-64', 'win8-64',]], # max cpus/cores??
83 [ 'Windows81', 'Windows81', g_k32, 1, 32, ['w81', 'w81sp[0-9]', 'win81',]], # max cpus/cores??
84 [ 'Windows81_64', 'Windows81_64', g_k64, 1, 64, ['w81-64', 'w81sp[0-9]-64', 'win81-64',]], # max cpus/cores??
85 [ 'Linux', 'Debian', g_k32, 1, 256, ['deb[0-9]*', 'debian[0-9]*', ]],
86 [ 'Linux_64', 'Debian_64', g_k64, 1, 256, ['deb[0-9]*-64', 'debian[0-9]*-64', ]],
87 [ 'Linux', 'RedHat', g_k32, 1, 256, ['rhel', 'rhel[0-9]', 'rhel[0-9]u[0-9]']],
88 [ 'Linux', 'Fedora', g_k32, 1, 256, ['fedora', 'fedora[0-9]*', ]],
89 [ 'Linux_64', 'Fedora_64', g_k64, 1, 256, ['fedora-64', 'fedora[0-9]*-64', ]],
90 [ 'Linux', 'Oracle', g_k32, 1, 256, ['ols[0-9]*', 'oel[0-9]*', ]],
91 [ 'Linux_64', 'Oracle_64', g_k64, 1, 256, ['ols[0-9]*-64', 'oel[0-9]*-64', ]],
92 [ 'Linux', 'OpenSUSE', g_k32, 1, 256, ['opensuse[0-9]*', 'suse[0-9]*', ]],
93 [ 'Linux_64', 'OpenSUSE_64', g_k64, 1, 256, ['opensuse[0-9]*-64', 'suse[0-9]*-64', ]],
94 [ 'Linux', 'Ubuntu', g_k32, 1, 256, ['ubuntu[0-9]*', ]],
95 [ 'Linux_64', 'Ubuntu_64', g_k64, 1, 256, ['ubuntu[0-9]*-64', ]],
96 [ 'Solaris', 'Solaris', g_k32, 1, 256, ['sol10', 'sol10u[0-9]']],
97 [ 'Solaris_64', 'Solaris_64', g_k64, 1, 256, ['sol10-64', 'sol10u-64[0-9]']],
98 [ 'Solaris_64', 'Solaris11_64', g_k64, 1, 256, ['sol11u1']],
99 [ 'BSD', 'FreeBSD_64', g_k32_64, 1, 1, ['bs-.*']], # boot sectors, wanted 64-bit type.
100];
101
102
103## @name Guest OS type string constants.
104## @{
105g_ksGuestOsTypeDarwin = 'darwin';
106g_ksGuestOsTypeFreeBSD = 'freebsd';
107g_ksGuestOsTypeLinux = 'linux';
108g_ksGuestOsTypeOS2 = 'os2';
109g_ksGuestOsTypeSolaris = 'solaris';
110g_ksGuestOsTypeWindows = 'windows';
111## @}
112
113## @name String constants for paravirtualization providers.
114## @{
115g_ksParavirtProviderNone = 'none';
116g_ksParavirtProviderDefault = 'default';
117g_ksParavirtProviderLegacy = 'legacy';
118g_ksParavirtProviderMinimal = 'minimal';
119g_ksParavirtProviderHyperV = 'hyperv';
120g_ksParavirtProviderKVM = 'kvm';
121## @}
122
123## Valid paravirtualization providers.
124g_kasParavirtProviders = ( g_ksParavirtProviderNone, g_ksParavirtProviderDefault, g_ksParavirtProviderLegacy,
125 g_ksParavirtProviderMinimal, g_ksParavirtProviderHyperV, g_ksParavirtProviderKVM );
126
127# Mapping for support of paravirtualisation providers per guest OS.
128#g_kdaParavirtProvidersSupported = {
129# g_ksGuestOsTypeDarwin : ( g_ksParavirtProviderMinimal, ),
130# g_ksGuestOsTypeFreeBSD : ( g_ksParavirtProviderNone, g_ksParavirtProviderMinimal, ),
131# g_ksGuestOsTypeLinux : ( g_ksParavirtProviderNone, g_ksParavirtProviderMinimal, g_ksParavirtProviderHyperV, g_ksParavirtProviderKVM),
132# g_ksGuestOsTypeOS2 : ( g_ksParavirtProviderNone, ),
133# g_ksGuestOsTypeSolaris : ( g_ksParavirtProviderNone, ),
134# g_ksGuestOsTypeWindows : ( g_ksParavirtProviderNone, g_ksParavirtProviderMinimal, g_ksParavirtProviderHyperV, )
135#}
136# Temporary tweak:
137# since for the most guests g_ksParavirtProviderNone is almost the same as g_ksParavirtProviderMinimal,
138# g_ksParavirtProviderMinimal is removed from the list in order to get maximum number of unique choices
139# during independent test runs when paravirt provider is taken randomly.
140g_kdaParavirtProvidersSupported = {
141 g_ksGuestOsTypeDarwin : ( g_ksParavirtProviderMinimal, ),
142 g_ksGuestOsTypeFreeBSD : ( g_ksParavirtProviderNone, ),
143 g_ksGuestOsTypeLinux : ( g_ksParavirtProviderNone, g_ksParavirtProviderHyperV, g_ksParavirtProviderKVM),
144 g_ksGuestOsTypeOS2 : ( g_ksParavirtProviderNone, ),
145 g_ksGuestOsTypeSolaris : ( g_ksParavirtProviderNone, ),
146 g_ksGuestOsTypeWindows : ( g_ksParavirtProviderNone, g_ksParavirtProviderHyperV, )
147}
148
149
150# pylint: enable=C0301
151
152def _intersects(asSet1, asSet2):
153 """
154 Checks if any of the strings in set 1 matches any of the regular
155 expressions in set 2.
156 """
157 for sStr1 in asSet1:
158 for sRx2 in asSet2:
159 if re.match(sStr1, sRx2 + '$'):
160 return True;
161 return False;
162
163
164class TestVm(object):
165 """
166 A Test VM - name + VDI/whatever.
167
168 This is just a data object.
169 """
170
171 def __init__(self, oSet, sVmName, sHd = None, sKind = None, acCpusSup = None, asVirtModesSup = None, # pylint: disable=R0913
172 fIoApic = None, fPae = None, sNic0AttachType = None, sHddControllerType = 'IDE Controller',
173 sFloppy = None, fVmmDevTestingPart = None, fVmmDevTestingMmio = False, asParavirtModesSup = None,
174 fRandomPvPMode = False):
175 self.oSet = oSet;
176 self.sVmName = sVmName;
177 self.sHd = sHd; # Relative to the testrsrc root.
178 self.acCpusSup = acCpusSup;
179 self.asVirtModesSup = asVirtModesSup;
180 self.asParavirtModesSup = asParavirtModesSup;
181 self.sKind = sKind;
182 self.sGuestOsType = None;
183 self.sDvdImage = None; # Relative to the testrsrc root.
184 self.fIoApic = fIoApic;
185 self.fPae = fPae;
186 self.sNic0AttachType = sNic0AttachType;
187 self.sHddControllerType = sHddControllerType;
188 self.sFloppy = sFloppy; # Relative to the testrsrc root, except when it isn't...
189 self.fVmmDevTestingPart = fVmmDevTestingPart;
190 self.fVmmDevTestingMmio = fVmmDevTestingMmio;
191
192 self.fSnapshotRestoreCurrent = False; # Whether to restore execution on the current snapshot.
193 self.fSkip = False; # All VMs are included in the configured set by default.
194 self.aInfo = None;
195 self._guessStuff(fRandomPvPMode);
196
197 def _mkCanonicalGuestOSType(self, sType):
198 """
199 Convert guest OS type into constant representation.
200 Raise exception if specified @param sType is unknown.
201 """
202 if sType.lower().startswith('darwin'):
203 return g_ksGuestOsTypeDarwin
204 if sType.lower().startswith('bsd'):
205 return g_ksGuestOsTypeFreeBSD
206 if sType.lower().startswith('linux'):
207 return g_ksGuestOsTypeLinux
208 if sType.lower().startswith('os2'):
209 return g_ksGuestOsTypeOS2
210 if sType.lower().startswith('solaris'):
211 return g_ksGuestOsTypeSolaris
212 if sType.lower().startswith('windows'):
213 return g_ksGuestOsTypeWindows
214 raise base.GenError(sWhat="unknown guest OS kind: %s" % str(sType))
215
216 def _guessStuff(self, fRandomPvPMode):
217 """
218 Used by the constructor to guess stuff.
219 """
220
221 sNm = self.sVmName.lower().strip();
222 asSplit = sNm.replace('-', ' ').split(' ');
223
224 if self.sKind is None:
225 # From name.
226 for aInfo in g_aaNameToDetails:
227 if _intersects(asSplit, aInfo[g_iRegEx]):
228 self.aInfo = aInfo;
229 self.sGuestOsType = self._mkCanonicalGuestOSType(aInfo[g_iGuestOsType])
230 self.sKind = aInfo[g_iKind];
231 break;
232 if self.sKind is None:
233 reporter.fatal('The OS of test VM "%s" cannot be guessed' % (self.sVmName,));
234
235 # Check for 64-bit, if required and supported.
236 if self.aInfo[g_iArch] == g_k32_64 and _intersects(asSplit, ['64', 'amd64']):
237 self.sKind = self.sKind + '_64';
238 else:
239 # Lookup the kind.
240 for aInfo in g_aaNameToDetails:
241 if self.sKind == aInfo[g_iKind]:
242 self.aInfo = aInfo;
243 break;
244 if self.aInfo is None:
245 reporter.fatal('The OS of test VM "%s" with sKind="%s" cannot be guessed' % (self.sVmName, self.sKind));
246
247 # Translate sKind into sGuest OS Type.
248 if self.sGuestOsType is None:
249 if self.aInfo is not None:
250 self.sGuestOsType = self._mkCanonicalGuestOSType(self.aInfo[g_iGuestOsType])
251 elif self.sKind.find("Windows") >= 0:
252 self.sGuestOsType = g_ksGuestOsTypeWindows
253 elif self.sKind.find("Linux") >= 0:
254 self.sGuestOsType = g_ksGuestOsTypeLinux;
255 elif self.sKind.find("Solaris") >= 0:
256 self.sGuestOsType = g_ksGuestOsTypeSolaris;
257 else:
258 reporter.fatal('The OS of test VM "%s", sKind="%s" cannot be guessed' % (self.sVmName, self.sKind));
259
260 # Restrict modes and such depending on the OS.
261 if self.asVirtModesSup is None:
262 self.asVirtModesSup = list(g_asVirtModes);
263 if self.sGuestOsType in (g_ksGuestOsTypeOS2, g_ksGuestOsTypeDarwin):
264 self.asVirtModesSup = [sVirtMode for sVirtMode in self.asVirtModesSup if sVirtMode != 'raw'];
265 if self.sKind.find('_64') > 0:
266 self.asVirtModesSup = [sVirtMode for sVirtMode in self.asVirtModesSup if sVirtMode != 'raw'];
267 # TEMPORARY HACK - START
268 sHostName = socket.getfqdn();
269 if sHostName.startswith('testboxpile1'):
270 self.asVirtModesSup = [sVirtMode for sVirtMode in self.asVirtModesSup if sVirtMode != 'raw'];
271 # TEMPORARY HACK - END
272
273 # Restrict the CPU count depending on the OS and/or percieved SMP readiness.
274 if self.acCpusSup is None:
275 if _intersects(asSplit, ['uni']):
276 self.acCpusSup = [1];
277 elif self.aInfo is not None:
278 self.acCpusSup = [i for i in range(self.aInfo[g_iMinCpu], self.aInfo[g_iMaxCpu]) ];
279 else:
280 self.acCpusSup = [1];
281
282 # Figure relevant PV modes based on the OS.
283 if self.asParavirtModesSup is None:
284 self.asParavirtModesSup = g_kdaParavirtProvidersSupported[self.sGuestOsType];
285 ## @todo Remove this hack as soon as we've got around to explictly configure test variations
286 ## on the server side. Client side random is interesting but not the best option.
287 if fRandomPvPMode:
288 random.seed();
289 self.asParavirtModesSup = (random.choice(self.asParavirtModesSup),);
290
291 return True;
292
293 def getReconfiguredVm(self, oTestDrv, cCpus, sVirtMode, sParavirtMode = None):
294 """
295 actionExecute worker that finds and reconfigure a test VM.
296
297 Returns (fRc, oVM) where fRc is True, None or False and oVM is a
298 VBox VM object that is only present when rc is True.
299 """
300
301 fRc = False;
302 oVM = oTestDrv.getVmByName(self.sVmName);
303 if oVM is not None:
304 if self.fSnapshotRestoreCurrent is True:
305 fRc = True;
306 else:
307 fHostSupports64bit = oTestDrv.hasHostLongMode();
308 if self.is64bitRequired() and not fHostSupports64bit:
309 fRc = None; # Skip the test.
310 elif self.isViaIncompatible() and oTestDrv.isHostCpuVia():
311 fRc = None; # Skip the test.
312 else:
313 oSession = oTestDrv.openSession(oVM);
314 if oSession is not None:
315 fRc = oSession.enableVirtEx(sVirtMode != 'raw');
316 fRc = fRc and oSession.enableNestedPaging(sVirtMode == 'hwvirt-np');
317 fRc = fRc and oSession.setCpuCount(cCpus);
318
319 if sParavirtMode is not None and oSession.fpApiVer >= 5.0:
320 adParavirtProviders = {
321 g_ksParavirtProviderNone : vboxcon.ParavirtProvider_None,
322 g_ksParavirtProviderDefault: vboxcon.ParavirtProvider_Default,
323 g_ksParavirtProviderLegacy : vboxcon.ParavirtProvider_Legacy,
324 g_ksParavirtProviderMinimal: vboxcon.ParavirtProvider_Minimal,
325 g_ksParavirtProviderHyperV : vboxcon.ParavirtProvider_HyperV,
326 g_ksParavirtProviderKVM : vboxcon.ParavirtProvider_KVM,
327 };
328 fRc = fRc and oSession.setParavirtProvider(adParavirtProviders[sParavirtMode]);
329
330 fCfg64Bit = self.is64bitRequired() or (self.is64bit() and fHostSupports64bit and sVirtMode != 'raw');
331 fRc = fRc and oSession.enableLongMode(fCfg64Bit);
332 if fCfg64Bit: # This is to avoid GUI pedantic warnings in the GUI. Sigh.
333 oOsType = oSession.getOsType();
334 if oOsType is not None:
335 if oOsType.is64Bit and sVirtMode == 'raw':
336 assert(oOsType.id[-3:] == '_64');
337 fRc = fRc and oSession.setOsType(oOsType.id[:-3]);
338 elif not oOsType.is64Bit and sVirtMode != 'raw':
339 fRc = fRc and oSession.setOsType(oOsType.id + '_64');
340
341 fRc = fRc and oSession.saveSettings();
342 if not oSession.close():
343 fRc = False;
344 if fRc is True:
345 return (True, oVM);
346 return (fRc, None);
347
348
349 def isWindows(self):
350 """ Checks if it's a Windows VM. """
351 return self.sGuestOsType == g_ksGuestOsTypeWindows;
352
353 def isOS2(self):
354 """ Checks if it's an OS/2 VM. """
355 return self.sGuestOsType == g_ksGuestOsTypeOS2;
356
357 def is64bit(self):
358 """ Checks if it's a 64-bit VM. """
359 return self.sKind.find('_64') >= 0;
360
361 def is64bitRequired(self):
362 """ Check if 64-bit is required or not. """
363 return (self.aInfo[g_iArch] & g_k64) != 0;
364
365 def isLoggedOntoDesktop(self):
366 """ Checks if the test VM is logging onto a graphical desktop by default. """
367 if self.isWindows():
368 return True;
369 if self.isOS2():
370 return True;
371 if self.sVmName.find('-desktop'):
372 return True;
373 return False;
374
375 def isViaIncompatible(self):
376 """
377 Identifies VMs that doesn't work on VIA.
378
379 Returns True if NOT supported on VIA, False if it IS supported.
380 """
381 # Oracle linux doesn't like VIA in our experience
382 if self.aInfo[g_iKind] in ['Oracle', 'Oracle_64']:
383 return True;
384 # OS/2: "The system detected an internal processing error at location
385 # 0168:fff1da1f - 000e:ca1f. 0a8606fd
386 if self.isOS2():
387 return True;
388 # Windows NT4 before SP4 won't work because of cmpxchg8b not being
389 # detected, leading to a STOP 3e(80,0,0,0).
390 if self.aInfo[g_iKind] == 'WindowsNT4':
391 if self.sVmName.find('sp') < 0:
392 return True; # no service pack.
393 if self.sVmName.find('sp0') >= 0 \
394 or self.sVmName.find('sp1') >= 0 \
395 or self.sVmName.find('sp2') >= 0 \
396 or self.sVmName.find('sp3') >= 0:
397 return True;
398 return False;
399
400
401
402class BootSectorTestVm(TestVm):
403 """
404 A Boot Sector Test VM.
405 """
406
407 def __init__(self, oSet, sVmName, sFloppy = None, asVirtModesSup = None, f64BitRequired = False):
408 self.f64BitRequired = f64BitRequired;
409 if asVirtModesSup is None:
410 asVirtModesSup = list(g_asVirtModes);
411 TestVm.__init__(self, oSet, sVmName,
412 acCpusSup = [1,],
413 sFloppy = sFloppy,
414 asVirtModesSup = asVirtModesSup,
415 fPae = True,
416 fIoApic = True,
417 fVmmDevTestingPart = True,
418 fVmmDevTestingMmio = True,
419 );
420
421 def is64bitRequired(self):
422 return self.f64BitRequired;
423
424
425
426class TestVmSet(object):
427 """
428 A set of Test VMs.
429 """
430
431 def __init__(self, oTestVmManager = None, acCpus = None, asVirtModes = None, fIgnoreSkippedVm = False):
432 self.oTestVmManager = oTestVmManager;
433 if acCpus is None:
434 acCpus = [1, 2];
435 self.acCpusDef = acCpus;
436 self.acCpus = acCpus;
437 if asVirtModes is None:
438 asVirtModes = list(g_asVirtModes);
439 self.asVirtModesDef = asVirtModes;
440 self.asVirtModes = asVirtModes;
441 self.aoTestVms = [];
442 self.fIgnoreSkippedVm = fIgnoreSkippedVm;
443 self.asParavirtModes = None; ##< If None, use the first PV mode of the test VM, otherwise all modes in this list.
444
445 def findTestVmByName(self, sVmName):
446 """
447 Returns the TestVm object with the given name.
448 Returns None if not found.
449 """
450 for oTestVm in self.aoTestVms:
451 if oTestVm.sVmName == sVmName:
452 return oTestVm;
453 return None;
454
455 def getAllVmNames(self, sSep = ':'):
456 """
457 Returns names of all the test VMs in the set separated by
458 sSep (defaults to ':').
459 """
460 sVmNames = '';
461 for oTestVm in self.aoTestVms:
462 if sVmNames == '':
463 sVmNames = oTestVm.sVmName;
464 else:
465 sVmNames = sVmNames + sSep + oTestVm.sVmName;
466 return sVmNames;
467
468 def showUsage(self):
469 """
470 Invoked by vbox.TestDriver.
471 """
472 reporter.log('');
473 reporter.log('Test VM selection and general config options:');
474 reporter.log(' --virt-modes <m1[:m2[:]]');
475 reporter.log(' Default: %s' % (':'.join(self.asVirtModesDef)));
476 reporter.log(' --skip-virt-modes <m1[:m2[:]]');
477 reporter.log(' Use this to avoid hwvirt or hwvirt-np when not supported by the host');
478 reporter.log(' since we cannot detect it using the main API. Use after --virt-modes.');
479 reporter.log(' --cpu-counts <c1[:c2[:]]');
480 reporter.log(' Default: %s' % (':'.join(str(c) for c in self.acCpusDef)));
481 reporter.log(' --test-vms <vm1[:vm2[:...]]>');
482 reporter.log(' Test the specified VMs in the given order. Use this to change');
483 reporter.log(' the execution order or limit the choice of VMs');
484 reporter.log(' Default: %s (all)' % (self.getAllVmNames(),));
485 reporter.log(' --skip-vms <vm1[:vm2[:...]]>');
486 reporter.log(' Skip the specified VMs when testing.');
487 reporter.log(' --snapshot-restore-current');
488 reporter.log(' Restores the current snapshot and resumes execution.');
489 reporter.log(' --paravirt-modes <pv1[:pv2[:]]>');
490 reporter.log(' Set of paravirtualized providers (modes) to tests. Intersected with what the test VM supports.');
491 reporter.log(' Default is the first PV mode the test VMs support, generally same as "legacy".');
492 ## @todo Add more options for controlling individual VMs.
493 return True;
494
495 def parseOption(self, asArgs, iArg):
496 """
497 Parses the set test vm set options (--test-vms and --skip-vms), modifying the set
498 Invoked by the testdriver method with the same name.
499
500 Keyword arguments:
501 asArgs -- The argument vector.
502 iArg -- The index of the current argument.
503
504 Returns iArg if the option was not recognized and the caller should handle it.
505 Returns the index of the next argument when something is consumed.
506
507 In the event of a syntax error, a InvalidOption or QuietInvalidOption
508 is thrown.
509 """
510
511 if asArgs[iArg] == '--virt-modes':
512 iArg += 1;
513 if iArg >= len(asArgs):
514 raise base.InvalidOption('The "--virt-modes" takes a colon separated list of modes');
515
516 self.asVirtModes = asArgs[iArg].split(':');
517 for s in self.asVirtModes:
518 if s not in self.asVirtModesDef:
519 raise base.InvalidOption('The "--virt-modes" value "%s" is not valid; valid values are: %s' \
520 % (s, ' '.join(self.asVirtModesDef)));
521
522 elif asArgs[iArg] == '--skip-virt-modes':
523 iArg += 1;
524 if iArg >= len(asArgs):
525 raise base.InvalidOption('The "--skip-virt-modes" takes a colon separated list of modes');
526
527 for s in asArgs[iArg].split(':'):
528 if s not in self.asVirtModesDef:
529 raise base.InvalidOption('The "--virt-modes" value "%s" is not valid; valid values are: %s' \
530 % (s, ' '.join(self.asVirtModesDef)));
531 if s in self.asVirtModes:
532 self.asVirtModes.remove(s);
533
534 elif asArgs[iArg] == '--cpu-counts':
535 iArg += 1;
536 if iArg >= len(asArgs):
537 raise base.InvalidOption('The "--cpu-counts" takes a colon separated list of cpu counts');
538
539 self.acCpus = [];
540 for s in asArgs[iArg].split(':'):
541 try: c = int(s);
542 except: raise base.InvalidOption('The "--cpu-counts" value "%s" is not an integer' % (s,));
543 if c <= 0: raise base.InvalidOption('The "--cpu-counts" value "%s" is zero or negative' % (s,));
544 self.acCpus.append(c);
545
546 elif asArgs[iArg] == '--test-vms':
547 iArg += 1;
548 if iArg >= len(asArgs):
549 raise base.InvalidOption('The "--test-vms" takes colon separated list');
550
551 for oTestVm in self.aoTestVms:
552 oTestVm.fSkip = True;
553
554 asTestVMs = asArgs[iArg].split(':');
555 for s in asTestVMs:
556 oTestVm = self.findTestVmByName(s);
557 if oTestVm is None:
558 raise base.InvalidOption('The "--test-vms" value "%s" is not valid; valid values are: %s' \
559 % (s, self.getAllVmNames(' ')));
560 oTestVm.fSkip = False;
561
562 elif asArgs[iArg] == '--skip-vms':
563 iArg += 1;
564 if iArg >= len(asArgs):
565 raise base.InvalidOption('The "--skip-vms" takes colon separated list');
566
567 asTestVMs = asArgs[iArg].split(':');
568 for s in asTestVMs:
569 oTestVm = self.findTestVmByName(s);
570 if oTestVm is None:
571 reporter.log('warning: The "--test-vms" value "%s" does not specify any of our test VMs.' % (s,));
572 else:
573 oTestVm.fSkip = True;
574
575 elif asArgs[iArg] == '--snapshot-restore-current':
576 for oTestVm in self.aoTestVms:
577 if oTestVm.fSkip is False:
578 oTestVm.fSnapshotRestoreCurrent = True;
579 reporter.log('VM "%s" will be restored.' % (oTestVm.sVmName));
580
581 elif asArgs[iArg] == '--paravirt-modes':
582 iArg += 1
583 if iArg >= len(asArgs):
584 raise base.InvalidOption('The "--paravirt-modes" takes a colon separated list of modes');
585
586 self.asParavirtModes = asArgs[iArg].split(':')
587 for sPvMode in self.asParavirtModes:
588 if sPvMode not in g_kasParavirtProviders:
589 raise base.InvalidOption('The "--paravirt-modes" value "%s" is not valid; valid values are: %s'
590 % (sPvMode, ', '.join(g_kasParavirtProviders),));
591 if len(self.asParavirtModes) == 0:
592 self.asParavirtModes = None;
593
594 else:
595 return iArg;
596 return iArg + 1;
597
598 def getResourceSet(self):
599 """
600 Implements base.TestDriver.getResourceSet
601 """
602 asResources = [];
603 for oTestVm in self.aoTestVms:
604 if not oTestVm.fSkip:
605 if oTestVm.sHd is not None:
606 asResources.append(oTestVm.sHd);
607 if oTestVm.sDvdImage is not None:
608 asResources.append(oTestVm.sDvdImage);
609 return asResources;
610
611 def actionConfig(self, oTestDrv, eNic0AttachType = None, sDvdImage = None):
612 """
613 For base.TestDriver.actionConfig. Configure the VMs with defaults and
614 a few tweaks as per arguments.
615
616 Returns True if successful.
617 Returns False if not.
618 """
619
620 for oTestVm in self.aoTestVms:
621 if oTestVm.fSkip:
622 continue;
623
624 if oTestVm.fSnapshotRestoreCurrent:
625 # If we want to restore a VM we don't need to create
626 # the machine anymore -- so just add it to the test VM list.
627 oVM = oTestDrv.addTestMachine(oTestVm.sVmName);
628 else:
629 ## @todo This could possibly be moved to the TestVM object.
630 if sDvdImage is not None:
631 sMyDvdImage = sDvdImage;
632 else:
633 sMyDvdImage = oTestVm.sDvdImage;
634
635 if eNic0AttachType is not None:
636 eMyNic0AttachType = eNic0AttachType;
637 elif oTestVm.sNic0AttachType is None:
638 eMyNic0AttachType = None;
639 elif oTestVm.sNic0AttachType == 'nat':
640 eMyNic0AttachType = vboxcon.NetworkAttachmentType_NAT;
641 elif oTestVm.sNic0AttachType == 'bridged':
642 eMyNic0AttachType = vboxcon.NetworkAttachmentType_Bridged;
643 else:
644 assert False, oTestVm.sNic0AttachType;
645
646 oVM = oTestDrv.createTestVM(oTestVm.sVmName, 1, \
647 sHd = oTestVm.sHd, \
648 sKind = oTestVm.sKind, \
649 fIoApic = oTestVm.fIoApic, \
650 fPae = oTestVm.fPae, \
651 eNic0AttachType = eMyNic0AttachType, \
652 sDvdImage = sMyDvdImage, \
653 sHddControllerType = oTestVm.sHddControllerType,
654 sFloppy = oTestVm.sFloppy,
655 fVmmDevTestingPart = oTestVm.fVmmDevTestingPart,
656 fVmmDevTestingMmio = oTestVm.fVmmDevTestingPart);
657 if oVM is None:
658 return False;
659
660 return True;
661
662 def _removeUnsupportedVirtModes(self, oTestDrv):
663 """
664 Removes unsupported virtualization modes.
665 """
666 if 'hwvirt' in self.asVirtModes and not oTestDrv.hasHostHwVirt():
667 reporter.log('Hardware assisted virtualization is not available on the host, skipping it.');
668 self.asVirtModes.remove('hwvirt');
669
670 if 'hwvirt-np' in self.asVirtModes and not oTestDrv.hasHostNestedPaging():
671 reporter.log('Nested paging not supported by the host, skipping it.');
672 self.asVirtModes.remove('hwvirt-np');
673
674 if 'raw' in self.asVirtModes and not oTestDrv.hasRawModeSupport():
675 reporter.log('Raw-mode virtualization is not available in this build (or perhaps for this host), skipping it.');
676 self.asVirtModes.remove('raw');
677
678 return True;
679
680 def actionExecute(self, oTestDrv, fnCallback): # pylint: disable=R0914
681 """
682 For base.TestDriver.actionExecute. Calls the callback function for
683 each of the VMs and basic configuration variations (virt-mode and cpu
684 count).
685
686 Returns True if all fnCallback calls returned True, otherwise False.
687
688 The callback can return True, False or None. The latter is for when the
689 test is skipped. (True is for success, False is for failure.)
690 """
691
692 self._removeUnsupportedVirtModes(oTestDrv);
693 cMaxCpus = oTestDrv.getHostCpuCount();
694
695 #
696 # The test loop.
697 #
698 fRc = True;
699 for oTestVm in self.aoTestVms:
700 if oTestVm.fSkip and self.fIgnoreSkippedVm:
701 reporter.log2('Ignoring VM %s (fSkip = True).' % (oTestVm.sVmName,));
702 continue;
703 reporter.testStart(oTestVm.sVmName);
704 if oTestVm.fSkip:
705 reporter.testDone(fSkipped = True);
706 continue;
707
708 # Intersect the supported modes and the ones being testing.
709 asVirtModesSup = [sMode for sMode in oTestVm.asVirtModesSup if sMode in self.asVirtModes];
710
711 # Ditto for CPUs.
712 acCpusSup = [cCpus for cCpus in oTestVm.acCpusSup if cCpus in self.acCpus];
713
714 # Ditto for paravirtualization modes, except if not specified we got a less obvious default.
715 if self.asParavirtModes is not None and oTestDrv.fpApiVer >= 5.0:
716 asParavirtModes = [sPvMode for sPvMode in oTestVm.asParavirtModesSup if sPvMode in self.asParavirtModes];
717 assert None not in asParavirtModes;
718 elif oTestDrv.fpApiVer >= 5.0:
719 asParavirtModes = (oTestVm.asParavirtModesSup[0],);
720 assert asParavirtModes[0] is not None;
721 else:
722 asParavirtModes = (None,);
723
724 for cCpus in acCpusSup:
725 if cCpus == 1:
726 reporter.testStart('1 cpu');
727 else:
728 reporter.testStart('%u cpus' % (cCpus));
729 if cCpus > cMaxCpus:
730 reporter.testDone(fSkipped = True);
731 continue;
732
733 cTests = 0;
734 for sVirtMode in asVirtModesSup:
735 if sVirtMode == 'raw' and cCpus > 1:
736 continue;
737 reporter.testStart('%s' % ( g_dsVirtModeDescs[sVirtMode], ) );
738 cStartTests = cTests;
739
740 for sParavirtMode in asParavirtModes:
741 if sParavirtMode is not None:
742 assert oTestDrv.fpApiVer >= 5.0;
743 reporter.testStart('%s' % ( sParavirtMode, ) );
744
745 # Reconfigure the VM.
746 try:
747 (rc2, oVM) = oTestVm.getReconfiguredVm(oTestDrv, cCpus, sVirtMode, sParavirtMode = sParavirtMode);
748 except KeyboardInterrupt:
749 raise;
750 except:
751 reporter.errorXcpt(cFrames = 9);
752 rc2 = False;
753 if rc2 is True:
754 # Do the testing.
755 try:
756 rc2 = fnCallback(oVM, oTestVm);
757 except KeyboardInterrupt:
758 raise;
759 except:
760 reporter.errorXcpt(cFrames = 9);
761 rc2 = False;
762 if rc2 is False:
763 reporter.maybeErr(reporter.testErrorCount() == 0, 'fnCallback failed');
764 elif rc2 is False:
765 reporter.log('getReconfiguredVm failed');
766 if rc2 is False:
767 fRc = False;
768
769 cTests = cTests + (rc2 is not None);
770 if sParavirtMode is not None:
771 reporter.testDone(fSkipped = (rc2 is None));
772
773 reporter.testDone(fSkipped = cTests == cStartTests);
774
775 reporter.testDone(fSkipped = cTests == 0);
776
777 _, cErrors = reporter.testDone();
778 if cErrors > 0:
779 fRc = False;
780 return fRc;
781
782 def enumerateTestVms(self, fnCallback):
783 """
784 Enumerates all the 'active' VMs.
785
786 Returns True if all fnCallback calls returned True.
787 Returns False if any returned False.
788 Returns None immediately if fnCallback returned None.
789 """
790 fRc = True;
791 for oTestVm in self.aoTestVms:
792 if not oTestVm.fSkip:
793 fRc2 = fnCallback(oTestVm);
794 if fRc2 is None:
795 return fRc2;
796 fRc = fRc and fRc2;
797 return fRc;
798
799
800
801class TestVmManager(object):
802 """
803 Test VM manager.
804 """
805
806 def __init__(self, sResourcePath):
807 self.sResourcePath = sResourcePath;
808
809
810 def getStandardVmSet(self, sTxsTransport):
811 """
812 Gets the set of standard test VMs.
813
814 This is supposed to do something seriously clever, like searching the
815 testrsrc tree for usable VMs, but for the moment it's all hard coded. :-)
816 """
817
818 oSet = TestVmSet(oTestVmManager = self);
819
820 oTestVm = TestVm(oSet, 'tst-nt4sp1', sHd = '4.2/' + sTxsTransport + '/nt4sp1/t-nt4sp1.vdi',
821 sKind = 'WindowsNT4', acCpusSup = [1]);
822 oSet.aoTestVms.append(oTestVm);
823
824 oTestVm = TestVm(oSet, 'tst-xppro', sHd = '4.2/' + sTxsTransport + '/xppro/t-xppro.vdi',
825 sKind = 'WindowsXP', acCpusSup = range(1, 33));
826 oSet.aoTestVms.append(oTestVm);
827
828 oTestVm = TestVm(oSet, 'tst-nt4sp6', sHd = '4.2/nt4sp6/t-nt4sp6.vdi',
829 sKind = 'WindowsNT4', acCpusSup = range(1, 33));
830 oSet.aoTestVms.append(oTestVm);
831
832 oTestVm = TestVm(oSet, 'tst-2ksp4', sHd = '4.2/win2ksp4/t-win2ksp4.vdi',
833 sKind = 'Windows2000', acCpusSup = range(1, 33));
834 oSet.aoTestVms.append(oTestVm);
835
836 oTestVm = TestVm(oSet, 'tst-xpsp2', sHd = '4.2/xpsp2/t-winxpsp2.vdi',
837 sKind = 'WindowsXP', acCpusSup = range(1, 33), fIoApic = True);
838 oSet.aoTestVms.append(oTestVm);
839
840 oTestVm = TestVm(oSet, 'tst-xpsp2-halaacpi', sHd = '4.2/xpsp2/t-winxp-halaacpi.vdi',
841 sKind = 'WindowsXP', acCpusSup = range(1, 33), fIoApic = True);
842 oSet.aoTestVms.append(oTestVm);
843
844 oTestVm = TestVm(oSet, 'tst-xpsp2-halacpi', sHd = '4.2/xpsp2/t-winxp-halacpi.vdi',
845 sKind = 'WindowsXP', acCpusSup = range(1, 33), fIoApic = True);
846 oSet.aoTestVms.append(oTestVm);
847
848 oTestVm = TestVm(oSet, 'tst-xpsp2-halapic', sHd = '4.2/xpsp2/t-winxp-halapic.vdi',
849 sKind = 'WindowsXP', acCpusSup = range(1, 33), fIoApic = True);
850 oSet.aoTestVms.append(oTestVm);
851
852 oTestVm = TestVm(oSet, 'tst-xpsp2-halmacpi', sHd = '4.2/xpsp2/t-winxp-halmacpi.vdi',
853 sKind = 'WindowsXP', acCpusSup = range(2, 33), fIoApic = True);
854 oSet.aoTestVms.append(oTestVm);
855
856 oTestVm = TestVm(oSet, 'tst-xpsp2-halmps', sHd = '4.2/xpsp2/t-winxp-halmps.vdi',
857 sKind = 'WindowsXP', acCpusSup = range(2, 33), fIoApic = True);
858 oSet.aoTestVms.append(oTestVm);
859
860 oTestVm = TestVm(oSet, 'tst-win7', sHd = '4.2/win7-32/t-win7.vdi',
861 sKind = 'Windows7', acCpusSup = range(1, 33), fIoApic = True);
862 oSet.aoTestVms.append(oTestVm);
863
864 oTestVm = TestVm(oSet, 'tst-win8', sHd = '4.2/win8-32/t-win8.vdi',
865 sKind = 'Windows8', acCpusSup = range(1, 33), fIoApic = True);
866 oSet.aoTestVms.append(oTestVm);
867
868 return oSet;
869
870 def getSmokeVmSet(self):
871 """
872 Gets a representative set of VMs for smoke testing.
873 """
874
875 oSet = TestVmSet(oTestVmManager = self);
876
877 oTestVm = TestVm(oSet, 'tst-nt4sp1', sHd = '4.2/nat/nt4sp1/t-nt4sp1.vdi',
878 sKind = 'WindowsNT4', acCpusSup = [1], sNic0AttachType = 'nat');
879 oSet.aoTestVms.append(oTestVm);
880
881 oTestVm = TestVm(oSet, 'tst-xppro', sHd = '4.2/nat/xppro/t-xppro.vdi',
882 sKind = 'WindowsXP', acCpusSup = range(1, 33), sNic0AttachType = 'nat');
883 oSet.aoTestVms.append(oTestVm);
884
885 oTestVm = TestVm(oSet, 'tst-rhel5', sHd = '3.0/tcp/rhel5.vdi',
886 sKind = 'RedHat', acCpusSup = range(1, 33), fIoApic = True, sNic0AttachType = 'nat');
887 oSet.aoTestVms.append(oTestVm);
888
889 oTestVm = TestVm(oSet, 'tst-win2k3ent', sHd = '3.0/tcp/win2k3ent-acpi.vdi',
890 sKind = 'Windows2003', acCpusSup = range(1, 33), fPae = True, sNic0AttachType = 'bridged');
891 oSet.aoTestVms.append(oTestVm);
892
893 oTestVm = TestVm(oSet, 'tst-sol10', sHd = '3.0/tcp/solaris10.vdi',
894 sKind = 'Solaris', acCpusSup = range(1, 33), fPae = True, sNic0AttachType = 'bridged');
895 oSet.aoTestVms.append(oTestVm);
896
897 oTestVm = TestVm(oSet, 'tst-sol10-64', sHd = '3.0/tcp/solaris10.vdi',
898 sKind = 'Solaris_64', acCpusSup = range(1, 33), sNic0AttachType = 'bridged');
899 oSet.aoTestVms.append(oTestVm);
900
901 oTestVm = TestVm(oSet, 'tst-sol11u1', sHd = '4.2/nat/sol11u1/t-sol11u1.vdi',
902 sKind = 'Solaris11_64', acCpusSup = range(1, 33), sNic0AttachType = 'nat',
903 fIoApic = True, sHddControllerType = 'SATA Controller');
904 oSet.aoTestVms.append(oTestVm);
905
906 oTestVm = TestVm(oSet, 'tst-nt4sp6', sHd = '4.2/nt4sp6/t-nt4sp6.vdi',
907 sKind = 'WindowsNT4', acCpusSup = range(1, 33));
908 oSet.aoTestVms.append(oTestVm);
909
910 oTestVm = TestVm(oSet, 'tst-2ksp4', sHd = '4.2/win2ksp4/t-win2ksp4.vdi',
911 sKind = 'Windows2000', acCpusSup = range(1, 33));
912 oSet.aoTestVms.append(oTestVm);
913
914 oTestVm = TestVm(oSet, 'tst-xpsp2', sHd = '4.2/xpsp2/t-winxpsp2.vdi',
915 sKind = 'WindowsXP', acCpusSup = range(1, 33), fIoApic = True);
916 oSet.aoTestVms.append(oTestVm);
917
918 oTestVm = TestVm(oSet, 'tst-xpsp2-halaacpi', sHd = '4.2/xpsp2/t-winxp-halaacpi.vdi',
919 sKind = 'WindowsXP', acCpusSup = range(1, 33), fIoApic = True);
920 oSet.aoTestVms.append(oTestVm);
921
922 oTestVm = TestVm(oSet, 'tst-xpsp2-halacpi', sHd = '4.2/xpsp2/t-winxp-halacpi.vdi',
923 sKind = 'WindowsXP', acCpusSup = range(1, 33), fIoApic = True);
924 oSet.aoTestVms.append(oTestVm);
925
926 oTestVm = TestVm(oSet, 'tst-xpsp2-halapic', sHd = '4.2/xpsp2/t-winxp-halapic.vdi',
927 sKind = 'WindowsXP', acCpusSup = range(1, 33), fIoApic = True);
928 oSet.aoTestVms.append(oTestVm);
929
930 oTestVm = TestVm(oSet, 'tst-xpsp2-halmacpi', sHd = '4.2/xpsp2/t-winxp-halmacpi.vdi',
931 sKind = 'WindowsXP', acCpusSup = range(2, 33), fIoApic = True);
932 oSet.aoTestVms.append(oTestVm);
933
934 oTestVm = TestVm(oSet, 'tst-xpsp2-halmps', sHd = '4.2/xpsp2/t-winxp-halmps.vdi',
935 sKind = 'WindowsXP', acCpusSup = range(2, 33), fIoApic = True);
936 oSet.aoTestVms.append(oTestVm);
937
938 oTestVm = TestVm(oSet, 'tst-win7', sHd = '4.2/win7-32/t-win7.vdi',
939 sKind = 'Windows7', acCpusSup = range(1, 33), fIoApic = True);
940 oSet.aoTestVms.append(oTestVm);
941
942 oTestVm = TestVm(oSet, 'tst-win8', sHd = '4.2/win8-32/t-win8.vdi',
943 sKind = 'Windows8', acCpusSup = range(1, 33), fIoApic = True);
944 oSet.aoTestVms.append(oTestVm);
945
946 return oSet;
947
948 def shutUpPyLint(self):
949 """ Shut up already! """
950 return self.sResourcePath;
951
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